From eduardo.abinader at riverbed.com Fri Jul 1 05:50:37 2016 From: eduardo.abinader at riverbed.com (Eduardo Abinader) Date: Fri, 1 Jul 2016 11:50:37 +0200 Subject: [OpenWrt-Devel] [LEDE-DEV] [PATCH] netifd: remove wireless device when device fails to setup In-Reply-To: <8e7f2f39-8f08-6c71-3082-97039ac76211@nbd.name> References: <57752A24.7020905@riverbed.com> <8e7f2f39-8f08-6c71-3082-97039ac76211@nbd.name> Message-ID: <57763CED.4070106@riverbed.com> Hi Felix, 1) Just set a non-allowed DFS channel for DE, for instance. 2) Enable wireless; it fails 3) Change to a valid channel; the wdev is not set up. There is also a leftover on /etc/init.d/network reload. I think it should call /sbin/wifi instead of /sbin/wifi reload. Eduardo On 01.07.2016 00:14, Felix Fietkau wrote: > On 2016-06-30 16:18, Eduardo Abinader wrote: >> Ensure wireless device struct is removed, when it fails to be set up, >> due to a invalid configuration, hence enabling the wireless dev >> to be set up again, when a new valid configuration is set. >> >> Signed-off-by: Eduardo Abinader >> --- >> wireless.c | 4 ++++ >> 1 file changed, 4 insertions(+) >> >> diff --git a/wireless.c b/wireless.c >> index 34dd328..bc31d4a 100644 >> --- a/wireless.c >> +++ b/wireless.c >> @@ -336,6 +336,10 @@ wireless_device_mark_down(struct wireless_device *wdev) >> >> wireless_process_kill_all(wdev, SIGTERM, true); >> >> + if (wdev->state == IFS_SETUP && !wdev->autostart) { >> + wdev->config_state = IFC_REMOVE; >> + } > This doesn't make sense to me. Could you please provide a test case that > reproduces the problem you're trying to fix? > > - Felix > _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From f.fainelli at gmail.com Fri Jul 1 17:56:38 2016 From: f.fainelli at gmail.com (Florian Fainelli) Date: Fri, 1 Jul 2016 14:56:38 -0700 Subject: [OpenWrt-Devel] [PATCH ubus] cmake: Fix find_library for ubusd and examples/server Message-ID: <1467410198-24118-1-git-send-email-f.fainelli@gmail.com> Both ubusd and cli TARGET_LINK_LIBRARIES reference ${json} which is obtained via find_library(), but since the find_library() is searched after the TARGET_LINK_LIBRARIES for ubusd, ubusd always gets an empty ${json} variable. examples/server also links against libjson-c, but we were not setting TARGET_LINK_LIBRARIES accordingly, so do that too with ${json} appended. This was causing linking errors for ubusd and then examples/server using an external toolchain (stbgcc-4.8-1.x). Fixes: 9f52d1769b762 ("cli: use the new json-c library name") Signed-off-by: Florian Fainelli --- CMakeLists.txt | 3 ++- examples/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 70a0de6536d9..7123096a0f93 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,10 +32,11 @@ INCLUDE_DIRECTORIES(${ubox_include_dir}) ADD_LIBRARY(ubus SHARED libubus.c libubus-io.c libubus-obj.c libubus-sub.c libubus-req.c libubus-acl.c) TARGET_LINK_LIBRARIES(ubus ${ubox_library}) +find_library(json NAMES json-c json) + ADD_EXECUTABLE(ubusd ubusd.c ubusd_id.c ubusd_obj.c ubusd_proto.c ubusd_event.c ubusd_acl.c ubusd_monitor.c) TARGET_LINK_LIBRARIES(ubusd ${ubox_library} ${blob_library} ${json}) -find_library(json NAMES json-c json) ADD_EXECUTABLE(cli cli.c) SET_TARGET_PROPERTIES(cli PROPERTIES OUTPUT_NAME ubus) TARGET_LINK_LIBRARIES(cli ubus ${ubox_library} ${blob_library} ${json}) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 006dac42a27c..81f999752950 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -5,7 +5,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/..) IF (BUILD_EXAMPLES) ADD_EXECUTABLE(server server.c count.c) - TARGET_LINK_LIBRARIES(server ubus ${ubox_library} ${blob_library}) + TARGET_LINK_LIBRARIES(server ubus ${ubox_library} ${blob_library} ${json}) ADD_EXECUTABLE(client client.c count.c) TARGET_LINK_LIBRARIES(client ubus ${ubox_library}) -- 2.7.4 _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From frodo at morgul.net Sat Jul 2 02:26:34 2016 From: frodo at morgul.net (Noah Meyerhans) Date: Fri, 1 Jul 2016 23:26:34 -0700 Subject: [OpenWrt-Devel] [RFD] Future In-Reply-To: <57744805.6000902@gmail.com> References: <57744805.6000902@gmail.com> Message-ID: <20160702062634.GB13609@insomnia.internal.morgul.net> On Wed, Jun 29, 2016 at 03:13:25PM -0700, Florian Fainelli wrote: > > I am against a Face-2-Face meeting. I think not everybody can travel to > > some other country for some 100$ on a short notice. For people that do > > OpenWrt/LEDE for a living and have their own company or get support form > > a company this is probably not problem, but some people have other jobs > > beside OpenWrt/LEDE and have to take some days off and then pay the > > money for traveling. The purpose of LEDE was to focus more on the community. > > > > I am for a telephone conference like google hangout or this fuze meeting > > prpl uses, to make it easy for everybody to participate. > > Pretty much on the same boat as you here, and on the west coast of the > US, so not very easy to travel in a short notice. If you actually meet > F2F and have the ability to make people join via Audio or Video that > would be terrific. One thing I've learned from being involved in Debian over the years is that face to face meetings can be hugely benefitial for building community (see Debconf, happening right now in South Africa). In part this is because in-person meetings allow for substantially more bandwidth between participants, so it's quicker and easier to come to agreements. Beyond that, though, participants interact with each other as people, with all the extra considerations that come along with that. Casual conversation over lunch or at a pub at the end of the day, for example, really helps to break down barriers between people. So I think it's a really good idea for people to get together. A couple of details about Debconf that may be worth considering: 1. The organization solicits help from sponsors in order to help subsidize travel costs for people who need it. I doubt that either OpenWRT or LEDE are in a position to do this right now, but it may be something to consider for the future. 2. Debconf is held in a different city (often on a different continent) each year. This helps to ensure that burden of travelling is distributed as evenly as possible. Whether or not additional meetings happen in the future is unclear, but it'd be good for them to happen in different parts of the world if they do. noah -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 811 bytes Desc: not available URL: -------------- next part -------------- _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From ardeleanalex at gmail.com Sat Jul 2 04:11:34 2016 From: ardeleanalex at gmail.com (Alexandru Ardelean) Date: Sat, 2 Jul 2016 11:11:34 +0300 Subject: [OpenWrt-Devel] Unable to opkg install openvswitch In-Reply-To: References: Message-ID: On Tue, Jun 28, 2016 at 4:38 PM, Alexandru Ardelean wrote: > On Tue, Jun 28, 2016 at 4:29 PM, ??? wrote: >> At first, i reset my router using tftp with ArcherC7v2_tp_recovery.bin file. >> I set it internet works, and then I did opkg update and opkg install >> openvswitch. >> >> then i saw that error message. >> >> FYI, here is a link that someone already asked, it looks similar with my >> problem but i couldn't find an answer. >> https://dev.openwrt.org/ticket/22212 >> >> Thanks >> DongGyu Cho >> >> >> >> 2016-06-28 21:37 GMT+09:00 Alexandru Ardelean : >>> >>> On Tue, Jun 28, 2016 at 1:05 PM, ??? wrote: >>> > Hi, >>> > >>> > I'm trying to install openvswitch on OpenWRT in Archer C7. >>> > >>> > When i try to install openvswitch, error message below had came up. >>> > >>> > Downloading >>> > >>> > http://downloads.openwrt.org/chaos_calmer/15.05.1/ar71xx/generic/packages/packages/kmod-openvswitch_3.18.21+2.3.90-58be9c9fd732b5bdd3d4c2e9b8cc2313f570094d_ar71xx.ipk. >>> > Collected errors: >>> > >>> > satisfy_dependencies_for: Cannot satisfy the following dependencies for >>> > kmod-openvswitch: >>> > kernel (= 3.18.21-1-3d4bd113f3f10b8986a142b8792db9c5) * >>> > opkg_install_cmd: Cannot install package kmod-openvswitch. >>> > >>> > root at OpenWrt:~# >>> > >>> > >>> > How can i solve it? If anyone know, please let me know. >>> > >>> > >>> > Regards, >>> > >>> > DongGyu Cho >>> > >>> > >>> > >>> > _______________________________________________ >>> > openwrt-devel mailing list >>> > openwrt-devel at lists.openwrt.org >>> > https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel >>> > >>> >>> So, did you do a >>> >>> opkg update >>> >>> first ? >>> >>> Can you give tell me which command series did you try ? >>> >>> Thanks >>> Alex >> >> > > Oh. > Will check It seems that the kernel version for OpenWrt 15.05.1 is 3.18.23. While the OVS kernel module expects 3.18.21. I just started reading more in-depth the tickets and that seems to be the case. And it seems to be more kernel modules having this issue. So, you either build OpenVswitch manually for CC, or you wait for a re-spin of the CC release. I cannot help out more on this, since I am only a package maintainer for the OVS package. I am not too involved in the big release process to help out more. Thanks Alex _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From nbd at nbd.name Sat Jul 2 04:25:36 2016 From: nbd at nbd.name (Felix Fietkau) Date: Sat, 2 Jul 2016 10:25:36 +0200 Subject: [OpenWrt-Devel] [LEDE-DEV] [PATCH] netifd: remove wireless device when device fails to setup In-Reply-To: <57763CED.4070106@riverbed.com> References: <57752A24.7020905@riverbed.com> <8e7f2f39-8f08-6c71-3082-97039ac76211@nbd.name> <57763CED.4070106@riverbed.com> Message-ID: <1fb359ce-b3a6-9719-1800-38ea9784d168@nbd.name> On 2016-07-01 11:50, Eduardo Abinader wrote: > Hi Felix, > > 1) Just set a non-allowed DFS channel for DE, for instance. > 2) Enable wireless; it fails > 3) Change to a valid channel; the wdev is not set up. > > There is also a leftover on /etc/init.d/network reload. > I think it should call /sbin/wifi instead of /sbin/wifi reload. No, it should not. /sbin/wifi restarts wireless unconditionally, whereas wifi reload only restarts if the configuration changed. I understand the issue now, but in my opinion this fix is not correct. It eliminates the state of the wireless device entirely, thus not giving the user the chance to see that netifd failed to bring it up. I think the main issue is the handling of the autostart flag and its multiple uses. It gets used to prevent auto-restart after error, but it is also used to indicate that the user wanted to shut down the wireless interface. I think for the error case we need to leave autostart alone and use a separate flag (which gets cleared if the configuration gets updated). That way the state would be preserved and a restart would be triggered on actual config changes. - Felix _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hojuruku at gmail.com Sat Jul 2 16:47:15 2016 From: hojuruku at gmail.com (Luke McKee) Date: Sun, 3 Jul 2016 03:47:15 +0700 Subject: [OpenWrt-Devel] procd: patch to support busybox mkfs.ext2 Message-ID: Hi guys, This is a little one. Busybox mkfs.ext2 works and with this setup the ext4 module can mount /tmp without a journal. See #22666 I tested it. Also the Makefile for procd doesn't have any dependencies for busybox CONFIG_BUSYBOX_CONFIG_MKFS_EXT2=y OR e2fsprogs. See the zram-swap Makefile. Mkfs.ext2 is also installed with e2fsprogs so this wont break anything for those who install the more bloated utility. As we all know there is no need for mounting a journal on volatile memory, so that's the other justification for this patch. busybox supports all the commandline arguments given to mkfs.ext2 Also THE PATH WAS WRONG IN THE ORIGINAL PATCH for the error messages :P Maybe e2fsprogs has to be patched so it installs to /sbin like most other distros (e.g. gentoo) --- zram.c.orig 2016-07-03 02:55:02.412237548 +0700 +++ zram.c 2016-07-03 02:55:54.691233783 +0700 @@ -82,7 +82,7 @@ int mount_zram_on_tmp(void) { - char *mkfs[] = { "/usr/sbin/mkfs.ext4", "-b", "4096", "-F", "-L", "TEMP", "-m", "0", "/dev/zram0", NULL }; + char *mkfs[] = { "/sbin/mkfs.ext2", "-b", "4096", "-F", "-L", "TEMP", "-m", "0", "/dev/zram0", NULL }; FILE *fp; long zramsize; pid_t pid; @@ -107,10 +107,10 @@ pid = fork(); if (!pid) { execvp(mkfs[0], mkfs); - ERROR("Can't exec /sbin/mkfs.ext4\n"); + ERROR("Can't exec /sbin/mkfs.ext2\n"); exit(-1); } else if (pid <= 0) { - ERROR("Can't exec /sbin/mkfs.ext4\n"); + ERROR("Can't exec /sbin/mkfs.ext2\n"); return -1; } else { waitpid(pid, NULL, 0); _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hojuruku at gmail.com Sat Jul 2 17:26:38 2016 From: hojuruku at gmail.com (Luke McKee) Date: Sun, 3 Jul 2016 04:26:38 +0700 Subject: [OpenWrt-Devel] procd: patch to support busybox mkfs.ext2 Message-ID: For some further background... the original procd zram patch uses ext2 :) https://dev.openwrt.org/ticket/19586#comment:9 https://lists.openwrt.org/pipermail/openwrt-devel/2014-December/029587.html It shows you what happens when someone enables this option from make menuconfig. There needs to be some dependency testing. I suggest apply the patch and make it dependent on busybox mkfs.ext2 only. Leave mkfs.ext4 e2fsprogs in /usr/sbin and let users choose which they want from a fully qualified path in scripts. _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hojuruku at gmail.com Sat Jul 2 20:10:19 2016 From: hojuruku at gmail.com (Luke McKee) Date: Sun, 3 Jul 2016 07:10:19 +0700 Subject: [OpenWrt-Devel] procd: patch to support busybox mkfs.ext2 In-Reply-To: References: Message-ID: v2 of the patch. uses lz4 compression by default. lz4 is always installed by openwrt Makefile Config.in if zram. lz4 is best for compressed filesystems as we all know (if you had to choose between that and lzo). zram-swap can keep using lzo for speed! I'll work in a compatibility patch for zram-swap script next to see if zram0 is already being used and hot-add a new device. -------------- next part -------------- A non-text attachment was scrubbed... Name: 01-zrambusybox.patch Type: text/x-patch Size: 1102 bytes Desc: not available URL: -------------- next part -------------- _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hojuruku at gmail.com Sat Jul 2 20:37:05 2016 From: hojuruku at gmail.com (Luke McKee) Date: Sun, 3 Jul 2016 07:37:05 +0700 Subject: [OpenWrt-Devel] procd: patch to support busybox mkfs.ext2 In-Reply-To: References: Message-ID: Actually lzo compresses better but they are both fast. lz4 is faster on embedded devices. zram-swap should use lz4 if available and the patch can be as it was.http://blog.jpountz.net/post/28092106032/wow-lz4-is-fast lz4 has compression levels. in any case, speed > size on embedded devices. interestingly enough, higher lz4 compression yields faster decompression http://www.ilsistemista.net/index.php/linux-a-unix/44-linux-compressors-comparison-on-centos-6-5-x86-64-lzo-vs-lz4-vs-gzip-vs-bzip2-vs-lzma.html?start=4 They are mostly the same. On average 2.8 compression ratio in lz4 vs 3.0 in lzo. Can't hurt to go with the fastest. On 3 July 2016 at 07:10, Luke McKee wrote: > v2 of the patch. uses lz4 compression by default. lz4 is always > installed by openwrt Makefile Config.in if zram. > > lz4 is best for compressed filesystems as we all know (if you had to > choose between that and lzo). > zram-swap can keep using lzo for speed! > > I'll work in a compatibility patch for zram-swap script next to see if > zram0 is already being used and hot-add a new device. _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hojuruku at gmail.com Sun Jul 3 02:14:27 2016 From: hojuruku at gmail.com (Luke McKee) Date: Sun, 3 Jul 2016 13:14:27 +0700 Subject: [OpenWrt-Devel] procd: patch v3 to support busybox mkfs.ext2 Message-ID: To quote Arjen: If the only reason to switch to ext2 is to remove the journal, why not just add -O ^has_journal to the mount options? ---- That's not a mount option. That's a tune2fs option. Journaling isn't the the only problem. The biggest problem is BLOAT. You need libext2+e2fsprogs in a 4MB flash root image with the current zram setup. Would someone want /tmp on zram if they had to add all this to the 4MB squashfs image. -rw-r--r-- 1 lmc users 199739 Jul 3 06:15 e2fsprogs_1.43.1-1_mips_24kc.ipk -rw-r--r-- 1 lmc users 151873 Jul 3 06:15 libext2fs_1.43.1-1_mips_24kc.ipk The simple answer is most openwrt users would say no to this feature do to how it's implemented. I actually was going for ext2 like the original patch, but I was sold that ext4 can mount ext2 formatted filesystems (without a journal) (see man ext4). The ext4 filesystem driver vs ext2 does bloat a bit, but I don't mind it as I can mount ext4 over nbd for my extroot. Busybox is only 40k of source including the headers. mkfs.ext4 is 360k compressed! https://git.busybox.net/busybox/tree/util-linux/mkfs_ext2.c Also -O ^has_journal is an tune2fs option not a mount option. And that tune2fs feature isn't in busybox, hence the bloat issue. "BusyBox v1.24.2 () multi-call binary. Usage: tune2fs [-c MAX_MOUNT_COUNT] [-i DAYS] [-C MOUNT_COUNT] [-L LABEL] BLOCKDEV Adjust filesystem options on ext[23] filesystems" Busybox tune2fs is useless. So 90% of the userbase with size constrained flash file-systems will want to use busybox mkfs.ext2 instead. busybox mkfs.ext2 and mkfs.ext2 don't conflict because the package installs in /usr/sbin and busybox installs in /sbin I move that the feature be dependent ONLY on busybox mkfs.ext2. Busybox mount isn't required because procd includes sys/mount.h In order words set the path to /sbin/mkfs.ext2 (busybox) Attached is the new patch. Allow users in the Makefile configuration to choose to use LZ4 (more speed ~15% less compression) if they so desire. John can do the makefile if and when he merges the patch. I'm out of the debate now, I got it in my lede/packgaes/system/procd/patches/ directory :) I'm happy -------------- next part -------------- A non-text attachment was scrubbed... Name: 01-zrambusybox.patch Type: text/x-patch Size: 1131 bytes Desc: not available URL: -------------- next part -------------- _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From john at phrozen.org Sun Jul 3 02:24:58 2016 From: john at phrozen.org (John Crispin) Date: Sun, 3 Jul 2016 08:24:58 +0200 Subject: [OpenWrt-Devel] procd: patch v3 to support busybox mkfs.ext2 In-Reply-To: References: Message-ID: <056418e9-a364-e8d5-dff8-267ff237fffc@phrozen.org> Hi, few comments 1) the patch needs to be split into 2, ext2 change/lzo change 2) send them inline please and not as attachement 3) the V3 needs to be in the subject prefix [PATCH V3] procd: ... 4) the Signed-off-by: line is missing John On 03/07/2016 08:14, Luke McKee wrote: > To quote Arjen: > If the only reason to switch to ext2 is to remove the journal, why not > just add > > -O ^has_journal > > to the mount options? > > ---- > > That's not a mount option. That's a tune2fs option. > > Journaling isn't the the only problem. The biggest problem is BLOAT. > You need libext2+e2fsprogs in a 4MB flash root image with the current > zram setup. > Would someone want /tmp on zram if they had to add all this to the 4MB > squashfs image. > > -rw-r--r-- 1 lmc users 199739 Jul 3 06:15 e2fsprogs_1.43.1-1_mips_24kc.ipk > -rw-r--r-- 1 lmc users 151873 Jul 3 06:15 libext2fs_1.43.1-1_mips_24kc.ipk > > The simple answer is most openwrt users would say no to this feature > do to how it's implemented. > > I actually was going for ext2 like the original patch, but I was sold > that ext4 can mount ext2 formatted filesystems (without a journal) > (see man ext4). The ext4 filesystem driver vs ext2 does bloat a bit, > but I don't mind it as I can mount ext4 over nbd for my extroot. > > Busybox is only 40k of source including the headers. mkfs.ext4 is 360k > compressed! > https://git.busybox.net/busybox/tree/util-linux/mkfs_ext2.c > > Also -O ^has_journal is an tune2fs option not a mount option. And that > tune2fs feature isn't in busybox, hence the bloat issue. > > "BusyBox v1.24.2 () multi-call binary. > > Usage: tune2fs [-c MAX_MOUNT_COUNT] [-i DAYS] [-C MOUNT_COUNT] [-L > LABEL] BLOCKDEV > > Adjust filesystem options on ext[23] filesystems" > Busybox tune2fs is useless. > > So 90% of the userbase with size constrained flash file-systems will > want to use busybox mkfs.ext2 instead. busybox mkfs.ext2 and mkfs.ext2 > don't conflict because the package installs in /usr/sbin and busybox > installs in /sbin > > I move that the feature be dependent ONLY on busybox mkfs.ext2. > Busybox mount isn't required because procd includes sys/mount.h > In order words set the path to /sbin/mkfs.ext2 (busybox) > > Attached is the new patch. Allow users in the Makefile configuration > to choose to use LZ4 (more speed ~15% less compression) if they so > desire. > John can do the makefile if and when he merges the patch. > > I'm out of the debate now, I got it in my > lede/packgaes/system/procd/patches/ directory :) I'm happy > _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hojuruku at gmail.com Sun Jul 3 05:29:54 2016 From: hojuruku at gmail.com (Luke McKee) Date: Sun, 3 Jul 2016 16:29:54 +0700 Subject: [OpenWrt-Devel] [PATCH V3] Re: procd: patch to support busybox mkfs.ext2 In-Reply-To: <056418e9-a364-e8d5-dff8-267ff237fffc@phrozen.org> References: <056418e9-a364-e8d5-dff8-267ff237fffc@phrozen.org> Message-ID: On 07/03/2016 01:24 PM, John Crispin wrote: > Hi, > > few comments > > 1) the patch needs to be split into 2, ext2 change/lzo change > 2) send them inline please and not as attachement > 3) the V3 needs to be in the subject prefix [PATCH V3] procd: ... > 4) the Signed-off-by: line is missing > > John Hi John, 1) no can do. You are going to merge it into your project git page anyway, unless openwrt locked you out of your own project you are a maintainer of on git. In which case reply with the rebuke to .... 2) ok I fired up thunderbird, google mail destroys patches in plain text mode 3) done 4) done Don't blame me for the long email. I thought I was already done earlier but ..... I have tested this with lede trunk with v2 of the patch. V3 is the same just with a #ifdef, lz4 (faster less compression). It definitely works. It has 4mb flash. 140k of text files generated in my setup and placed in /tmp turned into 7.1k - neat! - however tmpfs has garbage collection zram doesn't exit unless you create a cron job that will dd if=/dev/zero bs=4096 of=/tmp/zero.bin count=sizeofreespace; rm /tmp/zero.bin. Deleting a file from /tmp doesn't allow memory reclamation like with tmpfs. Under normal use it will take a long time for this to really fill up, especially if ext2 is over-writing the same files & inodes. Zram module estimates there is 28meg of /tmp storage which is more than you'd get with tmpfs. My tp-link has 32mb ram 28 usable. Secure deletion on ext4 was never popular: https://lwn.net/Articles/462437/ Also of NOTE is tmpfs is STILL getting mounted. People with this feature on could in theory disable tmpfs. John you might want to look into disabling the tmpfs mount of ZRAM_TMPFS mounted instead. John: Constraints for the Makefile for procd to go with this I didn't submit, because I'm not sure config stanzas like package stanzas can have DEPENDS. Maybe you have to make it a fake package or something that really just passes on the defines to gcc so you can set up package dependencies. ===================================== 1) Thou shall turn on CONFIG_BUSYBOX_CONFIG_MKFS_EXT2=y Justification: ~15-20k binary vs 350k (with stripping) for mkfs.ext2 and if you want the proper mkfs.ext4 etc you can install it in your overlay - extroot. Busybox mkfs.ext2 and e2fsprogs are configured not to collide with each-other. This patch makes the need for e2fsprogs libext2 redundant. Not having this (like we do right now) will flood the bug reports with idiots (like me) wondering why they bricked their router when it can't mount /tmp. 2) Debatable: Thou shall disable zram-swap, zram-swap shall block this PROC_ZRAM_TMPFS option. Justification: Right now they both want to use /dev/zram0, but the system will have no space for running apps if they are both running at the same time. You need to allocate 1/3 ram to each at best. That will have be a new compile time option in a further patch, that I will release should someone make the argument for wanting both of these. You either want 1 of 3 possible setups. #1 This patch. Best for people who need to opkg -d ram a lot of stuff #2 tmpfs and progs BOTH can use zram-swap which makes it a better overall choice, after thinking about this patch it isn't worth it as much as just using zram-swap. But better have a working feature than a broken one as it exists in buildroot now Or #3 Assuming you have a fast storage device connected to your openwrt (most don't but some NASes do) ZSWAP kernel will dynamically use free memory to offer a pre-swap cache, and allow compressed data (lzo/lz4) to be wrote to swap. It may require an actual initialized swap device to work. I haven't RTFMed yet. 3) Debatable: LZ4 should be on by default. (My two cents) Justification: It's almost compresses well as LZO but it's less CPU intensive for those without Floating point SMID's which is most home routers. So put some help about that in the Makefile. LZ4 is included as a dependency to the zram.ko module and will be loaded at early boot by modprobe / procd. Contrary to rumors circulating on openwrt's trac it actually works :) https://dev.openwrt.org/ticket/22666#comment:3 4) Highly recommended: Makefile should block option if your kernel isn't 4.4. Justification: https://dev.openwrt.org/ticket/21705 & above 5) Stop openwrt folks trying to patch the kernel to make two zram devices by default because you can hot-add them. https://dev.openwrt.org/ticket/19586#comment:10 Here's the patch --------------------------------------------- procd: remove dependency on bloated e2fsprogs/libext2 and use CONFIG_BUSYBOX_CONFIG_MKFS_EXT2=y At a minimum (see accompanying email on mailing list) advising my two cents on the pros and cons of this patch you need to add a configuration option to the Makefile if you want lz4 support config PROCD_ZRAM_TMPFS bool default n prompt "Mount /tmp using zram." endmenu & ifeq ($(CONFIG_PROCD_ZRAM_TMPFS_LZ4),y) CMAKE_OPTIONS += -DZRAM_TMPFS_LZ4=1 endif Signed-off-by: Luke McKee --- a/initd/zram.c 2016-07-03 06:39:51.011999930 +0700 +++ b/initd/zram.c 2016-07-03 07:00:34.143492847 +0700 @@ -82,7 +82,7 @@ int mount_zram_on_tmp(void) { - char *mkfs[] = { "/usr/sbin/mkfs.ext4", "-b", "4096", "-F", "-L", "TEMP", "-m", "0", "/dev/zram0", NULL }; + char *mkfs[] = { "/sbin/mkfs.ext2", "-b", "4096", "-F", "-L", "TEMP", "-m", "0", "/dev/zram0", NULL }; FILE *fp; long zramsize; pid_t pid; @@ -94,6 +95,15 @@ } mkdev("*", 0600); +#ifdef ZRAM_TMPFS_LZ4 + fp = fopen("/sys/block/zram0/comp_algorithm", "r+"); + if (fp == NULL) { + ERROR("Can't open /sys/block/zram0/comp_algorithm: %s\n", strerror(errno)); + return errno; + } + fprintf(fp, "%s", "lz4" ); + fclose(fp); +#endif zramsize = proc_meminfo() / 2; fp = fopen("/sys/block/zram0/disksize", "r+"); @@ -107,10 +116,10 @@ pid = fork(); if (!pid) { execvp(mkfs[0], mkfs); - ERROR("Can't exec /sbin/mkfs.ext4\n"); + ERROR("Can't exec /sbin/mkfs.ext2\n"); exit(-1); } else if (pid <= 0) { - ERROR("Can't exec /sbin/mkfs.ext4\n"); + ERROR("Can't exec /sbin/mkfs.ext2\n"); return -1; } else { waitpid(pid, NULL, 0); _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From m.storchak at gmail.com Sun Jul 3 05:30:57 2016 From: m.storchak at gmail.com (Maxim Storchak) Date: Sun, 3 Jul 2016 12:30:57 +0300 Subject: [OpenWrt-Devel] procd: patch to support busybox mkfs.ext2 In-Reply-To: References: Message-ID: On 7/3/16 00:26, Luke McKee wrote: > For some further background... > > the original procd zram patch uses ext2 :) > > https://dev.openwrt.org/ticket/19586#comment:9 > https://lists.openwrt.org/pipermail/openwrt-devel/2014-December/029587.html > > It shows you what happens when someone enables this option from make menuconfig. > There needs to be some dependency testing. I suggest apply the patch > and make it dependent on busybox mkfs.ext2 only. > Leave mkfs.ext4 e2fsprogs in /usr/sbin and let users choose which they > want from a fully qualified path in scripts. Is there a reason to use full path specification? Why can't mkfs.ext{2|4} be called and whichever is found first in PATH gets executed? In this case only one of e2fsprogs and busybox implementations should be required. Let busybox be default, but please leave an option to use full e2fsprogs and disable mkfs.ext* in busybox. Something like DEPENDS:= ... +!BUSYBOX_CONFIG_MKFS_EXT2:e2fsprogs -- Best regards, Maxim Storchak mailto:m.storchak at gmail.com _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hojuruku at gmail.com Sun Jul 3 06:31:49 2016 From: hojuruku at gmail.com (Luke McKee) Date: Sun, 3 Jul 2016 17:31:49 +0700 Subject: [OpenWrt-Devel] procd: patch to support busybox mkfs.ext2 Message-ID: m.storchak at gmail dot com wrote: Is there a reason to use full path specification? Why can't mkfs.ext{2|4} be called and whichever is found first in PATH gets executed? In this case only one of e2fsprogs and busybox implementations should be required. Let busybox be default, but please leave an option to use full e2fsprogs and disable mkfs.ext* in busybox. Something like DEPENDS:= ... +!BUSYBOX_CONFIG_MKFS_EXT2:e2fsprogs Oh for the love of god. .... I'm fixing something that's in my opinion completely useless for 90% of the openwrt market due to size constraints to put libext2fs and e2fsprogs in rootfs and can't be used as is. Look at a technical level zram-swap works better, so as far as I'm concerned roll back this whole d$#$ feature. It's a niche market for those who want to have scripts to opkg -d ram install stuff and updated their profile to include LD_LIBRARY_PATH=/tmp/lib:/tmp/usr/lib or reconfigured their overlayfs. Addressing your concerns: 1) If you format with mkfs.ext4 you have the added overhead of writing to the ram twice for a journal, you don't need because it's in ram. So #1 we won't be calling mkfs.ext4, and as someone else suggested we won't call tune2fs because busybox doesn't support trimming ext4 features like someone else said. 2) Your second point: DEPENDS work like that for packages, but I'm not sure if they work in define Package/procd/config stanzas - for the second time. so I passed the buck to the maintainer who's job is to do the Makefile. Depends for Package/xyz/config is undocumented at openwrt dev dogs. 3) I'm not a C programmer but I RTFM http://linux.die.net/man/2/execve, You've got to fork before you can run another process, unix semantics. So now your proposed mod asks the patch to adds all this unnecessary crap to see first see files exist and they are executable. Bash scans the path for you - C doesn't. We'll if you really really want to use the bloat ware in rootfs image, then this patch will work, without busybox's 20k mkfs.ext2. Ext2 uses 7k ram (compressed). The journal is going to add double the compression/cpu overhead too, and waste a bit of ram. You'll be using more then 7k with ext4. execve() also allows executable shell scripts (assuming you have the kernel bin_fmt enabled for it) So if you really really want to use this patch without busybox mkfs.ext2 and use the fatter one... put #/bin/ash until [ -z "$1" ] do MKFS_ARGS="$MKFS_ARGS $1 " shift done /usr/sbin/mkfs.ext2 ${MKFS_ARGS} In the place of /sbin/mkfs.ext2 Considering that 95% of openwrt users are consumer routers with 4-8mb flash do we install 500k of stripped compressed code for mkfs.ext2 from e2fsprogs. For the extra 20k busybox bloat (I h haven't measured it's 40k of source) what's wrong with having two mkfs.ext2's if you are so obsessed with putting bloatware in your image. Most routers aren't formatting ext4 fs. I was bitching about using ext4 vs ext2, but relented. Does anyone remember when openwrt ran in a 2MB image on a WRT54G? On top of this patchwork at lede chomped up my patch for no good reason when i used thunderbird in text mode.. http://patchwork.ozlabs.org/patch/643714/ I can see why the openwrt-devs get grumpy at working with everyone ;) And before anyone grumbles about LZ4, I got half the upload speed using LZ4 sshing a openwrt image /tmp so LZO will be even worse (the default as it was before this patch). 1.6MB per second. _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hojuruku at gmail.com Sun Jul 3 07:03:32 2016 From: hojuruku at gmail.com (Luke McKee) Date: Sun, 3 Jul 2016 18:03:32 +0700 Subject: [OpenWrt-Devel] [RFD] Future - suggestion for the teleconference Message-ID: <84110a12-4e59-c3e7-9175-d83e010deb3a@gmail.com> Suggestion for the teleconference: Talkshoe.com Talkshoe is free. It has a web client too with a chat log when the conference call starts. Someone make an account. It's got SIP and a US number. That way nobody get's everyone ease's IP addresses and nobody can play funny buggers with a firewall to make people miss the meeting. Someone from LEDE should be the MC seeing they don't block/ban/mute peoples...... _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From Eduardo.Abinader at riverbed.com Mon Jul 4 02:52:12 2016 From: Eduardo.Abinader at riverbed.com (Eduardo Abinader) Date: Mon, 4 Jul 2016 06:52:12 +0000 Subject: [OpenWrt-Devel] [LEDE-DEV] [PATCH] netifd: remove wireless device when device fails to setup In-Reply-To: <1fb359ce-b3a6-9719-1800-38ea9784d168@nbd.name> References: <57752A24.7020905@riverbed.com> <8e7f2f39-8f08-6c71-3082-97039ac76211@nbd.name> <57763CED.4070106@riverbed.com>, <1fb359ce-b3a6-9719-1800-38ea9784d168@nbd.name> Message-ID: Thanks for the feedback, Felix. I will submit another patch(es) with the changes you commented. Ok? Eduardo ________________________________________ From: Felix Fietkau [nbd at nbd.name] Sent: Saturday, July 02, 2016 10:25 AM To: Eduardo Abinader; openwrt-devel at lists.openwrt.org; lede-dev at lists.infradead.org Subject: Re: [LEDE-DEV] [PATCH] netifd: remove wireless device when device fails to setup On 2016-07-01 11:50, Eduardo Abinader wrote: > Hi Felix, > > 1) Just set a non-allowed DFS channel for DE, for instance. > 2) Enable wireless; it fails > 3) Change to a valid channel; the wdev is not set up. > > There is also a leftover on /etc/init.d/network reload. > I think it should call /sbin/wifi instead of /sbin/wifi reload. No, it should not. /sbin/wifi restarts wireless unconditionally, whereas wifi reload only restarts if the configuration changed. I understand the issue now, but in my opinion this fix is not correct. It eliminates the state of the wireless device entirely, thus not giving the user the chance to see that netifd failed to bring it up. I think the main issue is the handling of the autostart flag and its multiple uses. It gets used to prevent auto-restart after error, but it is also used to indicate that the user wanted to shut down the wireless interface. I think for the error case we need to leave autostart alone and use a separate flag (which gets cleared if the configuration gets updated). That way the state would be preserved and a restart would be triggered on actual config changes. - Felix _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From nbd at nbd.name Mon Jul 4 05:21:36 2016 From: nbd at nbd.name (Felix Fietkau) Date: Mon, 4 Jul 2016 11:21:36 +0200 Subject: [OpenWrt-Devel] [LEDE-DEV] [PATCH] netifd: remove wireless device when device fails to setup In-Reply-To: References: <57752A24.7020905@riverbed.com> <8e7f2f39-8f08-6c71-3082-97039ac76211@nbd.name> <57763CED.4070106@riverbed.com> <1fb359ce-b3a6-9719-1800-38ea9784d168@nbd.name> Message-ID: <7e1aa12f-1e84-fa10-78e7-9a7360764d46@nbd.name> On 2016-07-04 08:52, Eduardo Abinader wrote: > Thanks for the feedback, Felix. > > I will submit another patch(es) with the changes you commented. Ok? Sure, thanks. - Felix _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From john at phrozen.org Mon Jul 4 05:27:38 2016 From: john at phrozen.org (John Crispin) Date: Mon, 4 Jul 2016 11:27:38 +0200 Subject: [OpenWrt-Devel] [PATCH] include/toplevel.mk: fix defconfig when ~/.openwrt/defconfig exists Message-ID: <1467624458-41165-1-git-send-email-john@phrozen.org> ./scripts/feeds update will reset the .config file if ~/.openwrt/defconfig exists, thus resetting the target to ar71xx. Signed-off-by: John Crispin --- i am not sure if this is correct or if refresh_config() inside scripts feeds should be called with a paramter to not run defconfig --- include/toplevel.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/toplevel.mk b/include/toplevel.mk index 581083d..398fba7 100644 --- a/include/toplevel.mk +++ b/include/toplevel.mk @@ -110,7 +110,7 @@ config-clean: FORCE defconfig: scripts/config/conf prepare-tmpinfo FORCE touch .config - @if [ -e $(HOME)/.openwrt/defconfig ]; then cp $(HOME)/.openwrt/defconfig .config; fi + @if [ \! -e .config -a -e $(HOME)/.openwrt/defconfig ]; then cp $(HOME)/.openwrt/defconfig .config; fi $< --defconfig=.config Config.in confdefault-y=allyes -- 1.7.10.4 _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From nbd at nbd.name Mon Jul 4 05:34:37 2016 From: nbd at nbd.name (Felix Fietkau) Date: Mon, 4 Jul 2016 11:34:37 +0200 Subject: [OpenWrt-Devel] [PATCH] include/toplevel.mk: fix defconfig when ~/.openwrt/defconfig exists In-Reply-To: <1467624458-41165-1-git-send-email-john@phrozen.org> References: <1467624458-41165-1-git-send-email-john@phrozen.org> Message-ID: <2039a714-8b4d-99b3-8d06-704eb3bf681e@nbd.name> On 2016-07-04 11:27, John Crispin wrote: > ./scripts/feeds update will reset the .config file if ~/.openwrt/defconfig > exists, thus resetting the target to ar71xx. > > Signed-off-by: John Crispin > --- > > i am not sure if this is correct or if refresh_config() inside scripts > feeds should be called with a paramter to not run defconfig > --- > include/toplevel.mk | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/include/toplevel.mk b/include/toplevel.mk > index 581083d..398fba7 100644 > --- a/include/toplevel.mk > +++ b/include/toplevel.mk > @@ -110,7 +110,7 @@ config-clean: FORCE > > defconfig: scripts/config/conf prepare-tmpinfo FORCE > touch .config > - @if [ -e $(HOME)/.openwrt/defconfig ]; then cp $(HOME)/.openwrt/defconfig .config; fi > + @if [ \! -e .config -a -e $(HOME)/.openwrt/defconfig ]; then cp $(HOME)/.openwrt/defconfig .config; fi Use -s instead of -e for .config here. -e will always be true since it's called after the touch command above. - Felix _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From thierry.dutre.tch at gmail.com Mon Jul 4 09:09:41 2016 From: thierry.dutre.tch at gmail.com (Thierry Du Tre) Date: Mon, 4 Jul 2016 15:09:41 +0200 Subject: [OpenWrt-Devel] netifd , route config behavior inconsistent with Wiki Message-ID: Hi Felix, I noticed an inconsistency with following description on the Wiki page for network config, section type 'route' (IPv4 Routes), option 'gateway' : "Network gateway. If omitted, the gateway from the parent interface is taken; if set to 0.0.0.0 no gateway will be specified for the route" It seems that in case a route is added without value for gateway set, this will result in creating a device route, so without a 'via' gateway ip. For example : config route option interface 'wan' option target '1.2.3.0' option netmask '255.255.255.0' When wan interface is up, the following routes are created : - default via 172.18.16.1 dev pppoe-wan proto static metric 1 - 1.2.3.0/24 dev pppoe-wan proto static scope link metric 1 Where based on the Wiki description, I'd expect the following route : 1.2.3.0/24 via 172.18.16.1 dev pppoe-wan proto static metric 1 As I am trying to create a setup with multiple wan interfaces, there will be multiple default routes and the described behavior would be useful to get traffic destined for some subnets being forwarded via a specific interface. Would you think, that a patch -when proposed- might be accepted ? Or is the Wiki to be updated in order to describe the actual behavior in current implementation ? Regards, Thierry Du Tre _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From weedy2887 at gmail.com Mon Jul 4 17:16:14 2016 From: weedy2887 at gmail.com (Weedy) Date: Mon, 4 Jul 2016 17:16:14 -0400 Subject: [OpenWrt-Devel] [RFD] Future - suggestion for the teleconference In-Reply-To: <84110a12-4e59-c3e7-9175-d83e010deb3a@gmail.com> References: <84110a12-4e59-c3e7-9175-d83e010deb3a@gmail.com> Message-ID: On 3 Jul 2016 07:03, "Luke McKee" wrote: > > Suggestion for the teleconference: > > Talkshoe.com > > Talkshoe is free. It has a web client too with a chat log when the > conference call starts. Google hangouts? -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From xypron.glpk at gmx.de Mon Jul 4 18:27:49 2016 From: xypron.glpk at gmx.de (Heinrich Schuchardt) Date: Tue, 5 Jul 2016 00:27:49 +0200 Subject: [OpenWrt-Devel] [BUG] package/devel/valgrind: cannot build for sunxi Message-ID: Sunxi Lamobo R1 is a subarchitecture of arm_v7. So valgrind should build out of the box. Unfortunately it is disabled, because host_cpu = arm and not arm_v7. A messy workaround is to patch configure.ac adding arm*) AC_MSG_RESULT([ok (${host_cpu})]) ARCH_MAX="arm" ;; I guess host_cpu should be set to arm_v7 for sunxi and i.mx6 targets. Best regards Heinrich Schuchardt _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From xypron.glpk at gmx.de Mon Jul 4 18:41:30 2016 From: xypron.glpk at gmx.de (Heinrich Schuchardt) Date: Tue, 5 Jul 2016 00:41:30 +0200 Subject: [OpenWrt-Devel] [BUG] package/devel/valgrind: cannot build for sunxi In-Reply-To: References: Message-ID: Debian has the following patch in http://http.debian.net/debian/pool/main/v/valgrind/valgrind_3.11.0-1.debian.tar.xz Description: Fix FTBFS on armhf by correctly detecting the architecture Origin: vendor Bug-Debian: http://bugs.debian.org/730844 Author: Alessandro Ghedini Last-Update: 2013-11-30 --- a/configure.ac +++ b/configure.ac @@ -234,7 +234,7 @@ ARCH_MAX="s390x" ;; - armv7*) + arm*) AC_MSG_RESULT([ok (${host_cpu})]) ARCH_MAX="arm" ;; _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From nbd at nbd.name Tue Jul 5 04:26:36 2016 From: nbd at nbd.name (Felix Fietkau) Date: Tue, 5 Jul 2016 10:26:36 +0200 Subject: [OpenWrt-Devel] [LEDE-DEV] [BUG] package/devel/valgrind: cannot build for sunxi In-Reply-To: References: Message-ID: On 2016-07-05 00:27, Heinrich Schuchardt wrote: > Sunxi Lamobo R1 is a subarchitecture of arm_v7. So valgrind should build > out of the box. > > Unfortunately it is disabled, because host_cpu = arm and not arm_v7. > > A messy workaround is to patch configure.ac adding > > arm*) > AC_MSG_RESULT([ok (${host_cpu})]) > ARCH_MAX="arm" > ;; > > I guess host_cpu should be set to arm_v7 for sunxi and i.mx6 targets. I've pushed an update of the valgrind package along with some fixes for architecture detection to my staging tree at: https://git.lede-project.org/?p=lede/nbd/staging.git;a=summary It builds fine for me on sunxi - if you have some time, please test it. - Felix _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From aleksander at aleksander.es Tue Jul 5 16:12:41 2016 From: aleksander at aleksander.es (Aleksander Morgado) Date: Tue, 5 Jul 2016 22:12:41 +0200 Subject: [OpenWrt-Devel] cold boot hotplug events Message-ID: Hey, At which stage of the system boot are the hotplug events for the already available hardware emitted? E.g. if I want to talk to a system daemon for each hotplug event, I'd like to make sure the daemon is already up and running. Currently I've got such a daemon started with a /etc/rc.d/S70- rule, and during a cold boot the hotplug events end up emitted way before this daemon is launched. What would be the best way to synchronize this? Cheers! -- Aleksander https://aleksander.es _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From rajan.vaja at gmail.com Wed Jul 6 09:33:43 2016 From: rajan.vaja at gmail.com (Rajan Vaja) Date: Wed, 6 Jul 2016 19:03:43 +0530 Subject: [OpenWrt-Devel] [PATCH] coova-chilli: Fix UCI parse error Message-ID: <1467812023-3773-1-git-send-email-rajan.vaja@gmail.com> UCI commands report errors in parsing coova-chilli sample configuration file. Fix this issue by using proper format in configuration. Signed-off-by: Rajan Vaja --- net/coova-chilli/files/chilli.config | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/coova-chilli/files/chilli.config b/net/coova-chilli/files/chilli.config index ab8ca1f..4c037c6 100644 --- a/net/coova-chilli/files/chilli.config +++ b/net/coova-chilli/files/chilli.config @@ -89,13 +89,13 @@ config chilli # IP address of radius server 1 # For most installations you need to modify this option. - radiusserver1 rad01.chillispot.org + option radiusserver1 rad01.chillispot.org # IP address of radius server 2 # If you have only one radius server you should set radiusserver2 to the # same value as radiusserver1. # For most installations you need to modify this option. - radiusserver2 rad02.chillispot.org + option radiusserver2 rad02.chillispot.org # Radius authentication port # The UDP port number to use for radius authentication requests. @@ -154,7 +154,7 @@ config chilli # Ethernet interface to listen to. # This is the network interface which is connected to the access points. # In a typical configuration this option should be set to eth1. - dhcpif eth1 + option dhcpif eth1 # Use specified MAC address. # An address in the range 00:00:5E:00:02:00 - 00:00:5E:FF:FF:FF falls @@ -171,7 +171,7 @@ config chilli # Universal access method (UAM) parameters # URL of web server handling authentication. - uamserver https://radius.chillispot.org/hotspotlogin + option uamserver https://radius.chillispot.org/hotspotlogin # URL of welcome homepage. # Unauthenticated users will be redirected to this URL. If not specified -- 1.9.1 _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From baptiste at bitsofnetworks.org Wed Jul 6 10:47:32 2016 From: baptiste at bitsofnetworks.org (Baptiste Jonglez) Date: Wed, 6 Jul 2016 16:47:32 +0200 Subject: [OpenWrt-Devel] [PATCH] coova-chilli: Fix UCI parse error In-Reply-To: <1467812023-3773-1-git-send-email-rajan.vaja@gmail.com> References: <1467812023-3773-1-git-send-email-rajan.vaja@gmail.com> Message-ID: <20160706144731.GC2040@lud.polynome.dn42> Hi Rajan, On Wed, Jul 06, 2016 at 07:03:43PM +0530, Rajan Vaja wrote: > UCI commands report errors in parsing coova-chilli > sample configuration file. Fix this issue by using > proper format in configuration. This package is maintained in the openwrt-packages Github repository: https://github.com/openwrt/packages/tree/master/net/coova-chilli So, you should send a pull request there. Baptiste > --- > net/coova-chilli/files/chilli.config | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/net/coova-chilli/files/chilli.config b/net/coova-chilli/files/chilli.config > index ab8ca1f..4c037c6 100644 > --- a/net/coova-chilli/files/chilli.config > +++ b/net/coova-chilli/files/chilli.config > @@ -89,13 +89,13 @@ config chilli > > # IP address of radius server 1 > # For most installations you need to modify this option. > - radiusserver1 rad01.chillispot.org > + option radiusserver1 rad01.chillispot.org > > # IP address of radius server 2 > # If you have only one radius server you should set radiusserver2 to the > # same value as radiusserver1. > # For most installations you need to modify this option. > - radiusserver2 rad02.chillispot.org > + option radiusserver2 rad02.chillispot.org > > # Radius authentication port > # The UDP port number to use for radius authentication requests. > @@ -154,7 +154,7 @@ config chilli > # Ethernet interface to listen to. > # This is the network interface which is connected to the access points. > # In a typical configuration this option should be set to eth1. > - dhcpif eth1 > + option dhcpif eth1 > > # Use specified MAC address. > # An address in the range 00:00:5E:00:02:00 - 00:00:5E:FF:FF:FF falls > @@ -171,7 +171,7 @@ config chilli > # Universal access method (UAM) parameters > > # URL of web server handling authentication. > - uamserver https://radius.chillispot.org/hotspotlogin > + option uamserver https://radius.chillispot.org/hotspotlogin > > # URL of welcome homepage. > # Unauthenticated users will be redirected to this URL. If not specified -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: not available URL: -------------- next part -------------- _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hojuruku at gmail.com Wed Jul 6 19:19:40 2016 From: hojuruku at gmail.com (Luke McKee) Date: Thu, 7 Jul 2016 06:19:40 +0700 Subject: [OpenWrt-Devel] mini_snmpd: coming back to openwrt soon & other matters Message-ID: Hey Devs, mini_snmpd went to oldpackages because the original developer's page went offline a few years ago, however it's been taken up by a new maintainer who's implemented all the previous 1.2b openwrt patches in a more ingenious way. The other fork isn't worth considering. http://troglobit.github.io/mini-snmpd.html Here's my first attempt at writing a procd init script that isn't properly documented on openwrt or lede, both marked WIP. https://wiki.openwrt.org/inbox/procd-init-scripts https://www.lede-project.org/docs/procd.html https://github.com/hojuruku/openwrt-packages/blob/mini_snmpd/net/mini_snmpd/files/mini_snmpd.init The script uses all the features of mini_snmpd unlike the old one and can even be bound to a dynamic interface like a ppp link and restart as needed. Also shellcheck.net is awesome! Some questions I still have outstanding before I do the pull request, I asked on lede-dev but nobody answered because I outed myself as someone who doesn't support gay marriage then got banned for taking the bait when a few pushed on the issue and said it's homophobic to critize my family's persecution by the mafia. I won't spout my story, but here's my fathers http://truthnews.com.au/web/radio/story/cultural_marxism_101 2nd hour. Mine involves never seeing my first born child due to the actions of a now convicted gay pedophile police officer (see videos on http://youtube.com/hojuruku) Speaking of bait I only went to #lede-dev because there are people on FreeNode #openwrt all day long like plntk that are constantly poaching openwrt users and saying they need to run lede trunk to solve all their wifi troubles. Also with Lede-devs trying turn a offer for hosting into a offer for 2TB of space or more for a continuous integration compute cluster things might be getting interesting soon. If it wasn't for IRC I wouldn't have tried it. Skyrider: well - the last comment refers to lede (an openwrt fork/spinoff) -you can see the progress at https://lede-project.org/ - the wireless drivers recently changed again (in the last week) - and since that unit is new I would advise to use a trunk/snapshot image and then report if you have issues My two cents on the split is openwrt.org should put someone full time like ffmpeg vs libav with the same problem did constantly merging in all of lede's changes + all openwrt changes. After alot of work the rival will eventually be put to bed by their parent. I know libav will be. It's in sabayon they are considering removing it and going back soon. OK now those init script questions for Crispin or anyone else who knows procd 1) should I use logger in procd or does procd have some other way of logging messages from init scripts? echo is good? 2) Is there any real benefit to doing a #procd_add_validation validate_section_mini_snmpd? What's it for? Luci uses it? More info please? 3) No documentation on seccomp apart from a LKML post, need more. mini_snmpd could do with a patch to run as nobody after binding to the interface, but would that work? can it stat the filesystem free space if it doesn't have access to the mountpoint? 4) I might have found a strange bug with jsonfilter. It's adding whitespaces to variable results it returns it can break things: https://github.com/troglobit/mini-snmpd/issues/4 5) anything else wrong with the script before I add the validation code (needs documentation) and do the pull request? To make my pppoe lan party trend take off in Vietnam thanks to lax security on the fibre GPONs - all I need to do is fix rp-ppoe (again another oldpackages) and get some VN special openwrt TP-LINK OEM modified routers working. If anyone has experience adding new TP-Link routers to openwrt you can get the split factory firmware (not available for download on their website). Also how may I go about petitioning TP-Link to give me some OEM only firmware. Apart from a single white sticker on the box it came in it looks exactly like a regular TP-Link 841nd v9.2 - just different flash I think. https://forum.openwrt.org/viewtopic.php?pid=330161#p330161 Cheers, Luke i got the got tghe init script going. Is there any benefit or reason for having procd do uci validation. Would the luci folks want that? procd has no developer documentation so it was fun working it out. here's the code https://github.com/hojuruku/openwrt-packages/blob/mini_snmpd/net/mini_snmpd/files/mini_snmpd.init i don't know what is the point what is your chances of taking a pull request when I'm done. the lede guys hate me because i disrespected those who abuse infants. it would be funny if blogic was just like the guy who created systemd :P oh sorry. you were discussing non lede related things in public irc and you were asked to stop but did continue after you bring it up. yeah who cares if i'm in the same boat as snowden and assange. no big deal. i bet those two guys better shut their gobs too http://bit.ly/aurefugee2 - UNHCR confirmed political refugee. the channel is a developer channel for discussing developer related things like C so those who write ash scripts can stick it up their ash? you didn't see my comment earlier about what i think about this whole lede vs openwrt thing now i know better. oh the perks of forking off from your master. you can demand free hosting accounts is the latest. oh no .. we don't want your hosting - we want a free continuous integration compile cluster with 2TB please... Maybe if I want that much free hosting - I could go along to an opensource project, stab them in the back and fork it. Seriously.. you guys better make up soon.. it's not looking good. so when do you get massive hosting credits worth a few thousand bucks for leaving openwrt and not working out your differences? it's like wives to divorce their husbands so they can get double income, one male slave on child support and the other paying for the privilege of sex. that's like the openwrt lede/divorce. look at the motives for it now. how is your free digital ocean.. ahem now compute cluster coming along? if it turns out lede is gay cleek it will be like brendan etch vs mozillia all over again because some corrupt IRS people leaked his private info he gave money to prop 8 in California and then the queers brag he lost his job. Who cares if the guy invented the modern web browser ahem javascript - he doesn't support gay marriage - he has no place in web browser development! get him out! NOW! https://twitter.com/brendaneich/status/583792067156946944 you can't say that last irc msg ^^^ isn't about software development or relates my situtation with lede. :P sorry i dont see any argument - the CI is currently done by openwrt and not lede and both have nearly the same buildbot setup plntyk: seen the lede mailing list and IRC? not for long buddy nbd and others are trying to turn an offer of free hosting into a 2TB compute continuous integration cluster. "I'll take your free hosting offer with an 2TB upsize please" don't pretend you didn't' see all that mate. lede will be gobbled up like ffmpeg gobbled up libav. it's only a matter of time. i wonder how long a re-branded android fork would last? oh someone like google has lawyers. I did not make any offer - what are you referring to ? i dont even have money to spend on such hosting stuff Why would lede be "gobbled" up ? by Whom? plntyk: the hosting offers are from smaller companies? Small companies give away 2TB free to #lede-dev ? Digital Ocean? Small? They are up there with amazon. too much lies and spin for me to even read what he writes. take it to lede-dev. hojuruku: digitalocean is different from amazon - they are not traded publicly and are still in funding phase - some commercial entities like to use seoftware projects to test their infrastructure and gain knowledge/experience plntyk: that thrash me with 1000s of paid google adverts when i was a linode customer before their XXX customer service manager did an illegal warrantless dump of my linode, just like how they stole all those millions of bitcoins https://techcrunch.com/2015/07/08/digitalocean-raises-83m-series-b-round-led-by-access-industries/ 83 million dollars, wow not big... _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hojuruku at gmail.com Wed Jul 6 22:42:23 2016 From: hojuruku at gmail.com (Luke McKee) Date: Thu, 7 Jul 2016 09:42:23 +0700 Subject: [OpenWrt-Devel] [LEDE-DEV] [PATCH] netifd: remove wireless device when device fails to setup Message-ID: The I think said patch would break scripts that see what devices are available as in CONFIGURED, and set up procd triggers to reload when the device is fixed or comes back online and gets given an IP address. If DFS pulls down a wifi then it should change ubus interface state to down, not remove the whole interface from ubus. E.g. the mini_upnpd script I wrote or sysntpd script from busybox. https://github.com/hojuruku/openwrt-packages/blob/mini_snmpd/net/mini_snmpd/files/mini_snmpd.init https://lists.openwrt.org/pipermail/openwrt-devel/2016-July/041930.html Many init scripts may need to be rewritten if this patch is accepted, to use uci instead of ubus / jsonfilter (used by default for network_ functions now too in /lib/functions which means 95% of all init scripts) to see if an interface is CONFIGURED - not up. On 2016-07-01 11:50, Eduardo Abinader wrote: > Hi Felix, > > 1) Just set a non-allowed DFS channel for DE, for instance. > 2) Enable wireless; it fails > 3) Change to a valid channel; the wdev is not set up. > > There is also a leftover on /etc/init.d/network reload. > I think it should call /sbin/wifi instead of /sbin/wifi reload. No, it should not. /sbin/wifi restarts wireless unconditionally, whereas wifi reload only restarts if the configuration changed. I understand the issue now, but in my opinion this fix is not correct. It eliminates the state of the wireless device entirely, thus not giving the user the chance to see that netifd failed to bring it up. I think the main issue is the handling of the autostart flag and its multiple uses. It gets used to prevent auto-restart after error, but it is also used to indicate that the user wanted to shut down the wireless interface. I think for the error case we need to leave autostart alone and use a separate flag (which gets cleared if the configuration gets updated). That way the state would be preserved and a restart would be triggered on actual config changes. - Felix _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hojuruku at gmail.com Fri Jul 8 16:35:46 2016 From: hojuruku at gmail.com (Luke McKee) Date: Sat, 9 Jul 2016 03:35:46 +0700 Subject: [OpenWrt-Devel] procd ubox jsonfilter: dev question. how to properly handle interface changes per instance only in init scripts Message-ID: https://github.com/hojuruku/openwrt-packages/blob/mini_snmpd/net/mini_snmpd/files/mini_snmpd.init any comments on the script. I'd like some feedback on how to do per instance restarts if an interface changes. i just updated it. its nearly done just for knowing how to properly do per instance interface restarts so the daemons are only reloaded if the interface they are bound to changes, whilst the other instances are not restarted The script is now using /sbin/validate_data / uci_validate_section() to take configuration from uci. You'll notice in the comments there are some issues with ash (no array variables - not fixable) And one with jsonfilter and the other with /sbin/validate_data not properly handling setting default variables. Will these get upstream fixes? root at wifi:/etc/init.d# /etc/init.d/mini_snmpd start { "name": "mini_snmpd", "script": "\/etc\/init.d\/mini_snmpd", "instances": { "instance1": { "command": [ "\/usr\/bin\/mini_snmpd", "-n", "-c", "public", "-C", "Luke McKee ", "-t", "2", "-a", "-d \/overlay,\/tmp", "-i loopback,lan,wan" ], "stdout": true, "stderr": true, "respawn": [ "600", "10", "10" ] } }, "triggers": [ [ "config.change", [ "if", [ "eq", "package", "mini_snmpd" ], [ "run_script", "\/etc\/init.d\/mini_snmpd", "reload" ] ] ] ], "validate": [ { "package": "mini_snmpd", "type": "mini_snmpd", "data": { "enabled": "bool", "ipv6": "bool", "debug": "bool", "auth": "bool", "community": "rangelength(1,32)", "contact": "maxlength(255)", "location": "maxlength(255)", "listen_interface": "(uciname)", "udp_port": "port", "tcp_port": "port", "vendor_oid": "string", "mib_timeout": "and(min(1),uinteger)", "disks": "list(directory)", "interfaces": "list(uciname)" } } ] } _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From zajec5 at gmail.com Fri Jul 8 17:27:25 2016 From: zajec5 at gmail.com (=?UTF-8?B?UmFmYcWCIE1pxYJlY2tp?=) Date: Fri, 8 Jul 2016 23:27:25 +0200 Subject: [OpenWrt-Devel] [GIT PULL] brcmfmac update in mac80211 Message-ID: <57801ABD.8050305@gmail.com> The following changes since commit 07ba83cf6fe116ebcf909465665a79a596036d79: Merge pull request #25 from wigyori/master (2016-07-08 17:00:34 +0200) are available in the git repository at: git://git.infradead.org/users/rafal/openwrt.git master for you to fetch changes up to 76cbb843d40b8a2556877924b631f28059e41059: mac80211: brcmfmac: fix interfaces management (2016-07-08 23:11:29 +0200) ---------------------------------------------------------------- Hi Zoltan, As you noticed, I commited some changes to the svn trunk which AFAIU should not be used anymore. You asked me for getting them into a pull request and there it is. This updates brcmfmac to the state it can be finally used with BCM4366. All patches are backports coming from the wireless-drivers-next. ---------------------------------------------------------------- Rafa? Mi?ecki (5): mac80211: brcmfmac: fix lockup related to P2P interface mac80211: brcmfmac: rename patches from commit fixing P2P mac80211: brcmfmac: backport changes from 2016-06-29 mac80211: refresh brcmfmac patches mac80211: brcmfmac: fix interfaces management ...d-fallback-for-devices-that-do-not-report.patch | 4 +- ...ac-Fix-did-not-remove-int-handler-warning.patch | 2 +- ...ac-rework-function-picking-free-BSS-index.patch | 4 +- .../patches/351-0006-brcmfmac-use-kmemdup.patch | 2 +- ...d-field-storing-control-channel-to-the-st.patch | 24 ++-- ...mac-support-get_channel-cfg80211-callback.patch | 4 +- ...-print-errors-if-creating-interface-fails.patch | 2 +- ...fix-setting-AP-channel-with-new-firmwares.patch | 12 +- ...n-t-remove-interface-on-link-down-firmwar.patch | 4 +- ...vise-SDIO-error-message-in-brcmf_sdio_dri.patch | 2 +- ...ange-rx_seq-check-log-from-error-print-to.patch | 2 +- ...cmfmac-drop-unused-pm_block-vif-attribute.patch | 8 +- ...ac-include-required-headers-in-cfg80211.h.patch | 37 +++++ ...ightly-simplify-building-interface-combin.patch | 108 +++++++++++++++ ...x-lockup-when-removing-P2P-interface-afte.patch | 154 +++++++++++++++++++++ ...e-const-char-for-interface-name-in-brcmf_.patch | 39 ++++++ ...-include-also-core.h-header-in-cfg80211.h.patch | 33 +++++ ...dd-missing-break-when-deleting-P2P_DEVICE.patch | 27 ++++ ...lete-interface-directly-in-code-that-sent.patch | 75 ++++++++++ ...pport-removing-AP-interfaces-with-interfa.patch | 84 +++++++++++ ...mfmac-register-wiphy-s-during-module_init.patch | 2 +- ...rkaround-bug-with-some-inconsistent-BSSes.patch | 2 +- .../863-brcmfmac-Disable-power-management.patch | 2 +- 23 files changed, 595 insertions(+), 38 deletions(-) create mode 100644 package/kernel/mac80211/patches/351-0018-brcmfmac-include-required-headers-in-cfg80211.h.patch create mode 100644 package/kernel/mac80211/patches/351-0019-brcmfmac-slightly-simplify-building-interface-combin.patch create mode 100644 package/kernel/mac80211/patches/351-0020-brcmfmac-fix-lockup-when-removing-P2P-interface-afte.patch create mode 100644 package/kernel/mac80211/patches/351-0021-brcmfmac-use-const-char-for-interface-name-in-brcmf_.patch create mode 100644 package/kernel/mac80211/patches/351-0022-brcmfmac-include-also-core.h-header-in-cfg80211.h.patch create mode 100644 package/kernel/mac80211/patches/351-0023-brcmfmac-add-missing-break-when-deleting-P2P_DEVICE.patch create mode 100644 package/kernel/mac80211/patches/352-0001-brcmfmac-delete-interface-directly-in-code-that-sent.patch create mode 100644 package/kernel/mac80211/patches/352-0002-brcmfmac-support-removing-AP-interfaces-with-interfa.patch _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hello at leoxiong.com Sat Jul 9 05:54:43 2016 From: hello at leoxiong.com (Leo Xiong) Date: Sat, 9 Jul 2016 21:54:43 +1200 Subject: [OpenWrt-Devel] Publish GPG signing key/fingerprint on wiki Message-ID: <5780C9E3.1050803@leoxiong.com> Hi, It's great to see that OpenWRT now has GPG signed sha256sums with the images/packages on downloads.openwrt.org. However, I have not found any references to the signing key used for the checksums. Could the GPG key/fingerprint be published onto a wiki page? Thanks, Leo -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 473 bytes Desc: OpenPGP digital signature URL: -------------- next part -------------- _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From xypron.glpk at gmx.de Sun Jul 10 18:16:31 2016 From: xypron.glpk at gmx.de (Heinrich Schuchardt) Date: Mon, 11 Jul 2016 00:16:31 +0200 Subject: [OpenWrt-Devel] [RFC] Use CONFIG_USE_STRIP=y as default Message-ID: <847aab53-0602-9c66-79ae-dd963128cc35@gmx.de> Currently the default for stripping when building Lede/OpenWRT is CONFIG_USE_SSTRIP=y. This has the following impacts: Linking with GCC against libraries on the OpenWRT device is impossible. Python packages like pyusb that dynamically link against C libraries cannot be used. Debugging with gdb is not possible. Cf. the comments in https://dev.openwrt.org/browser/trunk/tools/sstrip/src/sstrip.c The size difference between libraries stripped with SSTRIP and STRIP is very small: libusb-1.0.so.0.1.0 STRIP: 47720 bytes SSTRIP: 46412 bytes In the example above the size increase is less then 3 %. I suggest to change the default to CONFIG_USE_STRIP=y. _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From nbd at nbd.name Mon Jul 11 01:36:48 2016 From: nbd at nbd.name (Felix Fietkau) Date: Mon, 11 Jul 2016 07:36:48 +0200 Subject: [OpenWrt-Devel] [LEDE-DEV] [RFC] Use CONFIG_USE_STRIP=y as default In-Reply-To: <847aab53-0602-9c66-79ae-dd963128cc35@gmx.de> References: <847aab53-0602-9c66-79ae-dd963128cc35@gmx.de> Message-ID: <69ccadd3-0c83-7f56-fe5d-bd0c7d166e08@nbd.name> On 2016-07-11 00:16, Heinrich Schuchardt wrote: > Currently the default for stripping when building Lede/OpenWRT is > CONFIG_USE_SSTRIP=y. > > This has the following impacts: > > Linking with GCC against libraries on the OpenWRT device is impossible. > > Python packages like pyusb that dynamically link against C libraries > cannot be used. > > Debugging with gdb is not possible. > > Cf. the comments in > https://dev.openwrt.org/browser/trunk/tools/sstrip/src/sstrip.c > > The size difference between libraries stripped with SSTRIP and STRIP is > very small: > > libusb-1.0.so.0.1.0 > STRIP: 47720 bytes > SSTRIP: 46412 bytes > > In the example above the size increase is less then 3 %. > > I suggest to change the default to CONFIG_USE_STRIP=y. NACK for the CONFIG_USE_STRIP change. Most dynamic linking (e.g. via dlopen) works just fine. If python has an issue there, we should fix that, or use strip instead of sstrip only for pyusb and similar things. As for using GCC on OpenWrt, I think that's exotic enough to not be a reason to push a size increase onto everybody else. Regarding debugging with gdb, I use the gdbserver + cross gdb on the host, and it tends to work just fine even with sstrip. - Felix _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From john at phrozen.org Mon Jul 11 08:21:44 2016 From: john at phrozen.org (John Crispin) Date: Mon, 11 Jul 2016 14:21:44 +0200 Subject: [OpenWrt-Devel] [LEDE-DEV] [PATCH] [mksh] Update to r52c In-Reply-To: References: Message-ID: Hi could you please * change the subject prefix to "utils/mksh:" and remove the [] On 11/07/2016 09:18, Alive 4ever wrote: > Update mksh package to sync with current latest upstream (r52c). > ---- * remove this tearline > Signed-off-by: alive4ever * we need a real name please John > --- > utils/mksh/Makefile | 4 +-- > utils/mksh/patches/100-dot_mkshrc | 52 ++++++++++++++++++--------------------- > 2 files changed, 26 insertions(+), 30 deletions(-) > > diff --git a/utils/mksh/Makefile b/utils/mksh/Makefile > index 89380a9..445974c 100644 > --- a/utils/mksh/Makefile > +++ b/utils/mksh/Makefile > @@ -9,7 +9,7 @@ > include $(TOPDIR)/rules.mk > > PKG_NAME:=mksh > -PKG_VERSION:=50d > +PKG_VERSION:=52c > PKG_RELEASE:=1 > > PKG_MAINTAINER:=Thorsten Glaser > @@ -17,7 +17,7 @@ PKG_LICENSE:=MirOS > > PKG_SOURCE:=$(PKG_NAME)-R$(PKG_VERSION).tgz > PKG_SOURCE_URL:=http://www.mirbsd.org/MirOS/dist/mir/mksh > -PKG_MD5SUM:=1c3882c07a760b23df1ad94ad0b4ed2e > +PKG_MD5SUM:=cc3884e02314447e7b4a3073b8d65d1e > > PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) > > diff --git a/utils/mksh/patches/100-dot_mkshrc b/utils/mksh/patches/100-dot_mkshrc > index a7bf840..1ee2a2e 100644 > --- a/utils/mksh/patches/100-dot_mkshrc > +++ b/utils/mksh/patches/100-dot_mkshrc > @@ -1,3 +1,5 @@ > +Refreshed for mksh-r52c, based on tg's patch > + > From 23712cea8e2a623fd952eb781df0011c501703d0 Mon Sep 17 00:00:00 2001 > From: Thorsten Glaser > Date: Thu, 25 Jul 2013 22:07:33 +0200 > @@ -9,42 +11,36 @@ Subject: [PATCH] Make default mkshrc file suitable for OpenWrt environment: > * OpenWrt and FreeWRT-1.0 fix: > - since this is not ~/.mkshrc make sure subshells find it > --- > - dot.mkshrc | 10 +++++++--- > - 1 file changed, 7 insertions(+), 3 deletions(-) > - > -diff --git a/dot.mkshrc b/dot.mkshrc > -index 233a10c..caf482c 100644 > +Signed-off-by: alive4ever > --- a/dot.mkshrc > +++ b/dot.mkshrc > -@@ -28,8 +28,8 @@ case $KSH_VERSION in > +@@ -28,8 +28,9 @@ > *) return 0 ;; > esac > > --PS1='#'; (( USER_ID )) && PS1='$'; [[ ${HOSTNAME:=$(ulimit -c 0; hostname -s \ > -- 2>/dev/null)} = *([ ]|localhost) ]] && HOSTNAME=$(ulimit -c 0; hostname \ > -+PS1='#'; (( USER_ID )) && PS1='$'; [[ ${HOSTNAME:=$( -+ )} = *([ ]|localhost) ]] && HOSTNAME=$(ulimit -c 0; hostname \ > - 2>/dev/null); : ${EDITOR:=/bin/ed} ${HOSTNAME:=nil} ${TERM:=vt100} > - : ${MKSH:=$(whence -p mksh)}; PS4='[$EPOCHREALTIME] '; PS1=$'\001\r''${| > - local e=$? > -@@ -50,7 +50,7 @@ unalias ls > - alias l='ls -F' > - alias la='l -a' > - alias ll='l -l' > --alias lo='l -alo' > -+alias lo='l -al' > - alias doch='sudo mksh -c "$(fc -ln -1)"' > - whence -p rot13 >/dev/null || alias rot13='tr \ > +-PS1='#'; (( USER_ID )) && PS1='$'; \: "${TERM:=vt100}${HOSTNAME:=$(\ulimit -c \ > +- 0; hostname 2>/dev/null)}${EDITOR:=/bin/ed}${USER:=$(\ulimit -c 0; id -un \ > ++PS1='#'; (( USER_ID )) && PS1='$'; \: "${HOSTNAME:=$( ++ )} = *([ ]|localhost) && HOSTNAME=$(\ulimit -c \ > ++ 0; hostname 2>/dev/null)}${EDITOR:=/bin/vi}${USER:=$(\ulimit -c 0; id -un \ > + 2>/dev/null || \echo \?)}${MKSH:=$(\builtin whence -p mksh)}" > + HOSTNAME=${HOSTNAME%%*([ ]).*}; HOSTNAME=${HOSTNAME##*([ ])} > + [[ $HOSTNAME = ?(ip6-)localhost?(6) ]] && HOSTNAME= > +@@ -52,7 +53,7 @@ > + \alias l='ls -F' > + \alias la='l -a' > + \alias ll='l -l' > +-\alias lo='l -alo' > ++\alias lo='l -al' > + \alias doch='sudo mksh -c "$(\builtin fc -ln -1)"' > + \command -v rot13 >/dev/null || \alias rot13='tr \ > abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ \ > -@@ -402,4 +402,8 @@ alias cls='print -n \\033c' > +@@ -601,4 +602,8 @@ > > - unset p > + \unset p > > +# we need this in OpenWrt for subshells that are not login shells > -+: ${ENV=/etc/mkshrc} > ++\: ${ENV=/etc/mkshrc} > +[[ -z $ENV ]] || export ENV > + > - : place customisations above this line > --- > -2.1.1 > - > + \: place customisations above this line > _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From cuero.bugot at gmail.com Mon Jul 11 10:44:15 2016 From: cuero.bugot at gmail.com (Cuero Bugot) Date: Mon, 11 Jul 2016 16:44:15 +0200 Subject: [OpenWrt-Devel] [PATCH] [Build] Allows external kernel tree to be a relative path Message-ID: From: Cuero Bugot CONFIG_EXTERNAL_KERNEL_TREE .config settings allows building the kernel from an external tree directory. It currently only accept absolute path. This patch is about allowing relative path. This is particularly convenient if you have your openwrt and kernel sources hosted remotely, have several persons working on the same sources, but possibly on different location on their machine! The code bellow check if the path is relative or absolute, and if relative prepend it with openwrt TOPDIR path. --- diff --git a/config/Config-devel.in b/config/Config-devel.in index 938f0b3..5ab32d6 100644 --- a/config/Config-devel.in +++ b/config/Config-devel.in @@ -64,6 +64,9 @@ menuconfig DEVEL config EXTERNAL_KERNEL_TREE string "Use external kernel tree" if DEVEL default "" + help + Path to the external kernel source tree. If the provided path is not absolute, it is + relative to the openwrt top directory. config KERNEL_GIT_CLONE_URI string "Enter git repository to clone" if DEVEL diff --git a/include/kernel-defaults.mk b/include/kernel-defaults.mk index 406fd46..fdfcb23 100644 --- a/include/kernel-defaults.mk +++ b/include/kernel-defaults.mk @@ -63,7 +63,13 @@ else if [ -d $(LINUX_DIR) ]; then \ rmdir $(LINUX_DIR); \ fi - ln -s $(CONFIG_EXTERNAL_KERNEL_TREE) $(LINUX_DIR) + # Check if the provided external path is absolute or relative + # if the path is relative, build the proper path from the openwrt top dir. + if [ "${CONFIG_EXTERNAL_KERNEL_TREE:0:1}" = "/" ]; then \ + ln -s $(CONFIG_EXTERNAL_KERNEL_TREE) $(LINUX_DIR); \ + else \ + ln -s $(TOPDIR)/$(CONFIG_EXTERNAL_KERNEL_TREE) $(LINUX_DIR); \ + fi endef endif Signed-off-by: Cuero Bugot -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From kviswanathan.83 at gmail.com Tue Jul 12 09:51:33 2016 From: kviswanathan.83 at gmail.com (kasi viswanathan) Date: Tue, 12 Jul 2016 19:21:33 +0530 Subject: [OpenWrt-Devel] Request to update information page for Banana Pro Message-ID: Hi, I have successfully loaded the latest openwrt image on Lemaker's banana pro board after compiling the latest code from scratch from the main repo. The below link seems to be outdated: https://wiki.openwrt.org/toh/lemaker/bananapro And the installation procedures points to the below link which is also not working as expected. https://wiki.openwrt.org/doc/hardware/soc/soc.allwinner.sunxi#installationprocess Since i was able to successfully load the image i just want to share/update the same in the webpage. Pls help me to proceed further. Thanks, Kasiviswanathan.V _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From wigyori at uid0.hu Tue Jul 12 09:59:41 2016 From: wigyori at uid0.hu (Zoltan HERPAI) Date: Tue, 12 Jul 2016 15:59:41 +0200 (CEST) Subject: [OpenWrt-Devel] Request to update information page for Banana Pro In-Reply-To: References: Message-ID: On Tue, 12 Jul 2016, kasi viswanathan wrote: > I have successfully loaded the latest openwrt image on Lemaker's > banana pro board after compiling the latest code from scratch from the > main repo. > > The below link seems to be outdated: > > https://wiki.openwrt.org/toh/lemaker/bananapro > > And the installation procedures points to the below link which is also > not working as expected. > > https://wiki.openwrt.org/doc/hardware/soc/soc.allwinner.sunxi#installationprocess > > Since i was able to successfully load the image i just want to > share/update the same in the webpage. > > Pls help me to proceed further. Hi Kasi, Please register an account on the wiki site, and feel free to update the page. Thanks, Zoltan H _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From kviswanathan.83 at gmail.com Tue Jul 12 10:36:48 2016 From: kviswanathan.83 at gmail.com (kasi viswanathan) Date: Tue, 12 Jul 2016 20:06:48 +0530 Subject: [OpenWrt-Devel] Request to update information page for Banana Pro In-Reply-To: References: Message-ID: Thanks On Tue, Jul 12, 2016 at 7:29 PM, Zoltan HERPAI wrote: > On Tue, 12 Jul 2016, kasi viswanathan wrote: > >> I have successfully loaded the latest openwrt image on Lemaker's >> banana pro board after compiling the latest code from scratch from the >> main repo. >> >> The below link seems to be outdated: >> >> https://wiki.openwrt.org/toh/lemaker/bananapro >> >> And the installation procedures points to the below link which is also >> not working as expected. >> >> >> https://wiki.openwrt.org/doc/hardware/soc/soc.allwinner.sunxi#installationprocess >> >> Since i was able to successfully load the image i just want to >> share/update the same in the webpage. >> >> Pls help me to proceed further. > > > Hi Kasi, > > Please register an account on the wiki site, and feel free to update the > page. > > Thanks, > Zoltan H _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From valent at otvorenamreza.org Tue Jul 12 17:39:27 2016 From: valent at otvorenamreza.org (Valent Turkovic) Date: Tue, 12 Jul 2016 23:39:27 +0200 Subject: [OpenWrt-Devel] Sync data from tmpfs to internal or external flash periodically ! Message-ID: While reading some articles on Arch wiki [1] I have discovered anything-sync-daemon [2] which is just awesome if you are embedded developer or enthusiast using OpenWrt. Function of the asd (anything-sync-daemon) is to periodically sync contents of tmpfs (ram drive) to some physical memory (hdd, flash drive, sd card, internal flash), this speeds up things considerably while also lowering the wear of physical memory storage device. Most OpenWrt devices have really small internal flash (4MB being most common, some models have up to 16MB of internal flash), and if you write to internal flash you can wear it out quite fast and render it unusable. I have worked on few projects which all collect and log some data, we usually use sd cards to save data to, but still they also also wear out after 6-12 months of use. I see asd (anything-sync-daemon) like an awesome tool that would collect data and sync every hour data from tmpfs to sc card so it would reduce wear and tear of sd card. You can also use asd for having permanent openwrt logs, and sync them to internal flash so that you have logs even after a reboot, of is you use rrdtool graphs you can also have your rrdtool database synced so you have data and rrd graphs also after reboot... There are lots of use cases I can think of... But currently there is no package for asd in openwrt package repos. Has nobody discovered this package yet? Is there some other package that provides similar functionality already to OpenWrt? Thanks! [1] https://wiki.archlinux.org/index.php/Anything-sync-daemon [2] https://github.com/graysky2/anything-sync-daemon _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From yutang.jiang at nxp.com Wed Jul 13 06:19:26 2016 From: yutang.jiang at nxp.com (Yutang Jiang) Date: Wed, 13 Jul 2016 10:19:26 +0000 Subject: [OpenWrt-Devel] [PATCH 1/2] layerscape: add ls1043ardb-64b target In-Reply-To: <1468432570-7202-1-git-send-email-yutang.jiang@nxp.com> References: <1468432570-7202-1-git-send-email-yutang.jiang@nxp.com> Message-ID: Hi All, I'm NXP engineer, we plan to add some layerscape platform develop boards support into Openwrt. Now, the ls1043ardb-64b is the first one. There are two patches: the first one is for target folder, the second is for kernel patches. Be cautious to open the second patch! It is too large! Thanks & Best Regards Jiang Yutang -----Original Message----- From: yutang.jiang at nxp.com [mailto:yutang.jiang at nxp.com] Sent: Thursday, July 14, 2016 1:56 AM To: openwrt-devel at lists.openwrt.org Cc: Yutang Jiang Subject: [PATCH 1/2] layerscape: add ls1043ardb-64b target From: Yutang Jiang Add support for NXP layerscape ls1043ardb-64b Dev board. ls1043ardb-64b target is using 4.1 kernel and rcw/u-boot/fman images from NXP QorIQ SDK V2.0 release. All of 4.1 kernel patches will be in the second patch, it have more than 100 kernel patches: platform/flash/dpaa/mmc/usb/pcie etc, porting from SDK release or upstream. Signed-off-by: Yutang Jiang --- target/linux/layerscape-64b/Makefile | 26 + target/linux/layerscape-64b/README.ls1043ardb | 860 ++++++ target/linux/layerscape-64b/base-files/etc/inittab | 6 + target/linux/layerscape-64b/image/Makefile | 64 + .../linux/layerscape-64b/image/checkimagesize.sh | 16 + .../linux/layerscape-64b/ls1043ardb/config-default | 3146 ++++++++++++++++++++ target/linux/layerscape-64b/ls1043ardb/target.mk | 16 + 7 files changed, 4134 insertions(+) create mode 100644 target/linux/layerscape-64b/Makefile create mode 100644 target/linux/layerscape-64b/README.ls1043ardb create mode 100644 target/linux/layerscape-64b/base-files/etc/inittab create mode 100644 target/linux/layerscape-64b/image/Makefile create mode 100755 target/linux/layerscape-64b/image/checkimagesize.sh create mode 100644 target/linux/layerscape-64b/ls1043ardb/config-default create mode 100644 target/linux/layerscape-64b/ls1043ardb/target.mk diff --git a/target/linux/layerscape-64b/Makefile b/target/linux/layerscape-64b/Makefile new file mode 100644 index 0000000..63d55b9 --- /dev/null +++ b/target/linux/layerscape-64b/Makefile @@ -0,0 +1,26 @@ +# +# Copyright (C) 2016 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk + +ARCH:=aarch64 +BOARD:=layerscape-64b +BOARDNAME:=layerscape 64b +CFLAGS:=-Os -pipe -fno-caller-saves +DEVICE_TYPE:=developerboard +KERNEL_PATCHVER:=4.1 +KERNELNAME:=Image dtbs +FEATURES:=squashfs +SUBTARGETS:=ls1043ardb +MAINTAINER:=Jiang Yutang + +include $(INCLUDE_DIR)/target.mk + +define Target/Description + Build firmware images for $(BOARDNAME) SoC devices. +endef + +$(eval $(call BuildTarget)) diff --git a/target/linux/layerscape-64b/README.ls1043ardb b/target/linux/layerscape-64b/README.ls1043ardb new file mode 100644 index 0000000..9f6a0af --- /dev/null +++ b/target/linux/layerscape-64b/README.ls1043ardb @@ -0,0 +1,860 @@ +1.NOR Flash Memory Map Layout for LS1043ARDB +------------------------------------------ +Start End Offset Description Size +0x60000000 0x600FFFFF bank0 rcw + pbi 1M +0x60100000 0x601FFFFF bank0 U-Boot image 1M +0x60200000 0x602FFFFF bank0 U-Boot Env 1M +0x60300000 0x603FFFFF bank0 Fman ucode 1M +0x60400000 0x63FFFFFF bank0 OpenWrt firmware 60M +0x64000000 0x67FFFFFF bank4 Otherbank 64M + +2.Partitioning of the Flash +------------------------- +#################################################################################################### +# Layer0 # raw flash, 128M # +#################################################################################################### +# # mtd0 # mtd1 # mtd2 # mtd3 # mtd9 # mtd8 # +# Layer1 # rcw # u-boot # u-boot-env # fman # firmware # otherbank # +# # 1M # 1M # 1M # 1M # 60M # 64M # +#################################################################################################### +# # # # # # mtd4 # mtd5 # mtd6 # # +# Layer2 # # # # # dtb # kernel # rootfs # # +# # # # # # 1M # 5M # 54M # # +#################################################################################################### +# # # # # # # # # mtd7 # # +# Layer3 # # # # # # # /dev/root # rootfs_data # # +# # # # # # # # "/rom" # "/overlay" # # +# # # # # # # # SquashFS # JFFS2 # # +#################################################################################################### + +3.Flashing firmware image and bootup kernel in u-boot +----------------------------------------------------- +setenv gatewayip +setenv ipaddr +setenv serverip +setenv loadaddr 82000000 && setenv ramdiskaddr 88000000 && setenv fdtaddr 8f000000 +setenv wrtboot 'setenv bootargs root=/dev/mtdblock6 rootfstype=squashfs,jffs2 noinitrd earlycon=uart8250,mmio,0x21c0500 console=ttyS0,115200 mtdparts=60000000.nor:1M(rcw),1M(u-boot),1M(u-boot-env),1M(fman),1M(dtb),5M(kernel),54M(rootfs),64M(otherbank),60M at 0x400000(firmware) && cp.b 60400000 $fdtaddr 100000 && cp.b 60500000 $loadaddr 500000 && bootm $loadaddr - $fdtaddr' +save +tftp a0000000 your_tftpserver_folder/openwrt-layerscape-64b-ls1043ardb-firmware && protect off all && erase 60400000 +3c00000 && cp.b a0000000 60400000 $filesize +run wrtboot + +4.Boot log +--------------------------------- +U-Boot 2015.01QorIQ-SDK-V1.7+gc297f5b (Dec 20 2015 - 13:08:26) + +Clock Configuration: + CPU0(A53):1600 MHz CPU1(A53):1600 MHz CPU2(A53):1600 MHz + CPU3(A53):1600 MHz + Bus: 400 MHz DDR: 1600 MT/s FMAN: 500 MHz +Reset Configuration Word (RCW): + 00000000: 08100010 0a000000 00000000 00000000 + 00000010: 14550002 80004012 e0025000 c1002000 + 00000020: 00000000 00000000 00000000 00038800 + 00000030: 00000000 00001101 00000096 00000001 +Board: LS1043ARDB, boot from vBank 0 +CPLD: V1.4 +PCBA: V3.0 +SERDES Reference Clocks: +SD1_CLK1 = 156.25MHZ, SD1_CLK2 = 100.00MHZ +I2C: ready +DRAM: Initializing DDR.... +Detected UDIMM Fixed DDR on board +2 GiB (DDR4, 32-bit, CL=11, ECC off) +Firmware 'Microcode version 0.0.1 for LS1021a r1.0' for 1021 V1.0 +QE: uploading microcode 'Microcode for LS1021a r1.0' version 0.0.1 +Using SERDES1 Protocol: 5205 (0x1455) +fman_port_enet_if:71: port(FM1_DTSEC3) is OK +fman_port_enet_if:77: port(FM1_DTSEC4) is OK +Flash: 128 MiB +NAND: 512 MiB +MMC: FSL_SDHC: 0 +EEPROM: NXID v1 +PCIe1: disabled +PCIe2: Root Complex no link, regs @ 0x3500000 +PCIe3: Root Complex x1 gen1, regs @ 0x3600000 + 01:00.0 - 8086:10d3 - Network controller +PCIe3: Bus 00 - 01 +In: serial +Out: serial +Err: serial +Net: Fman1: Uploading microcode version 106.4.17 +e1000: 68:05:ca:35:fa:4a + FM1 at DTSEC1, FM1 at DTSEC2, FM1 at DTSEC3, FM1 at DTSEC4, FM1 at DTSEC5, FM1 at DTSEC6, FM1 at TGEC1, e1000#0 [PRIME] +Warning: e1000#0 MAC addresses don't match: +Address in SROM is 68:05:ca:35:fa:4a +Address in environment is 00:e0:0c:00:73:07 + +=> +=> pri +baudrate=115200 +bootargs=console=ttyS0,115200 root=/dev/ram0 earlycon=uart8250,0x21c0500,115200 +bootcmd=cpld reset altbank +bootdelay=-1 +console=ttyAMA0,38400n8 +eth10addr=00:E0:0C:00:73:0a +eth11addr=00:E0:0C:00:73:0b +eth12addr=00:E0:0C:00:73:0c +eth13addr=00:E0:0C:00:73:0d +eth14addr=00:E0:0C:00:73:0e +eth15addr=00:E0:0C:00:73:0f +eth1addr=00:E0:0C:00:73:01 +eth2addr=00:E0:0C:00:73:02 +eth3addr=00:E0:0C:00:73:03 +eth4addr=00:E0:0C:00:73:04 +eth5addr=00:E0:0C:00:73:05 +eth6addr=00:E0:0C:00:73:06 +eth7addr=00:E0:0C:00:73:07 +eth8addr=00:E0:0C:00:73:08 +eth9addr=00:E0:0C:00:73:09 +ethact=e1000#0 +ethaddr=00:E0:0C:00:73:00 +ethprime=e1000#0 +faddr_fman_mc=0x64300000 +faddr_rcw=0x64000000 +faddr_uboot=0x64100000 +fdt_high=0xffffffffffffffff +fman_ucode=60300000 +gatewayip=192.168.1.1 +hwconfig=fsl_ddr:bank_intlv=auto;dspi +img_fman_mc=b28495/sdk/sdk-ls1043a/201512200957-b0dba1d/ls1043ardb/fsl_fman_ucode_t2080_r1.1_106_4_17.bin +img_rcw=b28495/sdk/sdk-ls1043a/201512200957-b0dba1d/ls1043ardb/rcw/ls1043ardb/RR_FQPP_1455/rcw_1600.bin +img_uboot=b28495/armv8-staging/ls1043a/u-boot-ls1043ardb.bin +initrd_high=0xffffffffffffffff +ipaddr=192.168.2.135 +kernel_addr=0x100000 +kernel_load=0xa0000000 +kernel_size=0x2800000 +kernel_start=0x61100000 +loadaddr=0x80100000 +netmask=255.255.255.0 +raddr_temp=0x90000000 +ramdisk_addr=0x800000 +ramdisk_size=0x2000000 +scsidevs=0 +serverip=192.168.2.1 +stderr=serial +stdin=serial +stdout=serial +upbank4=tftp 82000000 b18965/ls1043-rdb/u-boot-dtb.bin && protect off all && erase 64100000 641fffff && cp.b 0x82000000 64100000 100000 && run bootcmd + +Environment size: 1653/131068 bytes +=> cpld reset altbank + +U-Boot 2016.07-rc2-g15030c7 (Jul 13 2016 - 02:10:41 +0800), Build: jenkins-armv8-u-boot-build-ls1043-1s2085-247 + +SoC: unknown (0x87920410) +Clock Configuration: + CPU0(A53):1600 MHz CPU1(A53):1600 MHz CPU2(A53):1600 MHz + CPU3(A53):1600 MHz + Bus: 400 MHz DDR: 1600 MT/s FMAN: 500 MHz +Reset Configuration Word (RCW): + 00000000: 08100010 0a000000 00000000 00000000 + 00000010: 14550002 80004012 e0025000 c1002000 + 00000020: 00000000 00000000 00000000 00038800 + 00000030: 00000000 00001101 00000096 00000001 +Model: LS1043A RDB Board +Board: LS1043ARDB, boot from vBank 4 +CPLD: V1.4 +PCBA: V3.0 +SERDES Reference Clocks: +SD1_CLK1 = 156.25MHZ, SD1_CLK2 = 100.00MHZ +I2C: ready +DRAM: Initializing DDR.... +Detected UDIMM Fixed DDR on board +2 GiB (DDR4, 32-bit, CL=11, ECC off) +Not a microcode +Waking secondary cores to start from ffd08000 +All (4) cores are up. +Using SERDES1 Protocol: 5205 (0x1455) +Flash: 128 MiB +NAND: 512 MiB +MMC: FSL_SDHC: 0 +EEPROM: NXID v1 +PCIe1: disabled +PCIe2: Root Complex no link, regs @ 0x3500000 +PCIe3: Root Complex x1 gen1, regs @ 0x3600000 +PCI: + 01:00.0 - 8086:10d3 - Network controller +PCIe3: Bus 00 - 01 +In: serial +Out: serial +Err: serial +SEC0: RNG instantiated +Net: Fman1: Uploading microcode version 106.4.17 +e1000: 68:05:ca:35:fa:4a + FM1 at DTSEC1, FM1 at DTSEC2, FM1 at DTSEC3, FM1 at DTSEC4, FM1 at DTSEC5, FM1 at DTSEC6, FM1 at TGEC1, e1000#0 [PRIME] +Warning: e1000#0 MAC addresses don't match: +Address in SROM is 68:05:ca:35:fa:4a +Address in environment is 00:e0:0c:00:73:07 + +=> pri +baudrate=115200 +bootargs=console=ttyS0,115200 root=/dev/ram0 earlycon=uart8250,mmio,0x21c0500 +bootcmd=cp.b $kernel_start $kernel_load $kernel_size && bootm $kernel_load +bootdelay=-1 +console=ttyAMA0,38400n8 +eth10addr=00:E0:0C:00:73:0a +eth11addr=00:E0:0C:00:73:0b +eth12addr=00:E0:0C:00:73:0c +eth13addr=00:E0:0C:00:73:0d +eth14addr=00:E0:0C:00:73:0e +eth15addr=00:E0:0C:00:73:0f +eth1addr=00:E0:0C:00:73:01 +eth2addr=00:E0:0C:00:73:02 +eth3addr=00:E0:0C:00:73:03 +eth4addr=00:E0:0C:00:73:04 +eth5addr=00:E0:0C:00:73:05 +eth6addr=00:E0:0C:00:73:06 +eth7addr=00:E0:0C:00:73:07 +eth8addr=00:E0:0C:00:73:08 +eth9addr=00:E0:0C:00:73:09 +ethact=e1000#0 +ethaddr=00:E0:0C:00:73:00 +ethprime=e1000#0 +fdt_high=0xffffffffffffffff +fdtcontroladdr=ffbc5728 +fman_ucode=60300000 +hwconfig=fsl_ddr:bank_intlv=auto;dspi +initrd_high=0xffffffffffffffff +kernel_addr=0x100000 +kernel_load=0xa0000000 +kernel_size=0x2800000 +kernel_start=0x61100000 +loadaddr=0x80100000 +ramdisk_addr=0x800000 +ramdisk_size=0x2000000 +stderr=serial +stdin=serial +stdout=serial + +Environment size: 1089/131068 bytes +=> setenv ipaddr 192.168.2.135 +=> setenv serverip 192.168.2.1 +=> setenv gatewayip 192.168.1.1 +=> setenv loadaddr 82000000 && setenv ramdiskaddr 88000000 && setenv fdtaddr 8f000000 +=> setenv wrtboot 'setenv bootargs root=/dev/mtdblock6 rootfstype=squashfs,jffs2 noinitrd earlycon=uart8250,mmio,0x21c0500 console=ttyS0,115200 mtdparts=60000000.nor:1M(rcw),1M(u-boot),1M(u-boot-env),1M(fman),1M(dtb),5M(kernel),54M(rootfs),64M(otherbank),60M at 0x400000(firmware) && cp.b 60400000 $fdtaddr 100000 && cp.b 60500000 $loadaddr 500000 && bootm $loadaddr - $fdtaddr' +=> save +Saving Environment to Flash... +Un-Protected 1 sectors +Erasing Flash... +. done +Erased 1 sectors +Writing to Flash... 9....8....7....6....5....4....3....2....1....done +Protected 1 sectors +=> +=> tftp a0000000 jyt/openwrt/ls1043/openwrt-layerscape-64b-ls1043ardb-firmware && protect off all && erase 60400000 +3c00000 && cp.b a0000000 60400000 $filesize +Using e1000#0 device +TFTP from server 192.168.2.1; our IP address is 192.168.2.135 +Filename 'jyt/openwrt/ls1043/openwrt-layerscape-64b-ls1043ardb-firmware'. +Load address: 0xa0000000 +Loading: ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ############################################################# + 10.9 MiB/s +done +Bytes transferred = 62914560 (3c00000 hex) +Un-Protect Flash Bank # 1 + +................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................ done +Erased 480 sectors +Copy to Flash... 9....8....7....6....5....4....3....2....1....done +=> +=> run wrtboot +## Booting kernel from Legacy Image at 82000000 ... + Image Name: ARM64 OpenWrt Linux-4.1.23 + Image Type: AArch64 Linux Kernel Image (gzip compressed) + Data Size: 3899658 Bytes = 3.7 MiB + Load Address: 80080000 + Entry Point: 80080000 + Verifying Checksum ... OK +## Flattened Device Tree blob at 8f000000 + Booting using the fdt blob at 0x8f000000 + Uncompressing Kernel Image ... OK + Using Device Tree in place at 000000008f000000, end 000000008f0183bd +WARNING: Missing crypto node + +Starting kernel ... + +[ 0.000000] Booting Linux on physical CPU 0x0 +[ 0.000000] Linux version 4.1.23 (jyt at BP) (gcc version 5.3.0 (OpenWrt GCC 5.3.0 r49395) ) #1 SMP Wed Jul 13 10:42:53 UTC 2016 +[ 0.000000] CPU: AArch64 Processor [410fd034] revision 4 +[ 0.000000] Detected VIPT I-cache on CPU0 +[ 0.000000] alternatives: enabling workaround for ARM erratum 845719 +[ 0.000000] earlycon: Early serial console at MMIO 0x21c0500 (options '') +[ 0.000000] bootconsole [uart0] enabled +[ 0.000000] efi: Getting EFI parameters from FDT: +[ 0.000000] efi: UEFI not found. +[ 0.000000] Reserved memory: initialized node bman-fbpr, compatible id fsl,bman-fbpr +[ 0.000000] Reserved memory: initialized node qman-fqd, compatible id fsl,qman-fqd +[ 0.000000] Reserved memory: initialized node qman-pfdr, compatible id fsl,qman-pfdr +[ 0.000000] PERCPU: Embedded 16 pages/cpu @ffff80007fd8d000 s27072 r8192 d30272 u65536 +[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 516615 +[ 0.000000] Kernel command line: root=/dev/mtdblock6 rootfstype=squashfs,jffs2 noinitrd earlycon=uart8250,mmio,0x21c0500 console=ttyS0,115200 mtdparts=60000000.nor:1M(rcw),1M(u-boot),1M(u-boot-env),1M(fman),1M(dtb),5M(kernel),54M(rootfs),64M(otherbank),60M at 0x400000(firmware) +[ 0.000000] log_buf_len individual max cpu contribution: 4096 bytes +[ 0.000000] log_buf_len total cpu_extra contributions: 12288 bytes +[ 0.000000] log_buf_len min size: 16384 bytes +[ 0.000000] log_buf_len: 32768 bytes +[ 0.000000] early log buf free: 14560(88%) +[ 0.000000] PID hash table entries: 4096 (order: 3, 32768 bytes) +[ 0.000000] Dentry cache hash table entries: 262144 (order: 9, 2097152 bytes) +[ 0.000000] Inode-cache hash table entries: 131072 (order: 8, 1048576 bytes) +[ 0.000000] software IO TLB [mem 0xf6a00000-0xfaa00000] (64MB) mapped at [ffff800076a00000-ffff80007a9fffff] +[ 0.000000] Memory: 1933896K/2095104K available (5768K kernel code, 340K rwdata, 2500K rodata, 276K init, 721K bss, 161208K reserved, 0K cma-reserved) +[ 0.000000] Virtual kernel memory layout: +[ 0.000000] vmalloc : 0xffff000000000000 - 0xffff7c7fbfff0000 (127486 GB) +[ 0.000000] vmemmap : 0xffff7c7fc0000000 - 0xffff7fffc0000000 ( 3584 GB maximum) +[ 0.000000] 0xffff7c7fc0000000 - 0xffff7c7fc1bf9000 ( 27 MB actual) +[ 0.000000] fixed : 0xffff7ffffabfd000 - 0xffff7ffffac00000 ( 12 KB) +[ 0.000000] PCI I/O : 0xffff7ffffae00000 - 0xffff7ffffbe00000 ( 16 MB) +[ 0.000000] modules : 0xffff7ffffc000000 - 0xffff800000000000 ( 64 MB) +[ 0.000000] memory : 0xffff800000000000 - 0xffff80007fe00000 ( 2046 MB) +[ 0.000000] .init : 0xffff800000896000 - 0xffff8000008db000 ( 276 KB) +[ 0.000000] .text : 0xffff800000080000 - 0xffff8000008951a4 ( 8277 KB) +[ 0.000000] .data : 0xffff8000008e6000 - 0xffff80000093b000 ( 340 KB) +[ 0.000000] Hierarchical RCU implementation. +[ 0.000000] CONFIG_RCU_FANOUT set to non-default value of 32 +[ 0.000000] RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=4. +[ 0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4 +[ 0.000000] NR_IRQS:64 nr_irqs:64 0 +[ 0.000000] Architected cp15 timer(s) running at 25.00MHz (phys). +[ 0.000000] clocksource arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x5c40939b5, max_idle_ns: 440795202646 ns +[ 0.000002] sched_clock: 56 bits at 25MHz, resolution 40ns, wraps every 4398046511100ns +[ 0.008237] Calibrating delay loop (skipped), value calculated using timer frequency.. 50.00 BogoMIPS (lpj=250000) +[ 0.018642] pid_max: default: 32768 minimum: 301 +[ 0.023339] Mount-cache hash table entries: 4096 (order: 3, 32768 bytes) +[ 0.030074] Mountpoint-cache hash table entries: 4096 (order: 3, 32768 bytes) +[ 0.037599] EFI services will not be available. +[ 0.042623] CPU1: Booted secondary processor +[ 0.042627] Detected VIPT I-cache on CPU1 +[ 0.042768] CPU2: Booted secondary processor +[ 0.042771] Detected VIPT I-cache on CPU2 +[ 0.042902] CPU3: Booted secondary processor +[ 0.042904] Detected VIPT I-cache on CPU3 +[ 0.042932] Brought up 4 CPUs +[ 0.070816] SMP: Total of 4 processors activated. +[ 0.075536] CPU: All CPU(s) started at EL2 +[ 0.079655] alternatives: patching kernel code +[ 0.086792] DMI not present or invalid. +[ 0.090754] clocksource jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns +[ 0.100593] atomic64_test: passed +[ 0.104311] NET: Registered protocol family 16 +[ 0.109363] fsl-mc bus type registered +[ 0.113169] MC object device driver fsl_mc_dprc registered +[ 0.118714] MC object device driver fsl_mc_allocator registered +[ 0.124694] Bman ver:0a02,02,01 +[ 0.130025] qman-fqd addr 0xff800000 size 0x400000 +[ 0.134833] qman-pfdr addr 0xfc000000 size 0x2000000 +[ 0.139821] Qman ver:0a01,03,02,00 +[ 0.143310] vdso: 2 pages (1 code @ ffff8000008ed000, 1 data @ ffff8000008ec000) +[ 0.150845] DMA: preallocated 256 KiB pool for atomic allocations +[ 0.157052] Serial: AMBA PL011 UART driver +[ 0.201606] ACPI: Interpreter disabled. +[ 0.205877] SCSI subsystem initialized +[ 0.210022] usbcore: registered new interface driver usbfs +[ 0.215577] usbcore: registered new interface driver hub +[ 0.220937] usbcore: registered new device driver usb +[ 0.226079] pps_core: LinuxPPS API ver. 1 registered +[ 0.231062] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti +[ 0.240273] PTP clock support registered +[ 0.244377] bman-fbpr addr 0xfe000000 size 0x1000000 +[ 0.249389] Bman err interrupt handler present +[ 0.253972] unknown BMan version in portal node,default to rev1.0 +[ 0.260113] unknown BMan version in portal node,default to rev1.0 +[ 0.266250] unknown BMan version in portal node,default to rev1.0 +[ 0.272381] unknown BMan version in portal node,default to rev1.0 +[ 0.278516] unknown BMan version in portal node,default to rev1.0 +[ 0.284647] unknown BMan version in portal node,default to rev1.0 +[ 0.290782] unknown BMan version in portal node,default to rev1.0 +[ 0.296912] unknown BMan version in portal node,default to rev1.0 +[ 0.303047] unknown BMan version in portal node,default to rev1.0 +[ 0.309253] Bman portal initialised, cpu 0 +[ 0.313427] Bman portal initialised, cpu 1 +[ 0.317595] Bman portal initialised, cpu 2 +[ 0.321763] Bman portal initialised, cpu 3 +[ 0.325877] Bman portals initialised +[ 0.330330] Qman err interrupt handler present +[ 0.334788] Can't find Qman clock frequency +[ 0.339153] QMan: Allocated lookup table at ffff00000016d000, entry count 65537 +[ 0.346528] unknown QMan version in portal node,default to rev1.1 +[ 0.352650] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 0' has 0x0101 +[ 0.360957] unknown QMan version in portal node,default to rev1.1 +[ 0.367080] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 10000' has 0x0101 +[ 0.375736] unknown QMan version in portal node,default to rev1.1 +[ 0.381856] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 20000' has 0x0101 +[ 0.390512] unknown QMan version in portal node,default to rev1.1 +[ 0.396633] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 30000' has 0x0101 +[ 0.405288] unknown QMan version in portal node,default to rev1.1 +[ 0.411409] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 40000' has 0x0101 +[ 0.420064] unknown QMan version in portal node,default to rev1.1 +[ 0.426185] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 50000' has 0x0101 +[ 0.434840] unknown QMan version in portal node,default to rev1.1 +[ 0.440961] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 60000' has 0x0101 +[ 0.449616] unknown QMan version in portal node,default to rev1.1 +[ 0.455737] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 70000' has 0x0101 +[ 0.464392] unknown QMan version in portal node,default to rev1.1 +[ 0.470513] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 80000' has 0x0101 +[ 0.479838] Qman portal initialised, cpu 0 +[ 0.484406] Qman portal initialised, cpu 1 +[ 0.488967] Qman portal initialised, cpu 2 +[ 0.493528] Qman portal initialised, cpu 3 +[ 0.497641] Qman portals initialised +[ 0.501299] Bman: BPID allocator includes range 32:32 +[ 0.506401] Qman: FQID allocator includes range 256:256 +[ 0.511649] Qman: FQID allocator includes range 32768:32768 +[ 0.517278] Qman: CGRID allocator includes range 0:256 +[ 0.522546] Qman: pool channel allocator includes range 1025:15 +[ 0.528532] No USDPAA memory, no 'usdpaa_mem' bootarg +[ 0.533638] fsl-ifc 1530000.ifc: Freescale Integrated Flash Controller +[ 0.540200] fsl-ifc 1530000.ifc: IFC version 1.4, 8 banks +[ 0.546185] Switched to clocksource arch_sys_counter +[ 0.551318] pnp: PnP ACPI: disabled +[ 0.555272] NET: Registered protocol family 2 +[ 0.559947] TCP established hash table entries: 16384 (order: 5, 131072 bytes) +[ 0.567305] TCP bind hash table entries: 16384 (order: 6, 262144 bytes) +[ 0.574134] TCP: Hash tables configured (established 16384 bind 16384) +[ 0.580737] UDP hash table entries: 1024 (order: 3, 32768 bytes) +[ 0.586802] UDP-Lite hash table entries: 1024 (order: 3, 32768 bytes) +[ 0.593377] NET: Registered protocol family 1 +[ 0.597875] RPC: Registered named UNIX socket transport module. +[ 0.603818] RPC: Registered udp transport module. +[ 0.608545] RPC: Registered tcp transport module. +[ 0.613265] RPC: Registered tcp NFSv4.1 backchannel transport module. +[ 0.620431] futex hash table entries: 1024 (order: 4, 65536 bytes) +[ 0.626825] HugeTLB registered 2 MB page size, pre-allocated 0 pages +[ 0.633410] VFS: Disk quotas dquot_6.6.0 +[ 0.637375] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes) +[ 0.644461] squashfs: version 4.0 (2009/01/31) Phillip Lougher +[ 0.650483] NFS: Registering the id_resolver key type +[ 0.655568] Key type id_resolver registered +[ 0.659770] Key type id_legacy registered +[ 0.663822] jffs2: version 2.2 (NAND) (ZLIB) (RTIME) (c) 2001-2006 Red Hat, Inc. +[ 0.671368] fuse init (API version 7.23) +[ 0.675762] io scheduler noop registered (default) +[ 0.681443] PCI host bridge /soc/pcie at 3500000 ranges: +[ 0.686528] IO 0x4800010000..0x480001ffff -> 0x00000000 +[ 0.692038] MEM 0x4840000000..0x487fffffff -> 0x40000000 +[ 0.697623] layerscape-pcie 3500000.pcie: PCI host bridge to bus 0000:00 +[ 0.704357] pci_bus 0000:00: root bus resource [bus 00-ff] +[ 0.709871] pci_bus 0000:00: root bus resource [io 0x0000-0xffff] +[ 0.716079] pci_bus 0000:00: root bus resource [mem 0x4840000000-0x487fffffff] (bus address [0x40000000-0x7fffffff]) +[ 0.726722] pci 0000:00:00.0: IOMMU is currently not supported for PCI +[ 0.733403] pci 0000:00:00.0: bridge configuration invalid ([bus 00-00]), reconfiguring +[ 0.741527] pci 0000:00:00.0: BAR 1: assigned [mem 0x4840000000-0x4843ffffff] +[ 0.748702] pci 0000:00:00.0: BAR 0: assigned [mem 0x4844000000-0x4844ffffff] +[ 0.755872] pci 0000:00:00.0: BAR 6: assigned [mem 0x4845000000-0x4845ffffff pref] +[ 0.763481] pci 0000:00:00.0: PCI bridge to [bus 01] +[ 0.768488] pcieport 0000:00:00.0: enabling device (0000 -> 0002) +[ 0.774773] PCI host bridge /soc/pcie at 3600000 ranges: +[ 0.779854] IO 0x5000010000..0x500001ffff -> 0x00000000 +[ 0.785364] MEM 0x5040000000..0x507fffffff -> 0x40000000 +[ 0.790943] layerscape-pcie 3600000.pcie: PCI host bridge to bus 0001:00 +[ 0.797679] pci_bus 0001:00: root bus resource [bus 00-ff] +[ 0.803188] pci_bus 0001:00: root bus resource [io 0x10000-0x1ffff] (bus address [0x0000-0xffff]) +[ 0.812195] pci_bus 0001:00: root bus resource [mem 0x5040000000-0x507fffffff] (bus address [0x40000000-0x7fffffff]) +[ 0.822821] pci 0001:00:00.0: IOMMU is currently not supported for PCI +[ 0.829935] pci 0001:01:00.0: IOMMU is currently not supported for PCI +[ 0.856229] pci 0001:00:00.0: BAR 1: assigned [mem 0x5040000000-0x5043ffffff] +[ 0.863399] pci 0001:00:00.0: BAR 0: assigned [mem 0x5044000000-0x5044ffffff] +[ 0.870574] pci 0001:00:00.0: BAR 6: assigned [mem 0x5045000000-0x5045ffffff pref] +[ 0.878184] pci 0001:00:00.0: BAR 8: assigned [mem 0x5046000000-0x50460fffff] +[ 0.885352] pci 0001:00:00.0: BAR 7: assigned [io 0x10000-0x10fff] +[ 0.891652] pci 0001:01:00.0: BAR 1: assigned [mem 0x5046000000-0x504607ffff] +[ 0.898835] pci 0001:01:00.0: BAR 6: assigned [mem 0x5046080000-0x50460bffff pref] +[ 0.906443] pci 0001:01:00.0: BAR 0: assigned [mem 0x50460c0000-0x50460dffff] +[ 0.913622] pci 0001:01:00.0: BAR 3: assigned [mem 0x50460e0000-0x50460e3fff] +[ 0.920805] pci 0001:01:00.0: BAR 2: assigned [io 0x10000-0x1001f] +[ 0.927113] pci 0001:00:00.0: PCI bridge to [bus 01] +[ 0.932098] pci 0001:00:00.0: bridge window [io 0x10000-0x10fff] +[ 0.938395] pci 0001:00:00.0: bridge window [mem 0x5046000000-0x50460fffff] +[ 0.945959] Serial: 8250/16550 driver, 2 ports, IRQ sharing disabled +[ 0.952850] console [ttyS0] disabled +[ 0.956457] 21c0500.serial: ttyS0 at MMIO 0x21c0500 (irq = 15, base_baud = 25000000) is a 16550A +[ 0.965295] console [ttyS0] enabled +[ 0.965295] console [ttyS0] enabled +[ 0.972271] bootconsole [uart0] disabled +[ 0.972271] bootconsole [uart0] disabled +[ 0.980258] 21c0600.serial: ttyS1 at MMIO 0x21c0600 (irq = 15, base_baud = 25000000) is a 16550A +[ 0.989130] of_serial: probe of 21d0500.serial failed with error -28 +[ 0.995500] of_serial: probe of 21d0600.serial failed with error -28 +[ 1.002046] Unable to detect cache hierarcy from DT for CPU 0 +[ 1.010995] brd: module loaded +[ 1.016003] loop: module loaded +[ 1.021262] 60000000.nor: Found 1 x16 devices at 0x0 in 16-bit bank. Manufacturer ID 0x000089 Chip ID 0x00227e +[ 1.031262] Amd/Fujitsu Extended Query Table at 0x0040 +[ 1.036401] Amd/Fujitsu Extended Query version 1.3. +[ 1.041443] number of CFI chips: 1 +[ 1.044845] 9 cmdlinepart partitions found on MTD device 60000000.nor +[ 1.051277] Creating 9 MTD partitions on "60000000.nor": +[ 1.056582] 0x000000000000-0x000000100000 : "rcw" +[ 1.061496] ftl_cs: FTL header not found. +[ 1.065695] 0x000000100000-0x000000200000 : "u-boot" +[ 1.070861] ftl_cs: FTL header not found. +[ 1.075034] 0x000000200000-0x000000300000 : "u-boot-env" +[ 1.080553] ftl_cs: FTL header not found. +[ 1.084729] 0x000000300000-0x000000400000 : "fman" +[ 1.089719] ftl_cs: FTL header not found. +[ 1.093895] 0x000000400000-0x000000500000 : "dtb" +[ 1.098800] ftl_cs: FTL header not found. +[ 1.102973] 0x000000500000-0x000000a00000 : "kernel" +[ 1.108137] ftl_cs: FTL header not found. +[ 1.112309] 0x000000a00000-0x000004000000 : "rootfs" +[ 1.117474] ftl_cs: FTL header not found. +[ 1.121650] mtd: device 6 (rootfs) set to be root filesystem +[ 1.127314] 1 squashfs-split partitions found on MTD device rootfs +[ 1.133483] 0x000000b00000-0x000004000000 : "rootfs_data" +[ 1.139080] ftl_cs: FTL header not found. +[ 1.143257] 0x000004000000-0x000008000000 : "otherbank" +[ 1.148680] ftl_cs: FTL header not found. +[ 1.152854] 0x000000400000-0x000004000000 : "firmware" +[ 1.158193] ftl_cs: FTL header not found. +[ 1.162814] nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xac +[ 1.169161] nand: Micron MT29F4G08ABBDAH4 +[ 1.173160] nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64 +[ 1.180985] Bad block table found at page 262080, version 0x01 +[ 1.187286] Bad block table found at page 262016, version 0x01 +[ 1.195438] ftl_cs: FTL header not found. +[ 1.199625] fsl,ifc-nand 7e800000.nand: IFC NAND device at 0x7e800000, bank 1 +[ 1.207436] libphy: Fixed MDIO Bus: probed +[ 1.211523] tun: Universal TUN/TAP device driver, 1.6 +[ 1.216567] tun: (C) 1999-2004 Max Krasnyansky +[ 1.222917] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.229378] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.235873] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.240891] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.245906] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.250927] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.255942] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.260961] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.265978] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.282650] Freescale FM module, FMD API version 21.1.0 +[ 1.289546] Freescale FM Ports module +[ 1.293200] fsl_mac: fsl_mac: FSL FMan MAC API based driver +[ 1.298867] fsl_mac 1ae0000.ethernet: FMan MEMAC +[ 1.303479] fsl_mac 1ae0000.ethernet: FMan MAC address: 00:e0:0c:00:73:00 +[ 1.310309] fsl_mac 1ae2000.ethernet: FMan MEMAC +[ 1.314918] fsl_mac 1ae2000.ethernet: FMan MAC address: 00:e0:0c:00:73:01 +[ 1.321744] fsl_mac 1ae4000.ethernet: FMan MEMAC +[ 1.326358] fsl_mac 1ae4000.ethernet: FMan MAC address: 00:e0:0c:00:73:02 +[ 1.333182] fsl_mac 1ae6000.ethernet: FMan MEMAC +[ 1.337797] fsl_mac 1ae6000.ethernet: FMan MAC address: 00:e0:0c:00:73:03 +[ 1.344623] fsl_mac 1ae8000.ethernet: FMan MEMAC +[ 1.349237] fsl_mac 1ae8000.ethernet: FMan MAC address: 00:e0:0c:00:73:04 +[ 1.356064] fsl_mac 1aea000.ethernet: FMan MEMAC +[ 1.360677] fsl_mac 1aea000.ethernet: FMan MAC address: 00:e0:0c:00:73:05 +[ 1.367507] fsl_mac 1af0000.ethernet: FMan MEMAC +[ 1.372117] fsl_mac 1af0000.ethernet: FMan MAC address: 00:e0:0c:00:73:06 +[ 1.378965] fsl_dpa: FSL DPAA Ethernet driver +[ 1.387069] fsl_dpa: fsl_dpa: Probed interface eth0 +[ 1.395740] fsl_dpa: fsl_dpa: Probed interface eth1 +[ 1.404752] fsl_dpa: fsl_dpa: Probed interface eth2 +[ 1.414121] fsl_dpa: fsl_dpa: Probed interface eth3 +[ 1.423819] fsl_dpa: fsl_dpa: Probed interface eth4 +[ 1.433876] fsl_dpa: fsl_dpa: Probed interface eth5 +[ 1.444266] fsl_dpa: fsl_dpa: Probed interface eth6 +[ 1.449230] fsl_advanced: FSL DPAA Advanced drivers: +[ 1.454185] fsl_proxy: FSL DPAA Proxy initialization driver +[ 1.459931] fsl_dpa_shared: FSL DPAA Shared Ethernet driver +[ 1.465573] fsl_dpa_macless: FSL DPAA MACless Ethernet driver +[ 1.471394] fsl_oh: FSL FMan Offline Parsing port driver +[ 1.476801] e1000e: Intel(R) PRO/1000 Network Driver - 2.3.2-k +[ 1.482621] e1000e: Copyright(c) 1999 - 2014 Intel Corporation. +[ 1.488810] e1000e 0001:01:00.0: Interrupt Throttling Rate (ints/sec) set to dynamic conservative mode +[ 1.622241] e1000e 0001:01:00.0 eth7: registered PHC clock +[ 1.627724] e1000e 0001:01:00.0 eth7: (PCI Express:2.5GT/s:Width x1) 68:05:ca:35:fa:4a +[ 1.635630] e1000e 0001:01:00.0 eth7: Intel(R) PRO/1000 Network Connection +[ 1.642508] e1000e 0001:01:00.0 eth7: MAC: 3, PHY: 8, PBA No: E46981-008 +[ 2.850000] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver +[ 2.856526] ehci-pci: EHCI PCI platform driver +[ 2.860996] ehci-platform: EHCI generic platform driver +[ 2.866357] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver +[ 2.872530] ohci-pci: OHCI PCI platform driver +[ 2.877005] ohci-platform: OHCI generic platform driver +[ 2.882534] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller +[ 2.888023] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 1 +[ 2.895749] xhci-hcd xhci-hcd.0.auto: hcc params 0x0220f66d hci version 0x100 quirks 0x00010010 +[ 2.904464] xhci-hcd xhci-hcd.0.auto: irq 23, io mem 0x02f00000 +[ 2.910617] hub 1-0:1.0: USB hub found +[ 2.914367] hub 1-0:1.0: 1 port detected +[ 2.918365] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller +[ 2.923843] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 2 +[ 2.931513] usb usb2: We don't know the algorithms for LPM for this host, disabling LPM. +[ 2.939796] hub 2-0:1.0: USB hub found +[ 2.943543] hub 2-0:1.0: 1 port detected +[ 2.947545] xhci-hcd xhci-hcd.1.auto: xHCI Host Controller +[ 2.953026] xhci-hcd xhci-hcd.1.auto: new USB bus registered, assigned bus number 3 +[ 2.960744] xhci-hcd xhci-hcd.1.auto: hcc params 0x0220f66d hci version 0x100 quirks 0x00010010 +[ 2.969451] xhci-hcd xhci-hcd.1.auto: irq 24, io mem 0x03000000 +[ 2.975566] hub 3-0:1.0: USB hub found +[ 2.979320] hub 3-0:1.0: 1 port detected +[ 2.983307] xhci-hcd xhci-hcd.1.auto: xHCI Host Controller +[ 2.988790] xhci-hcd xhci-hcd.1.auto: new USB bus registered, assigned bus number 4 +[ 2.996458] usb usb4: We don't know the algorithms for LPM for this host, disabling LPM. +[ 3.004729] hub 4-0:1.0: USB hub found +[ 3.008481] hub 4-0:1.0: 1 port detected +[ 3.012480] xhci-hcd xhci-hcd.2.auto: xHCI Host Controller +[ 3.017991] xhci-hcd xhci-hcd.2.auto: new USB bus registered, assigned bus number 5 +[ 3.025707] xhci-hcd xhci-hcd.2.auto: hcc params 0x0220f66d hci version 0x100 quirks 0x00010010 +[ 3.034412] xhci-hcd xhci-hcd.2.auto: irq 25, io mem 0x03100000 +[ 3.040531] hub 5-0:1.0: USB hub found +[ 3.044279] hub 5-0:1.0: 1 port detected +[ 3.048281] xhci-hcd xhci-hcd.2.auto: xHCI Host Controller +[ 3.053760] xhci-hcd xhci-hcd.2.auto: new USB bus registered, assigned bus number 6 +[ 3.061430] usb usb6: We don't know the algorithms for LPM for this host, disabling LPM. +[ 3.069708] hub 6-0:1.0: USB hub found +[ 3.073455] hub 6-0:1.0: 1 port detected +[ 3.077582] usbcore: registered new interface driver usb-storage +[ 3.083766] i2c /dev entries driver +[ 3.087623] sdhci: Secure Digital Host Controller Interface driver +[ 3.093791] sdhci: Copyright(c) Pierre Ossman +[ 3.098176] sdhci-pltfm: SDHCI platform and OF driver helper +[ 3.104921] sdhci-esdhc 1560000.esdhc: No vmmc regulator found +[ 3.110750] sdhci-esdhc 1560000.esdhc: No vqmmc regulator found +[ 3.156192] mmc0: SDHCI controller on 1560000.esdhc [1560000.esdhc] using ADMA 64-bit +[ 3.164615] Freescale USDPAA process driver +[ 3.168795] fsl-usdpaa: no region found +[ 3.172622] Freescale USDPAA process IRQ driver +[ 3.177347] NET: Registered protocol family 10 +[ 3.182411] NET: Registered protocol family 17 +[ 3.186868] bridge: automatic filtering via arp/ip/ip6tables has been deprecated. Update your scripts to load br_netfilter if you need this. +[ 3.199490] 8021q: 802.1Q VLAN Support v1.8 +[ 3.203680] Key type dns_resolver registered +[ 3.208335] fsl_generic: FSL DPAA Generic Ethernet driver +[ 3.213827] hctosys: unable to open rtc device (rtc0) +[ 3.216453] mmc0: new SDHC card at address c1e7 +[ 3.216565] mmcblk0: mmc0:c1e7 SD04G 3.69 GiB +[ 3.222248] mmcblk0: p1 +[ 3.230787] fdt: not creating '/sys/firmware/fdt': CRC check failed +[ 3.238957] VFS: Mounted root (squashfs filesystem) readonly on device 31:6. +[ 3.246102] Freeing unused kernel memory: 276K (ffff800000896000 - ffff8000008db000) +[ 3.246198] usb 1-1: new high-speed USB device number 2 using xhci-hcd +[ 3.260367] Freeing alternatives memory: 32K (ffff8000008db000 - ffff8000008e3000) +[ 3.336224] usb 4-1: new SuperSpeed USB device number 2 using xhci-hcd +[ 3.366274] usb usb5-port1: over-current condition +[ 3.396207] usb usb6-port1: over-current condition +[ 3.472057] init: Console is alive +[ 3.475789] usb-storage 4-1:1.0: USB Mass Storage device detected +[ 3.482115] scsi host0: usb-storage 4-1:1.0 +[ 3.489002] usb 1-1: ep 0x81 - rounding interval to 128 microframes, ep desc says 255 microframes +[ 3.497883] usb 1-1: ep 0x2 - rounding interval to 128 microframes, ep desc says 255 microframes +[ 3.506239] init: - preinit - +[ 3.509783] usb-storage 1-1:1.0: USB Mass Storage device detected +[ 3.516309] scsi host1: usb-storage 1-1:1.0 +[ 3.520651] random: procd urandom read with 3 bits of entropy available +Press the [f] key and hit [enter] to enter failsafe mode +Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level +[ 4.516452] scsi 1:0:0:0: Direct-Access Kingston DT 101 G2 1.00 PQ: 0 ANSI: 2 +[ 4.525022] sd 1:0:0:0: [sda] 3913664 512-byte logical blocks: (2.00 GB/1.87 GiB) +[ 4.532654] sd 1:0:0:0: [sda] Write Protect is off +[ 4.537584] sd 1:0:0:0: [sda] No Caching mode page found +[ 4.542886] sd 1:0:0:0: [sda] Assuming drive cache: write through +[ 4.550171] scsi 0:0:0:0: Direct-Access Kingston DataTraveler 3.0 PMAP PQ: 0 ANSI: 6 +[ 4.550327] sda: sda1 +[ 4.558933] sd 1:0:0:0: [sda] Attached SCSI removable disk +[ 5.540189] mount_root: jffs2 not ready yet, using temporary tmpfs overlay +[ 5.549108] procd: - early - +[ 5.690793] sd 0:0:0:0: [sdb] 30728832 512-byte logical blocks: (15.7 GB/14.7 GiB) +[ 5.698536] sd 0:0:0:0: [sdb] Write Protect is off +[ 5.703407] sd 0:0:0:0: [sdb] No Caching mode page found +[ 5.708715] sd 0:0:0:0: [sdb] Assuming drive cache: write through +[ 5.739138] sdb: sdb1 +[ 5.742231] sd 0:0:0:0: [sdb] Attached SCSI removable disk +[ 6.242632] procd: - ubus - +[ 6.295216] procd: - init - +Please press Enter to activate this console. +[ 7.614535] jffs2_scan_eraseblock(): End of filesystem marker found at 0x0 +[ 7.621575] jffs2_build_filesystem(): unlocking the mtd device... done. +[ 7.628199] jffs2_build_filesystem(): erasing all blocks after the end marker... +[ 7.700603] device eth0 entered promiscuous mode +[ 7.706092] br-lan: port 1(eth0) entered forwarding state +[ 7.711515] br-lan: port 1(eth0) entered forwarding state +[ 9.697128] br-lan: port 1(eth0) entered disabled state + + + +BusyBox v1.24.2 () built-in shell (ash) + + _______ ________ __ + | |.-----.-----.-----.| | | |.----.| |_ + | - || _ | -__| || | | || _|| _| + |_______|| __|_____|__|__||________||__| |____| + |__| W I R E L E S S F R E E D O M + ----------------------------------------------------- + DESIGNATED DRIVER (Bleeding Edge, r49395) + ----------------------------------------------------- + * 2 oz. Orange Juice Combine all juices in a + * 2 oz. Pineapple Juice tall glass filled with + * 2 oz. Grapefruit Juice ice, stir well. + * 2 oz. Cranberry Juice + ----------------------------------------------------- +root at OpenWrt:/# +root at OpenWrt:/# ifconfig +br-lan Link encap:Ethernet HWaddr 00:E0:0C:00:73:00 + inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0 + inet6 addr: fd78:b98d:d12a::1/60 Scope:Global + inet6 addr: fe80::2e0:cff:fe00:7300/64 Scope:Link + UP BROADCAST MULTICAST MTU:1500 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 frame:0 + TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:0 (0.0 B) TX bytes:896 (896.0 B) + +eth0 Link encap:Ethernet HWaddr 00:E0:0C:00:73:00 + UP BROADCAST MULTICAST MTU:1500 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 frame:0 + TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:0 (0.0 B) TX bytes:792 (792.0 B) + Memory:1ae0000-1ae0fff + +eth1 Link encap:Ethernet HWaddr 00:E0:0C:00:73:01 + inet6 addr: fe80::2e0:cff:fe00:7301/64 Scope:Link + UP BROADCAST MULTICAST MTU:1500 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 frame:0 + TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:0 (0.0 B) TX bytes:1160 (1.1 KiB) + Memory:1ae2000-1ae2fff + +lo Link encap:Local Loopback + inet addr:127.0.0.1 Mask:255.0.0.0 + inet6 addr: ::1/128 Scope:Host + UP LOOPBACK RUNNING MTU:65536 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 frame:0 + TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) + +root at OpenWrt:/# cat /proc/mtd +dev: size erasesize name +mtd0: 00100000 00020000 "rcw" +mtd1: 00100000 00020000 "u-boot" +mtd2: 00100000 00020000 "u-boot-env" +mtd3: 00100000 00020000 "fman" +mtd4: 00100000 00020000 "dtb" +mtd5: 00500000 00020000 "kernel" +mtd6: 03600000 00020000 "rootfs" +mtd7: 03500000 00020000 "rootfs_data" +mtd8: 04000000 00020000 "otherbank" +mtd9: 03c00000 00020000 "firmware" +mtd10: 20000000 00020000 "7e800000.flash" +root at OpenWrt:/# +root at OpenWrt:/# mount +/dev/root on /rom type squashfs (ro,relatime) +proc on /proc type proc (rw,nosuid,nodev,noexec,noatime) +sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,noatime) +tmpfs on /tmp type tmpfs (rw,nosuid,nodev,noatime) +tmpfs on /tmp/root type tmpfs (rw,noatime,mode=755) +overlayfs:/tmp/root on / type overlay (rw,noatime,lowerdir=/,upperdir=/tmp/root/upper,workdir=/tmp/root/work) +tmpfs on /dev type tmpfs (rw,nosuid,relatime,size=512k,mode=755) +devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,mode=600) +debugfs on /sys/kernel/debug type debugfs (rw,noatime) +root at OpenWrt:/# +root at OpenWrt:/# cat /etc/config/network + +config interface 'loopback' + option ifname 'lo' + option proto 'static' + option ipaddr '127.0.0.1' + option netmask '255.0.0.0' + +config globals 'globals' + option ula_prefix 'fd78:b98d:d12a::/48' + +config interface 'lan' + option type 'bridge' + option ifname 'eth0' + option proto 'static' + option ipaddr '192.168.1.1' + option netmask '255.255.255.0' + option ip6assign '60' + +config interface 'wan' + option ifname 'eth1' + option proto 'dhcp' + +config interface 'wan6' + option ifname 'eth1' + option proto 'dhcpv6' + +root at OpenWrt:/# +root at OpenWrt:/# ls -l +drwxr-xr-x 2 root root 739 Jun 30 05:39 bin +drwxr-xr-x 5 root root 2300 Jun 30 05:39 dev +drwxr-xr-x 1 root root 120 Jun 30 05:39 etc +drwxrwxr-x 9 root root 372 Jun 30 05:39 lib +lrwxrwxrwx 1 root root 3 Jun 30 05:39 lib64 -> lib +drwxr-xr-x 2 root root 3 Jun 30 05:39 mnt +drwxr-xr-x 2 root root 3 Jun 30 05:39 overlay +dr-xr-xr-x 72 root root 0 Jan 1 1970 proc +drwxr-xr-x 16 root root 212 Jun 30 05:39 rom +drwxr-xr-x 2 root root 3 Jun 30 05:39 root +drwxr-xr-x 2 root root 653 Jun 30 05:39 sbin +dr-xr-xr-x 11 root root 0 Jan 1 1970 sys +drwxrwxrwt 12 root root 340 Jun 30 05:39 tmp +drwxr-xr-x 7 root root 90 Jun 30 05:39 usr +lrwxrwxrwx 1 root root 4 Jun 30 05:39 var -> /tmp +drwxr-xr-x 2 root root 3 Jun 30 05:39 www +root at OpenWrt:/# diff --git a/target/linux/layerscape-64b/base-files/etc/inittab b/target/linux/layerscape-64b/base-files/etc/inittab new file mode 100644 index 0000000..7adc69a --- /dev/null +++ b/target/linux/layerscape-64b/base-files/etc/inittab @@ -0,0 +1,6 @@ +::sysinit:/etc/init.d/rcS S boot +::shutdown:/etc/init.d/rcS K shutdown +ttyS0::askfirst:/bin/ash --login +tts/0::askfirst:/bin/ash --login +ttyAMA0::askfirst:/bin/ash --login +tty1::askfirst:/bin/ash --login diff --git a/target/linux/layerscape-64b/image/Makefile b/target/linux/layerscape-64b/image/Makefile new file mode 100644 index 0000000..43e7269 --- /dev/null +++ b/target/linux/layerscape-64b/image/Makefile @@ -0,0 +1,64 @@ +# +# Copyright (C) 2016 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/image.mk + +# make uImage and dtb +define Image/uImage-dtb + gzip -9c < $(KDIR)/Image > $(KDIR)/Image.gz + $(eval ARCH_BACK = $(ARCH)) + $(eval ARCH = $(LINUX_KARCH)) + $(call Image/BuildKernel/MkuImage, gzip, $(KERNEL_LOADADDR), \ + $(KERNEL_ENTRY_POINT), $(KDIR)/Image.gz, \ + $(KDIR)/$(IMG_PREFIX)-uImage) + $(eval ARCH = $(ARCH_BACK)) + + $(call Image/BuildDTB,$(DTS_DIR)/$(DEVICE_DTS).dts,$(KDIR)/$(IMG_PREFIX)-dtb) +endef + +# $(1) source image name +# $(2) partition image name +# $(3) partition image size(M) +define Image/Build/flashpartitionimage + ./checkimagesize.sh $(1) $(3) + dd if=/dev/zero bs=1M count=$(3) | sed 's/\x00/\xff/g' > $(2) + dd if=$(1) of=$(2) conv=notrunc +endef + +# make squashfs then merge uImage/dtb/squashfs to one firmware image arranged +# by individual partition +define Image/Build/squashfs + $(call prepare_generic_squashfs,$(KDIR)/root.squashfs) + + $(call Image/Build/flashpartitionimage,$(KDIR)/$(IMG_PREFIX)-dtb,$(KDIR)/$(IMG_PREFIX)-dtb-par,$(DTB_PARTITION_SIZE)) + $(call Image/Build/flashpartitionimage,$(KDIR)/$(IMG_PREFIX)-uImage,$(KDIR)/$(IMG_PREFIX)-uImage-par,$(KERNEL_PARTITION_SIZE)) + $(call Image/Build/flashpartitionimage,$(KDIR)/root.squashfs,$(KDIR)/root.squashfs-par,$(SQUASHFS_PARTITION_SIZE)) + cat $(KDIR)/$(IMG_PREFIX)-dtb-par $(KDIR)/$(IMG_PREFIX)-uImage-par \ + $(KDIR)/root.squashfs-par > $(BIN_DIR)/$(IMG_PREFIX)-firmware + $(RM) $(KDIR)/$(IMG_PREFIX)-dtb-par $(KDIR)/$(IMG_PREFIX)-uImage-par \ + $(KDIR)/root.squashfs-par +endef + +# target macros +define Target/Default + KERNEL_LOADADDR = 0x80080000 + KERNEL_ENTRY_POINT = 0x80080000 +endef + +# callback function: Image/BuildKernel +define Image/BuildKernel + $(eval $(call Target/Default)) + $(eval $(call Subtarget/Default)) + $(call Image/uImage-dtb) +endef + +# callback function: Image/Build +define Image/Build + $(call Image/Build/$(1),$(1)) +endef + +$(eval $(call BuildImage)) diff --git a/target/linux/layerscape-64b/image/checkimagesize.sh b/target/linux/layerscape-64b/image/checkimagesize.sh new file mode 100755 index 0000000..e65c7fe --- /dev/null +++ b/target/linux/layerscape-64b/image/checkimagesize.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# +# Licensed under the terms of the GNU GPL License version 2 or later. +# +# $(1) source image name +# $(2) partition image size(M) + +SOURCE_IMAGE_SIZE=`du -b $1 | awk '{print $1}'` +PARTITION_IMAGE_SIZE=`expr $2 \* 1024 \* 1024` + +if [ $SOURCE_IMAGE_SIZE -gt $PARTITION_IMAGE_SIZE ]; then + echo "error: $1 too large than limited $2(M)" + exit 1 +else + exit 0 +fi diff --git a/target/linux/layerscape-64b/ls1043ardb/config-default b/target/linux/layerscape-64b/ls1043ardb/config-default new file mode 100644 index 0000000..1543907 --- /dev/null +++ b/target/linux/layerscape-64b/ls1043ardb/config-default @@ -0,0 +1,3146 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm64 4.1.23 Kernel Configuration +# +CONFIG_ARM64=y +CONFIG_64BIT=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_MMU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_HAVE_GENERIC_RCU_GUP=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=4 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +# CONFIG_CROSS_MEMORY_ATTACH is not set +# CONFIG_FHANDLE is not set +# CONFIG_USELIB is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_ARCH_AUDITSYSCALL=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_HANDLE_DOMAIN_IRQ=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_SPARSE_IRQ=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_TASKSTATS is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +CONFIG_SRCU=y +# CONFIG_TASKS_RCU is not set +CONFIG_RCU_STALL_COMMON=y +# CONFIG_RCU_USER_QS is not set +CONFIG_RCU_FANOUT=32 +CONFIG_RCU_FANOUT_LEAF=16 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_RCU_FAST_NO_HZ is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_RCU_KTHREAD_PRIO=0 +# CONFIG_RCU_NOCB_CPU is not set +# CONFIG_RCU_EXPEDITE_BOOT is not set +CONFIG_BUILD_BIN2C=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +CONFIG_GENERIC_SCHED_CLOCK=y +# CONFIG_CGROUPS is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_CRASHLOG=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_KALLSYMS_UNCOMPRESSED=y +CONFIG_BPF=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_MULTIUSER=y +# CONFIG_SGETMASK_SYSCALL is not set +# CONFIG_SYSFS_SYSCALL is not set +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_BPF_SYSCALL=y +CONFIG_SHMEM=y +# CONFIG_AIO is not set +# CONFIG_ADVISE_SYSCALLS is not set +CONFIG_PCI_QUIRKS=y +CONFIG_EMBEDDED=y +# CONFIG_MANGLE_BOOTARGS is not set +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +# CONFIG_PERF_EVENTS is not set +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_SYSTEM_TRUSTED_KEYRING is not set +# CONFIG_PROFILING is not set +# CONFIG_JUMP_LABEL is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_RCU_TABLE_FREE=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR_NONE is not set +CONFIG_CC_STACKPROTECTOR_REGULAR=y +# CONFIG_CC_STACKPROTECTOR_STRONG is not set +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_COMPAT_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_COMPRESS is not set +CONFIG_MODULE_STRIPPED=y +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_CMDLINE_PARSER is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +# CONFIG_CMDLINE_PARTITION is not set +CONFIG_BLOCK_COMPAT=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +CONFIG_INLINE_READ_UNLOCK=y +CONFIG_INLINE_READ_UNLOCK_IRQ=y +CONFIG_INLINE_WRITE_UNLOCK=y +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_LOCK_SPIN_ON_OWNER=y +# CONFIG_FREEZER is not set + +# +# Platform selection +# +# CONFIG_ARCH_EXYNOS7 is not set +CONFIG_ARCH_LAYERSCAPE=y +# CONFIG_ARCH_MEDIATEK is not set +# CONFIG_ARCH_QCOM is not set +# CONFIG_ARCH_SEATTLE is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_SPRD is not set +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_XGENE is not set +# CONFIG_ARCH_ZYNQMP is not set + +# +# Bus support +# +CONFIG_HAS_FSL_QBMAN=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_SYSCALL=y +CONFIG_PCI_BUS_ADDR_T_64BIT=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_DISABLE_COMMON_QUIRKS is not set +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_PRI is not set +# CONFIG_PCI_PASID is not set +CONFIG_PCI_LABEL=y + +# +# PCI host controller drivers +# +CONFIG_PCIE_DW=y +CONFIG_PCI_LAYERSCAPE=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIEAER=y +# CONFIG_PCIE_ECRC is not set +# CONFIG_PCIEAER_INJECT is not set +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEBUG is not set +CONFIG_PCIEASPM_DEFAULT=y +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_PERFORMANCE is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# Kernel Features +# + +# +# ARM errata workarounds via the alternatives framework +# +CONFIG_ARM64_ERRATUM_826319=y +CONFIG_ARM64_ERRATUM_827319=y +CONFIG_ARM64_ERRATUM_824069=y +CONFIG_ARM64_ERRATUM_819472=y +CONFIG_ARM64_ERRATUM_832075=y +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_64K_PAGES is not set +# CONFIG_ARM64_VA_BITS_39 is not set +CONFIG_ARM64_VA_BITS_48=y +CONFIG_ARM64_VA_BITS=48 +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_SMP=y +# CONFIG_SCHED_MC is not set +# CONFIG_SCHED_SMT is not set +CONFIG_NR_CPUS=64 +CONFIG_HOTPLUG_CPU=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_NO_BOOTMEM=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_TRANSPARENT_HUGEPAGE is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_FRONTSWAP is not set +# CONFIG_CMA is not set +# CONFIG_ZPOOL is not set +# CONFIG_ZBUD is not set +# CONFIG_ZSMALLOC is not set +CONFIG_GENERIC_EARLY_IOREMAP=y +# CONFIG_SECCOMP is not set +# CONFIG_XEN is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +# CONFIG_ARMV8_DEPRECATED is not set + +# +# Boot options +# +CONFIG_CMDLINE="console=ttyAMA0" +# CONFIG_CMDLINE_FORCE is not set +CONFIG_EFI_STUB=y +CONFIG_EFI=y +CONFIG_DMI=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_COREDUMP=y +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y + +# +# Power management options +# +# CONFIG_SUSPEND is not set +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y + +# +# CPU Power Management +# + +# +# CPU Idle +# +# CONFIG_CPU_IDLE is not set +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set +CONFIG_NET=y +CONFIG_COMPAT_NETLINK_MESSAGES=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_NET_IP_TUNNEL is not set +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +# CONFIG_IP_PIMSM_V1 is not set +# CONFIG_IP_PIMSM_V2 is not set +CONFIG_SYN_COOKIES=y +# CONFIG_NET_IPVTI is not set +# CONFIG_NET_UDP_TUNNEL is not set +# CONFIG_NET_FOU is not set +# CONFIG_GENEVE is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +CONFIG_TCP_CONG_ADVANCED=y +# CONFIG_TCP_CONG_BIC is not set +CONFIG_TCP_CONG_CUBIC=y +# CONFIG_TCP_CONG_WESTWOOD is not set +# CONFIG_TCP_CONG_HTCP is not set +# CONFIG_TCP_CONG_HSTCP is not set +# CONFIG_TCP_CONG_HYBLA is not set +# CONFIG_TCP_CONG_VEGAS is not set +# CONFIG_TCP_CONG_SCALABLE is not set +# CONFIG_TCP_CONG_LP is not set +# CONFIG_TCP_CONG_VENO is not set +# CONFIG_TCP_CONG_YEAH is not set +# CONFIG_TCP_CONG_ILLINOIS is not set +# CONFIG_TCP_CONG_DCTCP is not set +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_BEET is not set +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_SIT is not set +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_GRE is not set +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +# CONFIG_IPV6_MROUTE_MULTIPLE_TABLES is not set +# CONFIG_IPV6_PIMSM_V2 is not set +CONFIG_SOCK_DIAG=y +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NET_PTP_CLASSIFY=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +# CONFIG_BRIDGE_NETFILTER is not set + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NETFILTER_NETLINK_ACCT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +CONFIG_NF_CONNTRACK=m +CONFIG_NF_LOG_COMMON=m +# CONFIG_NF_CONNTRACK_MARK is not set +# CONFIG_NF_CONNTRACK_ZONES is not set +CONFIG_NF_CONNTRACK_PROCFS=y +# CONFIG_NF_CONNTRACK_EVENTS is not set +CONFIG_NF_CONNTRACK_RTCACHE=m +# CONFIG_NF_CONNTRACK_TIMEOUT is not set +# CONFIG_NF_CONNTRACK_TIMESTAMP is not set +# CONFIG_NF_CT_PROTO_DCCP is not set +# CONFIG_NF_CT_PROTO_SCTP is not set +# CONFIG_NF_CT_PROTO_UDPLITE is not set +# CONFIG_NF_CONNTRACK_AMANDA is not set +# CONFIG_NF_CONNTRACK_FTP is not set +# CONFIG_NF_CONNTRACK_H323 is not set +# CONFIG_NF_CONNTRACK_IRC is not set +# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set +# CONFIG_NF_CONNTRACK_SNMP is not set +# CONFIG_NF_CONNTRACK_PPTP is not set +# CONFIG_NF_CONNTRACK_SANE is not set +# CONFIG_NF_CONNTRACK_SIP is not set +# CONFIG_NF_CONNTRACK_TFTP is not set +# CONFIG_NF_CT_NETLINK is not set +# CONFIG_NF_CT_NETLINK_TIMEOUT is not set +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +# CONFIG_NF_NAT_AMANDA is not set +# CONFIG_NF_NAT_FTP is not set +# CONFIG_NF_NAT_IRC is not set +# CONFIG_NF_NAT_SIP is not set +# CONFIG_NF_NAT_TFTP is not set +CONFIG_NF_NAT_REDIRECT=m +# CONFIG_NF_TABLES is not set +CONFIG_NETFILTER_XTABLES=m + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m +# CONFIG_NETFILTER_XT_CONNMARK is not set + +# +# Xtables targets +# +# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set +# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set +# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set +CONFIG_NETFILTER_XT_TARGET_CT=m +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +# CONFIG_NETFILTER_XT_TARGET_HL is not set +# CONFIG_NETFILTER_XT_TARGET_HMARK is not set +# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set +# CONFIG_NETFILTER_XT_TARGET_LED is not set +CONFIG_NETFILTER_XT_TARGET_LOG=m +# CONFIG_NETFILTER_XT_TARGET_MARK is not set +CONFIG_NETFILTER_XT_NAT=m +# CONFIG_NETFILTER_XT_TARGET_NETMAP is not set +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +# CONFIG_NETFILTER_XT_TARGET_TEE is not set +# CONFIG_NETFILTER_XT_TARGET_TPROXY is not set +# CONFIG_NETFILTER_XT_TARGET_TRACE is not set +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set + +# +# Xtables matches +# +# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_BPF is not set +# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +# CONFIG_NETFILTER_XT_MATCH_CPU is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set +# CONFIG_NETFILTER_XT_MATCH_ECN is not set +# CONFIG_NETFILTER_XT_MATCH_ESP is not set +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_HELPER is not set +# CONFIG_NETFILTER_XT_MATCH_HL is not set +# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set +CONFIG_NETFILTER_XT_MATCH_ID=m +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +# CONFIG_NETFILTER_XT_MATCH_MARK is not set +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +# CONFIG_NETFILTER_XT_MATCH_POLICY is not set +# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set +CONFIG_NETFILTER_XT_MATCH_STATE=m +# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set +# CONFIG_NETFILTER_XT_MATCH_STRING is not set +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +CONFIG_NETFILTER_XT_MATCH_TIME=m +# CONFIG_NETFILTER_XT_MATCH_U32 is not set +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_CONNTRACK_IPV4=m +# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set +# CONFIG_NF_LOG_ARP is not set +CONFIG_NF_LOG_IPV4=m +CONFIG_NF_REJECT_IPV4=m +CONFIG_NF_NAT_IPV4=m +CONFIG_NF_NAT_MASQUERADE_IPV4=m +# CONFIG_NF_NAT_PPTP is not set +# CONFIG_NF_NAT_H323 is not set +CONFIG_IP_NF_IPTABLES=m +# CONFIG_IP_NF_MATCH_AH is not set +# CONFIG_IP_NF_MATCH_ECN is not set +# CONFIG_IP_NF_MATCH_RPFILTER is not set +# CONFIG_IP_NF_MATCH_TTL is not set +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +# CONFIG_IP_NF_TARGET_SYNPROXY is not set +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +# CONFIG_IP_NF_TARGET_NETMAP is not set +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_MANGLE=m +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_TTL is not set +CONFIG_IP_NF_RAW=m +# CONFIG_IP_NF_ARPTABLES is not set + +# +# IPv6: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV6 is not set +# CONFIG_NF_CONNTRACK_IPV6 is not set +# CONFIG_NF_REJECT_IPV6 is not set +CONFIG_NF_LOG_IPV6=m +# CONFIG_IP6_NF_IPTABLES is not set +# CONFIG_BRIDGE_NF_EBTABLES is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +CONFIG_STP=y +CONFIG_BRIDGE=y +CONFIG_BRIDGE_IGMP_SNOOPING=y +# CONFIG_BRIDGE_VLAN_FILTERING is not set +CONFIG_HAVE_NET_DSA=y +CONFIG_VLAN_8021Q=y +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_VLAN_8021Q_MVRP is not set +# CONFIG_DECNET is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +# CONFIG_6LOWPAN is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +# CONFIG_NET_SCH_CBQ is not set +# CONFIG_NET_SCH_HTB is not set +# CONFIG_NET_SCH_HFSC is not set +# CONFIG_NET_SCH_PRIO is not set +# CONFIG_NET_SCH_MULTIQ is not set +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFB is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_ESFQ is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_QFQ is not set +# CONFIG_NET_SCH_CODEL is not set +CONFIG_NET_SCH_FQ_CODEL=y +# CONFIG_NET_SCH_FQ is not set +# CONFIG_NET_SCH_HHF is not set +# CONFIG_NET_SCH_PIE is not set +# CONFIG_NET_SCH_PLUG is not set + +# +# Classification +# +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_TCINDEX is not set +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_FW is not set +# CONFIG_NET_CLS_U32 is not set +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_CLS_BPF is not set +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_MPLS is not set +# CONFIG_HSR is not set +# CONFIG_NET_SWITCHDEV is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_BPF_JIT is not set +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set +# CONFIG_LIB80211_CRYPT_WEP is not set +# CONFIG_LIB80211_CRYPT_CCMP is not set +# CONFIG_LIB80211_CRYPT_TKIP is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +CONFIG_HAVE_BPF_JIT=y + +# +# Device Drivers +# +CONFIG_ARM_AMBA=y +# CONFIG_TEGRA_AHB is not set + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +CONFIG_ALLOW_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_REGMAP=y +# CONFIG_REGMAP_I2C is not set +# CONFIG_REGMAP_SPI is not set +CONFIG_REGMAP_MMIO=y +# CONFIG_DMA_SHARED_BUFFER is not set + +# +# Bus devices +# +CONFIG_VEXPRESS_CONFIG=y +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y + +# +# OpenWrt specific MTD options +# +CONFIG_MTD_ROOTFS_ROOT_DEV=y +# CONFIG_MTD_SPLIT_FIRMWARE is not set +CONFIG_MTD_SPLIT=y +CONFIG_MTD_SPLIT_SUPPORT=y + +# +# Rootfs partition parsers +# +CONFIG_MTD_SPLIT_SQUASHFS_ROOT=y + +# +# Firmware partition parsers +# +# CONFIG_MTD_SPLIT_SEAMA_FW is not set +# CONFIG_MTD_SPLIT_UIMAGE_FW is not set +# CONFIG_MTD_SPLIT_FIT_FW is not set +# CONFIG_MTD_SPLIT_LZMA_FW is not set +# CONFIG_MTD_SPLIT_TPLINK_FW is not set +# CONFIG_MTD_SPLIT_TRX_FW is not set +# CONFIG_MTD_SPLIT_BRNIMAGE_FW is not set +# CONFIG_MTD_SPLIT_EVA_FW is not set +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +CONFIG_FTL=y +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set +# CONFIG_MTD_PARTITIONED_MASTER is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +# CONFIG_MTD_CFI_NOSWAP is not set +CONFIG_MTD_CFI_BE_BYTE_SWAP=y +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_GPIO_ADDR is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_LATCH_ADDR is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_DENALI is not set +# CONFIG_MTD_NAND_GPIO is not set +# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_RICOH is not set +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_DOCG4 is not set +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +CONFIG_MTD_NAND_FSL_IFC=y +# CONFIG_MTD_NAND_HISI504 is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR & LPDDR2 PCM memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_SPI_NOR is not set +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +# CONFIG_OF_UNITTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_IRQ=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_OF_MTD=y +CONFIG_OF_RESERVED_MEM=y +# CONFIG_OF_OVERLAY is not set +# CONFIG_PARPORT is not set +CONFIG_PNP=y +CONFIG_PNP_DEBUG_MESSAGES=y + +# +# Protocols +# +CONFIG_PNPACPI=y +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_NVME is not set +# CONFIG_BLK_DEV_SKD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=262144 +# CONFIG_BLK_DEV_PMEM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_VIRTIO_BLK=y +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_BLK_DEV_RSXX is not set + +# +# Misc devices +# +# CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_FSL_USDPAA=y +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_SRAM is not set +CONFIG_VEXPRESS_SYSCFG=y +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_CB710_CORE is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# Intel MIC Bus Driver +# + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# +# CONFIG_GENWQE is not set +# CONFIG_ECHO is not set +# CONFIG_CXL_BASE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +# CONFIG_SCSI_PROC_FS is not set + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_HAVE_PATA_PLATFORM=y +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_ATA_ACPI=y +CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# +CONFIG_SATA_AHCI=y +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_AHCI_XGENE=y +# CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_ACARD_AHCI is not set +# CONFIG_SATA_SIL24 is not set +CONFIG_ATA_SFF=y + +# +# SFF controllers with custom DMA interface +# +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_SX4 is not set +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# +# CONFIG_ATA_PIIX is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_SVW is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set + +# +# PATA SFF controllers with BMDMA +# +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_ATP867X is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RDC is not set +# CONFIG_PATA_SCH is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_TOSHIBA is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set + +# +# PIO-only SFF controllers +# +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_OPTI is not set +CONFIG_PATA_PLATFORM=y +CONFIG_PATA_OF_PLATFORM=y +# CONFIG_PATA_RZ1000 is not set + +# +# Generic fallback / legacy drivers +# +# CONFIG_PATA_ACPI is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_LEGACY is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +CONFIG_NETDEVICES=y +CONFIG_MII=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_NET_FC is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_IPVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +CONFIG_TUN=y +# CONFIG_VETH is not set +CONFIG_VIRTIO_NET=y +# CONFIG_NLMON is not set +# CONFIG_ARCNET is not set + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_3COM=y +# CONFIG_VORTEX is not set +# CONFIG_TYPHOON is not set +CONFIG_NET_VENDOR_ADAPTEC=y +# CONFIG_ADAPTEC_STARFIRE is not set +CONFIG_NET_VENDOR_AGERE=y +# CONFIG_ET131X is not set +CONFIG_NET_VENDOR_ALTEON=y +# CONFIG_ACENIC is not set +# CONFIG_ALTERA_TSE is not set +CONFIG_NET_VENDOR_AMD=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_PCNET32 is not set +# CONFIG_AMD_XGBE is not set +CONFIG_NET_VENDOR_ARC=y +# CONFIG_ARC_EMAC is not set +CONFIG_NET_VENDOR_ATHEROS=y +# CONFIG_ATL2 is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_ALX is not set +CONFIG_NET_CADENCE=y +# CONFIG_MACB is not set +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_BCMGENET is not set +# CONFIG_BNX2 is not set +# CONFIG_CNIC is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2X is not set +# CONFIG_SYSTEMPORT is not set +CONFIG_NET_VENDOR_BROCADE=y +# CONFIG_BNA is not set +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHELSIO_T4 is not set +# CONFIG_CHELSIO_T4VF is not set +CONFIG_NET_VENDOR_CISCO=y +# CONFIG_ENIC is not set +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_DEC=y +# CONFIG_NET_TULIP is not set +CONFIG_NET_VENDOR_DLINK=y +# CONFIG_DL2K is not set +# CONFIG_SUNDANCE is not set +CONFIG_NET_VENDOR_EMULEX=y +# CONFIG_BE2NET is not set +CONFIG_NET_VENDOR_EXAR=y +# CONFIG_S2IO is not set +# CONFIG_VXGE is not set +CONFIG_NET_VENDOR_FREESCALE=y +# CONFIG_FSL_PQ_MDIO is not set +CONFIG_FSL_XGMAC_MDIO=y +# CONFIG_GIANFAR is not set + +# +# Frame Manager support +# +CONFIG_FSL_SDK_FMAN=y +# CONFIG_FSL_SDK_FMAN_TEST is not set + +# +# FMAN Processor support +# +CONFIG_FMAN_ARM=y +# CONFIG_FMAN_P3040_P4080_P5020 is not set +# CONFIG_FMAN_P1023 is not set +# CONFIG_FMAN_V3H is not set +# CONFIG_FMAN_V3L is not set +# CONFIG_FMAN_MIB_CNT_OVF_IRQ_EN is not set +CONFIG_FSL_FM_MAX_FRAME_SIZE=1522 +CONFIG_FSL_FM_RX_EXTRA_HEADROOM=64 +# CONFIG_FMAN_PFC is not set +CONFIG_FSL_SDK_DPAA_ETH=y +# CONFIG_FSL_DPAA_HOOKS is not set +# CONFIG_FSL_DPAA_MACSEC is not set +CONFIG_FSL_DPAA_OFFLINE_PORTS=y +CONFIG_FSL_DPAA_ADVANCED_DRIVERS=y +CONFIG_FSL_DPAA_GENERIC_DRIVER=y +# CONFIG_FSL_DPAA_TS is not set +# CONFIG_FSL_DPAA_1588 is not set +CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE=y +CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT=128 +CONFIG_FSL_DPAA_ETH_REFILL_THRESHOLD=80 +CONFIG_FSL_DPAA_CS_THRESHOLD_1G=0x06000000 +CONFIG_FSL_DPAA_CS_THRESHOLD_10G=0x10000000 +CONFIG_FSL_DPAA_INGRESS_CS_THRESHOLD=0x10000000 +CONFIG_FSL_DPAA_ETH_DEBUGFS=y +# CONFIG_FSL_DPAA_ETH_DEBUG is not set +# CONFIG_FSL_DPAA_DBG_LOOP is not set +CONFIG_NET_VENDOR_HP=y +# CONFIG_HP100 is not set +CONFIG_NET_VENDOR_INTEL=y +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +CONFIG_E1000E=y +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +# CONFIG_IXGBEVF is not set +# CONFIG_I40E is not set +# CONFIG_I40EVF is not set +# CONFIG_FM10K is not set +CONFIG_NET_VENDOR_I825XX=y +# CONFIG_IP1000 is not set +# CONFIG_JME is not set +CONFIG_NET_VENDOR_MARVELL=y +# CONFIG_MVMDIO is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +CONFIG_NET_VENDOR_MELLANOX=y +# CONFIG_MLX4_EN is not set +# CONFIG_MLX4_CORE is not set +# CONFIG_MLX5_CORE is not set +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_KSZ884X_PCI is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +CONFIG_NET_VENDOR_MYRI=y +# CONFIG_MYRI10GE is not set +# CONFIG_FEALNX is not set +CONFIG_NET_VENDOR_NATSEMI=y +# CONFIG_NATSEMI is not set +# CONFIG_NS83820 is not set +CONFIG_NET_VENDOR_8390=y +# CONFIG_NE2K_PCI is not set +CONFIG_NET_VENDOR_NVIDIA=y +# CONFIG_FORCEDETH is not set +CONFIG_NET_VENDOR_OKI=y +# CONFIG_ETHOC is not set +# CONFIG_NET_PACKET_ENGINE is not set +CONFIG_NET_VENDOR_QLOGIC=y +# CONFIG_QLA3XXX is not set +# CONFIG_QLCNIC is not set +# CONFIG_QLGE is not set +# CONFIG_NETXEN_NIC is not set +CONFIG_NET_VENDOR_QUALCOMM=y +# CONFIG_QCA7000 is not set +CONFIG_NET_VENDOR_REALTEK=y +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_R8169 is not set +CONFIG_NET_VENDOR_RDC=y +# CONFIG_R6040 is not set +CONFIG_NET_VENDOR_ROCKER=y +CONFIG_NET_VENDOR_SAMSUNG=y +# CONFIG_SXGBE_ETH is not set +CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SILAN=y +# CONFIG_SC92031 is not set +CONFIG_NET_VENDOR_SIS=y +# CONFIG_SIS900 is not set +# CONFIG_SIS190 is not set +# CONFIG_SFC is not set +CONFIG_NET_VENDOR_SMSC=y +CONFIG_SMC91X=y +# CONFIG_EPIC100 is not set +# CONFIG_SMSC911X is not set +# CONFIG_SMSC9420 is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_SUN=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NIU is not set +CONFIG_NET_VENDOR_TEHUTI=y +# CONFIG_TEHUTI is not set +CONFIG_NET_VENDOR_TI=y +# CONFIG_TI_CPSW_ALE is not set +# CONFIG_TLAN is not set +CONFIG_NET_VENDOR_VIA=y +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_NET_SB1000 is not set +CONFIG_PHYLIB=y +CONFIG_MDIO_BOARDINFO=y +# CONFIG_SWCONFIG is not set + +# +# MII PHY device drivers +# +CONFIG_AQUANTIA_PHY=y +# CONFIG_AT803X_PHY is not set +# CONFIG_AMD_PHY is not set +# CONFIG_AMD_XGBE_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +CONFIG_VITESSE_PHY=y +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +CONFIG_REALTEK_PHY=y +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_ADM6996_PHY is not set +# CONFIG_MVSWITCH_PHY is not set +# CONFIG_MVSW61XX_PHY is not set +# CONFIG_IP17XX_PHY is not set +# CONFIG_AR8216_PHY is not set +# CONFIG_RTL8306_PHY is not set +CONFIG_FIXED_PHY=y +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_RTL8366_SMI is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PSB6970_PHY is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_USB_NET_DRIVERS=y +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_RTL8152 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set +CONFIG_WLAN=y +# CONFIG_PRISM54 is not set +# CONFIG_HOSTAP is not set +CONFIG_WL_TI=y + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_VMXNET3 is not set +CONFIG_ISDN=y +# CONFIG_ISDN_I4L is not set +# CONFIG_ISDN_CAPI is not set +# CONFIG_ISDN_DRV_GIGASET is not set +# CONFIG_HYSDN is not set +# CONFIG_MISDN is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +# CONFIG_VT is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_SYSRQ is not set +CONFIG_SERIAL_8250_DMA=y +# CONFIG_SERIAL_8250_PCI is not set +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_DW is not set +# CONFIG_SERIAL_8250_FINTEK is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_RP2 is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set +# CONFIG_TTY_PRINTK is not set +# CONFIG_VIRTIO_CONSOLE is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# PCMCIA character devices +# +# CONFIG_RAW_DRIVER is not set +# CONFIG_HPET is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +# CONFIG_XILLYBUS is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_ACPI_I2C_OPREGION=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +CONFIG_I2C_MUX_PCA954x=y +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# ACPI drivers +# +# CONFIG_I2C_SCMI is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_DESIGNWARE_PCI is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_RK3X is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_SLAVE is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_GPIO_OLD is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +CONFIG_SPI_PL022=y +# CONFIG_SPI_PXA2XX is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_ROCKCHIP is not set +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPMI is not set +# CONFIG_HSI is not set + +# +# PPS support +# +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_GPIO is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=y + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_OF_GPIO=y +CONFIG_GPIO_ACPI=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_GENERIC=y + +# +# Memory mapped GPIO drivers +# +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ALTERA is not set +# CONFIG_GPIO_DWAPB is not set +CONFIG_GPIO_GENERIC_PLATFORM=y +# CONFIG_GPIO_GRGPIO is not set +CONFIG_GPIO_MPC8XXX=y +CONFIG_GPIO_PL061=y +# CONFIG_GPIO_SCH311X is not set +# CONFIG_GPIO_SYSCON is not set +# CONFIG_GPIO_VX855 is not set +CONFIG_GPIO_XGENE=y + +# +# I2C GPIO expanders +# +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set + +# +# MFD GPIO expanders +# + +# +# PCI GPIO expanders +# +# CONFIG_GPIO_AMD8111 is not set +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_ML_IOH is not set +# CONFIG_GPIO_RDC321X is not set + +# +# SPI GPIO expanders +# +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set + +# +# USB GPIO expanders +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +CONFIG_POWER_RESET=y +# CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +# CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_RESTART is not set +CONFIG_POWER_RESET_VEXPRESS=y +# CONFIG_POWER_RESET_XGENE is not set +# CONFIG_POWER_RESET_SYSCON is not set +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set +CONFIG_POWER_RESET_LAYERSCAPE=y +# CONFIG_POWER_AVS is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_CORE is not set +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_GPIO_WATCHDOG is not set +# CONFIG_XILINX_WATCHDOG is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_CADENCE_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_I6300ESB_WDT is not set +# CONFIG_GPIO_WDT is not set +# CONFIG_MEN_A21_WDT is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_ATMEL_HLCDC is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_AXP20X is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9063 is not set +# CONFIG_MFD_DA9150 is not set +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_INTEL_SOC_PMIC is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_RTSX_PCI is not set +# CONFIG_MFD_RT5033 is not set +# CONFIG_MFD_RTSX_USB is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK808 is not set +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +CONFIG_MFD_VEXPRESS_SYSREG=y +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGA_ARB is not set + +# +# Direct Rendering Manager +# +# CONFIG_DRM is not set + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +CONFIG_FB_ARMCLCD=y +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_I740 is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_CARMINE is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_FB_SSD1307 is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_VGASTATE is not set +CONFIG_VIDEOMODE_HELPERS=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_SOUND is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_OTG_FSM is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PCI=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_FSL is not set +CONFIG_USB_EHCI_HCD_PLATFORM=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FUSBH200_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_MAX3421_HCD is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PCI=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HCD_TEST_MODE is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set +# CONFIG_USB_MUSB_HDRC is not set +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_HOST=y + +# +# Platform Glue Driver Support +# +CONFIG_USB_DWC3_PCI=y + +# +# Debugging features +# +# CONFIG_USB_DWC3_DEBUG is not set +# CONFIG_USB_DWC2 is not set +# CONFIG_USB_CHIPIDEA is not set +CONFIG_USB_ISP1760=y +CONFIG_USB_ISP1760_HCD=y +CONFIG_USB_ISP1760_HOST_ROLE=y + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_LINK_LAYER_TEST is not set + +# +# USB Physical Layer drivers +# +# CONFIG_USB_PHY is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y +# CONFIG_USB_GADGET is not set +# CONFIG_USB_LED_TRIG is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_ARMMMCI=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +# CONFIG_MMC_SDHCI_PCI is not set +# CONFIG_MMC_SDHCI_ACPI is not set +CONFIG_MMC_SDHCI_PLTFM=y +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +CONFIG_MMC_SDHCI_OF_ESDHC=y +# CONFIG_MMC_SDHCI_F_SDH30 is not set +# CONFIG_MMC_TIFM_SD is not set +CONFIG_MMC_SPI=y +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_VIA_SDMMC is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_USDHI6ROL0 is not set +# CONFIG_MMC_TOSHIBA_PCI is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLASS_FLASH is not set + +# +# LED drivers +# +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_LP8860 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_INTEL_SS4200 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_LM355x is not set + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_SYSCON is not set +# CONFIG_LEDS_PM8941_WLED is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +# CONFIG_LEDS_TRIGGER_ONESHOT is not set +# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_CPU is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +# CONFIG_LEDS_TRIGGER_MORSE is not set +CONFIG_LEDS_TRIGGER_NETDEV=y +# CONFIG_LEDS_TRIGGER_USBDEV is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABX80X is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12057 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set +# CONFIG_RTC_DRV_PT7C4338 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_MCP795 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1685_FAMILY is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +CONFIG_RTC_DRV_EFI=y +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_RTC7301 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_RTC_DRV_SNVS is not set +CONFIG_RTC_DRV_XGENE=y + +# +# HID Sensor RTC drivers +# +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +# CONFIG_AMBA_PL08X is not set +# CONFIG_DW_DMAC is not set +# CONFIG_DW_DMAC_PCI is not set +# CONFIG_HSU_DMA_PCI is not set +# CONFIG_PL330_DMA is not set +# CONFIG_FSL_EDMA is not set +CONFIG_DMA_ENGINE=y +CONFIG_DMA_ACPI=y +CONFIG_DMA_OF=y + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_VFIO is not set +# CONFIG_VIRT_DRIVERS is not set +CONFIG_VIRTIO=y + +# +# Virtio drivers +# +# CONFIG_VIRTIO_PCI is not set +# CONFIG_VIRTIO_BALLOON is not set +CONFIG_VIRTIO_MMIO=y +# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_COMEDI is not set +# CONFIG_RTL8192U is not set +# CONFIG_RTLLIB is not set +# CONFIG_R8712U is not set +# CONFIG_R8188EU is not set +# CONFIG_RTS5208 is not set +# CONFIG_FB_SM7XX is not set +# CONFIG_FB_SM750 is not set +# CONFIG_FB_XGI is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +# CONFIG_USB_WPAN_HCD is not set +# CONFIG_WIMAX_GDM72XX is not set +# CONFIG_LTE_GDM724X is not set +# CONFIG_MTD_SPINAND_MT29F is not set +# CONFIG_LUSTRE_FS is not set +# CONFIG_DGNC is not set +# CONFIG_DGAP is not set +# CONFIG_GS_FPGABOOT is not set +# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set +# CONFIG_FB_TFT is not set +# CONFIG_I2O is not set +CONFIG_FSL_MC_BUS=y +CONFIG_FSL_DPA=y + +# +# Freescale Datapath QMan/BMan options +# +# CONFIG_FSL_DPA_CHECKING is not set +CONFIG_FSL_DPA_CAN_WAIT=y +CONFIG_FSL_DPA_CAN_WAIT_SYNC=y +CONFIG_FSL_DPA_PIRQ_FAST=y +CONFIG_FSL_DPA_PIRQ_SLOW=y +CONFIG_FSL_DPA_PORTAL_SHARE=y +CONFIG_FSL_BMAN=y +CONFIG_FSL_BMAN_CONFIG=y +# CONFIG_FSL_BMAN_TEST is not set +CONFIG_FSL_BMAN_DEBUGFS=y +CONFIG_FSL_QMAN=y +CONFIG_FSL_QMAN_POLL_LIMIT=32 +CONFIG_FSL_QMAN_CONFIG=y +# CONFIG_FSL_QMAN_TEST is not set +CONFIG_FSL_QMAN_DEBUGFS=y +CONFIG_FSL_QMAN_FQD_SZ=10 +CONFIG_FSL_QMAN_PFDR_SZ=13 +CONFIG_FSL_QMAN_CI_SCHED_CFG_SRCCIV=4 +CONFIG_FSL_QMAN_CI_SCHED_CFG_SRQ_W=3 +CONFIG_FSL_QMAN_CI_SCHED_CFG_RW_W=2 +CONFIG_FSL_QMAN_CI_SCHED_CFG_BMAN_W=2 +CONFIG_FSL_QMAN_PIRQ_DQRR_ITHRESH=12 +CONFIG_FSL_QMAN_PIRQ_MR_ITHRESH=4 +CONFIG_FSL_QMAN_PIRQ_IPERIOD=100 +CONFIG_FSL_QMAN_FQ_LOOKUP=y +CONFIG_QMAN_CEETM_UPDATE_PERIOD=1000 +CONFIG_FSL_QMAN_INIT_TIMEOUT=10 +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Common Clock Framework +# +CONFIG_COMMON_CLK_VERSATILE=y +CONFIG_CLK_SP810=y +CONFIG_CLK_VEXPRESS_OSC=y +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI570 is not set +CONFIG_CLK_QORIQ=y +CONFIG_COMMON_CLK_XGENE=y +# CONFIG_COMMON_CLK_PXA is not set +# CONFIG_COMMON_CLK_CDCE706 is not set + +# +# Hardware Spinlock drivers +# + +# +# Clock Source drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_MMIO=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ATMEL_PIT is not set +# CONFIG_SH_TIMER_CMT is not set +# CONFIG_SH_TIMER_MTU2 is not set +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_EM_TIMER_STI is not set +# CONFIG_MAILBOX is not set +CONFIG_IOMMU_API=y +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +CONFIG_IOMMU_IO_PGTABLE=y +CONFIG_IOMMU_IO_PGTABLE_LPAE=y +# CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST is not set +CONFIG_OF_IOMMU=y +CONFIG_ARM_SMMU=y + +# +# Remoteproc drivers +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers +# + +# +# SOC (System On Chip) specific Drivers +# +# CONFIG_SOC_TI is not set +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +CONFIG_MEMORY=y +CONFIG_FSL_IFC=y +# CONFIG_IIO is not set +# CONFIG_VME_BUS is not set +# CONFIG_PWM is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_LS1_MSI=y +# CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# CONFIG_BCM_KONA_USB2_PHY is not set +CONFIG_PHY_XGENE=y +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set +CONFIG_RAS=y +# CONFIG_THUNDERBOLT is not set + +# +# Android +# +# CONFIG_ANDROID is not set + +# +# Firmware Drivers +# +# CONFIG_FIRMWARE_MEMMAP is not set +CONFIG_DMIID=y +# CONFIG_DMI_SYSFS is not set + +# +# EFI (Extensible Firmware Interface) Support +# +# CONFIG_EFI_VARS is not set +CONFIG_EFI_PARAMS_FROM_FDT=y +CONFIG_EFI_RUNTIME_WRAPPERS=y +CONFIG_EFI_ARMSTUB=y +CONFIG_ACPI=y +CONFIG_ACPI_GENERIC_GSI=y +# CONFIG_ACPI_PROCFS_POWER is not set +# CONFIG_ACPI_EC_DEBUGFS is not set +# CONFIG_ACPI_DOCK is not set +# CONFIG_ACPI_CUSTOM_DSDT is not set +# CONFIG_ACPI_DEBUG is not set +# CONFIG_ACPI_PCI_SLOT is not set +# CONFIG_ACPI_CONTAINER is not set +# CONFIG_ACPI_HED is not set +# CONFIG_ACPI_CUSTOM_METHOD is not set +CONFIG_ACPI_REDUCED_HARDWARE_ONLY=y +# CONFIG_PMIC_OPREGION is not set + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_DEFAULTS_TO_ORDERED=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_EXT4_FS=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_ENCRYPTION is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_F2FS_FS is not set +# CONFIG_YAFFS_FS is not set +# CONFIG_FS_DAX is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +# CONFIG_DIRECT_IO is not set +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +CONFIG_QUOTA=y +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +CONFIG_PRINT_QUOTA_WARNING=y +# CONFIG_QUOTA_DEBUG is not set +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set +CONFIG_QUOTACTL=y +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=y +CONFIG_CUSE=y +CONFIG_OVERLAY_FS=y + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +# CONFIG_PROC_PAGE_MONITOR is not set +CONFIG_PROC_STRIPPED=y +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +CONFIG_TMPFS_XATTR=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +# CONFIG_CONFIGFS_FS is not set +CONFIG_EFIVAR_FS=m +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +# CONFIG_JFFS2_LZMA is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_FILE_CACHE=y +# CONFIG_SQUASHFS_FILE_DIRECT is not set +CONFIG_SQUASHFS_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_DECOMP_MULTI is not set +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +# CONFIG_SQUASHFS_XATTR is not set +CONFIG_SQUASHFS_ZLIB=y +# CONFIG_SQUASHFS_LZ4 is not set +# CONFIG_SQUASHFS_LZO is not set +# CONFIG_SQUASHFS_XZ is not set +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V2=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_SWAP is not set +# CONFIG_NFS_V4_1 is not set +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +# CONFIG_NFSD is not set +CONFIG_GRACE_PERIOD=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +# CONFIG_SUNRPC_DEBUG is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +# CONFIG_NLS_UTF8 is not set +CONFIG_KVM_COMPAT=y +# CONFIG_VIRTUALIZATION is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_DYNAMIC_DEBUG is not set + +# +# Compile-time checks and compiler options +# +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_INFO_REDUCED=y +# CONFIG_DEBUG_INFO_SPLIT is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +# CONFIG_GDB_SCRIPTS is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +CONFIG_STRIP_ASM_SYMS=y +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_TIMER_STATS is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +# CONFIG_STACKTRACE is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_HAVE_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set + +# +# RCU Debugging +# +# CONFIG_PROVE_RCU is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_TORTURE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_CPU_STALL_INFO is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set + +# +# Runtime Testing +# +# CONFIG_LKDTM is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +CONFIG_ATOMIC64_SELFTEST=y +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_MEMTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_ARM64_PTDUMP is not set +# CONFIG_STRICT_DEVMEM is not set +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set +# CONFIG_DEBUG_RODATA is not set +# CONFIG_CORESIGHT is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +# CONFIG_CRYPTO_AEAD is not set +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +# CONFIG_CRYPTO_RNG is not set +CONFIG_CRYPTO_RNG2=y +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_MCRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_CMAC is not set +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +# CONFIG_CRYPTO_XZ is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_DRBG_MENU is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_HW is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set + +# +# OCF Configuration +# +# CONFIG_OCF_OCF is not set +# CONFIG_ARM64_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +# CONFIG_CRC_CCITT is not set +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +# CONFIG_CRC32_SLICEBY8 is not set +# CONFIG_CRC32_SLICEBY4 is not set +CONFIG_CRC32_SARWATE=y +# CONFIG_CRC32_BIT is not set +CONFIG_CRC7=y +# CONFIG_LIBCRC32C is not set +# CONFIG_CRC8 is not set +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_LZ4_COMPRESS is not set +# CONFIG_LZ4HC_COMPRESS is not set +# CONFIG_LZ4_DECOMPRESS is not set +CONFIG_XZ_DEC=y +# CONFIG_XZ_DEC_X86 is not set +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_IA64 is not set +# CONFIG_XZ_DEC_ARM is not set +# CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_SPARC is not set +# CONFIG_XZ_DEC_BCJ is not set +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_TEXTSEARCH=y +# CONFIG_TEXTSEARCH_KMP is not set +# CONFIG_TEXTSEARCH_BM is not set +# CONFIG_TEXTSEARCH_FSM is not set +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_GLOB=y +# CONFIG_GLOB_SELFTEST is not set +CONFIG_NLATTR=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_AVERAGE=y +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set +CONFIG_LIBFDT=y +CONFIG_OID_REGISTRY=y +CONFIG_UCS2_STRING=y +CONFIG_ARCH_HAS_SG_CHAIN=y diff --git a/target/linux/layerscape-64b/ls1043ardb/target.mk b/target/linux/layerscape-64b/ls1043ardb/target.mk new file mode 100644 index 0000000..9f2580b --- /dev/null +++ b/target/linux/layerscape-64b/ls1043ardb/target.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2016 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +BOARDNAME += $(SUBTARGET) + +# subtarget macros +# PARTITION_SIZE unit: (M) +define Subtarget/Default + DEVICE_DTS = freescale/fsl-ls1043a-rdb + DTB_PARTITION_SIZE = 1 + KERNEL_PARTITION_SIZE = 5 + SQUASHFS_PARTITION_SIZE = 54 +endef -- 1.7.9.5 _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From jonas.gorski at gmail.com Wed Jul 13 06:42:02 2016 From: jonas.gorski at gmail.com (Jonas Gorski) Date: Wed, 13 Jul 2016 12:42:02 +0200 Subject: [OpenWrt-Devel] [PATCH 1/2] layerscape: add ls1043ardb-64b target In-Reply-To: <1468432570-7202-1-git-send-email-yutang.jiang@nxp.com> References: <1468432570-7202-1-git-send-email-yutang.jiang@nxp.com> Message-ID: Hi, On 13 July 2016 at 19:56, wrote: > From: Yutang Jiang > > Add support for NXP layerscape ls1043ardb-64b Dev board. Nice to see support for it here. A few things first, though > > ls1043ardb-64b target is using 4.1 kernel and rcw/u-boot/fman images from > NXP QorIQ SDK V2.0 release. Please update your codebase to 4.4 first. The next release kernel is currently planned to be 4.4. > All of 4.1 kernel patches will be in the second patch, it have more than > 100 kernel patches: platform/flash/dpaa/mmc/usb/pcie etc, porting from > SDK release or upstream. Please add them at the same time. If it's too large for an email, you can also put the commit in a public git repository. You can also create a pull request on github. I guess several of the patches will be obsolete with the switch to 4.4 anyway? > > Signed-off-by: Yutang Jiang > --- > target/linux/layerscape-64b/Makefile | 26 + > target/linux/layerscape-64b/README.ls1043ardb | 860 ++++++ > target/linux/layerscape-64b/base-files/etc/inittab | 6 + > target/linux/layerscape-64b/image/Makefile | 64 + > .../linux/layerscape-64b/image/checkimagesize.sh | 16 + > .../linux/layerscape-64b/ls1043ardb/config-default | 3146 ++++++++++++++++++++ > target/linux/layerscape-64b/ls1043ardb/target.mk | 16 + > 7 files changed, 4134 insertions(+) > create mode 100644 target/linux/layerscape-64b/Makefile > create mode 100644 target/linux/layerscape-64b/README.ls1043ardb > create mode 100644 target/linux/layerscape-64b/base-files/etc/inittab > create mode 100644 target/linux/layerscape-64b/image/Makefile > create mode 100755 target/linux/layerscape-64b/image/checkimagesize.sh > create mode 100644 target/linux/layerscape-64b/ls1043ardb/config-default > create mode 100644 target/linux/layerscape-64b/ls1043ardb/target.mk > > diff --git a/target/linux/layerscape-64b/Makefile b/target/linux/layerscape-64b/Makefile > new file mode 100644 > index 0000000..63d55b9 > --- /dev/null > +++ b/target/linux/layerscape-64b/Makefile > @@ -0,0 +1,26 @@ > +# > +# Copyright (C) 2016 OpenWrt.org > +# > +# This is free software, licensed under the GNU General Public License v2. > +# See /LICENSE for more information. > +# > +include $(TOPDIR)/rules.mk > + > +ARCH:=aarch64 > +BOARD:=layerscape-64b > +BOARDNAME:=layerscape 64b > +CFLAGS:=-Os -pipe -fno-caller-saves > +DEVICE_TYPE:=developerboard > +KERNEL_PATCHVER:=4.1 > +KERNELNAME:=Image dtbs > +FEATURES:=squashfs > +SUBTARGETS:=ls1043ardb > +MAINTAINER:=Jiang Yutang > + > +include $(INCLUDE_DIR)/target.mk > + > +define Target/Description > + Build firmware images for $(BOARDNAME) SoC devices. > +endef > + > +$(eval $(call BuildTarget)) > diff --git a/target/linux/layerscape-64b/README.ls1043ardb b/target/linux/layerscape-64b/README.ls1043ardb > new file mode 100644 > index 0000000..9f6a0af > --- /dev/null > +++ b/target/linux/layerscape-64b/README.ls1043ardb > @@ -0,0 +1,860 @@ (snip) I think a lot of this information (like the bootlog) is better served on the wiki, or shouldn't be here at all (like the contents of various uci files, which are subject to change, and nobody will remember to update the example output here). > diff --git a/target/linux/layerscape-64b/image/Makefile b/target/linux/layerscape-64b/image/Makefile > new file mode 100644 > index 0000000..43e7269 > --- /dev/null > +++ b/target/linux/layerscape-64b/image/Makefile > @@ -0,0 +1,64 @@ > +# > +# Copyright (C) 2016 OpenWrt.org > +# > +# This is free software, licensed under the GNU General Public License v2. > +# See /LICENSE for more information. > +# > +include $(TOPDIR)/rules.mk > +include $(INCLUDE_DIR)/image.mk > + > +# make uImage and dtb > +define Image/uImage-dtb > + gzip -9c < $(KDIR)/Image > $(KDIR)/Image.gz > + $(eval ARCH_BACK = $(ARCH)) > + $(eval ARCH = $(LINUX_KARCH)) > + $(call Image/BuildKernel/MkuImage, gzip, $(KERNEL_LOADADDR), \ > + $(KERNEL_ENTRY_POINT), $(KDIR)/Image.gz, \ > + $(KDIR)/$(IMG_PREFIX)-uImage) > + $(eval ARCH = $(ARCH_BACK)) > + > + $(call Image/BuildDTB,$(DTS_DIR)/$(DEVICE_DTS).dts,$(KDIR)/$(IMG_PREFIX)-dtb) > +endef > + > +# $(1) source image name > +# $(2) partition image name > +# $(3) partition image size(M) > +define Image/Build/flashpartitionimage > + ./checkimagesize.sh $(1) $(3) > + dd if=/dev/zero bs=1M count=$(3) | sed 's/\x00/\xff/g' > $(2) > + dd if=$(1) of=$(2) conv=notrunc > +endef > + > +# make squashfs then merge uImage/dtb/squashfs to one firmware image arranged > +# by individual partition > +define Image/Build/squashfs > + $(call prepare_generic_squashfs,$(KDIR)/root.squashfs) > + > + $(call Image/Build/flashpartitionimage,$(KDIR)/$(IMG_PREFIX)-dtb,$(KDIR)/$(IMG_PREFIX)-dtb-par,$(DTB_PARTITION_SIZE)) > + $(call Image/Build/flashpartitionimage,$(KDIR)/$(IMG_PREFIX)-uImage,$(KDIR)/$(IMG_PREFIX)-uImage-par,$(KERNEL_PARTITION_SIZE)) > + $(call Image/Build/flashpartitionimage,$(KDIR)/root.squashfs,$(KDIR)/root.squashfs-par,$(SQUASHFS_PARTITION_SIZE)) > + cat $(KDIR)/$(IMG_PREFIX)-dtb-par $(KDIR)/$(IMG_PREFIX)-uImage-par \ > + $(KDIR)/root.squashfs-par > $(BIN_DIR)/$(IMG_PREFIX)-firmware > + $(RM) $(KDIR)/$(IMG_PREFIX)-dtb-par $(KDIR)/$(IMG_PREFIX)-uImage-par \ > + $(KDIR)/root.squashfs-par > +endef > + > +# target macros > +define Target/Default > + KERNEL_LOADADDR = 0x80080000 > + KERNEL_ENTRY_POINT = 0x80080000 > +endef > + > +# callback function: Image/BuildKernel > +define Image/BuildKernel > + $(eval $(call Target/Default)) > + $(eval $(call Subtarget/Default)) > + $(call Image/uImage-dtb) > +endef > + > +# callback function: Image/Build > +define Image/Build > + $(call Image/Build/$(1),$(1)) > +endef > + > +$(eval $(call BuildImage)) Please update your image build code to the new image code with defining appropriate Device/* sections. This will then also eliminate > diff --git a/target/linux/layerscape-64b/image/checkimagesize.sh b/target/linux/layerscape-64b/image/checkimagesize.sh > new file mode 100755 > index 0000000..e65c7fe > --- /dev/null > +++ b/target/linux/layerscape-64b/image/checkimagesize.sh this file, as there is a size check build step available. > diff --git a/target/linux/layerscape-64b/ls1043ardb/config-default b/target/linux/layerscape-64b/ls1043ardb/config-default > new file mode 100644 > index 0000000..1543907 > --- /dev/null > +++ b/target/linux/layerscape-64b/ls1043ardb/config-default > @@ -0,0 +1,3146 @@ > +# > +# Automatically generated file; DO NOT EDIT. > +# Linux/arm64 4.1.23 Kernel Configuration > +# > (snip) Please minimize this config by running "make kernel_defconfig CONFIG_TARGET=subtarget" (or put this as the "main" config as target/layerscape-64b/config-default, then run just "make kernel_defconfig"). > diff --git a/target/linux/layerscape-64b/ls1043ardb/target.mk b/target/linux/layerscape-64b/ls1043ardb/target.mk > new file mode 100644 > index 0000000..9f2580b > --- /dev/null > +++ b/target/linux/layerscape-64b/ls1043ardb/target.mk > @@ -0,0 +1,16 @@ > +# > +# Copyright (C) 2016 OpenWrt.org > +# > +# This is free software, licensed under the GNU General Public License v2. > +# See /LICENSE for more information. > +# > +BOARDNAME += $(SUBTARGET) > + > +# subtarget macros > +# PARTITION_SIZE unit: (M) > +define Subtarget/Default > + DEVICE_DTS = freescale/fsl-ls1043a-rdb > + DTB_PARTITION_SIZE = 1 > + KERNEL_PARTITION_SIZE = 5 > + SQUASHFS_PARTITION_SIZE = 54 > +endef Please don't use subtargets for single boards - subtargets should be limited for variants that require different, incompatible compiler options or kernel options (e.g. little vs big endian, 32 vs 64 bit etc). Just make this the default device/profile of the target then. Regards Jonas _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From yutang.jiang at nxp.com Wed Jul 13 13:56:09 2016 From: yutang.jiang at nxp.com (yutang.jiang at nxp.com) Date: Thu, 14 Jul 2016 01:56:09 +0800 Subject: [OpenWrt-Devel] [PATCH 1/2] layerscape: add ls1043ardb-64b target Message-ID: <1468432570-7202-1-git-send-email-yutang.jiang@nxp.com> From: Yutang Jiang Add support for NXP layerscape ls1043ardb-64b Dev board. ls1043ardb-64b target is using 4.1 kernel and rcw/u-boot/fman images from NXP QorIQ SDK V2.0 release. All of 4.1 kernel patches will be in the second patch, it have more than 100 kernel patches: platform/flash/dpaa/mmc/usb/pcie etc, porting from SDK release or upstream. Signed-off-by: Yutang Jiang --- target/linux/layerscape-64b/Makefile | 26 + target/linux/layerscape-64b/README.ls1043ardb | 860 ++++++ target/linux/layerscape-64b/base-files/etc/inittab | 6 + target/linux/layerscape-64b/image/Makefile | 64 + .../linux/layerscape-64b/image/checkimagesize.sh | 16 + .../linux/layerscape-64b/ls1043ardb/config-default | 3146 ++++++++++++++++++++ target/linux/layerscape-64b/ls1043ardb/target.mk | 16 + 7 files changed, 4134 insertions(+) create mode 100644 target/linux/layerscape-64b/Makefile create mode 100644 target/linux/layerscape-64b/README.ls1043ardb create mode 100644 target/linux/layerscape-64b/base-files/etc/inittab create mode 100644 target/linux/layerscape-64b/image/Makefile create mode 100755 target/linux/layerscape-64b/image/checkimagesize.sh create mode 100644 target/linux/layerscape-64b/ls1043ardb/config-default create mode 100644 target/linux/layerscape-64b/ls1043ardb/target.mk diff --git a/target/linux/layerscape-64b/Makefile b/target/linux/layerscape-64b/Makefile new file mode 100644 index 0000000..63d55b9 --- /dev/null +++ b/target/linux/layerscape-64b/Makefile @@ -0,0 +1,26 @@ +# +# Copyright (C) 2016 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk + +ARCH:=aarch64 +BOARD:=layerscape-64b +BOARDNAME:=layerscape 64b +CFLAGS:=-Os -pipe -fno-caller-saves +DEVICE_TYPE:=developerboard +KERNEL_PATCHVER:=4.1 +KERNELNAME:=Image dtbs +FEATURES:=squashfs +SUBTARGETS:=ls1043ardb +MAINTAINER:=Jiang Yutang + +include $(INCLUDE_DIR)/target.mk + +define Target/Description + Build firmware images for $(BOARDNAME) SoC devices. +endef + +$(eval $(call BuildTarget)) diff --git a/target/linux/layerscape-64b/README.ls1043ardb b/target/linux/layerscape-64b/README.ls1043ardb new file mode 100644 index 0000000..9f6a0af --- /dev/null +++ b/target/linux/layerscape-64b/README.ls1043ardb @@ -0,0 +1,860 @@ +1.NOR Flash Memory Map Layout for LS1043ARDB +------------------------------------------ +Start End Offset Description Size +0x60000000 0x600FFFFF bank0 rcw + pbi 1M +0x60100000 0x601FFFFF bank0 U-Boot image 1M +0x60200000 0x602FFFFF bank0 U-Boot Env 1M +0x60300000 0x603FFFFF bank0 Fman ucode 1M +0x60400000 0x63FFFFFF bank0 OpenWrt firmware 60M +0x64000000 0x67FFFFFF bank4 Otherbank 64M + +2.Partitioning of the Flash +------------------------- +#################################################################################################### +# Layer0 # raw flash, 128M # +#################################################################################################### +# # mtd0 # mtd1 # mtd2 # mtd3 # mtd9 # mtd8 # +# Layer1 # rcw # u-boot # u-boot-env # fman # firmware # otherbank # +# # 1M # 1M # 1M # 1M # 60M # 64M # +#################################################################################################### +# # # # # # mtd4 # mtd5 # mtd6 # # +# Layer2 # # # # # dtb # kernel # rootfs # # +# # # # # # 1M # 5M # 54M # # +#################################################################################################### +# # # # # # # # # mtd7 # # +# Layer3 # # # # # # # /dev/root # rootfs_data # # +# # # # # # # # "/rom" # "/overlay" # # +# # # # # # # # SquashFS # JFFS2 # # +#################################################################################################### + +3.Flashing firmware image and bootup kernel in u-boot +----------------------------------------------------- +setenv gatewayip +setenv ipaddr +setenv serverip +setenv loadaddr 82000000 && setenv ramdiskaddr 88000000 && setenv fdtaddr 8f000000 +setenv wrtboot 'setenv bootargs root=/dev/mtdblock6 rootfstype=squashfs,jffs2 noinitrd earlycon=uart8250,mmio,0x21c0500 console=ttyS0,115200 mtdparts=60000000.nor:1M(rcw),1M(u-boot),1M(u-boot-env),1M(fman),1M(dtb),5M(kernel),54M(rootfs),64M(otherbank),60M at 0x400000(firmware) && cp.b 60400000 $fdtaddr 100000 && cp.b 60500000 $loadaddr 500000 && bootm $loadaddr - $fdtaddr' +save +tftp a0000000 your_tftpserver_folder/openwrt-layerscape-64b-ls1043ardb-firmware && protect off all && erase 60400000 +3c00000 && cp.b a0000000 60400000 $filesize +run wrtboot + +4.Boot log +--------------------------------- +U-Boot 2015.01QorIQ-SDK-V1.7+gc297f5b (Dec 20 2015 - 13:08:26) + +Clock Configuration: + CPU0(A53):1600 MHz CPU1(A53):1600 MHz CPU2(A53):1600 MHz + CPU3(A53):1600 MHz + Bus: 400 MHz DDR: 1600 MT/s FMAN: 500 MHz +Reset Configuration Word (RCW): + 00000000: 08100010 0a000000 00000000 00000000 + 00000010: 14550002 80004012 e0025000 c1002000 + 00000020: 00000000 00000000 00000000 00038800 + 00000030: 00000000 00001101 00000096 00000001 +Board: LS1043ARDB, boot from vBank 0 +CPLD: V1.4 +PCBA: V3.0 +SERDES Reference Clocks: +SD1_CLK1 = 156.25MHZ, SD1_CLK2 = 100.00MHZ +I2C: ready +DRAM: Initializing DDR.... +Detected UDIMM Fixed DDR on board +2 GiB (DDR4, 32-bit, CL=11, ECC off) +Firmware 'Microcode version 0.0.1 for LS1021a r1.0' for 1021 V1.0 +QE: uploading microcode 'Microcode for LS1021a r1.0' version 0.0.1 +Using SERDES1 Protocol: 5205 (0x1455) +fman_port_enet_if:71: port(FM1_DTSEC3) is OK +fman_port_enet_if:77: port(FM1_DTSEC4) is OK +Flash: 128 MiB +NAND: 512 MiB +MMC: FSL_SDHC: 0 +EEPROM: NXID v1 +PCIe1: disabled +PCIe2: Root Complex no link, regs @ 0x3500000 +PCIe3: Root Complex x1 gen1, regs @ 0x3600000 + 01:00.0 - 8086:10d3 - Network controller +PCIe3: Bus 00 - 01 +In: serial +Out: serial +Err: serial +Net: Fman1: Uploading microcode version 106.4.17 +e1000: 68:05:ca:35:fa:4a + FM1 at DTSEC1, FM1 at DTSEC2, FM1 at DTSEC3, FM1 at DTSEC4, FM1 at DTSEC5, FM1 at DTSEC6, FM1 at TGEC1, e1000#0 [PRIME] +Warning: e1000#0 MAC addresses don't match: +Address in SROM is 68:05:ca:35:fa:4a +Address in environment is 00:e0:0c:00:73:07 + +=> +=> pri +baudrate=115200 +bootargs=console=ttyS0,115200 root=/dev/ram0 earlycon=uart8250,0x21c0500,115200 +bootcmd=cpld reset altbank +bootdelay=-1 +console=ttyAMA0,38400n8 +eth10addr=00:E0:0C:00:73:0a +eth11addr=00:E0:0C:00:73:0b +eth12addr=00:E0:0C:00:73:0c +eth13addr=00:E0:0C:00:73:0d +eth14addr=00:E0:0C:00:73:0e +eth15addr=00:E0:0C:00:73:0f +eth1addr=00:E0:0C:00:73:01 +eth2addr=00:E0:0C:00:73:02 +eth3addr=00:E0:0C:00:73:03 +eth4addr=00:E0:0C:00:73:04 +eth5addr=00:E0:0C:00:73:05 +eth6addr=00:E0:0C:00:73:06 +eth7addr=00:E0:0C:00:73:07 +eth8addr=00:E0:0C:00:73:08 +eth9addr=00:E0:0C:00:73:09 +ethact=e1000#0 +ethaddr=00:E0:0C:00:73:00 +ethprime=e1000#0 +faddr_fman_mc=0x64300000 +faddr_rcw=0x64000000 +faddr_uboot=0x64100000 +fdt_high=0xffffffffffffffff +fman_ucode=60300000 +gatewayip=192.168.1.1 +hwconfig=fsl_ddr:bank_intlv=auto;dspi +img_fman_mc=b28495/sdk/sdk-ls1043a/201512200957-b0dba1d/ls1043ardb/fsl_fman_ucode_t2080_r1.1_106_4_17.bin +img_rcw=b28495/sdk/sdk-ls1043a/201512200957-b0dba1d/ls1043ardb/rcw/ls1043ardb/RR_FQPP_1455/rcw_1600.bin +img_uboot=b28495/armv8-staging/ls1043a/u-boot-ls1043ardb.bin +initrd_high=0xffffffffffffffff +ipaddr=192.168.2.135 +kernel_addr=0x100000 +kernel_load=0xa0000000 +kernel_size=0x2800000 +kernel_start=0x61100000 +loadaddr=0x80100000 +netmask=255.255.255.0 +raddr_temp=0x90000000 +ramdisk_addr=0x800000 +ramdisk_size=0x2000000 +scsidevs=0 +serverip=192.168.2.1 +stderr=serial +stdin=serial +stdout=serial +upbank4=tftp 82000000 b18965/ls1043-rdb/u-boot-dtb.bin && protect off all && erase 64100000 641fffff && cp.b 0x82000000 64100000 100000 && run bootcmd + +Environment size: 1653/131068 bytes +=> cpld reset altbank + +U-Boot 2016.07-rc2-g15030c7 (Jul 13 2016 - 02:10:41 +0800), Build: jenkins-armv8-u-boot-build-ls1043-1s2085-247 + +SoC: unknown (0x87920410) +Clock Configuration: + CPU0(A53):1600 MHz CPU1(A53):1600 MHz CPU2(A53):1600 MHz + CPU3(A53):1600 MHz + Bus: 400 MHz DDR: 1600 MT/s FMAN: 500 MHz +Reset Configuration Word (RCW): + 00000000: 08100010 0a000000 00000000 00000000 + 00000010: 14550002 80004012 e0025000 c1002000 + 00000020: 00000000 00000000 00000000 00038800 + 00000030: 00000000 00001101 00000096 00000001 +Model: LS1043A RDB Board +Board: LS1043ARDB, boot from vBank 4 +CPLD: V1.4 +PCBA: V3.0 +SERDES Reference Clocks: +SD1_CLK1 = 156.25MHZ, SD1_CLK2 = 100.00MHZ +I2C: ready +DRAM: Initializing DDR.... +Detected UDIMM Fixed DDR on board +2 GiB (DDR4, 32-bit, CL=11, ECC off) +Not a microcode +Waking secondary cores to start from ffd08000 +All (4) cores are up. +Using SERDES1 Protocol: 5205 (0x1455) +Flash: 128 MiB +NAND: 512 MiB +MMC: FSL_SDHC: 0 +EEPROM: NXID v1 +PCIe1: disabled +PCIe2: Root Complex no link, regs @ 0x3500000 +PCIe3: Root Complex x1 gen1, regs @ 0x3600000 +PCI: + 01:00.0 - 8086:10d3 - Network controller +PCIe3: Bus 00 - 01 +In: serial +Out: serial +Err: serial +SEC0: RNG instantiated +Net: Fman1: Uploading microcode version 106.4.17 +e1000: 68:05:ca:35:fa:4a + FM1 at DTSEC1, FM1 at DTSEC2, FM1 at DTSEC3, FM1 at DTSEC4, FM1 at DTSEC5, FM1 at DTSEC6, FM1 at TGEC1, e1000#0 [PRIME] +Warning: e1000#0 MAC addresses don't match: +Address in SROM is 68:05:ca:35:fa:4a +Address in environment is 00:e0:0c:00:73:07 + +=> pri +baudrate=115200 +bootargs=console=ttyS0,115200 root=/dev/ram0 earlycon=uart8250,mmio,0x21c0500 +bootcmd=cp.b $kernel_start $kernel_load $kernel_size && bootm $kernel_load +bootdelay=-1 +console=ttyAMA0,38400n8 +eth10addr=00:E0:0C:00:73:0a +eth11addr=00:E0:0C:00:73:0b +eth12addr=00:E0:0C:00:73:0c +eth13addr=00:E0:0C:00:73:0d +eth14addr=00:E0:0C:00:73:0e +eth15addr=00:E0:0C:00:73:0f +eth1addr=00:E0:0C:00:73:01 +eth2addr=00:E0:0C:00:73:02 +eth3addr=00:E0:0C:00:73:03 +eth4addr=00:E0:0C:00:73:04 +eth5addr=00:E0:0C:00:73:05 +eth6addr=00:E0:0C:00:73:06 +eth7addr=00:E0:0C:00:73:07 +eth8addr=00:E0:0C:00:73:08 +eth9addr=00:E0:0C:00:73:09 +ethact=e1000#0 +ethaddr=00:E0:0C:00:73:00 +ethprime=e1000#0 +fdt_high=0xffffffffffffffff +fdtcontroladdr=ffbc5728 +fman_ucode=60300000 +hwconfig=fsl_ddr:bank_intlv=auto;dspi +initrd_high=0xffffffffffffffff +kernel_addr=0x100000 +kernel_load=0xa0000000 +kernel_size=0x2800000 +kernel_start=0x61100000 +loadaddr=0x80100000 +ramdisk_addr=0x800000 +ramdisk_size=0x2000000 +stderr=serial +stdin=serial +stdout=serial + +Environment size: 1089/131068 bytes +=> setenv ipaddr 192.168.2.135 +=> setenv serverip 192.168.2.1 +=> setenv gatewayip 192.168.1.1 +=> setenv loadaddr 82000000 && setenv ramdiskaddr 88000000 && setenv fdtaddr 8f000000 +=> setenv wrtboot 'setenv bootargs root=/dev/mtdblock6 rootfstype=squashfs,jffs2 noinitrd earlycon=uart8250,mmio,0x21c0500 console=ttyS0,115200 mtdparts=60000000.nor:1M(rcw),1M(u-boot),1M(u-boot-env),1M(fman),1M(dtb),5M(kernel),54M(rootfs),64M(otherbank),60M at 0x400000(firmware) && cp.b 60400000 $fdtaddr 100000 && cp.b 60500000 $loadaddr 500000 && bootm $loadaddr - $fdtaddr' +=> save +Saving Environment to Flash... +Un-Protected 1 sectors +Erasing Flash... +. done +Erased 1 sectors +Writing to Flash... 9....8....7....6....5....4....3....2....1....done +Protected 1 sectors +=> +=> tftp a0000000 jyt/openwrt/ls1043/openwrt-layerscape-64b-ls1043ardb-firmware && protect off all && erase 60400000 +3c00000 && cp.b a0000000 60400000 $filesize +Using e1000#0 device +TFTP from server 192.168.2.1; our IP address is 192.168.2.135 +Filename 'jyt/openwrt/ls1043/openwrt-layerscape-64b-ls1043ardb-firmware'. +Load address: 0xa0000000 +Loading: ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ############################################################# + 10.9 MiB/s +done +Bytes transferred = 62914560 (3c00000 hex) +Un-Protect Flash Bank # 1 + +................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................ done +Erased 480 sectors +Copy to Flash... 9....8....7....6....5....4....3....2....1....done +=> +=> run wrtboot +## Booting kernel from Legacy Image at 82000000 ... + Image Name: ARM64 OpenWrt Linux-4.1.23 + Image Type: AArch64 Linux Kernel Image (gzip compressed) + Data Size: 3899658 Bytes = 3.7 MiB + Load Address: 80080000 + Entry Point: 80080000 + Verifying Checksum ... OK +## Flattened Device Tree blob at 8f000000 + Booting using the fdt blob at 0x8f000000 + Uncompressing Kernel Image ... OK + Using Device Tree in place at 000000008f000000, end 000000008f0183bd +WARNING: Missing crypto node + +Starting kernel ... + +[ 0.000000] Booting Linux on physical CPU 0x0 +[ 0.000000] Linux version 4.1.23 (jyt at BP) (gcc version 5.3.0 (OpenWrt GCC 5.3.0 r49395) ) #1 SMP Wed Jul 13 10:42:53 UTC 2016 +[ 0.000000] CPU: AArch64 Processor [410fd034] revision 4 +[ 0.000000] Detected VIPT I-cache on CPU0 +[ 0.000000] alternatives: enabling workaround for ARM erratum 845719 +[ 0.000000] earlycon: Early serial console at MMIO 0x21c0500 (options '') +[ 0.000000] bootconsole [uart0] enabled +[ 0.000000] efi: Getting EFI parameters from FDT: +[ 0.000000] efi: UEFI not found. +[ 0.000000] Reserved memory: initialized node bman-fbpr, compatible id fsl,bman-fbpr +[ 0.000000] Reserved memory: initialized node qman-fqd, compatible id fsl,qman-fqd +[ 0.000000] Reserved memory: initialized node qman-pfdr, compatible id fsl,qman-pfdr +[ 0.000000] PERCPU: Embedded 16 pages/cpu @ffff80007fd8d000 s27072 r8192 d30272 u65536 +[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 516615 +[ 0.000000] Kernel command line: root=/dev/mtdblock6 rootfstype=squashfs,jffs2 noinitrd earlycon=uart8250,mmio,0x21c0500 console=ttyS0,115200 mtdparts=60000000.nor:1M(rcw),1M(u-boot),1M(u-boot-env),1M(fman),1M(dtb),5M(kernel),54M(rootfs),64M(otherbank),60M at 0x400000(firmware) +[ 0.000000] log_buf_len individual max cpu contribution: 4096 bytes +[ 0.000000] log_buf_len total cpu_extra contributions: 12288 bytes +[ 0.000000] log_buf_len min size: 16384 bytes +[ 0.000000] log_buf_len: 32768 bytes +[ 0.000000] early log buf free: 14560(88%) +[ 0.000000] PID hash table entries: 4096 (order: 3, 32768 bytes) +[ 0.000000] Dentry cache hash table entries: 262144 (order: 9, 2097152 bytes) +[ 0.000000] Inode-cache hash table entries: 131072 (order: 8, 1048576 bytes) +[ 0.000000] software IO TLB [mem 0xf6a00000-0xfaa00000] (64MB) mapped at [ffff800076a00000-ffff80007a9fffff] +[ 0.000000] Memory: 1933896K/2095104K available (5768K kernel code, 340K rwdata, 2500K rodata, 276K init, 721K bss, 161208K reserved, 0K cma-reserved) +[ 0.000000] Virtual kernel memory layout: +[ 0.000000] vmalloc : 0xffff000000000000 - 0xffff7c7fbfff0000 (127486 GB) +[ 0.000000] vmemmap : 0xffff7c7fc0000000 - 0xffff7fffc0000000 ( 3584 GB maximum) +[ 0.000000] 0xffff7c7fc0000000 - 0xffff7c7fc1bf9000 ( 27 MB actual) +[ 0.000000] fixed : 0xffff7ffffabfd000 - 0xffff7ffffac00000 ( 12 KB) +[ 0.000000] PCI I/O : 0xffff7ffffae00000 - 0xffff7ffffbe00000 ( 16 MB) +[ 0.000000] modules : 0xffff7ffffc000000 - 0xffff800000000000 ( 64 MB) +[ 0.000000] memory : 0xffff800000000000 - 0xffff80007fe00000 ( 2046 MB) +[ 0.000000] .init : 0xffff800000896000 - 0xffff8000008db000 ( 276 KB) +[ 0.000000] .text : 0xffff800000080000 - 0xffff8000008951a4 ( 8277 KB) +[ 0.000000] .data : 0xffff8000008e6000 - 0xffff80000093b000 ( 340 KB) +[ 0.000000] Hierarchical RCU implementation. +[ 0.000000] CONFIG_RCU_FANOUT set to non-default value of 32 +[ 0.000000] RCU restricting CPUs from NR_CPUS=64 to nr_cpu_ids=4. +[ 0.000000] RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4 +[ 0.000000] NR_IRQS:64 nr_irqs:64 0 +[ 0.000000] Architected cp15 timer(s) running at 25.00MHz (phys). +[ 0.000000] clocksource arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x5c40939b5, max_idle_ns: 440795202646 ns +[ 0.000002] sched_clock: 56 bits at 25MHz, resolution 40ns, wraps every 4398046511100ns +[ 0.008237] Calibrating delay loop (skipped), value calculated using timer frequency.. 50.00 BogoMIPS (lpj=250000) +[ 0.018642] pid_max: default: 32768 minimum: 301 +[ 0.023339] Mount-cache hash table entries: 4096 (order: 3, 32768 bytes) +[ 0.030074] Mountpoint-cache hash table entries: 4096 (order: 3, 32768 bytes) +[ 0.037599] EFI services will not be available. +[ 0.042623] CPU1: Booted secondary processor +[ 0.042627] Detected VIPT I-cache on CPU1 +[ 0.042768] CPU2: Booted secondary processor +[ 0.042771] Detected VIPT I-cache on CPU2 +[ 0.042902] CPU3: Booted secondary processor +[ 0.042904] Detected VIPT I-cache on CPU3 +[ 0.042932] Brought up 4 CPUs +[ 0.070816] SMP: Total of 4 processors activated. +[ 0.075536] CPU: All CPU(s) started at EL2 +[ 0.079655] alternatives: patching kernel code +[ 0.086792] DMI not present or invalid. +[ 0.090754] clocksource jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns +[ 0.100593] atomic64_test: passed +[ 0.104311] NET: Registered protocol family 16 +[ 0.109363] fsl-mc bus type registered +[ 0.113169] MC object device driver fsl_mc_dprc registered +[ 0.118714] MC object device driver fsl_mc_allocator registered +[ 0.124694] Bman ver:0a02,02,01 +[ 0.130025] qman-fqd addr 0xff800000 size 0x400000 +[ 0.134833] qman-pfdr addr 0xfc000000 size 0x2000000 +[ 0.139821] Qman ver:0a01,03,02,00 +[ 0.143310] vdso: 2 pages (1 code @ ffff8000008ed000, 1 data @ ffff8000008ec000) +[ 0.150845] DMA: preallocated 256 KiB pool for atomic allocations +[ 0.157052] Serial: AMBA PL011 UART driver +[ 0.201606] ACPI: Interpreter disabled. +[ 0.205877] SCSI subsystem initialized +[ 0.210022] usbcore: registered new interface driver usbfs +[ 0.215577] usbcore: registered new interface driver hub +[ 0.220937] usbcore: registered new device driver usb +[ 0.226079] pps_core: LinuxPPS API ver. 1 registered +[ 0.231062] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti +[ 0.240273] PTP clock support registered +[ 0.244377] bman-fbpr addr 0xfe000000 size 0x1000000 +[ 0.249389] Bman err interrupt handler present +[ 0.253972] unknown BMan version in portal node,default to rev1.0 +[ 0.260113] unknown BMan version in portal node,default to rev1.0 +[ 0.266250] unknown BMan version in portal node,default to rev1.0 +[ 0.272381] unknown BMan version in portal node,default to rev1.0 +[ 0.278516] unknown BMan version in portal node,default to rev1.0 +[ 0.284647] unknown BMan version in portal node,default to rev1.0 +[ 0.290782] unknown BMan version in portal node,default to rev1.0 +[ 0.296912] unknown BMan version in portal node,default to rev1.0 +[ 0.303047] unknown BMan version in portal node,default to rev1.0 +[ 0.309253] Bman portal initialised, cpu 0 +[ 0.313427] Bman portal initialised, cpu 1 +[ 0.317595] Bman portal initialised, cpu 2 +[ 0.321763] Bman portal initialised, cpu 3 +[ 0.325877] Bman portals initialised +[ 0.330330] Qman err interrupt handler present +[ 0.334788] Can't find Qman clock frequency +[ 0.339153] QMan: Allocated lookup table at ffff00000016d000, entry count 65537 +[ 0.346528] unknown QMan version in portal node,default to rev1.1 +[ 0.352650] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 0' has 0x0101 +[ 0.360957] unknown QMan version in portal node,default to rev1.1 +[ 0.367080] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 10000' has 0x0101 +[ 0.375736] unknown QMan version in portal node,default to rev1.1 +[ 0.381856] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 20000' has 0x0101 +[ 0.390512] unknown QMan version in portal node,default to rev1.1 +[ 0.396633] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 30000' has 0x0101 +[ 0.405288] unknown QMan version in portal node,default to rev1.1 +[ 0.411409] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 40000' has 0x0101 +[ 0.420064] unknown QMan version in portal node,default to rev1.1 +[ 0.426185] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 50000' has 0x0101 +[ 0.434840] unknown QMan version in portal node,default to rev1.1 +[ 0.440961] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 60000' has 0x0101 +[ 0.449616] unknown QMan version in portal node,default to rev1.1 +[ 0.455737] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 70000' has 0x0101 +[ 0.464392] unknown QMan version in portal node,default to rev1.1 +[ 0.470513] Revision=0x0302, but portal '/qman-portals at 500000000/qman-portal at 80000' has 0x0101 +[ 0.479838] Qman portal initialised, cpu 0 +[ 0.484406] Qman portal initialised, cpu 1 +[ 0.488967] Qman portal initialised, cpu 2 +[ 0.493528] Qman portal initialised, cpu 3 +[ 0.497641] Qman portals initialised +[ 0.501299] Bman: BPID allocator includes range 32:32 +[ 0.506401] Qman: FQID allocator includes range 256:256 +[ 0.511649] Qman: FQID allocator includes range 32768:32768 +[ 0.517278] Qman: CGRID allocator includes range 0:256 +[ 0.522546] Qman: pool channel allocator includes range 1025:15 +[ 0.528532] No USDPAA memory, no 'usdpaa_mem' bootarg +[ 0.533638] fsl-ifc 1530000.ifc: Freescale Integrated Flash Controller +[ 0.540200] fsl-ifc 1530000.ifc: IFC version 1.4, 8 banks +[ 0.546185] Switched to clocksource arch_sys_counter +[ 0.551318] pnp: PnP ACPI: disabled +[ 0.555272] NET: Registered protocol family 2 +[ 0.559947] TCP established hash table entries: 16384 (order: 5, 131072 bytes) +[ 0.567305] TCP bind hash table entries: 16384 (order: 6, 262144 bytes) +[ 0.574134] TCP: Hash tables configured (established 16384 bind 16384) +[ 0.580737] UDP hash table entries: 1024 (order: 3, 32768 bytes) +[ 0.586802] UDP-Lite hash table entries: 1024 (order: 3, 32768 bytes) +[ 0.593377] NET: Registered protocol family 1 +[ 0.597875] RPC: Registered named UNIX socket transport module. +[ 0.603818] RPC: Registered udp transport module. +[ 0.608545] RPC: Registered tcp transport module. +[ 0.613265] RPC: Registered tcp NFSv4.1 backchannel transport module. +[ 0.620431] futex hash table entries: 1024 (order: 4, 65536 bytes) +[ 0.626825] HugeTLB registered 2 MB page size, pre-allocated 0 pages +[ 0.633410] VFS: Disk quotas dquot_6.6.0 +[ 0.637375] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes) +[ 0.644461] squashfs: version 4.0 (2009/01/31) Phillip Lougher +[ 0.650483] NFS: Registering the id_resolver key type +[ 0.655568] Key type id_resolver registered +[ 0.659770] Key type id_legacy registered +[ 0.663822] jffs2: version 2.2 (NAND) (ZLIB) (RTIME) (c) 2001-2006 Red Hat, Inc. +[ 0.671368] fuse init (API version 7.23) +[ 0.675762] io scheduler noop registered (default) +[ 0.681443] PCI host bridge /soc/pcie at 3500000 ranges: +[ 0.686528] IO 0x4800010000..0x480001ffff -> 0x00000000 +[ 0.692038] MEM 0x4840000000..0x487fffffff -> 0x40000000 +[ 0.697623] layerscape-pcie 3500000.pcie: PCI host bridge to bus 0000:00 +[ 0.704357] pci_bus 0000:00: root bus resource [bus 00-ff] +[ 0.709871] pci_bus 0000:00: root bus resource [io 0x0000-0xffff] +[ 0.716079] pci_bus 0000:00: root bus resource [mem 0x4840000000-0x487fffffff] (bus address [0x40000000-0x7fffffff]) +[ 0.726722] pci 0000:00:00.0: IOMMU is currently not supported for PCI +[ 0.733403] pci 0000:00:00.0: bridge configuration invalid ([bus 00-00]), reconfiguring +[ 0.741527] pci 0000:00:00.0: BAR 1: assigned [mem 0x4840000000-0x4843ffffff] +[ 0.748702] pci 0000:00:00.0: BAR 0: assigned [mem 0x4844000000-0x4844ffffff] +[ 0.755872] pci 0000:00:00.0: BAR 6: assigned [mem 0x4845000000-0x4845ffffff pref] +[ 0.763481] pci 0000:00:00.0: PCI bridge to [bus 01] +[ 0.768488] pcieport 0000:00:00.0: enabling device (0000 -> 0002) +[ 0.774773] PCI host bridge /soc/pcie at 3600000 ranges: +[ 0.779854] IO 0x5000010000..0x500001ffff -> 0x00000000 +[ 0.785364] MEM 0x5040000000..0x507fffffff -> 0x40000000 +[ 0.790943] layerscape-pcie 3600000.pcie: PCI host bridge to bus 0001:00 +[ 0.797679] pci_bus 0001:00: root bus resource [bus 00-ff] +[ 0.803188] pci_bus 0001:00: root bus resource [io 0x10000-0x1ffff] (bus address [0x0000-0xffff]) +[ 0.812195] pci_bus 0001:00: root bus resource [mem 0x5040000000-0x507fffffff] (bus address [0x40000000-0x7fffffff]) +[ 0.822821] pci 0001:00:00.0: IOMMU is currently not supported for PCI +[ 0.829935] pci 0001:01:00.0: IOMMU is currently not supported for PCI +[ 0.856229] pci 0001:00:00.0: BAR 1: assigned [mem 0x5040000000-0x5043ffffff] +[ 0.863399] pci 0001:00:00.0: BAR 0: assigned [mem 0x5044000000-0x5044ffffff] +[ 0.870574] pci 0001:00:00.0: BAR 6: assigned [mem 0x5045000000-0x5045ffffff pref] +[ 0.878184] pci 0001:00:00.0: BAR 8: assigned [mem 0x5046000000-0x50460fffff] +[ 0.885352] pci 0001:00:00.0: BAR 7: assigned [io 0x10000-0x10fff] +[ 0.891652] pci 0001:01:00.0: BAR 1: assigned [mem 0x5046000000-0x504607ffff] +[ 0.898835] pci 0001:01:00.0: BAR 6: assigned [mem 0x5046080000-0x50460bffff pref] +[ 0.906443] pci 0001:01:00.0: BAR 0: assigned [mem 0x50460c0000-0x50460dffff] +[ 0.913622] pci 0001:01:00.0: BAR 3: assigned [mem 0x50460e0000-0x50460e3fff] +[ 0.920805] pci 0001:01:00.0: BAR 2: assigned [io 0x10000-0x1001f] +[ 0.927113] pci 0001:00:00.0: PCI bridge to [bus 01] +[ 0.932098] pci 0001:00:00.0: bridge window [io 0x10000-0x10fff] +[ 0.938395] pci 0001:00:00.0: bridge window [mem 0x5046000000-0x50460fffff] +[ 0.945959] Serial: 8250/16550 driver, 2 ports, IRQ sharing disabled +[ 0.952850] console [ttyS0] disabled +[ 0.956457] 21c0500.serial: ttyS0 at MMIO 0x21c0500 (irq = 15, base_baud = 25000000) is a 16550A +[ 0.965295] console [ttyS0] enabled +[ 0.965295] console [ttyS0] enabled +[ 0.972271] bootconsole [uart0] disabled +[ 0.972271] bootconsole [uart0] disabled +[ 0.980258] 21c0600.serial: ttyS1 at MMIO 0x21c0600 (irq = 15, base_baud = 25000000) is a 16550A +[ 0.989130] of_serial: probe of 21d0500.serial failed with error -28 +[ 0.995500] of_serial: probe of 21d0600.serial failed with error -28 +[ 1.002046] Unable to detect cache hierarcy from DT for CPU 0 +[ 1.010995] brd: module loaded +[ 1.016003] loop: module loaded +[ 1.021262] 60000000.nor: Found 1 x16 devices at 0x0 in 16-bit bank. Manufacturer ID 0x000089 Chip ID 0x00227e +[ 1.031262] Amd/Fujitsu Extended Query Table at 0x0040 +[ 1.036401] Amd/Fujitsu Extended Query version 1.3. +[ 1.041443] number of CFI chips: 1 +[ 1.044845] 9 cmdlinepart partitions found on MTD device 60000000.nor +[ 1.051277] Creating 9 MTD partitions on "60000000.nor": +[ 1.056582] 0x000000000000-0x000000100000 : "rcw" +[ 1.061496] ftl_cs: FTL header not found. +[ 1.065695] 0x000000100000-0x000000200000 : "u-boot" +[ 1.070861] ftl_cs: FTL header not found. +[ 1.075034] 0x000000200000-0x000000300000 : "u-boot-env" +[ 1.080553] ftl_cs: FTL header not found. +[ 1.084729] 0x000000300000-0x000000400000 : "fman" +[ 1.089719] ftl_cs: FTL header not found. +[ 1.093895] 0x000000400000-0x000000500000 : "dtb" +[ 1.098800] ftl_cs: FTL header not found. +[ 1.102973] 0x000000500000-0x000000a00000 : "kernel" +[ 1.108137] ftl_cs: FTL header not found. +[ 1.112309] 0x000000a00000-0x000004000000 : "rootfs" +[ 1.117474] ftl_cs: FTL header not found. +[ 1.121650] mtd: device 6 (rootfs) set to be root filesystem +[ 1.127314] 1 squashfs-split partitions found on MTD device rootfs +[ 1.133483] 0x000000b00000-0x000004000000 : "rootfs_data" +[ 1.139080] ftl_cs: FTL header not found. +[ 1.143257] 0x000004000000-0x000008000000 : "otherbank" +[ 1.148680] ftl_cs: FTL header not found. +[ 1.152854] 0x000000400000-0x000004000000 : "firmware" +[ 1.158193] ftl_cs: FTL header not found. +[ 1.162814] nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xac +[ 1.169161] nand: Micron MT29F4G08ABBDAH4 +[ 1.173160] nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64 +[ 1.180985] Bad block table found at page 262080, version 0x01 +[ 1.187286] Bad block table found at page 262016, version 0x01 +[ 1.195438] ftl_cs: FTL header not found. +[ 1.199625] fsl,ifc-nand 7e800000.nand: IFC NAND device at 0x7e800000, bank 1 +[ 1.207436] libphy: Fixed MDIO Bus: probed +[ 1.211523] tun: Universal TUN/TAP device driver, 1.6 +[ 1.216567] tun: (C) 1999-2004 Max Krasnyansky +[ 1.222917] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.229378] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.235873] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.240891] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.245906] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.250927] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.255942] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.260961] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.265978] libphy: Freescale XGMAC MDIO Bus: probed +[ 1.282650] Freescale FM module, FMD API version 21.1.0 +[ 1.289546] Freescale FM Ports module +[ 1.293200] fsl_mac: fsl_mac: FSL FMan MAC API based driver +[ 1.298867] fsl_mac 1ae0000.ethernet: FMan MEMAC +[ 1.303479] fsl_mac 1ae0000.ethernet: FMan MAC address: 00:e0:0c:00:73:00 +[ 1.310309] fsl_mac 1ae2000.ethernet: FMan MEMAC +[ 1.314918] fsl_mac 1ae2000.ethernet: FMan MAC address: 00:e0:0c:00:73:01 +[ 1.321744] fsl_mac 1ae4000.ethernet: FMan MEMAC +[ 1.326358] fsl_mac 1ae4000.ethernet: FMan MAC address: 00:e0:0c:00:73:02 +[ 1.333182] fsl_mac 1ae6000.ethernet: FMan MEMAC +[ 1.337797] fsl_mac 1ae6000.ethernet: FMan MAC address: 00:e0:0c:00:73:03 +[ 1.344623] fsl_mac 1ae8000.ethernet: FMan MEMAC +[ 1.349237] fsl_mac 1ae8000.ethernet: FMan MAC address: 00:e0:0c:00:73:04 +[ 1.356064] fsl_mac 1aea000.ethernet: FMan MEMAC +[ 1.360677] fsl_mac 1aea000.ethernet: FMan MAC address: 00:e0:0c:00:73:05 +[ 1.367507] fsl_mac 1af0000.ethernet: FMan MEMAC +[ 1.372117] fsl_mac 1af0000.ethernet: FMan MAC address: 00:e0:0c:00:73:06 +[ 1.378965] fsl_dpa: FSL DPAA Ethernet driver +[ 1.387069] fsl_dpa: fsl_dpa: Probed interface eth0 +[ 1.395740] fsl_dpa: fsl_dpa: Probed interface eth1 +[ 1.404752] fsl_dpa: fsl_dpa: Probed interface eth2 +[ 1.414121] fsl_dpa: fsl_dpa: Probed interface eth3 +[ 1.423819] fsl_dpa: fsl_dpa: Probed interface eth4 +[ 1.433876] fsl_dpa: fsl_dpa: Probed interface eth5 +[ 1.444266] fsl_dpa: fsl_dpa: Probed interface eth6 +[ 1.449230] fsl_advanced: FSL DPAA Advanced drivers: +[ 1.454185] fsl_proxy: FSL DPAA Proxy initialization driver +[ 1.459931] fsl_dpa_shared: FSL DPAA Shared Ethernet driver +[ 1.465573] fsl_dpa_macless: FSL DPAA MACless Ethernet driver +[ 1.471394] fsl_oh: FSL FMan Offline Parsing port driver +[ 1.476801] e1000e: Intel(R) PRO/1000 Network Driver - 2.3.2-k +[ 1.482621] e1000e: Copyright(c) 1999 - 2014 Intel Corporation. +[ 1.488810] e1000e 0001:01:00.0: Interrupt Throttling Rate (ints/sec) set to dynamic conservative mode +[ 1.622241] e1000e 0001:01:00.0 eth7: registered PHC clock +[ 1.627724] e1000e 0001:01:00.0 eth7: (PCI Express:2.5GT/s:Width x1) 68:05:ca:35:fa:4a +[ 1.635630] e1000e 0001:01:00.0 eth7: Intel(R) PRO/1000 Network Connection +[ 1.642508] e1000e 0001:01:00.0 eth7: MAC: 3, PHY: 8, PBA No: E46981-008 +[ 2.850000] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver +[ 2.856526] ehci-pci: EHCI PCI platform driver +[ 2.860996] ehci-platform: EHCI generic platform driver +[ 2.866357] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver +[ 2.872530] ohci-pci: OHCI PCI platform driver +[ 2.877005] ohci-platform: OHCI generic platform driver +[ 2.882534] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller +[ 2.888023] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 1 +[ 2.895749] xhci-hcd xhci-hcd.0.auto: hcc params 0x0220f66d hci version 0x100 quirks 0x00010010 +[ 2.904464] xhci-hcd xhci-hcd.0.auto: irq 23, io mem 0x02f00000 +[ 2.910617] hub 1-0:1.0: USB hub found +[ 2.914367] hub 1-0:1.0: 1 port detected +[ 2.918365] xhci-hcd xhci-hcd.0.auto: xHCI Host Controller +[ 2.923843] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 2 +[ 2.931513] usb usb2: We don't know the algorithms for LPM for this host, disabling LPM. +[ 2.939796] hub 2-0:1.0: USB hub found +[ 2.943543] hub 2-0:1.0: 1 port detected +[ 2.947545] xhci-hcd xhci-hcd.1.auto: xHCI Host Controller +[ 2.953026] xhci-hcd xhci-hcd.1.auto: new USB bus registered, assigned bus number 3 +[ 2.960744] xhci-hcd xhci-hcd.1.auto: hcc params 0x0220f66d hci version 0x100 quirks 0x00010010 +[ 2.969451] xhci-hcd xhci-hcd.1.auto: irq 24, io mem 0x03000000 +[ 2.975566] hub 3-0:1.0: USB hub found +[ 2.979320] hub 3-0:1.0: 1 port detected +[ 2.983307] xhci-hcd xhci-hcd.1.auto: xHCI Host Controller +[ 2.988790] xhci-hcd xhci-hcd.1.auto: new USB bus registered, assigned bus number 4 +[ 2.996458] usb usb4: We don't know the algorithms for LPM for this host, disabling LPM. +[ 3.004729] hub 4-0:1.0: USB hub found +[ 3.008481] hub 4-0:1.0: 1 port detected +[ 3.012480] xhci-hcd xhci-hcd.2.auto: xHCI Host Controller +[ 3.017991] xhci-hcd xhci-hcd.2.auto: new USB bus registered, assigned bus number 5 +[ 3.025707] xhci-hcd xhci-hcd.2.auto: hcc params 0x0220f66d hci version 0x100 quirks 0x00010010 +[ 3.034412] xhci-hcd xhci-hcd.2.auto: irq 25, io mem 0x03100000 +[ 3.040531] hub 5-0:1.0: USB hub found +[ 3.044279] hub 5-0:1.0: 1 port detected +[ 3.048281] xhci-hcd xhci-hcd.2.auto: xHCI Host Controller +[ 3.053760] xhci-hcd xhci-hcd.2.auto: new USB bus registered, assigned bus number 6 +[ 3.061430] usb usb6: We don't know the algorithms for LPM for this host, disabling LPM. +[ 3.069708] hub 6-0:1.0: USB hub found +[ 3.073455] hub 6-0:1.0: 1 port detected +[ 3.077582] usbcore: registered new interface driver usb-storage +[ 3.083766] i2c /dev entries driver +[ 3.087623] sdhci: Secure Digital Host Controller Interface driver +[ 3.093791] sdhci: Copyright(c) Pierre Ossman +[ 3.098176] sdhci-pltfm: SDHCI platform and OF driver helper +[ 3.104921] sdhci-esdhc 1560000.esdhc: No vmmc regulator found +[ 3.110750] sdhci-esdhc 1560000.esdhc: No vqmmc regulator found +[ 3.156192] mmc0: SDHCI controller on 1560000.esdhc [1560000.esdhc] using ADMA 64-bit +[ 3.164615] Freescale USDPAA process driver +[ 3.168795] fsl-usdpaa: no region found +[ 3.172622] Freescale USDPAA process IRQ driver +[ 3.177347] NET: Registered protocol family 10 +[ 3.182411] NET: Registered protocol family 17 +[ 3.186868] bridge: automatic filtering via arp/ip/ip6tables has been deprecated. Update your scripts to load br_netfilter if you need this. +[ 3.199490] 8021q: 802.1Q VLAN Support v1.8 +[ 3.203680] Key type dns_resolver registered +[ 3.208335] fsl_generic: FSL DPAA Generic Ethernet driver +[ 3.213827] hctosys: unable to open rtc device (rtc0) +[ 3.216453] mmc0: new SDHC card at address c1e7 +[ 3.216565] mmcblk0: mmc0:c1e7 SD04G 3.69 GiB +[ 3.222248] mmcblk0: p1 +[ 3.230787] fdt: not creating '/sys/firmware/fdt': CRC check failed +[ 3.238957] VFS: Mounted root (squashfs filesystem) readonly on device 31:6. +[ 3.246102] Freeing unused kernel memory: 276K (ffff800000896000 - ffff8000008db000) +[ 3.246198] usb 1-1: new high-speed USB device number 2 using xhci-hcd +[ 3.260367] Freeing alternatives memory: 32K (ffff8000008db000 - ffff8000008e3000) +[ 3.336224] usb 4-1: new SuperSpeed USB device number 2 using xhci-hcd +[ 3.366274] usb usb5-port1: over-current condition +[ 3.396207] usb usb6-port1: over-current condition +[ 3.472057] init: Console is alive +[ 3.475789] usb-storage 4-1:1.0: USB Mass Storage device detected +[ 3.482115] scsi host0: usb-storage 4-1:1.0 +[ 3.489002] usb 1-1: ep 0x81 - rounding interval to 128 microframes, ep desc says 255 microframes +[ 3.497883] usb 1-1: ep 0x2 - rounding interval to 128 microframes, ep desc says 255 microframes +[ 3.506239] init: - preinit - +[ 3.509783] usb-storage 1-1:1.0: USB Mass Storage device detected +[ 3.516309] scsi host1: usb-storage 1-1:1.0 +[ 3.520651] random: procd urandom read with 3 bits of entropy available +Press the [f] key and hit [enter] to enter failsafe mode +Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level +[ 4.516452] scsi 1:0:0:0: Direct-Access Kingston DT 101 G2 1.00 PQ: 0 ANSI: 2 +[ 4.525022] sd 1:0:0:0: [sda] 3913664 512-byte logical blocks: (2.00 GB/1.87 GiB) +[ 4.532654] sd 1:0:0:0: [sda] Write Protect is off +[ 4.537584] sd 1:0:0:0: [sda] No Caching mode page found +[ 4.542886] sd 1:0:0:0: [sda] Assuming drive cache: write through +[ 4.550171] scsi 0:0:0:0: Direct-Access Kingston DataTraveler 3.0 PMAP PQ: 0 ANSI: 6 +[ 4.550327] sda: sda1 +[ 4.558933] sd 1:0:0:0: [sda] Attached SCSI removable disk +[ 5.540189] mount_root: jffs2 not ready yet, using temporary tmpfs overlay +[ 5.549108] procd: - early - +[ 5.690793] sd 0:0:0:0: [sdb] 30728832 512-byte logical blocks: (15.7 GB/14.7 GiB) +[ 5.698536] sd 0:0:0:0: [sdb] Write Protect is off +[ 5.703407] sd 0:0:0:0: [sdb] No Caching mode page found +[ 5.708715] sd 0:0:0:0: [sdb] Assuming drive cache: write through +[ 5.739138] sdb: sdb1 +[ 5.742231] sd 0:0:0:0: [sdb] Attached SCSI removable disk +[ 6.242632] procd: - ubus - +[ 6.295216] procd: - init - +Please press Enter to activate this console. +[ 7.614535] jffs2_scan_eraseblock(): End of filesystem marker found at 0x0 +[ 7.621575] jffs2_build_filesystem(): unlocking the mtd device... done. +[ 7.628199] jffs2_build_filesystem(): erasing all blocks after the end marker... +[ 7.700603] device eth0 entered promiscuous mode +[ 7.706092] br-lan: port 1(eth0) entered forwarding state +[ 7.711515] br-lan: port 1(eth0) entered forwarding state +[ 9.697128] br-lan: port 1(eth0) entered disabled state + + + +BusyBox v1.24.2 () built-in shell (ash) + + _______ ________ __ + | |.-----.-----.-----.| | | |.----.| |_ + | - || _ | -__| || | | || _|| _| + |_______|| __|_____|__|__||________||__| |____| + |__| W I R E L E S S F R E E D O M + ----------------------------------------------------- + DESIGNATED DRIVER (Bleeding Edge, r49395) + ----------------------------------------------------- + * 2 oz. Orange Juice Combine all juices in a + * 2 oz. Pineapple Juice tall glass filled with + * 2 oz. Grapefruit Juice ice, stir well. + * 2 oz. Cranberry Juice + ----------------------------------------------------- +root at OpenWrt:/# +root at OpenWrt:/# ifconfig +br-lan Link encap:Ethernet HWaddr 00:E0:0C:00:73:00 + inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0 + inet6 addr: fd78:b98d:d12a::1/60 Scope:Global + inet6 addr: fe80::2e0:cff:fe00:7300/64 Scope:Link + UP BROADCAST MULTICAST MTU:1500 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 frame:0 + TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:0 (0.0 B) TX bytes:896 (896.0 B) + +eth0 Link encap:Ethernet HWaddr 00:E0:0C:00:73:00 + UP BROADCAST MULTICAST MTU:1500 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 frame:0 + TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:0 (0.0 B) TX bytes:792 (792.0 B) + Memory:1ae0000-1ae0fff + +eth1 Link encap:Ethernet HWaddr 00:E0:0C:00:73:01 + inet6 addr: fe80::2e0:cff:fe00:7301/64 Scope:Link + UP BROADCAST MULTICAST MTU:1500 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 frame:0 + TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:0 (0.0 B) TX bytes:1160 (1.1 KiB) + Memory:1ae2000-1ae2fff + +lo Link encap:Local Loopback + inet addr:127.0.0.1 Mask:255.0.0.0 + inet6 addr: ::1/128 Scope:Host + UP LOOPBACK RUNNING MTU:65536 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 frame:0 + TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) + +root at OpenWrt:/# cat /proc/mtd +dev: size erasesize name +mtd0: 00100000 00020000 "rcw" +mtd1: 00100000 00020000 "u-boot" +mtd2: 00100000 00020000 "u-boot-env" +mtd3: 00100000 00020000 "fman" +mtd4: 00100000 00020000 "dtb" +mtd5: 00500000 00020000 "kernel" +mtd6: 03600000 00020000 "rootfs" +mtd7: 03500000 00020000 "rootfs_data" +mtd8: 04000000 00020000 "otherbank" +mtd9: 03c00000 00020000 "firmware" +mtd10: 20000000 00020000 "7e800000.flash" +root at OpenWrt:/# +root at OpenWrt:/# mount +/dev/root on /rom type squashfs (ro,relatime) +proc on /proc type proc (rw,nosuid,nodev,noexec,noatime) +sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,noatime) +tmpfs on /tmp type tmpfs (rw,nosuid,nodev,noatime) +tmpfs on /tmp/root type tmpfs (rw,noatime,mode=755) +overlayfs:/tmp/root on / type overlay (rw,noatime,lowerdir=/,upperdir=/tmp/root/upper,workdir=/tmp/root/work) +tmpfs on /dev type tmpfs (rw,nosuid,relatime,size=512k,mode=755) +devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,mode=600) +debugfs on /sys/kernel/debug type debugfs (rw,noatime) +root at OpenWrt:/# +root at OpenWrt:/# cat /etc/config/network + +config interface 'loopback' + option ifname 'lo' + option proto 'static' + option ipaddr '127.0.0.1' + option netmask '255.0.0.0' + +config globals 'globals' + option ula_prefix 'fd78:b98d:d12a::/48' + +config interface 'lan' + option type 'bridge' + option ifname 'eth0' + option proto 'static' + option ipaddr '192.168.1.1' + option netmask '255.255.255.0' + option ip6assign '60' + +config interface 'wan' + option ifname 'eth1' + option proto 'dhcp' + +config interface 'wan6' + option ifname 'eth1' + option proto 'dhcpv6' + +root at OpenWrt:/# +root at OpenWrt:/# ls -l +drwxr-xr-x 2 root root 739 Jun 30 05:39 bin +drwxr-xr-x 5 root root 2300 Jun 30 05:39 dev +drwxr-xr-x 1 root root 120 Jun 30 05:39 etc +drwxrwxr-x 9 root root 372 Jun 30 05:39 lib +lrwxrwxrwx 1 root root 3 Jun 30 05:39 lib64 -> lib +drwxr-xr-x 2 root root 3 Jun 30 05:39 mnt +drwxr-xr-x 2 root root 3 Jun 30 05:39 overlay +dr-xr-xr-x 72 root root 0 Jan 1 1970 proc +drwxr-xr-x 16 root root 212 Jun 30 05:39 rom +drwxr-xr-x 2 root root 3 Jun 30 05:39 root +drwxr-xr-x 2 root root 653 Jun 30 05:39 sbin +dr-xr-xr-x 11 root root 0 Jan 1 1970 sys +drwxrwxrwt 12 root root 340 Jun 30 05:39 tmp +drwxr-xr-x 7 root root 90 Jun 30 05:39 usr +lrwxrwxrwx 1 root root 4 Jun 30 05:39 var -> /tmp +drwxr-xr-x 2 root root 3 Jun 30 05:39 www +root at OpenWrt:/# diff --git a/target/linux/layerscape-64b/base-files/etc/inittab b/target/linux/layerscape-64b/base-files/etc/inittab new file mode 100644 index 0000000..7adc69a --- /dev/null +++ b/target/linux/layerscape-64b/base-files/etc/inittab @@ -0,0 +1,6 @@ +::sysinit:/etc/init.d/rcS S boot +::shutdown:/etc/init.d/rcS K shutdown +ttyS0::askfirst:/bin/ash --login +tts/0::askfirst:/bin/ash --login +ttyAMA0::askfirst:/bin/ash --login +tty1::askfirst:/bin/ash --login diff --git a/target/linux/layerscape-64b/image/Makefile b/target/linux/layerscape-64b/image/Makefile new file mode 100644 index 0000000..43e7269 --- /dev/null +++ b/target/linux/layerscape-64b/image/Makefile @@ -0,0 +1,64 @@ +# +# Copyright (C) 2016 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/image.mk + +# make uImage and dtb +define Image/uImage-dtb + gzip -9c < $(KDIR)/Image > $(KDIR)/Image.gz + $(eval ARCH_BACK = $(ARCH)) + $(eval ARCH = $(LINUX_KARCH)) + $(call Image/BuildKernel/MkuImage, gzip, $(KERNEL_LOADADDR), \ + $(KERNEL_ENTRY_POINT), $(KDIR)/Image.gz, \ + $(KDIR)/$(IMG_PREFIX)-uImage) + $(eval ARCH = $(ARCH_BACK)) + + $(call Image/BuildDTB,$(DTS_DIR)/$(DEVICE_DTS).dts,$(KDIR)/$(IMG_PREFIX)-dtb) +endef + +# $(1) source image name +# $(2) partition image name +# $(3) partition image size(M) +define Image/Build/flashpartitionimage + ./checkimagesize.sh $(1) $(3) + dd if=/dev/zero bs=1M count=$(3) | sed 's/\x00/\xff/g' > $(2) + dd if=$(1) of=$(2) conv=notrunc +endef + +# make squashfs then merge uImage/dtb/squashfs to one firmware image arranged +# by individual partition +define Image/Build/squashfs + $(call prepare_generic_squashfs,$(KDIR)/root.squashfs) + + $(call Image/Build/flashpartitionimage,$(KDIR)/$(IMG_PREFIX)-dtb,$(KDIR)/$(IMG_PREFIX)-dtb-par,$(DTB_PARTITION_SIZE)) + $(call Image/Build/flashpartitionimage,$(KDIR)/$(IMG_PREFIX)-uImage,$(KDIR)/$(IMG_PREFIX)-uImage-par,$(KERNEL_PARTITION_SIZE)) + $(call Image/Build/flashpartitionimage,$(KDIR)/root.squashfs,$(KDIR)/root.squashfs-par,$(SQUASHFS_PARTITION_SIZE)) + cat $(KDIR)/$(IMG_PREFIX)-dtb-par $(KDIR)/$(IMG_PREFIX)-uImage-par \ + $(KDIR)/root.squashfs-par > $(BIN_DIR)/$(IMG_PREFIX)-firmware + $(RM) $(KDIR)/$(IMG_PREFIX)-dtb-par $(KDIR)/$(IMG_PREFIX)-uImage-par \ + $(KDIR)/root.squashfs-par +endef + +# target macros +define Target/Default + KERNEL_LOADADDR = 0x80080000 + KERNEL_ENTRY_POINT = 0x80080000 +endef + +# callback function: Image/BuildKernel +define Image/BuildKernel + $(eval $(call Target/Default)) + $(eval $(call Subtarget/Default)) + $(call Image/uImage-dtb) +endef + +# callback function: Image/Build +define Image/Build + $(call Image/Build/$(1),$(1)) +endef + +$(eval $(call BuildImage)) diff --git a/target/linux/layerscape-64b/image/checkimagesize.sh b/target/linux/layerscape-64b/image/checkimagesize.sh new file mode 100755 index 0000000..e65c7fe --- /dev/null +++ b/target/linux/layerscape-64b/image/checkimagesize.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# +# Licensed under the terms of the GNU GPL License version 2 or later. +# +# $(1) source image name +# $(2) partition image size(M) + +SOURCE_IMAGE_SIZE=`du -b $1 | awk '{print $1}'` +PARTITION_IMAGE_SIZE=`expr $2 \* 1024 \* 1024` + +if [ $SOURCE_IMAGE_SIZE -gt $PARTITION_IMAGE_SIZE ]; then + echo "error: $1 too large than limited $2(M)" + exit 1 +else + exit 0 +fi diff --git a/target/linux/layerscape-64b/ls1043ardb/config-default b/target/linux/layerscape-64b/ls1043ardb/config-default new file mode 100644 index 0000000..1543907 --- /dev/null +++ b/target/linux/layerscape-64b/ls1043ardb/config-default @@ -0,0 +1,3146 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm64 4.1.23 Kernel Configuration +# +CONFIG_ARM64=y +CONFIG_64BIT=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_MMU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ZONE_DMA=y +CONFIG_HAVE_GENERIC_RCU_GUP=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=4 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +# CONFIG_CROSS_MEMORY_ATTACH is not set +# CONFIG_FHANDLE is not set +# CONFIG_USELIB is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_ARCH_AUDITSYSCALL=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_HANDLE_DOMAIN_IRQ=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set +CONFIG_SPARSE_IRQ=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_TASKSTATS is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +CONFIG_SRCU=y +# CONFIG_TASKS_RCU is not set +CONFIG_RCU_STALL_COMMON=y +# CONFIG_RCU_USER_QS is not set +CONFIG_RCU_FANOUT=32 +CONFIG_RCU_FANOUT_LEAF=16 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_RCU_FAST_NO_HZ is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_RCU_KTHREAD_PRIO=0 +# CONFIG_RCU_NOCB_CPU is not set +# CONFIG_RCU_EXPEDITE_BOOT is not set +CONFIG_BUILD_BIN2C=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 +CONFIG_GENERIC_SCHED_CLOCK=y +# CONFIG_CGROUPS is not set +# CONFIG_CHECKPOINT_RESTORE is not set +# CONFIG_NAMESPACES is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_CRASHLOG=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_KALLSYMS_UNCOMPRESSED=y +CONFIG_BPF=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_MULTIUSER=y +# CONFIG_SGETMASK_SYSCALL is not set +# CONFIG_SYSFS_SYSCALL is not set +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_BPF_SYSCALL=y +CONFIG_SHMEM=y +# CONFIG_AIO is not set +# CONFIG_ADVISE_SYSCALLS is not set +CONFIG_PCI_QUIRKS=y +CONFIG_EMBEDDED=y +# CONFIG_MANGLE_BOOTARGS is not set +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +# CONFIG_PERF_EVENTS is not set +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_SYSTEM_TRUSTED_KEYRING is not set +# CONFIG_PROFILING is not set +# CONFIG_JUMP_LABEL is not set +# CONFIG_UPROBES is not set +# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_RCU_TABLE_FREE=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_CC_STACKPROTECTOR=y +CONFIG_CC_STACKPROTECTOR=y +# CONFIG_CC_STACKPROTECTOR_NONE is not set +CONFIG_CC_STACKPROTECTOR_REGULAR=y +# CONFIG_CC_STACKPROTECTOR_STRONG is not set +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_COMPAT_OLD_SIGACTION=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_MODULE_SIG is not set +# CONFIG_MODULE_COMPRESS is not set +CONFIG_MODULE_STRIPPED=y +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_CMDLINE_PARSER is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +# CONFIG_CMDLINE_PARTITION is not set +CONFIG_BLOCK_COMPAT=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +CONFIG_INLINE_READ_UNLOCK=y +CONFIG_INLINE_READ_UNLOCK_IRQ=y +CONFIG_INLINE_WRITE_UNLOCK=y +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_LOCK_SPIN_ON_OWNER=y +# CONFIG_FREEZER is not set + +# +# Platform selection +# +# CONFIG_ARCH_EXYNOS7 is not set +CONFIG_ARCH_LAYERSCAPE=y +# CONFIG_ARCH_MEDIATEK is not set +# CONFIG_ARCH_QCOM is not set +# CONFIG_ARCH_SEATTLE is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_SPRD is not set +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_XGENE is not set +# CONFIG_ARCH_ZYNQMP is not set + +# +# Bus support +# +CONFIG_HAS_FSL_QBMAN=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_SYSCALL=y +CONFIG_PCI_BUS_ADDR_T_64BIT=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_DISABLE_COMMON_QUIRKS is not set +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_PRI is not set +# CONFIG_PCI_PASID is not set +CONFIG_PCI_LABEL=y + +# +# PCI host controller drivers +# +CONFIG_PCIE_DW=y +CONFIG_PCI_LAYERSCAPE=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIEAER=y +# CONFIG_PCIE_ECRC is not set +# CONFIG_PCIEAER_INJECT is not set +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEBUG is not set +CONFIG_PCIEASPM_DEFAULT=y +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_PERFORMANCE is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# Kernel Features +# + +# +# ARM errata workarounds via the alternatives framework +# +CONFIG_ARM64_ERRATUM_826319=y +CONFIG_ARM64_ERRATUM_827319=y +CONFIG_ARM64_ERRATUM_824069=y +CONFIG_ARM64_ERRATUM_819472=y +CONFIG_ARM64_ERRATUM_832075=y +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_64K_PAGES is not set +# CONFIG_ARM64_VA_BITS_39 is not set +CONFIG_ARM64_VA_BITS_48=y +CONFIG_ARM64_VA_BITS=48 +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_SMP=y +# CONFIG_SCHED_MC is not set +# CONFIG_SCHED_SMT is not set +CONFIG_NR_CPUS=64 +CONFIG_HOTPLUG_CPU=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_ARCH_WANT_GENERAL_HUGETLB=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_NO_BOOTMEM=y +# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_TRANSPARENT_HUGEPAGE is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_FRONTSWAP is not set +# CONFIG_CMA is not set +# CONFIG_ZPOOL is not set +# CONFIG_ZBUD is not set +# CONFIG_ZSMALLOC is not set +CONFIG_GENERIC_EARLY_IOREMAP=y +# CONFIG_SECCOMP is not set +# CONFIG_XEN is not set +CONFIG_FORCE_MAX_ZONEORDER=11 +# CONFIG_ARMV8_DEPRECATED is not set + +# +# Boot options +# +CONFIG_CMDLINE="console=ttyAMA0" +# CONFIG_CMDLINE_FORCE is not set +CONFIG_EFI_STUB=y +CONFIG_EFI=y +CONFIG_DMI=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_BINFMT_SCRIPT=y +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_COREDUMP=y +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y + +# +# Power management options +# +# CONFIG_SUSPEND is not set +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y + +# +# CPU Power Management +# + +# +# CPU Idle +# +# CONFIG_CPU_IDLE is not set +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set +CONFIG_NET=y +CONFIG_COMPAT_NETLINK_MESSAGES=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_NET_IP_TUNNEL is not set +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +# CONFIG_IP_PIMSM_V1 is not set +# CONFIG_IP_PIMSM_V2 is not set +CONFIG_SYN_COOKIES=y +# CONFIG_NET_IPVTI is not set +# CONFIG_NET_UDP_TUNNEL is not set +# CONFIG_NET_FOU is not set +# CONFIG_GENEVE is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +CONFIG_TCP_CONG_ADVANCED=y +# CONFIG_TCP_CONG_BIC is not set +CONFIG_TCP_CONG_CUBIC=y +# CONFIG_TCP_CONG_WESTWOOD is not set +# CONFIG_TCP_CONG_HTCP is not set +# CONFIG_TCP_CONG_HSTCP is not set +# CONFIG_TCP_CONG_HYBLA is not set +# CONFIG_TCP_CONG_VEGAS is not set +# CONFIG_TCP_CONG_SCALABLE is not set +# CONFIG_TCP_CONG_LP is not set +# CONFIG_TCP_CONG_VENO is not set +# CONFIG_TCP_CONG_YEAH is not set +# CONFIG_TCP_CONG_ILLINOIS is not set +# CONFIG_TCP_CONG_DCTCP is not set +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_MIP6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET6_XFRM_MODE_TUNNEL is not set +# CONFIG_INET6_XFRM_MODE_BEET is not set +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_SIT is not set +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_GRE is not set +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +# CONFIG_IPV6_MROUTE_MULTIPLE_TABLES is not set +# CONFIG_IPV6_PIMSM_V2 is not set +CONFIG_SOCK_DIAG=y +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NET_PTP_CLASSIFY=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +# CONFIG_BRIDGE_NETFILTER is not set + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NETFILTER_NETLINK_ACCT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE is not set +# CONFIG_NETFILTER_NETLINK_LOG is not set +CONFIG_NF_CONNTRACK=m +CONFIG_NF_LOG_COMMON=m +# CONFIG_NF_CONNTRACK_MARK is not set +# CONFIG_NF_CONNTRACK_ZONES is not set +CONFIG_NF_CONNTRACK_PROCFS=y +# CONFIG_NF_CONNTRACK_EVENTS is not set +CONFIG_NF_CONNTRACK_RTCACHE=m +# CONFIG_NF_CONNTRACK_TIMEOUT is not set +# CONFIG_NF_CONNTRACK_TIMESTAMP is not set +# CONFIG_NF_CT_PROTO_DCCP is not set +# CONFIG_NF_CT_PROTO_SCTP is not set +# CONFIG_NF_CT_PROTO_UDPLITE is not set +# CONFIG_NF_CONNTRACK_AMANDA is not set +# CONFIG_NF_CONNTRACK_FTP is not set +# CONFIG_NF_CONNTRACK_H323 is not set +# CONFIG_NF_CONNTRACK_IRC is not set +# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set +# CONFIG_NF_CONNTRACK_SNMP is not set +# CONFIG_NF_CONNTRACK_PPTP is not set +# CONFIG_NF_CONNTRACK_SANE is not set +# CONFIG_NF_CONNTRACK_SIP is not set +# CONFIG_NF_CONNTRACK_TFTP is not set +# CONFIG_NF_CT_NETLINK is not set +# CONFIG_NF_CT_NETLINK_TIMEOUT is not set +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +# CONFIG_NF_NAT_AMANDA is not set +# CONFIG_NF_NAT_FTP is not set +# CONFIG_NF_NAT_IRC is not set +# CONFIG_NF_NAT_SIP is not set +# CONFIG_NF_NAT_TFTP is not set +CONFIG_NF_NAT_REDIRECT=m +# CONFIG_NF_TABLES is not set +CONFIG_NETFILTER_XTABLES=m + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=m +# CONFIG_NETFILTER_XT_CONNMARK is not set + +# +# Xtables targets +# +# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set +# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set +# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set +CONFIG_NETFILTER_XT_TARGET_CT=m +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +# CONFIG_NETFILTER_XT_TARGET_HL is not set +# CONFIG_NETFILTER_XT_TARGET_HMARK is not set +# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set +# CONFIG_NETFILTER_XT_TARGET_LED is not set +CONFIG_NETFILTER_XT_TARGET_LOG=m +# CONFIG_NETFILTER_XT_TARGET_MARK is not set +CONFIG_NETFILTER_XT_NAT=m +# CONFIG_NETFILTER_XT_TARGET_NETMAP is not set +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +CONFIG_NETFILTER_XT_TARGET_REDIRECT=m +# CONFIG_NETFILTER_XT_TARGET_TEE is not set +# CONFIG_NETFILTER_XT_TARGET_TPROXY is not set +# CONFIG_NETFILTER_XT_TARGET_TRACE is not set +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set + +# +# Xtables matches +# +# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_BPF is not set +# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_CONNMARK is not set +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +# CONFIG_NETFILTER_XT_MATCH_CPU is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set +# CONFIG_NETFILTER_XT_MATCH_ECN is not set +# CONFIG_NETFILTER_XT_MATCH_ESP is not set +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_HELPER is not set +# CONFIG_NETFILTER_XT_MATCH_HL is not set +# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set +CONFIG_NETFILTER_XT_MATCH_ID=m +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +# CONFIG_NETFILTER_XT_MATCH_MARK is not set +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +# CONFIG_NETFILTER_XT_MATCH_POLICY is not set +# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set +CONFIG_NETFILTER_XT_MATCH_STATE=m +# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set +# CONFIG_NETFILTER_XT_MATCH_STRING is not set +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +CONFIG_NETFILTER_XT_MATCH_TIME=m +# CONFIG_NETFILTER_XT_MATCH_U32 is not set +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_CONNTRACK_IPV4=m +# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set +# CONFIG_NF_LOG_ARP is not set +CONFIG_NF_LOG_IPV4=m +CONFIG_NF_REJECT_IPV4=m +CONFIG_NF_NAT_IPV4=m +CONFIG_NF_NAT_MASQUERADE_IPV4=m +# CONFIG_NF_NAT_PPTP is not set +# CONFIG_NF_NAT_H323 is not set +CONFIG_IP_NF_IPTABLES=m +# CONFIG_IP_NF_MATCH_AH is not set +# CONFIG_IP_NF_MATCH_ECN is not set +# CONFIG_IP_NF_MATCH_RPFILTER is not set +# CONFIG_IP_NF_MATCH_TTL is not set +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +# CONFIG_IP_NF_TARGET_SYNPROXY is not set +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +# CONFIG_IP_NF_TARGET_NETMAP is not set +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_MANGLE=m +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_TTL is not set +CONFIG_IP_NF_RAW=m +# CONFIG_IP_NF_ARPTABLES is not set + +# +# IPv6: Netfilter Configuration +# +# CONFIG_NF_DEFRAG_IPV6 is not set +# CONFIG_NF_CONNTRACK_IPV6 is not set +# CONFIG_NF_REJECT_IPV6 is not set +CONFIG_NF_LOG_IPV6=m +# CONFIG_IP6_NF_IPTABLES is not set +# CONFIG_BRIDGE_NF_EBTABLES is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_L2TP is not set +CONFIG_STP=y +CONFIG_BRIDGE=y +CONFIG_BRIDGE_IGMP_SNOOPING=y +# CONFIG_BRIDGE_VLAN_FILTERING is not set +CONFIG_HAVE_NET_DSA=y +CONFIG_VLAN_8021Q=y +# CONFIG_VLAN_8021Q_GVRP is not set +# CONFIG_VLAN_8021Q_MVRP is not set +# CONFIG_DECNET is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +# CONFIG_6LOWPAN is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +# CONFIG_NET_SCH_CBQ is not set +# CONFIG_NET_SCH_HTB is not set +# CONFIG_NET_SCH_HFSC is not set +# CONFIG_NET_SCH_PRIO is not set +# CONFIG_NET_SCH_MULTIQ is not set +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFB is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_ESFQ is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_QFQ is not set +# CONFIG_NET_SCH_CODEL is not set +CONFIG_NET_SCH_FQ_CODEL=y +# CONFIG_NET_SCH_FQ is not set +# CONFIG_NET_SCH_HHF is not set +# CONFIG_NET_SCH_PIE is not set +# CONFIG_NET_SCH_PLUG is not set + +# +# Classification +# +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_TCINDEX is not set +# CONFIG_NET_CLS_ROUTE4 is not set +# CONFIG_NET_CLS_FW is not set +# CONFIG_NET_CLS_U32 is not set +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_CLS_BPF is not set +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_MPLS is not set +# CONFIG_HSR is not set +# CONFIG_NET_SWITCHDEV is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_BPF_JIT is not set +CONFIG_NET_FLOW_LIMIT=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set +# CONFIG_LIB80211_CRYPT_WEP is not set +# CONFIG_LIB80211_CRYPT_CCMP is not set +# CONFIG_LIB80211_CRYPT_TKIP is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +CONFIG_HAVE_BPF_JIT=y + +# +# Device Drivers +# +CONFIG_ARM_AMBA=y +# CONFIG_TEGRA_AHB is not set + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +CONFIG_ALLOW_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_REGMAP=y +# CONFIG_REGMAP_I2C is not set +# CONFIG_REGMAP_SPI is not set +CONFIG_REGMAP_MMIO=y +# CONFIG_DMA_SHARED_BUFFER is not set + +# +# Bus devices +# +CONFIG_VEXPRESS_CONFIG=y +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y + +# +# OpenWrt specific MTD options +# +CONFIG_MTD_ROOTFS_ROOT_DEV=y +# CONFIG_MTD_SPLIT_FIRMWARE is not set +CONFIG_MTD_SPLIT=y +CONFIG_MTD_SPLIT_SUPPORT=y + +# +# Rootfs partition parsers +# +CONFIG_MTD_SPLIT_SQUASHFS_ROOT=y + +# +# Firmware partition parsers +# +# CONFIG_MTD_SPLIT_SEAMA_FW is not set +# CONFIG_MTD_SPLIT_UIMAGE_FW is not set +# CONFIG_MTD_SPLIT_FIT_FW is not set +# CONFIG_MTD_SPLIT_LZMA_FW is not set +# CONFIG_MTD_SPLIT_TPLINK_FW is not set +# CONFIG_MTD_SPLIT_TRX_FW is not set +# CONFIG_MTD_SPLIT_BRNIMAGE_FW is not set +# CONFIG_MTD_SPLIT_EVA_FW is not set +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +CONFIG_FTL=y +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +# CONFIG_MTD_OOPS is not set +# CONFIG_MTD_SWAP is not set +# CONFIG_MTD_PARTITIONED_MASTER is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +# CONFIG_MTD_CFI_NOSWAP is not set +CONFIG_MTD_CFI_BE_BYTE_SWAP=y +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PHYSMAP_OF=y +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_GPIO_ADDR is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_LATCH_ADDR is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +CONFIG_MTD_NAND_ECC=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_ECC_BCH is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_NAND_DENALI is not set +# CONFIG_MTD_NAND_GPIO is not set +# CONFIG_MTD_NAND_OMAP_BCH_BUILD is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_RICOH is not set +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_DOCG4 is not set +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +CONFIG_MTD_NAND_FSL_IFC=y +# CONFIG_MTD_NAND_HISI504 is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR & LPDDR2 PCM memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_SPI_NOR is not set +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y + +# +# Device Tree and Open Firmware support +# +# CONFIG_OF_UNITTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_ADDRESS_PCI=y +CONFIG_OF_IRQ=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_PCI=y +CONFIG_OF_PCI_IRQ=y +CONFIG_OF_MTD=y +CONFIG_OF_RESERVED_MEM=y +# CONFIG_OF_OVERLAY is not set +# CONFIG_PARPORT is not set +CONFIG_PNP=y +CONFIG_PNP_DEBUG_MESSAGES=y + +# +# Protocols +# +CONFIG_PNPACPI=y +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_NVME is not set +# CONFIG_BLK_DEV_SKD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=262144 +# CONFIG_BLK_DEV_PMEM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_VIRTIO_BLK=y +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_BLK_DEV_RSXX is not set + +# +# Misc devices +# +# CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_FSL_USDPAA=y +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set +# CONFIG_BMP085_I2C is not set +# CONFIG_BMP085_SPI is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_SRAM is not set +CONFIG_VEXPRESS_SYSCFG=y +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_CB710_CORE is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set + +# +# Intel MIC Bus Driver +# + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# +# CONFIG_GENWQE is not set +# CONFIG_ECHO is not set +# CONFIG_CXL_BASE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set +# CONFIG_SCSI_MQ_DEFAULT is not set +# CONFIG_SCSI_PROC_FS is not set + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_HAVE_PATA_PLATFORM=y +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_ATA_ACPI=y +CONFIG_SATA_PMP=y + +# +# Controllers with non-SFF native interface +# +CONFIG_SATA_AHCI=y +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_AHCI_XGENE=y +# CONFIG_SATA_INIC162X is not set +# CONFIG_SATA_ACARD_AHCI is not set +# CONFIG_SATA_SIL24 is not set +CONFIG_ATA_SFF=y + +# +# SFF controllers with custom DMA interface +# +# CONFIG_PDC_ADMA is not set +# CONFIG_SATA_QSTOR is not set +# CONFIG_SATA_SX4 is not set +CONFIG_ATA_BMDMA=y + +# +# SATA SFF controllers with BMDMA +# +# CONFIG_ATA_PIIX is not set +# CONFIG_SATA_MV is not set +# CONFIG_SATA_NV is not set +# CONFIG_SATA_PROMISE is not set +# CONFIG_SATA_SIL is not set +# CONFIG_SATA_SIS is not set +# CONFIG_SATA_SVW is not set +# CONFIG_SATA_ULI is not set +# CONFIG_SATA_VIA is not set +# CONFIG_SATA_VITESSE is not set + +# +# PATA SFF controllers with BMDMA +# +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_AMD is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_ATP867X is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_EFAR is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_IT8213 is not set +# CONFIG_PATA_IT821X is not set +# CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_MARVELL is not set +# CONFIG_PATA_NETCELL is not set +# CONFIG_PATA_NINJA32 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OLDPIIX is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC2027X is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_RDC is not set +# CONFIG_PATA_SCH is not set +# CONFIG_PATA_SERVERWORKS is not set +# CONFIG_PATA_SIL680 is not set +# CONFIG_PATA_SIS is not set +# CONFIG_PATA_TOSHIBA is not set +# CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_VIA is not set +# CONFIG_PATA_WINBOND is not set + +# +# PIO-only SFF controllers +# +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_MPIIX is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_OPTI is not set +CONFIG_PATA_PLATFORM=y +CONFIG_PATA_OF_PLATFORM=y +# CONFIG_PATA_RZ1000 is not set + +# +# Generic fallback / legacy drivers +# +# CONFIG_PATA_ACPI is not set +# CONFIG_ATA_GENERIC is not set +# CONFIG_PATA_LEGACY is not set +# CONFIG_MD is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +CONFIG_NETDEVICES=y +CONFIG_MII=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +# CONFIG_DUMMY is not set +# CONFIG_EQUALIZER is not set +# CONFIG_NET_FC is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_IPVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +CONFIG_TUN=y +# CONFIG_VETH is not set +CONFIG_VIRTIO_NET=y +# CONFIG_NLMON is not set +# CONFIG_ARCNET is not set + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_3COM=y +# CONFIG_VORTEX is not set +# CONFIG_TYPHOON is not set +CONFIG_NET_VENDOR_ADAPTEC=y +# CONFIG_ADAPTEC_STARFIRE is not set +CONFIG_NET_VENDOR_AGERE=y +# CONFIG_ET131X is not set +CONFIG_NET_VENDOR_ALTEON=y +# CONFIG_ACENIC is not set +# CONFIG_ALTERA_TSE is not set +CONFIG_NET_VENDOR_AMD=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_PCNET32 is not set +# CONFIG_AMD_XGBE is not set +CONFIG_NET_VENDOR_ARC=y +# CONFIG_ARC_EMAC is not set +CONFIG_NET_VENDOR_ATHEROS=y +# CONFIG_ATL2 is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_ALX is not set +CONFIG_NET_CADENCE=y +# CONFIG_MACB is not set +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_BCMGENET is not set +# CONFIG_BNX2 is not set +# CONFIG_CNIC is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2X is not set +# CONFIG_SYSTEMPORT is not set +CONFIG_NET_VENDOR_BROCADE=y +# CONFIG_BNA is not set +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHELSIO_T4 is not set +# CONFIG_CHELSIO_T4VF is not set +CONFIG_NET_VENDOR_CISCO=y +# CONFIG_ENIC is not set +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_DEC=y +# CONFIG_NET_TULIP is not set +CONFIG_NET_VENDOR_DLINK=y +# CONFIG_DL2K is not set +# CONFIG_SUNDANCE is not set +CONFIG_NET_VENDOR_EMULEX=y +# CONFIG_BE2NET is not set +CONFIG_NET_VENDOR_EXAR=y +# CONFIG_S2IO is not set +# CONFIG_VXGE is not set +CONFIG_NET_VENDOR_FREESCALE=y +# CONFIG_FSL_PQ_MDIO is not set +CONFIG_FSL_XGMAC_MDIO=y +# CONFIG_GIANFAR is not set + +# +# Frame Manager support +# +CONFIG_FSL_SDK_FMAN=y +# CONFIG_FSL_SDK_FMAN_TEST is not set + +# +# FMAN Processor support +# +CONFIG_FMAN_ARM=y +# CONFIG_FMAN_P3040_P4080_P5020 is not set +# CONFIG_FMAN_P1023 is not set +# CONFIG_FMAN_V3H is not set +# CONFIG_FMAN_V3L is not set +# CONFIG_FMAN_MIB_CNT_OVF_IRQ_EN is not set +CONFIG_FSL_FM_MAX_FRAME_SIZE=1522 +CONFIG_FSL_FM_RX_EXTRA_HEADROOM=64 +# CONFIG_FMAN_PFC is not set +CONFIG_FSL_SDK_DPAA_ETH=y +# CONFIG_FSL_DPAA_HOOKS is not set +# CONFIG_FSL_DPAA_MACSEC is not set +CONFIG_FSL_DPAA_OFFLINE_PORTS=y +CONFIG_FSL_DPAA_ADVANCED_DRIVERS=y +CONFIG_FSL_DPAA_GENERIC_DRIVER=y +# CONFIG_FSL_DPAA_TS is not set +# CONFIG_FSL_DPAA_1588 is not set +CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE=y +CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT=128 +CONFIG_FSL_DPAA_ETH_REFILL_THRESHOLD=80 +CONFIG_FSL_DPAA_CS_THRESHOLD_1G=0x06000000 +CONFIG_FSL_DPAA_CS_THRESHOLD_10G=0x10000000 +CONFIG_FSL_DPAA_INGRESS_CS_THRESHOLD=0x10000000 +CONFIG_FSL_DPAA_ETH_DEBUGFS=y +# CONFIG_FSL_DPAA_ETH_DEBUG is not set +# CONFIG_FSL_DPAA_DBG_LOOP is not set +CONFIG_NET_VENDOR_HP=y +# CONFIG_HP100 is not set +CONFIG_NET_VENDOR_INTEL=y +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +CONFIG_E1000E=y +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +# CONFIG_IXGBEVF is not set +# CONFIG_I40E is not set +# CONFIG_I40EVF is not set +# CONFIG_FM10K is not set +CONFIG_NET_VENDOR_I825XX=y +# CONFIG_IP1000 is not set +# CONFIG_JME is not set +CONFIG_NET_VENDOR_MARVELL=y +# CONFIG_MVMDIO is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +CONFIG_NET_VENDOR_MELLANOX=y +# CONFIG_MLX4_EN is not set +# CONFIG_MLX4_CORE is not set +# CONFIG_MLX5_CORE is not set +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_KSZ884X_PCI is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +CONFIG_NET_VENDOR_MYRI=y +# CONFIG_MYRI10GE is not set +# CONFIG_FEALNX is not set +CONFIG_NET_VENDOR_NATSEMI=y +# CONFIG_NATSEMI is not set +# CONFIG_NS83820 is not set +CONFIG_NET_VENDOR_8390=y +# CONFIG_NE2K_PCI is not set +CONFIG_NET_VENDOR_NVIDIA=y +# CONFIG_FORCEDETH is not set +CONFIG_NET_VENDOR_OKI=y +# CONFIG_ETHOC is not set +# CONFIG_NET_PACKET_ENGINE is not set +CONFIG_NET_VENDOR_QLOGIC=y +# CONFIG_QLA3XXX is not set +# CONFIG_QLCNIC is not set +# CONFIG_QLGE is not set +# CONFIG_NETXEN_NIC is not set +CONFIG_NET_VENDOR_QUALCOMM=y +# CONFIG_QCA7000 is not set +CONFIG_NET_VENDOR_REALTEK=y +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_R8169 is not set +CONFIG_NET_VENDOR_RDC=y +# CONFIG_R6040 is not set +CONFIG_NET_VENDOR_ROCKER=y +CONFIG_NET_VENDOR_SAMSUNG=y +# CONFIG_SXGBE_ETH is not set +CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SILAN=y +# CONFIG_SC92031 is not set +CONFIG_NET_VENDOR_SIS=y +# CONFIG_SIS900 is not set +# CONFIG_SIS190 is not set +# CONFIG_SFC is not set +CONFIG_NET_VENDOR_SMSC=y +CONFIG_SMC91X=y +# CONFIG_EPIC100 is not set +# CONFIG_SMSC911X is not set +# CONFIG_SMSC9420 is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_SUN=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NIU is not set +CONFIG_NET_VENDOR_TEHUTI=y +# CONFIG_TEHUTI is not set +CONFIG_NET_VENDOR_TI=y +# CONFIG_TI_CPSW_ALE is not set +# CONFIG_TLAN is not set +CONFIG_NET_VENDOR_VIA=y +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_NET_SB1000 is not set +CONFIG_PHYLIB=y +CONFIG_MDIO_BOARDINFO=y +# CONFIG_SWCONFIG is not set + +# +# MII PHY device drivers +# +CONFIG_AQUANTIA_PHY=y +# CONFIG_AT803X_PHY is not set +# CONFIG_AMD_PHY is not set +# CONFIG_AMD_XGBE_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +CONFIG_VITESSE_PHY=y +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_ICPLUS_PHY is not set +CONFIG_REALTEK_PHY=y +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_ADM6996_PHY is not set +# CONFIG_MVSWITCH_PHY is not set +# CONFIG_MVSW61XX_PHY is not set +# CONFIG_IP17XX_PHY is not set +# CONFIG_AR8216_PHY is not set +# CONFIG_RTL8306_PHY is not set +CONFIG_FIXED_PHY=y +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_RTL8366_SMI is not set +# CONFIG_MICREL_KS8995MA is not set +# CONFIG_PSB6970_PHY is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_USB_NET_DRIVERS=y +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_RTL8152 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set +CONFIG_WLAN=y +# CONFIG_PRISM54 is not set +# CONFIG_HOSTAP is not set +CONFIG_WL_TI=y + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_VMXNET3 is not set +CONFIG_ISDN=y +# CONFIG_ISDN_I4L is not set +# CONFIG_ISDN_CAPI is not set +# CONFIG_ISDN_DRV_GIGASET is not set +# CONFIG_HYSDN is not set +# CONFIG_MISDN is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +# CONFIG_VT is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_SYSRQ is not set +CONFIG_SERIAL_8250_DMA=y +# CONFIG_SERIAL_8250_PCI is not set +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_DW is not set +# CONFIG_SERIAL_8250_FINTEK is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_SERIAL_OF_PLATFORM=y +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_RP2 is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set +# CONFIG_TTY_PRINTK is not set +# CONFIG_VIRTIO_CONSOLE is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# PCMCIA character devices +# +# CONFIG_RAW_DRIVER is not set +# CONFIG_HPET is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +# CONFIG_XILLYBUS is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_ACPI_I2C_OPREGION=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_PCA9541 is not set +CONFIG_I2C_MUX_PCA954x=y +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# ACPI drivers +# +# CONFIG_I2C_SCMI is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_DESIGNWARE_PCI is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_RK3X is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_SLAVE is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_GPIO_OLD is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +CONFIG_SPI_PL022=y +# CONFIG_SPI_PXA2XX is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_ROCKCHIP is not set +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPMI is not set +# CONFIG_HSI is not set + +# +# PPS support +# +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_GPIO is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=y + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_DEVRES=y +CONFIG_OF_GPIO=y +CONFIG_GPIO_ACPI=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_GENERIC=y + +# +# Memory mapped GPIO drivers +# +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ALTERA is not set +# CONFIG_GPIO_DWAPB is not set +CONFIG_GPIO_GENERIC_PLATFORM=y +# CONFIG_GPIO_GRGPIO is not set +CONFIG_GPIO_MPC8XXX=y +CONFIG_GPIO_PL061=y +# CONFIG_GPIO_SCH311X is not set +# CONFIG_GPIO_SYSCON is not set +# CONFIG_GPIO_VX855 is not set +CONFIG_GPIO_XGENE=y + +# +# I2C GPIO expanders +# +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_SX150X is not set + +# +# MFD GPIO expanders +# + +# +# PCI GPIO expanders +# +# CONFIG_GPIO_AMD8111 is not set +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_ML_IOH is not set +# CONFIG_GPIO_RDC321X is not set + +# +# SPI GPIO expanders +# +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set + +# +# USB GPIO expanders +# +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +CONFIG_POWER_RESET=y +# CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +# CONFIG_POWER_RESET_LTC2952 is not set +# CONFIG_POWER_RESET_RESTART is not set +CONFIG_POWER_RESET_VEXPRESS=y +# CONFIG_POWER_RESET_XGENE is not set +# CONFIG_POWER_RESET_SYSCON is not set +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set +CONFIG_POWER_RESET_LAYERSCAPE=y +# CONFIG_POWER_AVS is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_CORE is not set +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_GPIO_WATCHDOG is not set +# CONFIG_XILINX_WATCHDOG is not set +# CONFIG_ARM_SP805_WATCHDOG is not set +# CONFIG_CADENCE_WATCHDOG is not set +# CONFIG_DW_WATCHDOG is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_I6300ESB_WDT is not set +# CONFIG_GPIO_WDT is not set +# CONFIG_MEN_A21_WDT is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_ATMEL_HLCDC is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_AXP20X is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9063 is not set +# CONFIG_MFD_DA9150 is not set +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_INTEL_SOC_PMIC is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_RTSX_PCI is not set +# CONFIG_MFD_RT5033 is not set +# CONFIG_MFD_RTSX_USB is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK808 is not set +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +CONFIG_MFD_VEXPRESS_SYSREG=y +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGA_ARB is not set + +# +# Direct Rendering Manager +# +# CONFIG_DRM is not set + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_FOREIGN_ENDIAN is not set +# CONFIG_FB_SYS_FOPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +CONFIG_FB_ARMCLCD=y +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_I740 is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_CARMINE is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_AUO_K190X is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_FB_SSD1307 is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +# CONFIG_VGASTATE is not set +CONFIG_VIDEOMODE_HELPERS=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_SOUND is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_OTG_FSM is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PCI=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_FSL is not set +CONFIG_USB_EHCI_HCD_PLATFORM=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_FUSBH200_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_MAX3421_HCD is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PCI=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HCD_TEST_MODE is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set +# CONFIG_USB_MUSB_HDRC is not set +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_HOST=y + +# +# Platform Glue Driver Support +# +CONFIG_USB_DWC3_PCI=y + +# +# Debugging features +# +# CONFIG_USB_DWC3_DEBUG is not set +# CONFIG_USB_DWC2 is not set +# CONFIG_USB_CHIPIDEA is not set +CONFIG_USB_ISP1760=y +CONFIG_USB_ISP1760_HCD=y +CONFIG_USB_ISP1760_HOST_ROLE=y + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_EHSET_TEST_FIXTURE is not set +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_LINK_LAYER_TEST is not set + +# +# USB Physical Layer drivers +# +# CONFIG_USB_PHY is not set +# CONFIG_NOP_USB_XCEIV is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_VIEWPORT=y +# CONFIG_USB_GADGET is not set +# CONFIG_USB_LED_TRIG is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_CLKGATE is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_ARMMMCI=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +# CONFIG_MMC_SDHCI_PCI is not set +# CONFIG_MMC_SDHCI_ACPI is not set +CONFIG_MMC_SDHCI_PLTFM=y +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +CONFIG_MMC_SDHCI_OF_ESDHC=y +# CONFIG_MMC_SDHCI_F_SDH30 is not set +# CONFIG_MMC_TIFM_SD is not set +CONFIG_MMC_SPI=y +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_VIA_SDMMC is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_USDHI6ROL0 is not set +# CONFIG_MMC_TOSHIBA_PCI is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLASS_FLASH is not set + +# +# LED drivers +# +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_LP8860 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_INTEL_SS4200 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_LM355x is not set + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_SYSCON is not set +# CONFIG_LEDS_PM8941_WLED is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +# CONFIG_LEDS_TRIGGER_ONESHOT is not set +# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_CPU is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +# CONFIG_LEDS_TRIGGER_MORSE is not set +CONFIG_LEDS_TRIGGER_NETDEV=y +# CONFIG_LEDS_TRIGGER_USBDEV is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABX80X is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12057 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set +# CONFIG_RTC_DRV_PT7C4338 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_MCP795 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1685_FAMILY is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +CONFIG_RTC_DRV_EFI=y +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_RTC7301 is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_RTC_DRV_SNVS is not set +CONFIG_RTC_DRV_XGENE=y + +# +# HID Sensor RTC drivers +# +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +# CONFIG_AMBA_PL08X is not set +# CONFIG_DW_DMAC is not set +# CONFIG_DW_DMAC_PCI is not set +# CONFIG_HSU_DMA_PCI is not set +# CONFIG_PL330_DMA is not set +# CONFIG_FSL_EDMA is not set +CONFIG_DMA_ENGINE=y +CONFIG_DMA_ACPI=y +CONFIG_DMA_OF=y + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +# CONFIG_VFIO is not set +# CONFIG_VIRT_DRIVERS is not set +CONFIG_VIRTIO=y + +# +# Virtio drivers +# +# CONFIG_VIRTIO_PCI is not set +# CONFIG_VIRTIO_BALLOON is not set +CONFIG_VIRTIO_MMIO=y +# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_STAGING=y +# CONFIG_COMEDI is not set +# CONFIG_RTL8192U is not set +# CONFIG_RTLLIB is not set +# CONFIG_R8712U is not set +# CONFIG_R8188EU is not set +# CONFIG_RTS5208 is not set +# CONFIG_FB_SM7XX is not set +# CONFIG_FB_SM750 is not set +# CONFIG_FB_XGI is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +# CONFIG_USB_WPAN_HCD is not set +# CONFIG_WIMAX_GDM72XX is not set +# CONFIG_LTE_GDM724X is not set +# CONFIG_MTD_SPINAND_MT29F is not set +# CONFIG_LUSTRE_FS is not set +# CONFIG_DGNC is not set +# CONFIG_DGAP is not set +# CONFIG_GS_FPGABOOT is not set +# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set +# CONFIG_FB_TFT is not set +# CONFIG_I2O is not set +CONFIG_FSL_MC_BUS=y +CONFIG_FSL_DPA=y + +# +# Freescale Datapath QMan/BMan options +# +# CONFIG_FSL_DPA_CHECKING is not set +CONFIG_FSL_DPA_CAN_WAIT=y +CONFIG_FSL_DPA_CAN_WAIT_SYNC=y +CONFIG_FSL_DPA_PIRQ_FAST=y +CONFIG_FSL_DPA_PIRQ_SLOW=y +CONFIG_FSL_DPA_PORTAL_SHARE=y +CONFIG_FSL_BMAN=y +CONFIG_FSL_BMAN_CONFIG=y +# CONFIG_FSL_BMAN_TEST is not set +CONFIG_FSL_BMAN_DEBUGFS=y +CONFIG_FSL_QMAN=y +CONFIG_FSL_QMAN_POLL_LIMIT=32 +CONFIG_FSL_QMAN_CONFIG=y +# CONFIG_FSL_QMAN_TEST is not set +CONFIG_FSL_QMAN_DEBUGFS=y +CONFIG_FSL_QMAN_FQD_SZ=10 +CONFIG_FSL_QMAN_PFDR_SZ=13 +CONFIG_FSL_QMAN_CI_SCHED_CFG_SRCCIV=4 +CONFIG_FSL_QMAN_CI_SCHED_CFG_SRQ_W=3 +CONFIG_FSL_QMAN_CI_SCHED_CFG_RW_W=2 +CONFIG_FSL_QMAN_CI_SCHED_CFG_BMAN_W=2 +CONFIG_FSL_QMAN_PIRQ_DQRR_ITHRESH=12 +CONFIG_FSL_QMAN_PIRQ_MR_ITHRESH=4 +CONFIG_FSL_QMAN_PIRQ_IPERIOD=100 +CONFIG_FSL_QMAN_FQ_LOOKUP=y +CONFIG_QMAN_CEETM_UPDATE_PERIOD=1000 +CONFIG_FSL_QMAN_INIT_TIMEOUT=10 +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Common Clock Framework +# +CONFIG_COMMON_CLK_VERSATILE=y +CONFIG_CLK_SP810=y +CONFIG_CLK_VEXPRESS_OSC=y +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI570 is not set +CONFIG_CLK_QORIQ=y +CONFIG_COMMON_CLK_XGENE=y +# CONFIG_COMMON_CLK_PXA is not set +# CONFIG_COMMON_CLK_CDCE706 is not set + +# +# Hardware Spinlock drivers +# + +# +# Clock Source drivers +# +CONFIG_CLKSRC_OF=y +CONFIG_CLKSRC_MMIO=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +# CONFIG_ATMEL_PIT is not set +# CONFIG_SH_TIMER_CMT is not set +# CONFIG_SH_TIMER_MTU2 is not set +# CONFIG_SH_TIMER_TMU is not set +# CONFIG_EM_TIMER_STI is not set +# CONFIG_MAILBOX is not set +CONFIG_IOMMU_API=y +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +CONFIG_IOMMU_IO_PGTABLE=y +CONFIG_IOMMU_IO_PGTABLE_LPAE=y +# CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST is not set +CONFIG_OF_IOMMU=y +CONFIG_ARM_SMMU=y + +# +# Remoteproc drivers +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers +# + +# +# SOC (System On Chip) specific Drivers +# +# CONFIG_SOC_TI is not set +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +CONFIG_MEMORY=y +CONFIG_FSL_IFC=y +# CONFIG_IIO is not set +# CONFIG_VME_BUS is not set +# CONFIG_PWM is not set +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_LS1_MSI=y +# CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# CONFIG_BCM_KONA_USB2_PHY is not set +CONFIG_PHY_XGENE=y +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set +CONFIG_RAS=y +# CONFIG_THUNDERBOLT is not set + +# +# Android +# +# CONFIG_ANDROID is not set + +# +# Firmware Drivers +# +# CONFIG_FIRMWARE_MEMMAP is not set +CONFIG_DMIID=y +# CONFIG_DMI_SYSFS is not set + +# +# EFI (Extensible Firmware Interface) Support +# +# CONFIG_EFI_VARS is not set +CONFIG_EFI_PARAMS_FROM_FDT=y +CONFIG_EFI_RUNTIME_WRAPPERS=y +CONFIG_EFI_ARMSTUB=y +CONFIG_ACPI=y +CONFIG_ACPI_GENERIC_GSI=y +# CONFIG_ACPI_PROCFS_POWER is not set +# CONFIG_ACPI_EC_DEBUGFS is not set +# CONFIG_ACPI_DOCK is not set +# CONFIG_ACPI_CUSTOM_DSDT is not set +# CONFIG_ACPI_DEBUG is not set +# CONFIG_ACPI_PCI_SLOT is not set +# CONFIG_ACPI_CONTAINER is not set +# CONFIG_ACPI_HED is not set +# CONFIG_ACPI_CUSTOM_METHOD is not set +CONFIG_ACPI_REDUCED_HARDWARE_ONLY=y +# CONFIG_PMIC_OPREGION is not set + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_DEFAULTS_TO_ORDERED=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_EXT4_FS=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_ENCRYPTION is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +# CONFIG_F2FS_FS is not set +# CONFIG_YAFFS_FS is not set +# CONFIG_FS_DAX is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +# CONFIG_DIRECT_IO is not set +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +CONFIG_QUOTA=y +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +CONFIG_PRINT_QUOTA_WARNING=y +# CONFIG_QUOTA_DEBUG is not set +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set +CONFIG_QUOTACTL=y +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=y +CONFIG_CUSE=y +CONFIG_OVERLAY_FS=y + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +# CONFIG_PROC_PAGE_MONITOR is not set +CONFIG_PROC_STRIPPED=y +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +CONFIG_TMPFS_XATTR=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +# CONFIG_CONFIGFS_FS is not set +CONFIG_EFIVAR_FS=m +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +# CONFIG_JFFS2_LZMA is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_FILE_CACHE=y +# CONFIG_SQUASHFS_FILE_DIRECT is not set +CONFIG_SQUASHFS_DECOMP_SINGLE=y +# CONFIG_SQUASHFS_DECOMP_MULTI is not set +# CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU is not set +# CONFIG_SQUASHFS_XATTR is not set +CONFIG_SQUASHFS_ZLIB=y +# CONFIG_SQUASHFS_LZ4 is not set +# CONFIG_SQUASHFS_LZO is not set +# CONFIG_SQUASHFS_XZ is not set +# CONFIG_SQUASHFS_4K_DEVBLK_SIZE is not set +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V2=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_SWAP is not set +# CONFIG_NFS_V4_1 is not set +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +# CONFIG_NFSD is not set +CONFIG_GRACE_PERIOD=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +# CONFIG_SUNRPC_DEBUG is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +# CONFIG_NLS_UTF8 is not set +CONFIG_KVM_COMPAT=y +# CONFIG_VIRTUALIZATION is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_DYNAMIC_DEBUG is not set + +# +# Compile-time checks and compiler options +# +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_INFO_REDUCED=y +# CONFIG_DEBUG_INFO_SPLIT is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +# CONFIG_GDB_SCRIPTS is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +CONFIG_STRIP_ASM_SYMS=y +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_TIMER_STATS is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +# CONFIG_STACKTRACE is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_HAVE_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set + +# +# RCU Debugging +# +# CONFIG_PROVE_RCU is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_TORTURE_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_CPU_STALL_INFO is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set + +# +# Runtime Testing +# +# CONFIG_LKDTM is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +CONFIG_ATOMIC64_SELFTEST=y +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_BPF is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_MEMTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_ARM64_PTDUMP is not set +# CONFIG_STRICT_DEVMEM is not set +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set +# CONFIG_DEBUG_SET_MODULE_RONX is not set +# CONFIG_DEBUG_RODATA is not set +# CONFIG_CORESIGHT is not set + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +# CONFIG_CRYPTO_AEAD is not set +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +# CONFIG_CRYPTO_RNG is not set +CONFIG_CRYPTO_RNG2=y +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_USER is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_MCRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_CMAC is not set +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32 is not set +# CONFIG_CRYPTO_CRCT10DIF is not set +# CONFIG_CRYPTO_GHASH is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +# CONFIG_CRYPTO_XZ is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_DRBG_MENU is not set +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_HW is not set +# CONFIG_ASYMMETRIC_KEY_TYPE is not set + +# +# OCF Configuration +# +# CONFIG_OCF_OCF is not set +# CONFIG_ARM64_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +# CONFIG_CRC_CCITT is not set +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +# CONFIG_CRC32_SLICEBY8 is not set +# CONFIG_CRC32_SLICEBY4 is not set +CONFIG_CRC32_SARWATE=y +# CONFIG_CRC32_BIT is not set +CONFIG_CRC7=y +# CONFIG_LIBCRC32C is not set +# CONFIG_CRC8 is not set +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_LZ4_COMPRESS is not set +# CONFIG_LZ4HC_COMPRESS is not set +# CONFIG_LZ4_DECOMPRESS is not set +CONFIG_XZ_DEC=y +# CONFIG_XZ_DEC_X86 is not set +# CONFIG_XZ_DEC_POWERPC is not set +# CONFIG_XZ_DEC_IA64 is not set +# CONFIG_XZ_DEC_ARM is not set +# CONFIG_XZ_DEC_ARMTHUMB is not set +# CONFIG_XZ_DEC_SPARC is not set +# CONFIG_XZ_DEC_BCJ is not set +# CONFIG_XZ_DEC_TEST is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_TEXTSEARCH=y +# CONFIG_TEXTSEARCH_KMP is not set +# CONFIG_TEXTSEARCH_BM is not set +# CONFIG_TEXTSEARCH_FSM is not set +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_GLOB=y +# CONFIG_GLOB_SELFTEST is not set +CONFIG_NLATTR=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +CONFIG_AVERAGE=y +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set +CONFIG_LIBFDT=y +CONFIG_OID_REGISTRY=y +CONFIG_UCS2_STRING=y +CONFIG_ARCH_HAS_SG_CHAIN=y diff --git a/target/linux/layerscape-64b/ls1043ardb/target.mk b/target/linux/layerscape-64b/ls1043ardb/target.mk new file mode 100644 index 0000000..9f2580b --- /dev/null +++ b/target/linux/layerscape-64b/ls1043ardb/target.mk @@ -0,0 +1,16 @@ +# +# Copyright (C) 2016 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +BOARDNAME += $(SUBTARGET) + +# subtarget macros +# PARTITION_SIZE unit: (M) +define Subtarget/Default + DEVICE_DTS = freescale/fsl-ls1043a-rdb + DTB_PARTITION_SIZE = 1 + KERNEL_PARTITION_SIZE = 5 + SQUASHFS_PARTITION_SIZE = 54 +endef -- 1.7.9.5 _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From yutang.jiang at nxp.com Wed Jul 13 13:56:10 2016 From: yutang.jiang at nxp.com (yutang.jiang at nxp.com) Date: Thu, 14 Jul 2016 01:56:10 +0800 Subject: [OpenWrt-Devel] [PATCH 2/2] ls1043ardb-64b: add 4.1 kernel patches In-Reply-To: <1468432570-7202-1-git-send-email-yutang.jiang@nxp.com> References: <1468432570-7202-1-git-send-email-yutang.jiang@nxp.com> Message-ID: <1468432570-7202-2-git-send-email-yutang.jiang@nxp.com> From: Yutang Jiang Signed-off-by: Yutang Jiang --- ...ls1043a-add-DTS-for-Freescale-LS1043A-SoC.patch | 558 + ...LS2080A-compilation-under-ARCH_LAYERSCAPE.patch | 31 + ...-dts-ls1043a-add-LS1043ARDB-board-support.patch | 156 + ...e-ARCH_LAYERSCAPE-for-Layerscape-SoC-fami.patch | 49 + ...-Move-chip-specific-knowledge-into-driver.patch | 1579 + .../0006-clk-qoriq-Add-ls2080a-support.patch | 181 + .../0007-clk-qoriq-Add-ls1043a-support.patch | 80 + .../0008-clk-qoriq-fix-memory-leak.patch | 36 + ...ls1043a-add-fman-bman-qman-ethernet-nodes.patch | 754 + .../0010-dts-ls1043ardb-add-mdio-phy-nodes.patch | 86 + ...d-ARM-specific-fucntions-required-for-ehc.patch | 86 + ...fsl-add-a-sanity-check-for-complete-handl.patch | 36 + ...-remove-dependency-FSL_SOC-for-ehci-fsl-d.patch | 30 + ...043a-Add-configure-gfladj-property-to-USB.patch | 38 + ...c-fsl-Move-fsl_guts.h-out-of-arch-powerpc.patch | 637 + ...river-memory-Removal-of-deprecated-NO_IRQ.patch | 29 + ...fsl-remove-dependency-FSL_SOC-for-Gianfar.patch | 36 + .../0018-temp-QE-headers-are-needed-by-FMD.patch | 1326 + .../patches-4.1/0019-fmd-add-SDK1.9-codebase.patch |115016 ++++++++++++++++++++ .../0020-devres-add-devm_alloc_percpu.patch | 147 + .../patches-4.1/0021-net-readd-skb_recycle.patch | 66 + .../0022-net-add-custom-NETIF-flags.patch | 41 + ...e-netdev-watchdog-aware-of-hardware-multi.patch | 53 + .../patches-4.1/0024-dpa-add-SDK1.9-codebase.patch |17026 +++ ...s-devicetree-doc-out-of-powerpc-directory.patch | 107 + ...c-fsl-move-mpc85xx.h-to-include-linux-fsl.patch | 300 + .../0027-fman-update-an-outdated-header.patch | 56 + ..._eth-add-promisc-handler-for-proxy-driver.patch | 37 + ..._eth-remove-VERSION-and-dpa_get_ringparam.patch | 241 + ...030-dpaa_eth-add-EEE-callbacks-in-ethtool.patch | 71 + ...ve-exported-counters-from-debugfs-into-et.patch | 619 + .../0032-dpaa_eth-set-MAC-handle-for-MEMAC.patch | 28 + .../0033-dpaa_eth-rename-ethtool-statistic.patch | 26 + ...move-PPC-dependencies-from-the-macsec-deb.patch | 54 + ...map-the-S-G-table-prior-to-iterate-throug.patch | 112 + ...6-dpaa_eth-memset-the-S-G-entry-structure.patch | 30 + .../0037-dpaa_eth-add-S-G-for-onic.patch | 495 + .../0038-dpaa_eth-remove-copyright-statement.patch | 28 + .../0039-dpaa_eth-remove-TODO-list.patch | 39 + ...h-create-macro-def-for-numerical-constant.patch | 38 + ...eth-use-IFF_UP-to-check-the-Eth-interface.patch | 68 + ..._eth-rename-variables-and-remove-comments.patch | 75 + ...043-dpaa_eth-remove-dead-unnecessary-code.patch | 123 + ...paa_eth-use-common-preprocessor-procedure.patch | 30 + ...45-dpaa_eth-fix-unload-procedure-for-onic.patch | 110 + ...eth-fix-call-to-of_node_put-in-dts-parser.patch | 45 + ...eth-generic-fix-an-uninitialized-variable.patch | 25 + ...ove-debugfs-into-ethtool-stats-for-macsec.patch | 757 + ...-Move-debugfs-into-ethtool-stats-for-oNIC.patch | 667 + ...d-counter-for-Scatter-Gather-frames-on-RX.patch | 104 + ...APIs-to-setup-HugeTLB-mappings-for-USDPAA.patch | 62 + .../0052-Port-QBMan-Code-from-SDK-1.9.patch |23605 ++++ ...d-invalidation-in-case-PAMU-is-not-enable.patch | 55 + .../0054-fsl_qbman-Use-do_div-when-dividing.patch | 30 + .../0055-arm64-Add-pdev_archdata-for-dmamask.patch | 58 + ...pdate-QBMan-drivers-to-support-little-end.patch | 2549 + ...an-Enable-DPAA1-QBMan-for-ARM64-platforms.patch | 36 + .../0058-dpaa_eth-fix-the-bitfields-of-a-FD.patch | 67 + .../0059-dpaa_eth-fix-S-G-for-ARM.patch | 56 + ...an-Convenient-accessors-for-S-G-structure.patch | 168 + ...-fix-CGR-congestion-indication-processing.patch | 40 + .../0062-qbman-fix-qm_sg_entry-structure.patch | 77 + ...fix-CGR-average-instantaneous-byte-counts.patch | 85 + ...064-fsl_qbman-Fix-Frame-Queue-Stash-setup.patch | 38 + .../0065-bman-fix-stockpile-logic.patch | 196 + .../patches-4.1/0066-fmd-add-LS1043-support.patch | 3599 + ...se-S-G-accessors-in-the-Shared-Mac-driver.patch | 78 + .../0068-dpaa_eth-fix-S-G-for-ARM.patch | 212 + ...mset-bm_buffer-and-qm_sg_entry-structures.patch | 26 + ...eth-Fix-dma_map-unmap-for-the-Tx-S-G-path.patch | 87 + ...e-raw_smp_processor_id-to-get-queue-mappi.patch | 32 + .../0072-dpaa_eth-added-qsgmii-support.patch | 56 + ...e-accessors-to-update-and-query-the-qm_sg.patch | 227 + ...-dpaa_eth-support-PTPd-1588-stack-for-ARM.patch | 48 + ...ad-ts-value-according-to-its-endianness-t.patch | 28 + ...76-dpaa_eth-fix-fq-dts-parser-for-macless.patch | 39 + ...7-dpaa_eth-fix-modification-of-const-data.patch | 226 + ...a_eth-add-primitives-for-buffer-alignment.patch | 32 + ...-dpaa_eth-remove-jumbo-frame-optimization.patch | 37 + ...aa_eth-allocate-one-full-page-for-buffers.patch | 33 + ...eth-create-particular-define-for-4K-issue.patch | 54 + ...-dpaa_eth-fix-S-G-for-TX-on-ARM-platforms.patch | 216 + ...h-create-a-S-G-frame-for-4K-contig-frames.patch | 39 + ...eth-fix-max-number-of-S-G-entries-for-ARM.patch | 47 + ...t-dma-coherent-mask-when-setting-dma-mask.patch | 26 + .../0086-dpaa_eth-force-DMA-coherency.patch | 26 + .../0087-dpaa_eth-force-DMA-coherency-ops.patch | 30 + ...88-dpaa_eth-devm_ioremap_prot-was-removed.patch | 59 + .../0089-dpaa_eth-include-needed-header.patch | 25 + .../patches-4.1/0090-dpaa_eth-small-fixes.patch | 129 + ...-dpaa_eth-use-proper-identifier-for-ARM64.patch | 27 + ...-dpaa_eth-enable-on-both-ARM64-or-FSL_SOC.patch | 25 + .../0093-dpaa_eth-remove-ASF-related-code.patch | 29 + ...md-fix-issue-with-HM-in-CC-in-compat-mode.patch | 33 + ...a_eth-do-not-print-debug-message-as-error.patch | 26 + .../0096-fmd-adapt-to-the-new-clocking-model.patch | 65 + ...arm64-dts-align-to-the-new-clocking-model.patch | 30 + ...iq-optimize-the-CPU-frequency-switching-t.patch | 130 + ...iq-Don-t-look-at-clock-implementation-det.patch | 279 + ...-net-phy-Add-support-for-Realtek-RTL8211F.patch | 126 + ...0101-net-phy-add-RealTek-RTL8211DN-phy-id.patch | 48 + ...e-get_phy_c45_ids-to-support-more-c45-phy.patch | 60 + ...0103-net-phy-fix-a-bug-in-get_phy_c45_ids.patch | 126 + ...4-net-mdio-fix-mdio_bus_match-for-c45-PHY.patch | 54 + .../0105-net-phy-add-driver-for-aquantia-phy.patch | 210 + ...-net-fsl-Enable-XGMAC_MDIO-on-LS2085A-SoC.patch | 42 + ...change-ls2-arch-define-to-ARCH_LAYERSCAPE.patch | 29 + ...-phy-fix-PHY_RUNNING-in-phy_state_machine.patch | 56 + ...hy-add-interrupt-support-for-aquantia-phy.patch | 113 + ...oremap-for-normal-cacheable-non-shareable.patch | 46 + ...upport-to-remap-kernel-cacheable-memory-t.patch | 33 + ...le-add-support-to-map-cacheable-and-non-s.patch | 27 + ...fmd-remove-misuse-of-IRQF_NO_SUSPEND-flag.patch | 77 + .../0114-ls2085a-Add-support-for-reset.patch | 145 + .../0115-dts-ls1043a-add-reset-node.patch | 33 + .../0116-ls1043a-Add-support-for-reset.patch | 61 + ...r-Kconfig-Change-define-to-ARCH_LAYERSCAP.patch | 27 + ...nware-Add-base-driver-for-Designware-PCIe.patch | 407 + ...are-find-msi-controller-via-msi-parent-ha.patch | 79 + ...0-pci-layerscape-Add-LS2085A-PCIe-support.patch | 326 + ...ape-PCIe-controller-stream-ID-partitionin.patch | 155 + ...yerscape-Add-compatible-string-for-LS2080.patch | 25 + ...ape-Add-compatible-in-probe-function-for-.patch | 28 + ...i-layerscape-Add-PCIe-RC-EP-mode-checking.patch | 48 + ...0125-PCI-layerscape-backport-from-4.4-rc1.patch | 387 + ...ape-PCIe-controller-stream-ID-partitionin.patch | 127 + ...7-pci-layerscape-fix-MSG-TLP-drop-setting.patch | 71 + .../0128-pci-msi-fix-compile-issue-on-arm32.patch | 40 + ...designware-add-modifications-from-4.4-rc1.patch | 836 + ...-designware-remove-designware-MSI-support.patch | 331 + ...ignware-Add-support-non-dw-MSI-controller.patch | 89 + .../patches-4.1/0132-arm-Add-MSI-support.patch | 369 + ...m64-layerscape-Enable-PCIe-for-Layerscape.patch | 25 + .../0134-ls1043a-msi-add-ls1043a-MSI-support.patch | 174 + .../patches-4.1/0135-arm64-add-NO_IRQ-macro.patch | 32 + ...o-Port-gpio-driver-to-support-layerscape-.patch | 296 + .../0137-layerscape-dts-Update-GPIO-node.patch | 72 + ...fc-Change-IO-accessor-based-on-endianness.patch | 686 + ...ers-memory-Add-deep-sleep-support-for-IFC.patch | 240 + ...ry-Update-dependency-of-IFC-for-Layerscap.patch | 61 + ...c-Segregate-IFC-fcm-and-runtime-registers.patch | 713 + ...-drivers-memory-Fix-build-error-for-arm64.patch | 58 + ...-compilation-error-when-COMPAT-not-enable.patch | 34 + ...sdhc-add-default-quirk-SDHCI_QUIRK_NO_HIS.patch | 32 + ...dd-fixup-of-broken-CMD23-for-Sandisk-card.patch | 42 + ...DT-binding-for-little-endian-eSDHC-host-c.patch | 28 + ...f-esdhc-support-both-BE-and-LE-host-contr.patch | 643 + ...fig-reconfigure-MMC_SDHCI_OF_ESDHC-option.patch | 42 + ...f-esdhc-avoid-writing-power-control-regis.patch | 36 + ...f-esdhc-add-remove-some-quirks-according-.patch | 65 + 150 files changed, 183449 insertions(+) create mode 100644 target/linux/layerscape-64b/patches-4.1/0001-arm64-ls1043a-add-DTS-for-Freescale-LS1043A-SoC.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0002-arm64-Move-LS2080A-compilation-under-ARCH_LAYERSCAPE.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0003-dts-ls1043a-add-LS1043ARDB-board-support.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0004-arm64-Define-ARCH_LAYERSCAPE-for-Layerscape-SoC-fami.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0005-clk-qoriq-Move-chip-specific-knowledge-into-driver.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0006-clk-qoriq-Add-ls2080a-support.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0007-clk-qoriq-Add-ls1043a-support.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0008-clk-qoriq-fix-memory-leak.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0009-dts-ls1043a-add-fman-bman-qman-ethernet-nodes.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0010-dts-ls1043ardb-add-mdio-phy-nodes.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0011-arch-arm-add-ARM-specific-fucntions-required-for-ehc.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0012-USB-Gadget-fsl-add-a-sanity-check-for-complete-handl.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0013-usb-kconfig-remove-dependency-FSL_SOC-for-ehci-fsl-d.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0014-arm-dts-ls1043a-Add-configure-gfladj-property-to-USB.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0015-powerpc-fsl-Move-fsl_guts.h-out-of-arch-powerpc.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0016-driver-memory-Removal-of-deprecated-NO_IRQ.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0017-net-fsl-remove-dependency-FSL_SOC-for-Gianfar.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0018-temp-QE-headers-are-needed-by-FMD.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0019-fmd-add-SDK1.9-codebase.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0020-devres-add-devm_alloc_percpu.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0021-net-readd-skb_recycle.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0022-net-add-custom-NETIF-flags.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0023-net-Make-the-netdev-watchdog-aware-of-hardware-multi.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0024-dpa-add-SDK1.9-codebase.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0025-dt-move-guts-devicetree-doc-out-of-powerpc-directory.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0026-powerpc-fsl-move-mpc85xx.h-to-include-linux-fsl.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0027-fman-update-an-outdated-header.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0028-dpaa_eth-add-promisc-handler-for-proxy-driver.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0029-dpaa_eth-remove-VERSION-and-dpa_get_ringparam.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0030-dpaa_eth-add-EEE-callbacks-in-ethtool.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0031-dpaa_eth-Move-exported-counters-from-debugfs-into-et.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0032-dpaa_eth-set-MAC-handle-for-MEMAC.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0033-dpaa_eth-rename-ethtool-statistic.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0034-dpaa_eth-Remove-PPC-dependencies-from-the-macsec-deb.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0035-dpaa_eth-Unmap-the-S-G-table-prior-to-iterate-throug.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0036-dpaa_eth-memset-the-S-G-entry-structure.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0037-dpaa_eth-add-S-G-for-onic.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0038-dpaa_eth-remove-copyright-statement.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0039-dpaa_eth-remove-TODO-list.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0040-dpaa_eth-create-macro-def-for-numerical-constant.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0041-dpaa_eth-use-IFF_UP-to-check-the-Eth-interface.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0042-dpaa_eth-rename-variables-and-remove-comments.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0043-dpaa_eth-remove-dead-unnecessary-code.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0044-dpaa_eth-use-common-preprocessor-procedure.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0045-dpaa_eth-fix-unload-procedure-for-onic.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0046-dpaa_eth-fix-call-to-of_node_put-in-dts-parser.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0047-dpaa_eth-generic-fix-an-uninitialized-variable.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0048-dpaa_eth-Move-debugfs-into-ethtool-stats-for-macsec.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0049-dpaa_eth-Move-debugfs-into-ethtool-stats-for-oNIC.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0050-dpaa_eth-Add-counter-for-Scatter-Gather-frames-on-RX.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0051-Add-APIs-to-setup-HugeTLB-mappings-for-USDPAA.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0052-Port-QBMan-Code-from-SDK-1.9.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0053-fsl_qman-Add-invalidation-in-case-PAMU-is-not-enable.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0054-fsl_qbman-Use-do_div-when-dividing.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0055-arm64-Add-pdev_archdata-for-dmamask.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0056-fsl_qbman-Update-QBMan-drivers-to-support-little-end.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0057-fsl_qbman-Enable-DPAA1-QBMan-for-ARM64-platforms.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0058-dpaa_eth-fix-the-bitfields-of-a-FD.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0059-dpaa_eth-fix-S-G-for-ARM.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0060-fsl_qbman-Convenient-accessors-for-S-G-structure.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0061-fsl_qman-fix-CGR-congestion-indication-processing.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0062-qbman-fix-qm_sg_entry-structure.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0063-fsl_qbman-fix-CGR-average-instantaneous-byte-counts.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0064-fsl_qbman-Fix-Frame-Queue-Stash-setup.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0065-bman-fix-stockpile-logic.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0066-fmd-add-LS1043-support.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0067-dpaa_eth-Use-S-G-accessors-in-the-Shared-Mac-driver.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0068-dpaa_eth-fix-S-G-for-ARM.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0069-dpaa_eth-memset-bm_buffer-and-qm_sg_entry-structures.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0070-dpaa_eth-Fix-dma_map-unmap-for-the-Tx-S-G-path.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0071-dpaa_eth-Use-raw_smp_processor_id-to-get-queue-mappi.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0072-dpaa_eth-added-qsgmii-support.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0073-dpaa_eth-Use-accessors-to-update-and-query-the-qm_sg.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0074-dpaa_eth-support-PTPd-1588-stack-for-ARM.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0075-dpaa_eth-read-ts-value-according-to-its-endianness-t.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0076-dpaa_eth-fix-fq-dts-parser-for-macless.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0077-dpaa_eth-fix-modification-of-const-data.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0078-dpaa_eth-add-primitives-for-buffer-alignment.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0079-dpaa_eth-remove-jumbo-frame-optimization.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0080-dpaa_eth-allocate-one-full-page-for-buffers.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0081-dpaa_eth-create-particular-define-for-4K-issue.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0082-dpaa_eth-fix-S-G-for-TX-on-ARM-platforms.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0083-dpaa_eth-create-a-S-G-frame-for-4K-contig-frames.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0084-dpaa_eth-fix-max-number-of-S-G-entries-for-ARM.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0085-dpaa_eth-set-dma-coherent-mask-when-setting-dma-mask.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0086-dpaa_eth-force-DMA-coherency.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0087-dpaa_eth-force-DMA-coherency-ops.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0088-dpaa_eth-devm_ioremap_prot-was-removed.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0089-dpaa_eth-include-needed-header.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0090-dpaa_eth-small-fixes.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0091-dpaa_eth-use-proper-identifier-for-ARM64.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0092-dpaa_eth-enable-on-both-ARM64-or-FSL_SOC.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0093-dpaa_eth-remove-ASF-related-code.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0094-fmd-fix-issue-with-HM-in-CC-in-compat-mode.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0095-dpaa_eth-do-not-print-debug-message-as-error.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0096-fmd-adapt-to-the-new-clocking-model.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0097-arm64-dts-align-to-the-new-clocking-model.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0098-cpufreq-qoriq-optimize-the-CPU-frequency-switching-t.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0099-cpufreq-qoriq-Don-t-look-at-clock-implementation-det.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0100-net-phy-Add-support-for-Realtek-RTL8211F.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0101-net-phy-add-RealTek-RTL8211DN-phy-id.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0102-net-phy-tune-get_phy_c45_ids-to-support-more-c45-phy.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0103-net-phy-fix-a-bug-in-get_phy_c45_ids.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0104-net-mdio-fix-mdio_bus_match-for-c45-PHY.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0105-net-phy-add-driver-for-aquantia-phy.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0106-net-fsl-Enable-XGMAC_MDIO-on-LS2085A-SoC.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0107-net-fsl-change-ls2-arch-define-to-ARCH_LAYERSCAPE.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0108-net-phy-fix-PHY_RUNNING-in-phy_state_machine.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0109-net-phy-add-interrupt-support-for-aquantia-phy.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0110-arm64-add-ioremap-for-normal-cacheable-non-shareable.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0111-arm64-add-support-to-remap-kernel-cacheable-memory-t.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0112-arm64-pgtable-add-support-to-map-cacheable-and-non-s.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0113-fmd-remove-misuse-of-IRQF_NO_SUSPEND-flag.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0114-ls2085a-Add-support-for-reset.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0115-dts-ls1043a-add-reset-node.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0116-ls1043a-Add-support-for-reset.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0117-reset-driver-Kconfig-Change-define-to-ARCH_LAYERSCAP.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0118-pci-designware-Add-base-driver-for-Designware-PCIe.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0119-pci-designware-find-msi-controller-via-msi-parent-ha.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0120-pci-layerscape-Add-LS2085A-PCIe-support.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0121-pci-layerscape-PCIe-controller-stream-ID-partitionin.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0122-pci-layerscape-Add-compatible-string-for-LS2080.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0123-pci-layerscape-Add-compatible-in-probe-function-for-.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0124-pci-layerscape-Add-PCIe-RC-EP-mode-checking.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0125-PCI-layerscape-backport-from-4.4-rc1.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0126-pci-layerscape-PCIe-controller-stream-ID-partitionin.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0127-pci-layerscape-fix-MSG-TLP-drop-setting.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0128-pci-msi-fix-compile-issue-on-arm32.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0129-PCI-designware-add-modifications-from-4.4-rc1.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0130-PCI-designware-remove-designware-MSI-support.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0131-pci-designware-Add-support-non-dw-MSI-controller.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0132-arm-Add-MSI-support.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0133-arm64-layerscape-Enable-PCIe-for-Layerscape.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0134-ls1043a-msi-add-ls1043a-MSI-support.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0135-arm64-add-NO_IRQ-macro.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0136-drivers-gpio-Port-gpio-driver-to-support-layerscape-.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0137-layerscape-dts-Update-GPIO-node.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0138-fsl_ifc-Change-IO-accessor-based-on-endianness.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0139-drivers-memory-Add-deep-sleep-support-for-IFC.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0140-driver-memory-Update-dependency-of-IFC-for-Layerscap.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0141-mtd-ifc-Segregate-IFC-fcm-and-runtime-registers.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0142-drivers-memory-Fix-build-error-for-arm64.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0143-fsl-ifc-fix-compilation-error-when-COMPAT-not-enable.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0144-mmc-sdhci-esdhc-add-default-quirk-SDHCI_QUIRK_NO_HIS.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0145-mmc-block-add-fixup-of-broken-CMD23-for-Sandisk-card.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0146-mmc-dt-add-DT-binding-for-little-endian-eSDHC-host-c.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0147-mmc-sdhci-of-esdhc-support-both-BE-and-LE-host-contr.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0148-mmc-kconfig-reconfigure-MMC_SDHCI_OF_ESDHC-option.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0149-mmc-sdhci-of-esdhc-avoid-writing-power-control-regis.patch create mode 100644 target/linux/layerscape-64b/patches-4.1/0150-mmc-sdhci-of-esdhc-add-remove-some-quirks-according-.patch diff --git a/target/linux/layerscape-64b/patches-4.1/0001-arm64-ls1043a-add-DTS-for-Freescale-LS1043A-SoC.patch b/target/linux/layerscape-64b/patches-4.1/0001-arm64-ls1043a-add-DTS-for-Freescale-LS1043A-SoC.patch new file mode 100644 index 0000000..96d8bc2 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0001-arm64-ls1043a-add-DTS-for-Freescale-LS1043A-SoC.patch @@ -0,0 +1,558 @@ +From 99904118b8ad879b3164173a50c74ca8a9efb687 Mon Sep 17 00:00:00 2001 +From: Mingkai Hu +Date: Mon, 21 Jul 2014 14:48:42 +0800 +Subject: [PATCH 001/151] arm64/ls1043a: add DTS for Freescale LS1043A SoC + +LS1043a is an SoC with 4 ARMv8 A53 cores and most other IP blocks +similar to LS1021a which complies to Chassis 2.1 spec. + +Following levels of DTSI/DTS files have been created for the +LS1043A SoC family: + +- fsl-ls1043a.dtsi: + DTS-Include file for FSL LS1043A SoC. + +Signed-off-by: Li Yang +Signed-off-by: Hou Zhiqiang +Signed-off-by: Mingkai Hu +Signed-off-by: Wenbin Song +Signed-off-by: Mingkai Hu +--- + arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 525 +++++++++++++++++++++++++ + 1 file changed, 525 insertions(+) + create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi + +diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +new file mode 100644 +index 0000000..cb00a84 +--- /dev/null ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +@@ -0,0 +1,525 @@ ++/* ++ * Device Tree Include file for Freescale Layerscape-1043A family SoC. ++ * ++ * Copyright 2014-2015, Freescale Semiconductor ++ * ++ * Mingkai Hu ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPLv2 or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/ { ++ compatible = "fsl,ls1043a"; ++ interrupt-parent = <&gic>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ++ cpus { ++ #address-cells = <2>; ++ #size-cells = <0>; ++ ++ /* ++ * We expect the enable-method for cpu's to be "psci", but this ++ * is dependent on the SoC FW, which will fill this in. ++ * ++ * Currently supported enable-method is psci v0.2 ++ */ ++ cpu0: cpu at 0 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x0 0x0>; ++ clocks = <&clockgen 1 0>; ++ }; ++ ++ cpu1: cpu at 1 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x0 0x1>; ++ clocks = <&clockgen 1 0>; ++ }; ++ ++ cpu2: cpu at 2 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x0 0x2>; ++ clocks = <&clockgen 1 0>; ++ }; ++ ++ cpu3: cpu at 3 { ++ device_type = "cpu"; ++ compatible = "arm,cortex-a53"; ++ reg = <0x0 0x3>; ++ clocks = <&clockgen 1 0>; ++ }; ++ }; ++ ++ memory at 80000000 { ++ device_type = "memory"; ++ reg = <0x0 0x80000000 0 0x80000000>; ++ /* DRAM space 1, size: 2GiB DRAM */ ++ }; ++ ++ sysclk: sysclk { ++ compatible = "fixed-clock"; ++ #clock-cells = <0>; ++ clock-frequency = <100000000>; ++ clock-output-names = "sysclk"; ++ }; ++ ++ timer { ++ compatible = "arm,armv8-timer"; ++ interrupts = <1 13 0x1>, /* Physical Secure PPI */ ++ <1 14 0x1>, /* Physical Non-Secure PPI */ ++ <1 11 0x1>, /* Virtual PPI */ ++ <1 10 0x1>; /* Hypervisor PPI */ ++ }; ++ ++ pmu { ++ compatible = "arm,armv8-pmuv3"; ++ interrupts = <0 106 0x4>, ++ <0 107 0x4>, ++ <0 95 0x4>, ++ <0 97 0x4>; ++ interrupt-affinity = <&cpu0>, ++ <&cpu1>, ++ <&cpu2>, ++ <&cpu3>; ++ }; ++ ++ gic: interrupt-controller at 1400000 { ++ compatible = "arm,gic-400"; ++ #interrupt-cells = <3>; ++ interrupt-controller; ++ reg = <0x0 0x1401000 0 0x1000>, /* GICD */ ++ <0x0 0x1402000 0 0x2000>, /* GICC */ ++ <0x0 0x1404000 0 0x2000>, /* GICH */ ++ <0x0 0x1406000 0 0x2000>; /* GICV */ ++ interrupts = <1 9 0xf08>; ++ }; ++ ++ soc { ++ compatible = "simple-bus"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ clockgen: clocking at 1ee1000 { ++ compatible = "fsl,ls1043a-clockgen"; ++ reg = <0x0 0x1ee1000 0x0 0x1000>; ++ #clock-cells = <2>; ++ clocks = <&sysclk>; ++ }; ++ ++ scfg: scfg at 1570000 { ++ compatible = "fsl,ls1043a-scfg", "syscon"; ++ reg = <0x0 0x1570000 0x0 0x10000>; ++ big-endian; ++ }; ++ ++ dcfg: dcfg at 1ee0000 { ++ compatible = "fsl,ls1043a-dcfg", "syscon"; ++ reg = <0x0 0x1ee0000 0x0 0x10000>; ++ }; ++ ++ ifc: ifc at 1530000 { ++ compatible = "fsl,ifc", "simple-bus"; ++ reg = <0x0 0x1530000 0x0 0x10000>; ++ interrupts = <0 43 0x4>; ++ }; ++ ++ esdhc: esdhc at 1560000 { ++ compatible = "fsl,ls1043a-esdhc", "fsl,esdhc"; ++ reg = <0x0 0x1560000 0x0 0x10000>; ++ interrupts = <0 62 0x4>; ++ clock-frequency = <0>; ++ voltage-ranges = <1800 1800 3300 3300>; ++ sdhci,auto-cmd12; ++ big-endian; ++ bus-width = <4>; ++ }; ++ ++ dspi0: dspi at 2100000 { ++ compatible = "fsl,ls1043a-dspi", "fsl,ls1021a-v1.0-dspi"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x0 0x2100000 0x0 0x10000>; ++ interrupts = <0 64 0x4>; ++ clock-names = "dspi"; ++ clocks = <&clockgen 4 0>; ++ spi-num-chipselects = <5>; ++ big-endian; ++ status = "disabled"; ++ }; ++ ++ dspi1: dspi at 2110000 { ++ compatible = "fsl,ls1043a-dspi", "fsl,ls1021a-v1.0-dspi"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x0 0x2110000 0x0 0x10000>; ++ interrupts = <0 65 0x4>; ++ clock-names = "dspi"; ++ clocks = <&clockgen 4 0>; ++ spi-num-chipselects = <5>; ++ big-endian; ++ status = "disabled"; ++ }; ++ ++ i2c0: i2c at 2180000 { ++ compatible = "fsl,vf610-i2c"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x0 0x2180000 0x0 0x10000>; ++ interrupts = <0 56 0x4>; ++ clock-names = "i2c"; ++ clocks = <&clockgen 4 0>; ++ dmas = <&edma0 1 39>, ++ <&edma0 1 38>; ++ dma-names = "tx", "rx"; ++ status = "disabled"; ++ }; ++ ++ i2c1: i2c at 2190000 { ++ compatible = "fsl,vf610-i2c"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x0 0x2190000 0x0 0x10000>; ++ interrupts = <0 57 0x4>; ++ clock-names = "i2c"; ++ clocks = <&clockgen 4 0>; ++ status = "disabled"; ++ }; ++ ++ i2c2: i2c at 21a0000 { ++ compatible = "fsl,vf610-i2c"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x0 0x21a0000 0x0 0x10000>; ++ interrupts = <0 58 0x4>; ++ clock-names = "i2c"; ++ clocks = <&clockgen 4 0>; ++ status = "disabled"; ++ }; ++ ++ i2c3: i2c at 21b0000 { ++ compatible = "fsl,vf610-i2c"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ reg = <0x0 0x21b0000 0x0 0x10000>; ++ interrupts = <0 59 0x4>; ++ clock-names = "i2c"; ++ clocks = <&clockgen 4 0>; ++ status = "disabled"; ++ }; ++ ++ duart0: serial at 21c0500 { ++ compatible = "fsl,ns16550", "ns16550a"; ++ reg = <0x00 0x21c0500 0x0 0x100>; ++ interrupts = <0 54 0x4>; ++ clocks = <&clockgen 4 0>; ++ }; ++ ++ duart1: serial at 21c0600 { ++ compatible = "fsl,ns16550", "ns16550a"; ++ reg = <0x00 0x21c0600 0x0 0x100>; ++ interrupts = <0 54 0x4>; ++ clocks = <&clockgen 4 0>; ++ }; ++ ++ duart2: serial at 21d0500 { ++ compatible = "fsl,ns16550", "ns16550a"; ++ reg = <0x0 0x21d0500 0x0 0x100>; ++ interrupts = <0 55 0x4>; ++ clocks = <&clockgen 4 0>; ++ }; ++ ++ duart3: serial at 21d0600 { ++ compatible = "fsl,ns16550", "ns16550a"; ++ reg = <0x0 0x21d0600 0x0 0x100>; ++ interrupts = <0 55 0x4>; ++ clocks = <&clockgen 4 0>; ++ }; ++ ++ gpio1: gpio at 2300000 { ++ compatible = "fsl,ls1043a-gpio"; ++ reg = <0x0 0x2300000 0x0 0x10000>; ++ interrupts = <0 66 0x4>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ gpio2: gpio at 2310000 { ++ compatible = "fsl,ls1043a-gpio"; ++ reg = <0x0 0x2310000 0x0 0x10000>; ++ interrupts = <0 67 0x4>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ gpio3: gpio at 2320000 { ++ compatible = "fsl,ls1043a-gpio"; ++ reg = <0x0 0x2320000 0x0 0x10000>; ++ interrupts = <0 68 0x4>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ gpio4: gpio at 2330000 { ++ compatible = "fsl,ls1043a-gpio"; ++ reg = <0x0 0x2330000 0x0 0x10000>; ++ interrupts = <0 134 0x4>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ lpuart0: serial at 2950000 { ++ compatible = "fsl,ls1021a-lpuart"; ++ reg = <0x0 0x2950000 0x0 0x1000>; ++ interrupts = <0 48 0x4>; ++ clocks = <&clockgen 0 0>; ++ clock-names = "ipg"; ++ status = "disabled"; ++ }; ++ ++ lpuart1: serial at 2960000 { ++ compatible = "fsl,ls1021a-lpuart"; ++ reg = <0x0 0x2960000 0x0 0x1000>; ++ interrupts = <0 49 0x4>; ++ clocks = <&clockgen 4 0>; ++ clock-names = "ipg"; ++ status = "disabled"; ++ }; ++ ++ lpuart2: serial at 2970000 { ++ compatible = "fsl,ls1021a-lpuart"; ++ reg = <0x0 0x2970000 0x0 0x1000>; ++ interrupts = <0 50 0x4>; ++ clocks = <&clockgen 4 0>; ++ clock-names = "ipg"; ++ status = "disabled"; ++ }; ++ ++ lpuart3: serial at 2980000 { ++ compatible = "fsl,ls1021a-lpuart"; ++ reg = <0x0 0x2980000 0x0 0x1000>; ++ interrupts = <0 51 0x4>; ++ clocks = <&clockgen 4 0>; ++ clock-names = "ipg"; ++ status = "disabled"; ++ }; ++ ++ lpuart4: serial at 2990000 { ++ compatible = "fsl,ls1021a-lpuart"; ++ reg = <0x0 0x2990000 0x0 0x1000>; ++ interrupts = <0 52 0x4>; ++ clocks = <&clockgen 4 0>; ++ clock-names = "ipg"; ++ status = "disabled"; ++ }; ++ ++ lpuart5: serial at 29a0000 { ++ compatible = "fsl,ls1021a-lpuart"; ++ reg = <0x0 0x29a0000 0x0 0x1000>; ++ interrupts = <0 53 0x4>; ++ clocks = <&clockgen 4 0>; ++ clock-names = "ipg"; ++ status = "disabled"; ++ }; ++ ++ wdog0: wdog at 2ad0000 { ++ compatible = "fsl,ls1043a-wdt", "fsl,imx21-wdt"; ++ reg = <0x0 0x2ad0000 0x0 0x10000>; ++ interrupts = <0 83 0x4>; ++ clocks = <&clockgen 4 0>; ++ clock-names = "wdog"; ++ big-endian; ++ }; ++ ++ edma0: edma at 2c00000 { ++ #dma-cells = <2>; ++ compatible = "fsl,vf610-edma"; ++ reg = <0x0 0x2c00000 0x0 0x10000>, ++ <0x0 0x2c10000 0x0 0x10000>, ++ <0x0 0x2c20000 0x0 0x10000>; ++ interrupts = <0 103 0x4>, ++ <0 103 0x4>; ++ interrupt-names = "edma-tx", "edma-err"; ++ dma-channels = <32>; ++ big-endian; ++ clock-names = "dmamux0", "dmamux1"; ++ clocks = <&clockgen 4 0>, ++ <&clockgen 4 0>; ++ }; ++ ++ usb0: usb3 at 2f00000 { ++ compatible = "snps,dwc3"; ++ reg = <0x0 0x2f00000 0x0 0x10000>; ++ interrupts = <0 60 0x4>; ++ dr_mode = "host"; ++ }; ++ ++ usb1: usb3 at 3000000 { ++ compatible = "snps,dwc3"; ++ reg = <0x0 0x3000000 0x0 0x10000>; ++ interrupts = <0 61 0x4>; ++ dr_mode = "host"; ++ }; ++ ++ usb2: usb3 at 3100000 { ++ compatible = "snps,dwc3"; ++ reg = <0x0 0x3100000 0x0 0x10000>; ++ interrupts = <0 63 0x4>; ++ dr_mode = "host"; ++ }; ++ ++ sata: sata at 3200000 { ++ compatible = "fsl,ls1043a-ahci"; ++ reg = <0x0 0x3200000 0x0 0x10000>; ++ interrupts = <0 69 0x4>; ++ clocks = <&clockgen 4 0>; ++ }; ++ ++ msi1: msi-controller1 at 1571000 { ++ compatible = "fsl,1s1043a-msi"; ++ reg = <0x0 0x1571000 0x0 0x4>, ++ <0x0 0x1571004 0x0 0x4>; ++ reg-names = "msiir", "msir"; ++ msi-controller; ++ interrupts = <0 116 0x4>; ++ }; ++ ++ msi2: msi-controller2 at 1572000 { ++ compatible = "fsl,1s1043a-msi"; ++ reg = <0x0 0x1572000 0x0 0x4>, ++ <0x0 0x1572004 0x0 0x4>; ++ reg-names = "msiir", "msir"; ++ msi-controller; ++ interrupts = <0 126 0x4>; ++ }; ++ ++ msi3: msi-controller3 at 1573000 { ++ compatible = "fsl,1s1043a-msi"; ++ reg = <0x0 0x1573000 0x0 0x4>, ++ <0x0 0x1573004 0x0 0x4>; ++ reg-names = "msiir", "msir"; ++ msi-controller; ++ interrupts = <0 160 0x4>; ++ }; ++ ++ pcie at 3400000 { ++ compatible = "fsl,ls1043a-pcie", "snps,dw-pcie"; ++ reg = <0x00 0x03400000 0x0 0x00100000 /* controller registers */ ++ 0x40 0x00000000 0x0 0x00002000>; /* configuration space */ ++ reg-names = "regs", "config"; ++ interrupts = <0 118 0x4>, /* controller interrupt */ ++ <0 117 0x4>; /* PME interrupt */ ++ interrupt-names = "intr", "pme"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; ++ num-lanes = <4>; ++ bus-range = <0x0 0xff>; ++ ranges = <0x81000000 0x0 0x00000000 0x40 0x00010000 0x0 0x00010000 /* downstream I/O */ ++ 0x82000000 0x0 0x40000000 0x40 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ ++ msi-parent = <&msi1>; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0000 0 0 1 &gic 0 110 0x4>, ++ <0000 0 0 2 &gic 0 111 0x4>, ++ <0000 0 0 3 &gic 0 112 0x4>, ++ <0000 0 0 4 &gic 0 113 0x4>; ++ }; ++ ++ pcie at 3500000 { ++ compatible = "fsl,ls1043a-pcie", "snps,dw-pcie"; ++ reg = <0x00 0x03500000 0x0 0x00100000 /* controller registers */ ++ 0x48 0x00000000 0x0 0x00002000>; /* configuration space */ ++ reg-names = "regs", "config"; ++ interrupts = <0 128 0x4>, ++ <0 127 0x4>; ++ interrupt-names = "intr", "pme"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; ++ num-lanes = <2>; ++ bus-range = <0x0 0xff>; ++ ranges = <0x81000000 0x0 0x00000000 0x48 0x00010000 0x0 0x00010000 /* downstream I/O */ ++ 0x82000000 0x0 0x40000000 0x48 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ ++ msi-parent = <&msi2>; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0000 0 0 1 &gic 0 120 0x4>, ++ <0000 0 0 2 &gic 0 121 0x4>, ++ <0000 0 0 3 &gic 0 122 0x4>, ++ <0000 0 0 4 &gic 0 123 0x4>; ++ }; ++ ++ pcie at 3600000 { ++ compatible = "fsl,ls1043a-pcie", "snps,dw-pcie"; ++ reg = <0x00 0x03600000 0x0 0x00100000 /* controller registers */ ++ 0x50 0x00000000 0x0 0x00002000>; /* configuration space */ ++ reg-names = "regs", "config"; ++ interrupts = <0 162 0x4>, ++ <0 161 0x4>; ++ interrupt-names = "intr", "pme"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ device_type = "pci"; ++ num-lanes = <2>; ++ bus-range = <0x0 0xff>; ++ ranges = <0x81000000 0x0 0x00000000 0x50 0x00010000 0x0 0x00010000 /* downstream I/O */ ++ 0x82000000 0x0 0x40000000 0x50 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */ ++ msi-parent = <&msi3>; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0000 0 0 1 &gic 0 154 0x4>, ++ <0000 0 0 2 &gic 0 155 0x4>, ++ <0000 0 0 3 &gic 0 156 0x4>, ++ <0000 0 0 4 &gic 0 157 0x4>; ++ }; ++ }; ++ ++}; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0002-arm64-Move-LS2080A-compilation-under-ARCH_LAYERSCAPE.patch b/target/linux/layerscape-64b/patches-4.1/0002-arm64-Move-LS2080A-compilation-under-ARCH_LAYERSCAPE.patch new file mode 100644 index 0000000..1886cc3 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0002-arm64-Move-LS2080A-compilation-under-ARCH_LAYERSCAPE.patch @@ -0,0 +1,31 @@ +From df2ccfd4f949234baad7bdabea187b31218976b5 Mon Sep 17 00:00:00 2001 +From: Rai Harninder-B01044 +Date: Mon, 18 Apr 2016 15:39:11 +0800 +Subject: [PATCH 002/151] arm64: Move LS2080A compilation under ARCH_LAYERSCAPE + +commit d40c2fe65ebfbd88fd5e2eafc92df6a597c28136 +[context adjustment] + +ARCH_LAYERSCAPE is the common define for Layerscape SoC family +So, move the compilation of LS2085A device tree files under +this define + +Signed-off-by: Rai Harninder-B01044 +Integrated-by: Zhao Qiang +--- + arch/arm64/boot/dts/freescale/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile +index 4f2de3e..fc6fca3 100644 +--- a/arch/arm64/boot/dts/freescale/Makefile ++++ b/arch/arm64/boot/dts/freescale/Makefile +@@ -1,4 +1,4 @@ +-dtb-$(CONFIG_ARCH_FSL_LS2085A) += fsl-ls2085a-simu.dtb ++dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2085a-simu.dtb + + always := $(dtb-y) + subdir-y := $(dts-dirs) +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0003-dts-ls1043a-add-LS1043ARDB-board-support.patch b/target/linux/layerscape-64b/patches-4.1/0003-dts-ls1043a-add-LS1043ARDB-board-support.patch new file mode 100644 index 0000000..ecbd875 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0003-dts-ls1043a-add-LS1043ARDB-board-support.patch @@ -0,0 +1,156 @@ +From ac9d9c52ee5d18870654b9e893ed81c7f9957a99 Mon Sep 17 00:00:00 2001 +From: Shaohui Xie +Date: Mon, 18 Apr 2016 15:44:25 +0800 +Subject: [PATCH 003/151] dts/ls1043a: add LS1043ARDB board support + +commit 9a6fce16a82d3412c9350b9f08eacebaa81c0a3d +[context adjustment] + +Signed-off-by: Shaohui Xie +Signed-off-by: Mingkai Hu +Signed-off-by: Wenbin Song +Signed-off-by: Hou Zhiqiang +Signed-off-by: Mingkai Hu +Integrated-by: Zhao Qiang +--- + arch/arm64/boot/dts/freescale/Makefile | 2 +- + arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts | 117 ++++++++++++++++++++++ + 2 files changed, 118 insertions(+), 1 deletion(-) + create mode 100644 arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts + +diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile +index fc6fca3..5d847c8 100644 +--- a/arch/arm64/boot/dts/freescale/Makefile ++++ b/arch/arm64/boot/dts/freescale/Makefile +@@ -1,4 +1,4 @@ +-dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2085a-simu.dtb ++dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2085a-simu.dtb fsl-ls1043a-rdb.dtb + + always := $(dtb-y) + subdir-y := $(dts-dirs) +diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts +new file mode 100644 +index 0000000..c95a0e7 +--- /dev/null ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts +@@ -0,0 +1,117 @@ ++/* ++ * Device Tree Include file for Freescale Layerscape-1043A family SoC. ++ * ++ * Copyright 2014-2015, Freescale Semiconductor ++ * ++ * Mingkai Hu ++ * ++ * This file is dual-licensed: you can use it either under the terms ++ * of the GPLv2 or the X11 license, at your option. Note that this dual ++ * licensing only applies to this file, and not this project as a ++ * whole. ++ * ++ * a) This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * Or, alternatively, ++ * ++ * b) Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation ++ * files (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, ++ * copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the ++ * Software is furnished to do so, subject to the following ++ * conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES ++ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT ++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, ++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ * OTHER DEALINGS IN THE SOFTWARE. ++ */ ++ ++/dts-v1/; ++#include "fsl-ls1043a.dtsi" ++ ++/ { ++ model = "LS1043A RDB Board"; ++ compatible = "fsl,ls1043a-rdb", "fsl,ls1043a"; ++}; ++ ++&i2c0 { ++ status = "okay"; ++ ina220 at 40 { ++ compatible = "ti,ina220"; ++ reg = <0x40>; ++ shunt-resistor = <1000>; ++ }; ++ adt7461a at 4c { ++ compatible = "adi,adt7461"; ++ reg = <0x4c>; ++ }; ++ eeprom at 56 { ++ compatible = "at24,24c512"; ++ reg = <0x52>; ++ }; ++ eeprom at 57 { ++ compatible = "at24,24c512"; ++ reg = <0x53>; ++ }; ++ rtc at 68 { ++ compatible = "pericom,pt7c4338"; ++ reg = <0x68>; ++ }; ++}; ++ ++&ifc { ++ status = "okay"; ++ #address-cells = <2>; ++ #size-cells = <1>; ++ /* NOR, NAND Flashes and FPGA on board */ ++ ranges = <0x0 0x0 0x0 0x60000000 0x08000000 ++ 0x1 0x0 0x0 0x7e800000 0x00010000 ++ 0x2 0x0 0x0 0x7fb00000 0x00000100>; ++ ++ nor at 0,0 { ++ compatible = "cfi-flash"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x0 0x0 0x8000000>; ++ bank-width = <2>; ++ device-width = <1>; ++ }; ++ ++ nand at 1,0 { ++ compatible = "fsl,ifc-nand"; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ reg = <0x1 0x0 0x10000>; ++ }; ++ ++ cpld: board-control at 2,0 { ++ compatible = "fsl,ls1043ardb-cpld"; ++ reg = <0x2 0x0 0x0000100>; ++ }; ++}; ++ ++&duart0 { ++ status = "okay"; ++}; ++ ++&duart1 { ++ status = "okay"; ++}; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0004-arm64-Define-ARCH_LAYERSCAPE-for-Layerscape-SoC-fami.patch b/target/linux/layerscape-64b/patches-4.1/0004-arm64-Define-ARCH_LAYERSCAPE-for-Layerscape-SoC-fami.patch new file mode 100644 index 0000000..1a09f69 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0004-arm64-Define-ARCH_LAYERSCAPE-for-Layerscape-SoC-fami.patch @@ -0,0 +1,49 @@ +From 2593849ea9e052411e9de5e68064942db901d9a9 Mon Sep 17 00:00:00 2001 +From: Rai Harninder-B01044 +Date: Tue, 27 Oct 2015 13:20:12 +0530 +Subject: [PATCH 004/151] arm64: Define ARCH_LAYERSCAPE for Layerscape SoC + family + +Introduce a common ARCH_LAYERSCAPE for layerscape SoC family +and remove the erstwhile specific ARCH_FSL_LS2085A + +Signed-off-by: Rai Harninder-B01044 +--- + arch/arm64/Kconfig | 6 +++--- + arch/arm64/configs/defconfig | 2 +- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index 6f0a3b4..bf4c50b 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -180,10 +180,10 @@ config ARCH_EXYNOS7 + help + This enables support for Samsung Exynos7 SoC family + +-config ARCH_FSL_LS2085A +- bool "Freescale LS2085A SOC" ++config ARCH_LAYERSCAPE ++ bool "Freescale Layerscape SoC family" + help +- This enables support for Freescale LS2085A SOC. ++ This enables support for Freescale Layerscape SoC family + + config ARCH_MEDIATEK + bool "Mediatek MT65xx & MT81xx ARMv8 SoC" +diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig +index 2ed7449..bfdc78c 100644 +--- a/arch/arm64/configs/defconfig ++++ b/arch/arm64/configs/defconfig +@@ -32,7 +32,7 @@ CONFIG_MODULE_UNLOAD=y + # CONFIG_BLK_DEV_BSG is not set + # CONFIG_IOSCHED_DEADLINE is not set + CONFIG_ARCH_EXYNOS7=y +-CONFIG_ARCH_FSL_LS2085A=y ++CONFIG_ARCH_LAYERSCAPE=y + CONFIG_ARCH_MEDIATEK=y + CONFIG_ARCH_SEATTLE=y + CONFIG_ARCH_TEGRA=y +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0005-clk-qoriq-Move-chip-specific-knowledge-into-driver.patch b/target/linux/layerscape-64b/patches-4.1/0005-clk-qoriq-Move-chip-specific-knowledge-into-driver.patch new file mode 100644 index 0000000..6e7df85 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0005-clk-qoriq-Move-chip-specific-knowledge-into-driver.patch @@ -0,0 +1,1579 @@ +From 600b6fee7a14ef13bbeccb3d4ca4bfb9c62c9e31 Mon Sep 17 00:00:00 2001 +From: Scott Wood +Date: Fri, 15 Jan 2016 07:34:25 +0000 +Subject: [PATCH 005/151] clk: qoriq: Move chip-specific knowledge into driver + +The device tree should describe the chips (or chip-like subblocks) in +the system, but it generally does not describe individual registers -- +it should identify, rather than describe, a programming interface. + +This has not been the case with the QorIQ clockgen nodes. The +knowledge of what each bit setting of CLKCnCSR means is encoded in +three places (binding, pll node, and mux node), and the last also needs +to know which options are valid on a particular chip. All three of +these locations are considered stable ABI, making it difficult to fix +mistakes (of which I have found several), much less refactor the +abstraction to be able to address problems, limitations, or new chips. + +Under the current binding, a pll clock specifier of 2 means that the +PLL is divided by 4 -- and the driver implements this, unless there +happen to be four clock-output-names rather than 3, in which case it +interprets it as PLL divided by 3. This does not appear in the binding +documentation at all. That hack is now considered stable ABI. + +The current device tree nodes contain errors, such as saying that +T1040 can set a core clock to PLL/4 when only PLL and PLL/2 are options. +The current binding also ignores some restrictions on clock selection, +such as p5020's requirement that if a core uses the "wrong" PLL, that +PLL must be clocked lower than the "correct" PLL and be at most 80% of +the rated CPU frequency. + +Possibly because of the lack of the ability to express such nuance in +the binding, some valid options are omitted from the device trees, such +as the ability on p4080 to run cores 0-3 from PLL3 and cores 4-7 from +PLL1 (again, only if they are at most 80% of rated CPU frequency). +This omission, combined with excessive caution in the cpufreq driver +(addressed in a subsequent patch), means that currently on a 1500 MHz +p4080 with typical PLL configuration, cpufreq can lower the frequency +to 1200 MHz on half the CPUs and do nothing on the others. With this +patchset, all CPUs can be lowered to 1200 MHz on a rev2 p4080, and on a +rev3 p4080 half can be lowered to 750 MHz and the other half to 600 +MHz. + +The current binding only deals with CPU clocks. To describe FMan in +the device tree, we need to describe its clock. Some chips have +additional muxes that work like the CPU muxes, but are not described in +the device tree. Others require inspecting the Reset Control Word to +determine which PLL is used. Rather than continue to extend this mess, +replace it. Have the driver bind to the chip-specific clockgen +compatible, and keep the detailed description of quirky chip variations +in the driver, where it can be easily fixed, refactored, and extended. + +Older device trees will continue to work (including a workaround for +old ls1021a device trees that are missing compatible and reg in the +clockgen node, which even the old binding required). The pll/mux +details in old device trees will be ignored, but "clocks" properties +pointing at the old nodes will still work, and be directed at the +corresponding new clock. + +Signed-off-by: Scott Wood +Acked-by: Stephen Boyd +(cherry picked from commit 0dfc86b3173feee96f36e71879aa6dd56a4d7925) +Signed-off-by: Scott Wood +--- + .../devicetree/bindings/clock/qoriq-clock.txt | 61 +- + drivers/clk/clk-qoriq.c | 1261 ++++++++++++++++---- + 2 files changed, 1090 insertions(+), 232 deletions(-) + +diff --git a/Documentation/devicetree/bindings/clock/qoriq-clock.txt b/Documentation/devicetree/bindings/clock/qoriq-clock.txt +index df4a259..16a3ec4 100644 +--- a/Documentation/devicetree/bindings/clock/qoriq-clock.txt ++++ b/Documentation/devicetree/bindings/clock/qoriq-clock.txt +@@ -1,6 +1,6 @@ + * Clock Block on Freescale QorIQ Platforms + +-Freescale qoriq chips take primary clocking input from the external ++Freescale QorIQ chips take primary clocking input from the external + SYSCLK signal. The SYSCLK input (frequency) is multiplied using + multiple phase locked loops (PLL) to create a variety of frequencies + which can then be passed to a variety of internal logic, including +@@ -13,14 +13,16 @@ which the chip complies. + Chassis Version Example Chips + --------------- ------------- + 1.0 p4080, p5020, p5040 +-2.0 t4240, b4860, t1040 ++2.0 t4240, b4860 + + 1. Clock Block Binding + + Required properties: +-- compatible: Should contain a specific clock block compatible string +- and a single chassis clock compatible string. +- Clock block strings include, but not limited to, one of the: ++- compatible: Should contain a chip-specific clock block compatible ++ string and (if applicable) may contain a chassis-version clock ++ compatible string. ++ ++ Chip-specific strings are of the form "fsl,-clockgen", such as: + * "fsl,p2041-clockgen" + * "fsl,p3041-clockgen" + * "fsl,p4080-clockgen" +@@ -30,15 +32,14 @@ Required properties: + * "fsl,b4420-clockgen" + * "fsl,b4860-clockgen" + * "fsl,ls1021a-clockgen" +- Chassis clock strings include: ++ Chassis-version clock strings include: + * "fsl,qoriq-clockgen-1.0": for chassis 1.0 clocks + * "fsl,qoriq-clockgen-2.0": for chassis 2.0 clocks + - reg: Describes the address of the device's resources within the + address space defined by its parent bus, and resource zero + represents the clock register set +-- clock-frequency: Input system clock frequency + +-Recommended properties: ++Optional properties: + - ranges: Allows valid translation between child's address space and + parent's. Must be present if the device has sub-nodes. + - #address-cells: Specifies the number of cells used to represent +@@ -47,8 +48,46 @@ Recommended properties: + - #size-cells: Specifies the number of cells used to represent + the size of an address. Must be present if the device has + sub-nodes and set to 1 if present ++- clock-frequency: Input system clock frequency (SYSCLK) ++- clocks: If clock-frequency is not specified, sysclk may be provided ++ as an input clock. Either clock-frequency or clocks must be ++ provided. ++ ++2. Clock Provider ++ ++The clockgen node should act as a clock provider, though in older device ++trees the children of the clockgen node are the clock providers. ++ ++When the clockgen node is a clock provider, #clock-cells = <2>. ++The first cell of the clock specifier is the clock type, and the ++second cell is the clock index for the specified type. ++ ++ Type# Name Index Cell ++ 0 sysclk must be 0 ++ 1 cmux index (n in CLKCnCSR) ++ 2 hwaccel index (n in CLKCGnHWACSR) ++ 3 fman 0 for fm1, 1 for fm2 ++ 4 platform pll 0=pll, 1=pll/2, 2=pll/3, 3=pll/4 ++ ++3. Example ++ ++ clockgen: global-utilities at e1000 { ++ compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0"; ++ clock-frequency = <133333333>; ++ reg = <0xe1000 0x1000>; ++ #clock-cells = <2>; ++ }; ++ ++ fman at 400000 { ++ ... ++ clocks = <&clockgen 3 0>; ++ ... ++ }; ++} ++4. Legacy Child Nodes + +-2. Clock Provider/Consumer Binding ++NOTE: These nodes are deprecated. Kernels should continue to support ++device trees with these nodes, but new device trees should not use them. + + Most of the bindings are from the common clock binding[1]. + [1] Documentation/devicetree/bindings/clock/clock-bindings.txt +@@ -82,7 +121,7 @@ Recommended properties: + - reg: Should be the offset and length of clock block base address. + The length should be 4. + +-Example for clock block and clock provider: ++Legacy Example: + / { + clockgen: global-utilities at e1000 { + compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0"; +@@ -142,7 +181,7 @@ Example for clock block and clock provider: + }; + }; + +-Example for clock consumer: ++Example for legacy clock consumer: + + / { + cpu0: PowerPC,e5500 at 0 { +diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c +index cda90a9..06281a3 100644 +--- a/drivers/clk/clk-qoriq.c ++++ b/drivers/clk/clk-qoriq.c +@@ -10,7 +10,9 @@ + + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + ++#include + #include ++#include + #include + #include + #include +@@ -19,213 +21,934 @@ + #include + #include + +-struct cmux_clk { ++#define PLL_DIV1 0 ++#define PLL_DIV2 1 ++#define PLL_DIV3 2 ++#define PLL_DIV4 3 ++ ++#define PLATFORM_PLL 0 ++#define CGA_PLL1 1 ++#define CGA_PLL2 2 ++#define CGA_PLL3 3 ++#define CGA_PLL4 4 /* only on clockgen-1.0, which lacks CGB */ ++#define CGB_PLL1 4 ++#define CGB_PLL2 5 ++ ++struct clockgen_pll_div { ++ struct clk *clk; ++ char name[32]; ++}; ++ ++struct clockgen_pll { ++ struct clockgen_pll_div div[4]; ++}; ++ ++#define CLKSEL_VALID 1 ++#define CLKSEL_80PCT 2 /* Only allowed if PLL <= 80% of max cpu freq */ ++ ++struct clockgen_sourceinfo { ++ u32 flags; /* CLKSEL_xxx */ ++ int pll; /* CGx_PLLn */ ++ int div; /* PLL_DIVn */ ++}; ++ ++#define NUM_MUX_PARENTS 16 ++ ++struct clockgen_muxinfo { ++ struct clockgen_sourceinfo clksel[NUM_MUX_PARENTS]; ++}; ++ ++#define NUM_HWACCEL 5 ++#define NUM_CMUX 8 ++ ++struct clockgen; ++ ++/* ++ * cmux freq must be >= platform pll. ++ * If not set, cmux freq must be >= platform pll/2 ++ */ ++#define CG_CMUX_GE_PLAT 1 ++#define CG_PLL_8BIT 2 /* PLLCnGSR[CFG] is 8 bits, not 6 */ ++ ++struct clockgen_chipinfo { ++ const char *compat, *guts_compat; ++ const struct clockgen_muxinfo *cmux_groups[2]; ++ const struct clockgen_muxinfo *hwaccel[NUM_HWACCEL]; ++ void (*init_periph)(struct clockgen *cg); ++ int cmux_to_group[NUM_CMUX]; /* -1 terminates if fewer than NUM_CMUX */ ++ u32 pll_mask; /* 1 << n bit set if PLL n is valid */ ++ u32 flags; /* CG_xxx */ ++}; ++ ++struct clockgen { ++ struct device_node *node; ++ void __iomem *regs; ++ struct clockgen_chipinfo info; /* mutable copy */ ++ struct clk *sysclk; ++ struct clockgen_pll pll[6]; ++ struct clk *cmux[NUM_CMUX]; ++ struct clk *hwaccel[NUM_HWACCEL]; ++ struct clk *fman[2]; ++ struct ccsr_guts __iomem *guts; ++}; ++ ++static struct clockgen clockgen; ++ ++static const struct clockgen_muxinfo p2041_cmux_grp1 = { ++ { ++ [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, ++ [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, ++ [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, ++ } ++}; ++ ++static const struct clockgen_muxinfo p2041_cmux_grp2 = { ++ { ++ [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, ++ [4] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, ++ [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, ++ } ++}; ++ ++static const struct clockgen_muxinfo p5020_cmux_grp1 = { ++ { ++ [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, ++ [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, ++ [4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 }, ++ } ++}; ++ ++static const struct clockgen_muxinfo p5020_cmux_grp2 = { ++ { ++ [0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 }, ++ [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, ++ [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, ++ } ++}; ++ ++static const struct clockgen_muxinfo p5040_cmux_grp1 = { ++ { ++ [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, ++ [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, ++ [4] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV1 }, ++ [5] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL2, PLL_DIV2 }, ++ } ++}; ++ ++static const struct clockgen_muxinfo p5040_cmux_grp2 = { ++ { ++ [0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 }, ++ [1] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV2 }, ++ [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, ++ [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, ++ } ++}; ++ ++static const struct clockgen_muxinfo p4080_cmux_grp1 = { ++ { ++ [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, ++ [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, ++ [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, ++ [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, ++ [8] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL3, PLL_DIV1 }, ++ } ++}; ++ ++static const struct clockgen_muxinfo p4080_cmux_grp2 = { ++ { ++ [0] = { CLKSEL_VALID | CLKSEL_80PCT, CGA_PLL1, PLL_DIV1 }, ++ [8] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV1 }, ++ [9] = { CLKSEL_VALID, CGA_PLL3, PLL_DIV2 }, ++ [12] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV1 }, ++ [13] = { CLKSEL_VALID, CGA_PLL4, PLL_DIV2 }, ++ } ++}; ++ ++static const struct clockgen_muxinfo t1023_cmux = { ++ { ++ [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, ++ [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, ++ } ++}; ++ ++static const struct clockgen_muxinfo t1040_cmux = { ++ { ++ [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, ++ [1] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, ++ [4] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, ++ [5] = { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, ++ } ++}; ++ ++ ++static const struct clockgen_muxinfo clockgen2_cmux_cga = { ++ { ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 }, ++ {}, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 }, ++ {}, ++ { CLKSEL_VALID, CGA_PLL3, PLL_DIV1 }, ++ { CLKSEL_VALID, CGA_PLL3, PLL_DIV2 }, ++ { CLKSEL_VALID, CGA_PLL3, PLL_DIV4 }, ++ }, ++}; ++ ++static const struct clockgen_muxinfo clockgen2_cmux_cga12 = { ++ { ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 }, ++ {}, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 }, ++ }, ++}; ++ ++static const struct clockgen_muxinfo clockgen2_cmux_cgb = { ++ { ++ { CLKSEL_VALID, CGB_PLL1, PLL_DIV1 }, ++ { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 }, ++ { CLKSEL_VALID, CGB_PLL1, PLL_DIV4 }, ++ {}, ++ { CLKSEL_VALID, CGB_PLL2, PLL_DIV1 }, ++ { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 }, ++ { CLKSEL_VALID, CGB_PLL2, PLL_DIV4 }, ++ }, ++}; ++ ++static const struct clockgen_muxinfo t1023_hwa1 = { ++ { ++ {}, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, ++ }, ++}; ++ ++static const struct clockgen_muxinfo t1023_hwa2 = { ++ { ++ [6] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, ++ }, ++}; ++ ++static const struct clockgen_muxinfo t2080_hwa1 = { ++ { ++ {}, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 }, ++ { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 }, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, ++ }, ++}; ++ ++static const struct clockgen_muxinfo t2080_hwa2 = { ++ { ++ {}, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV4 }, ++ { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 }, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, ++ }, ++}; ++ ++static const struct clockgen_muxinfo t4240_hwa1 = { ++ { ++ { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV2 }, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV4 }, ++ {}, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, ++ }, ++}; ++ ++static const struct clockgen_muxinfo t4240_hwa4 = { ++ { ++ [2] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 }, ++ [3] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 }, ++ [4] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV4 }, ++ [5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 }, ++ [6] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 }, ++ }, ++}; ++ ++static const struct clockgen_muxinfo t4240_hwa5 = { ++ { ++ [2] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV2 }, ++ [3] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV3 }, ++ [4] = { CLKSEL_VALID, CGB_PLL2, PLL_DIV4 }, ++ [5] = { CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 }, ++ [6] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV2 }, ++ [7] = { CLKSEL_VALID, CGB_PLL1, PLL_DIV3 }, ++ }, ++}; ++ ++#define RCWSR7_FM1_CLK_SEL 0x40000000 ++#define RCWSR7_FM2_CLK_SEL 0x20000000 ++#define RCWSR7_HWA_ASYNC_DIV 0x04000000 ++ ++static void __init p2041_init_periph(struct clockgen *cg) ++{ ++ u32 reg; ++ ++ reg = ioread32be(&cg->guts->rcwsr[7]); ++ ++ if (reg & RCWSR7_FM1_CLK_SEL) ++ cg->fman[0] = cg->pll[CGA_PLL2].div[PLL_DIV2].clk; ++ else ++ cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk; ++} ++ ++static void __init p4080_init_periph(struct clockgen *cg) ++{ ++ u32 reg; ++ ++ reg = ioread32be(&cg->guts->rcwsr[7]); ++ ++ if (reg & RCWSR7_FM1_CLK_SEL) ++ cg->fman[0] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk; ++ else ++ cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk; ++ ++ if (reg & RCWSR7_FM2_CLK_SEL) ++ cg->fman[1] = cg->pll[CGA_PLL3].div[PLL_DIV2].clk; ++ else ++ cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk; ++} ++ ++static void __init p5020_init_periph(struct clockgen *cg) ++{ ++ u32 reg; ++ int div = PLL_DIV2; ++ ++ reg = ioread32be(&cg->guts->rcwsr[7]); ++ if (reg & RCWSR7_HWA_ASYNC_DIV) ++ div = PLL_DIV4; ++ ++ if (reg & RCWSR7_FM1_CLK_SEL) ++ cg->fman[0] = cg->pll[CGA_PLL2].div[div].clk; ++ else ++ cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk; ++} ++ ++static void __init p5040_init_periph(struct clockgen *cg) ++{ ++ u32 reg; ++ int div = PLL_DIV2; ++ ++ reg = ioread32be(&cg->guts->rcwsr[7]); ++ if (reg & RCWSR7_HWA_ASYNC_DIV) ++ div = PLL_DIV4; ++ ++ if (reg & RCWSR7_FM1_CLK_SEL) ++ cg->fman[0] = cg->pll[CGA_PLL3].div[div].clk; ++ else ++ cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk; ++ ++ if (reg & RCWSR7_FM2_CLK_SEL) ++ cg->fman[1] = cg->pll[CGA_PLL3].div[div].clk; ++ else ++ cg->fman[1] = cg->pll[PLATFORM_PLL].div[PLL_DIV2].clk; ++} ++ ++static void __init t1023_init_periph(struct clockgen *cg) ++{ ++ cg->fman[0] = cg->hwaccel[1]; ++} ++ ++static void __init t1040_init_periph(struct clockgen *cg) ++{ ++ cg->fman[0] = cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk; ++} ++ ++static void __init t2080_init_periph(struct clockgen *cg) ++{ ++ cg->fman[0] = cg->hwaccel[0]; ++} ++ ++static void __init t4240_init_periph(struct clockgen *cg) ++{ ++ cg->fman[0] = cg->hwaccel[3]; ++ cg->fman[1] = cg->hwaccel[4]; ++} ++ ++static const struct clockgen_chipinfo chipinfo[] = { ++ { ++ .compat = "fsl,b4420-clockgen", ++ .guts_compat = "fsl,b4860-device-config", ++ .init_periph = t2080_init_periph, ++ .cmux_groups = { ++ &clockgen2_cmux_cga12, &clockgen2_cmux_cgb ++ }, ++ .hwaccel = { ++ &t2080_hwa1 ++ }, ++ .cmux_to_group = { ++ 0, 1, 1, 1, -1 ++ }, ++ .pll_mask = 0x3f, ++ .flags = CG_PLL_8BIT, ++ }, ++ { ++ .compat = "fsl,b4860-clockgen", ++ .guts_compat = "fsl,b4860-device-config", ++ .init_periph = t2080_init_periph, ++ .cmux_groups = { ++ &clockgen2_cmux_cga12, &clockgen2_cmux_cgb ++ }, ++ .hwaccel = { ++ &t2080_hwa1 ++ }, ++ .cmux_to_group = { ++ 0, 1, 1, 1, -1 ++ }, ++ .pll_mask = 0x3f, ++ .flags = CG_PLL_8BIT, ++ }, ++ { ++ .compat = "fsl,ls1021a-clockgen", ++ .cmux_groups = { ++ &t1023_cmux ++ }, ++ .cmux_to_group = { ++ 0, -1 ++ }, ++ .pll_mask = 0x03, ++ }, ++ { ++ .compat = "fsl,p2041-clockgen", ++ .guts_compat = "fsl,qoriq-device-config-1.0", ++ .init_periph = p2041_init_periph, ++ .cmux_groups = { ++ &p2041_cmux_grp1, &p2041_cmux_grp2 ++ }, ++ .cmux_to_group = { ++ 0, 0, 1, 1, -1 ++ }, ++ .pll_mask = 0x07, ++ }, ++ { ++ .compat = "fsl,p3041-clockgen", ++ .guts_compat = "fsl,qoriq-device-config-1.0", ++ .init_periph = p2041_init_periph, ++ .cmux_groups = { ++ &p2041_cmux_grp1, &p2041_cmux_grp2 ++ }, ++ .cmux_to_group = { ++ 0, 0, 1, 1, -1 ++ }, ++ .pll_mask = 0x07, ++ }, ++ { ++ .compat = "fsl,p4080-clockgen", ++ .guts_compat = "fsl,qoriq-device-config-1.0", ++ .init_periph = p4080_init_periph, ++ .cmux_groups = { ++ &p4080_cmux_grp1, &p4080_cmux_grp2 ++ }, ++ .cmux_to_group = { ++ 0, 0, 0, 0, 1, 1, 1, 1 ++ }, ++ .pll_mask = 0x1f, ++ }, ++ { ++ .compat = "fsl,p5020-clockgen", ++ .guts_compat = "fsl,qoriq-device-config-1.0", ++ .init_periph = p5020_init_periph, ++ .cmux_groups = { ++ &p2041_cmux_grp1, &p2041_cmux_grp2 ++ }, ++ .cmux_to_group = { ++ 0, 1, -1 ++ }, ++ .pll_mask = 0x07, ++ }, ++ { ++ .compat = "fsl,p5040-clockgen", ++ .guts_compat = "fsl,p5040-device-config", ++ .init_periph = p5040_init_periph, ++ .cmux_groups = { ++ &p5040_cmux_grp1, &p5040_cmux_grp2 ++ }, ++ .cmux_to_group = { ++ 0, 0, 1, 1, -1 ++ }, ++ .pll_mask = 0x0f, ++ }, ++ { ++ .compat = "fsl,t1023-clockgen", ++ .guts_compat = "fsl,t1023-device-config", ++ .init_periph = t1023_init_periph, ++ .cmux_groups = { ++ &t1023_cmux ++ }, ++ .hwaccel = { ++ &t1023_hwa1, &t1023_hwa2 ++ }, ++ .cmux_to_group = { ++ 0, 0, -1 ++ }, ++ .pll_mask = 0x03, ++ .flags = CG_PLL_8BIT, ++ }, ++ { ++ .compat = "fsl,t1040-clockgen", ++ .guts_compat = "fsl,t1040-device-config", ++ .init_periph = t1040_init_periph, ++ .cmux_groups = { ++ &t1040_cmux ++ }, ++ .cmux_to_group = { ++ 0, 0, 0, 0, -1 ++ }, ++ .pll_mask = 0x07, ++ .flags = CG_PLL_8BIT, ++ }, ++ { ++ .compat = "fsl,t2080-clockgen", ++ .guts_compat = "fsl,t2080-device-config", ++ .init_periph = t2080_init_periph, ++ .cmux_groups = { ++ &clockgen2_cmux_cga12 ++ }, ++ .hwaccel = { ++ &t2080_hwa1, &t2080_hwa2 ++ }, ++ .cmux_to_group = { ++ 0, -1 ++ }, ++ .pll_mask = 0x07, ++ .flags = CG_PLL_8BIT, ++ }, ++ { ++ .compat = "fsl,t4240-clockgen", ++ .guts_compat = "fsl,t4240-device-config", ++ .init_periph = t4240_init_periph, ++ .cmux_groups = { ++ &clockgen2_cmux_cga, &clockgen2_cmux_cgb ++ }, ++ .hwaccel = { ++ &t4240_hwa1, NULL, NULL, &t4240_hwa4, &t4240_hwa5 ++ }, ++ .cmux_to_group = { ++ 0, 0, 1, -1 ++ }, ++ .pll_mask = 0x3f, ++ .flags = CG_PLL_8BIT, ++ }, ++ {}, ++}; ++ ++struct mux_hwclock { + struct clk_hw hw; +- void __iomem *reg; +- unsigned int clk_per_pll; +- u32 flags; ++ struct clockgen *cg; ++ const struct clockgen_muxinfo *info; ++ u32 __iomem *reg; ++ u8 parent_to_clksel[NUM_MUX_PARENTS]; ++ s8 clksel_to_parent[NUM_MUX_PARENTS]; ++ int num_parents; + }; + +-#define PLL_KILL BIT(31) ++#define to_mux_hwclock(p) container_of(p, struct mux_hwclock, hw) ++#define CLKSEL_MASK 0x78000000 + #define CLKSEL_SHIFT 27 +-#define CLKSEL_ADJUST BIT(0) +-#define to_cmux_clk(p) container_of(p, struct cmux_clk, hw) + +-static int cmux_set_parent(struct clk_hw *hw, u8 idx) ++static int mux_set_parent(struct clk_hw *hw, u8 idx) + { +- struct cmux_clk *clk = to_cmux_clk(hw); ++ struct mux_hwclock *hwc = to_mux_hwclock(hw); + u32 clksel; + +- clksel = ((idx / clk->clk_per_pll) << 2) + idx % clk->clk_per_pll; +- if (clk->flags & CLKSEL_ADJUST) +- clksel += 8; +- clksel = (clksel & 0xf) << CLKSEL_SHIFT; +- iowrite32be(clksel, clk->reg); ++ if (idx >= hwc->num_parents) ++ return -EINVAL; ++ ++ clksel = hwc->parent_to_clksel[idx]; ++ iowrite32be((clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg); + + return 0; + } + +-static u8 cmux_get_parent(struct clk_hw *hw) ++static u8 mux_get_parent(struct clk_hw *hw) + { +- struct cmux_clk *clk = to_cmux_clk(hw); ++ struct mux_hwclock *hwc = to_mux_hwclock(hw); + u32 clksel; ++ s8 ret; + +- clksel = ioread32be(clk->reg); +- clksel = (clksel >> CLKSEL_SHIFT) & 0xf; +- if (clk->flags & CLKSEL_ADJUST) +- clksel -= 8; +- clksel = (clksel >> 2) * clk->clk_per_pll + clksel % 4; ++ clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT; + +- return clksel; ++ ret = hwc->clksel_to_parent[clksel]; ++ if (ret < 0) { ++ pr_err("%s: mux at %p has bad clksel\n", __func__, hwc->reg); ++ return 0; ++ } ++ ++ return ret; + } + + static const struct clk_ops cmux_ops = { +- .get_parent = cmux_get_parent, +- .set_parent = cmux_set_parent, ++ .get_parent = mux_get_parent, ++ .set_parent = mux_set_parent, + }; + +-static void __init core_mux_init(struct device_node *np) ++/* ++ * Don't allow setting for now, as the clock options haven't been ++ * sanitized for additional restrictions. ++ */ ++static const struct clk_ops hwaccel_ops = { ++ .get_parent = mux_get_parent, ++}; ++ ++static const struct clockgen_pll_div *get_pll_div(struct clockgen *cg, ++ struct mux_hwclock *hwc, ++ int idx) + { +- struct clk *clk; +- struct clk_init_data init; +- struct cmux_clk *cmux_clk; +- struct device_node *node; +- int rc, count, i; +- u32 offset; +- const char *clk_name; +- const char **parent_names; +- struct of_phandle_args clkspec; ++ int pll, div; + +- rc = of_property_read_u32(np, "reg", &offset); +- if (rc) { +- pr_err("%s: could not get reg property\n", np->name); +- return; +- } ++ if (!(hwc->info->clksel[idx].flags & CLKSEL_VALID)) ++ return NULL; + +- /* get the input clock source count */ +- count = of_property_count_strings(np, "clock-names"); +- if (count < 0) { +- pr_err("%s: get clock count error\n", np->name); +- return; +- } +- parent_names = kcalloc(count, sizeof(char *), GFP_KERNEL); +- if (!parent_names) +- return; ++ pll = hwc->info->clksel[idx].pll; ++ div = hwc->info->clksel[idx].div; + +- for (i = 0; i < count; i++) +- parent_names[i] = of_clk_get_parent_name(np, i); ++ return &cg->pll[pll].div[div]; ++} + +- cmux_clk = kzalloc(sizeof(*cmux_clk), GFP_KERNEL); +- if (!cmux_clk) +- goto err_name; ++static struct clk * __init create_mux_common(struct clockgen *cg, ++ struct mux_hwclock *hwc, ++ const struct clk_ops *ops, ++ unsigned long min_rate, ++ unsigned long pct80_rate, ++ const char *fmt, int idx) ++{ ++ struct clk_init_data init = {}; ++ struct clk *clk; ++ const struct clockgen_pll_div *div; ++ const char *parent_names[NUM_MUX_PARENTS]; ++ char name[32]; ++ int i, j; + +- cmux_clk->reg = of_iomap(np, 0); +- if (!cmux_clk->reg) { +- pr_err("%s: could not map register\n", __func__); +- goto err_clk; +- } ++ snprintf(name, sizeof(name), fmt, idx); + +- rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", 0, +- &clkspec); +- if (rc) { +- pr_err("%s: parse clock node error\n", __func__); +- goto err_clk; +- } ++ for (i = 0, j = 0; i < NUM_MUX_PARENTS; i++) { ++ unsigned long rate; + +- cmux_clk->clk_per_pll = of_property_count_strings(clkspec.np, +- "clock-output-names"); +- of_node_put(clkspec.np); ++ hwc->clksel_to_parent[i] = -1; + +- node = of_find_compatible_node(NULL, NULL, "fsl,p4080-clockgen"); +- if (node && (offset >= 0x80)) +- cmux_clk->flags = CLKSEL_ADJUST; ++ div = get_pll_div(cg, hwc, i); ++ if (!div) ++ continue; + +- rc = of_property_read_string_index(np, "clock-output-names", +- 0, &clk_name); +- if (rc) { +- pr_err("%s: read clock names error\n", np->name); +- goto err_clk; ++ rate = clk_get_rate(div->clk); ++ ++ if (hwc->info->clksel[i].flags & CLKSEL_80PCT && ++ rate > pct80_rate) ++ continue; ++ if (rate < min_rate) ++ continue; ++ ++ parent_names[j] = div->name; ++ hwc->parent_to_clksel[j] = i; ++ hwc->clksel_to_parent[i] = j; ++ j++; + } + +- init.name = clk_name; +- init.ops = &cmux_ops; ++ init.name = name; ++ init.ops = ops; + init.parent_names = parent_names; +- init.num_parents = count; ++ init.num_parents = hwc->num_parents = j; + init.flags = 0; +- cmux_clk->hw.init = &init; ++ hwc->hw.init = &init; ++ hwc->cg = cg; + +- clk = clk_register(NULL, &cmux_clk->hw); ++ clk = clk_register(NULL, &hwc->hw); + if (IS_ERR(clk)) { +- pr_err("%s: could not register clock\n", clk_name); +- goto err_clk; ++ pr_err("%s: Couldn't register %s: %ld\n", __func__, name, ++ PTR_ERR(clk)); ++ kfree(hwc); ++ return NULL; ++ } ++ ++ return clk; ++} ++ ++static struct clk * __init create_one_cmux(struct clockgen *cg, int idx) ++{ ++ struct mux_hwclock *hwc; ++ const struct clockgen_pll_div *div; ++ unsigned long plat_rate, min_rate; ++ u64 pct80_rate; ++ u32 clksel; ++ ++ hwc = kzalloc(sizeof(*hwc), GFP_KERNEL); ++ if (!hwc) ++ return NULL; ++ ++ hwc->reg = cg->regs + 0x20 * idx; ++ hwc->info = cg->info.cmux_groups[cg->info.cmux_to_group[idx]]; ++ ++ /* ++ * Find the rate for the default clksel, and treat it as the ++ * maximum rated core frequency. If this is an incorrect ++ * assumption, certain clock options (possibly including the ++ * default clksel) may be inappropriately excluded on certain ++ * chips. ++ */ ++ clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT; ++ div = get_pll_div(cg, hwc, clksel); ++ if (!div) ++ return NULL; ++ ++ pct80_rate = clk_get_rate(div->clk); ++ pct80_rate *= 8; ++ do_div(pct80_rate, 10); ++ ++ plat_rate = clk_get_rate(cg->pll[PLATFORM_PLL].div[PLL_DIV1].clk); ++ ++ if (cg->info.flags & CG_CMUX_GE_PLAT) ++ min_rate = plat_rate; ++ else ++ min_rate = plat_rate / 2; ++ ++ return create_mux_common(cg, hwc, &cmux_ops, min_rate, ++ pct80_rate, "cg-cmux%d", idx); ++} ++ ++static struct clk * __init create_one_hwaccel(struct clockgen *cg, int idx) ++{ ++ struct mux_hwclock *hwc; ++ ++ hwc = kzalloc(sizeof(*hwc), GFP_KERNEL); ++ if (!hwc) ++ return NULL; ++ ++ hwc->reg = cg->regs + 0x20 * idx + 0x10; ++ hwc->info = cg->info.hwaccel[idx]; ++ ++ return create_mux_common(cg, hwc, &hwaccel_ops, 0, 0, ++ "cg-hwaccel%d", idx); ++} ++ ++static void __init create_muxes(struct clockgen *cg) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(cg->cmux); i++) { ++ if (cg->info.cmux_to_group[i] < 0) ++ break; ++ if (cg->info.cmux_to_group[i] >= ++ ARRAY_SIZE(cg->info.cmux_groups)) { ++ WARN_ON_ONCE(1); ++ continue; ++ } ++ ++ cg->cmux[i] = create_one_cmux(cg, i); + } + ++ for (i = 0; i < ARRAY_SIZE(cg->hwaccel); i++) { ++ if (!cg->info.hwaccel[i]) ++ continue; ++ ++ cg->hwaccel[i] = create_one_hwaccel(cg, i); ++ } ++} ++ ++static void __init clockgen_init(struct device_node *np); ++ ++/* Legacy nodes may get probed before the parent clockgen node */ ++static void __init legacy_init_clockgen(struct device_node *np) ++{ ++ if (!clockgen.node) ++ clockgen_init(of_get_parent(np)); ++} ++ ++/* Legacy node */ ++static void __init core_mux_init(struct device_node *np) ++{ ++ struct clk *clk; ++ struct resource res; ++ int idx, rc; ++ ++ legacy_init_clockgen(np); ++ ++ if (of_address_to_resource(np, 0, &res)) ++ return; ++ ++ idx = (res.start & 0xf0) >> 5; ++ clk = clockgen.cmux[idx]; ++ + rc = of_clk_add_provider(np, of_clk_src_simple_get, clk); + if (rc) { +- pr_err("Could not register clock provider for node:%s\n", +- np->name); +- goto err_clk; ++ pr_err("%s: Couldn't register clk provider for node %s: %d\n", ++ __func__, np->name, rc); ++ return; + } +- goto err_name; ++} + +-err_clk: +- kfree(cmux_clk); +-err_name: +- /* free *_names because they are reallocated when registered */ +- kfree(parent_names); ++static struct clk *sysclk_from_fixed(struct device_node *node, const char *name) ++{ ++ u32 rate; ++ ++ if (of_property_read_u32(node, "clock-frequency", &rate)) ++ return ERR_PTR(-ENODEV); ++ ++ return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate); + } + +-static void __init core_pll_init(struct device_node *np) ++static struct clk *sysclk_from_parent(const char *name) ++{ ++ struct clk *clk; ++ const char *parent_name; ++ ++ clk = of_clk_get(clockgen.node, 0); ++ if (IS_ERR(clk)) ++ return clk; ++ ++ /* Register the input clock under the desired name. */ ++ parent_name = __clk_get_name(clk); ++ clk = clk_register_fixed_factor(NULL, name, parent_name, ++ 0, 1, 1); ++ if (IS_ERR(clk)) ++ pr_err("%s: Couldn't register %s: %ld\n", __func__, name, ++ PTR_ERR(clk)); ++ ++ return clk; ++} ++ ++static struct clk * __init create_sysclk(const char *name) ++{ ++ struct device_node *sysclk; ++ struct clk *clk; ++ ++ clk = sysclk_from_fixed(clockgen.node, name); ++ if (!IS_ERR(clk)) ++ return clk; ++ ++ clk = sysclk_from_parent(name); ++ if (!IS_ERR(clk)) ++ return clk; ++ ++ sysclk = of_get_child_by_name(clockgen.node, "sysclk"); ++ if (sysclk) { ++ clk = sysclk_from_fixed(sysclk, name); ++ if (!IS_ERR(clk)) ++ return clk; ++ } ++ ++ pr_err("%s: No input clock\n", __func__); ++ return NULL; ++} ++ ++/* Legacy node */ ++static void __init sysclk_init(struct device_node *node) ++{ ++ struct clk *clk; ++ ++ legacy_init_clockgen(node); ++ ++ clk = clockgen.sysclk; ++ if (clk) ++ of_clk_add_provider(node, of_clk_src_simple_get, clk); ++} ++ ++#define PLL_KILL BIT(31) ++ ++static void __init create_one_pll(struct clockgen *cg, int idx) + { ++ u32 __iomem *reg; + u32 mult; +- int i, rc, count; +- const char *clk_name, *parent_name; +- struct clk_onecell_data *onecell_data; +- struct clk **subclks; +- void __iomem *base; ++ struct clockgen_pll *pll = &cg->pll[idx]; ++ int i; + +- base = of_iomap(np, 0); +- if (!base) { +- pr_err("iomap error\n"); ++ if (!(cg->info.pll_mask & (1 << idx))) + return; +- } + +- /* get the multiple of PLL */ +- mult = ioread32be(base); ++ if (idx == PLATFORM_PLL) ++ reg = cg->regs + 0xc00; ++ else ++ reg = cg->regs + 0x800 + 0x20 * (idx - 1); + +- /* check if this PLL is disabled */ ++ /* Get the multiple of PLL */ ++ mult = ioread32be(reg); ++ ++ /* Check if this PLL is disabled */ + if (mult & PLL_KILL) { +- pr_debug("PLL:%s is disabled\n", np->name); +- goto err_map; ++ pr_debug("%s(): pll %p disabled\n", __func__, reg); ++ return; + } +- mult = (mult >> 1) & 0x3f; + +- parent_name = of_clk_get_parent_name(np, 0); +- if (!parent_name) { +- pr_err("PLL: %s must have a parent\n", np->name); +- goto err_map; ++ if ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL) ++ mult = (mult & GENMASK(8, 1)) >> 1; ++ else ++ mult = (mult & GENMASK(6, 1)) >> 1; ++ ++ for (i = 0; i < ARRAY_SIZE(pll->div); i++) { ++ struct clk *clk; ++ ++ snprintf(pll->div[i].name, sizeof(pll->div[i].name), ++ "cg-pll%d-div%d", idx, i + 1); ++ ++ clk = clk_register_fixed_factor(NULL, ++ pll->div[i].name, "cg-sysclk", 0, mult, i + 1); ++ if (IS_ERR(clk)) { ++ pr_err("%s: %s: register failed %ld\n", ++ __func__, pll->div[i].name, PTR_ERR(clk)); ++ continue; ++ } ++ ++ pll->div[i].clk = clk; + } ++} ++ ++static void __init create_plls(struct clockgen *cg) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(cg->pll); i++) ++ create_one_pll(cg, i); ++} + ++static void __init legacy_pll_init(struct device_node *np, int idx) ++{ ++ struct clockgen_pll *pll; ++ struct clk_onecell_data *onecell_data; ++ struct clk **subclks; ++ int count, rc; ++ ++ legacy_init_clockgen(np); ++ ++ pll = &clockgen.pll[idx]; + count = of_property_count_strings(np, "clock-output-names"); +- if (count < 0 || count > 4) { +- pr_err("%s: clock is not supported\n", np->name); +- goto err_map; +- } + +- subclks = kcalloc(count, sizeof(struct clk *), GFP_KERNEL); ++ BUILD_BUG_ON(ARRAY_SIZE(pll->div) < 4); ++ subclks = kcalloc(4, sizeof(struct clk *), GFP_KERNEL); + if (!subclks) +- goto err_map; ++ return; + + onecell_data = kmalloc(sizeof(*onecell_data), GFP_KERNEL); + if (!onecell_data) + goto err_clks; + +- for (i = 0; i < count; i++) { +- rc = of_property_read_string_index(np, "clock-output-names", +- i, &clk_name); +- if (rc) { +- pr_err("%s: could not get clock names\n", np->name); +- goto err_cell; +- } +- +- /* +- * when count == 4, there are 4 output clocks: +- * /1, /2, /3, /4 respectively +- * when count < 4, there are at least 2 output clocks: +- * /1, /2, (/4, if count == 3) respectively. +- */ +- if (count == 4) +- subclks[i] = clk_register_fixed_factor(NULL, clk_name, +- parent_name, 0, mult, 1 + i); +- else +- +- subclks[i] = clk_register_fixed_factor(NULL, clk_name, +- parent_name, 0, mult, 1 << i); +- +- if (IS_ERR(subclks[i])) { +- pr_err("%s: could not register clock\n", clk_name); +- goto err_cell; +- } ++ if (count <= 3) { ++ subclks[0] = pll->div[0].clk; ++ subclks[1] = pll->div[1].clk; ++ subclks[2] = pll->div[3].clk; ++ } else { ++ subclks[0] = pll->div[0].clk; ++ subclks[1] = pll->div[1].clk; ++ subclks[2] = pll->div[2].clk; ++ subclks[3] = pll->div[3].clk; + } + + onecell_data->clks = subclks; +@@ -233,125 +956,221 @@ static void __init core_pll_init(struct device_node *np) + + rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data); + if (rc) { +- pr_err("Could not register clk provider for node:%s\n", +- np->name); ++ pr_err("%s: Couldn't register clk provider for node %s: %d\n", ++ __func__, np->name, rc); + goto err_cell; + } + +- iounmap(base); + return; + err_cell: + kfree(onecell_data); + err_clks: + kfree(subclks); +-err_map: +- iounmap(base); + } + +-static void __init sysclk_init(struct device_node *node) ++/* Legacy node */ ++static void __init pltfrm_pll_init(struct device_node *np) + { +- struct clk *clk; +- const char *clk_name = node->name; +- struct device_node *np = of_get_parent(node); +- u32 rate; ++ legacy_pll_init(np, PLATFORM_PLL); ++} + +- if (!np) { +- pr_err("could not get parent node\n"); ++/* Legacy node */ ++static void __init core_pll_init(struct device_node *np) ++{ ++ struct resource res; ++ int idx; ++ ++ if (of_address_to_resource(np, 0, &res)) + return; ++ ++ if ((res.start & 0xfff) == 0xc00) { ++ /* ++ * ls1021a devtree labels the platform PLL ++ * with the core PLL compatible ++ */ ++ pltfrm_pll_init(np); ++ } else { ++ idx = (res.start & 0xf0) >> 5; ++ legacy_pll_init(np, CGA_PLL1 + idx); + } ++} + +- if (of_property_read_u32(np, "clock-frequency", &rate)) { +- of_node_put(node); +- return; ++static struct clk *clockgen_clk_get(struct of_phandle_args *clkspec, void *data) ++{ ++ struct clockgen *cg = data; ++ struct clk *clk; ++ struct clockgen_pll *pll; ++ u32 type, idx; ++ ++ if (clkspec->args_count < 2) { ++ pr_err("%s: insufficient phandle args\n", __func__); ++ return ERR_PTR(-EINVAL); + } + +- of_property_read_string(np, "clock-output-names", &clk_name); ++ type = clkspec->args[0]; ++ idx = clkspec->args[1]; + +- clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate); +- if (!IS_ERR(clk)) +- of_clk_add_provider(np, of_clk_src_simple_get, clk); ++ switch (type) { ++ case 0: ++ if (idx != 0) ++ goto bad_args; ++ clk = cg->sysclk; ++ break; ++ case 1: ++ if (idx >= ARRAY_SIZE(cg->cmux)) ++ goto bad_args; ++ clk = cg->cmux[idx]; ++ break; ++ case 2: ++ if (idx >= ARRAY_SIZE(cg->hwaccel)) ++ goto bad_args; ++ clk = cg->hwaccel[idx]; ++ break; ++ case 3: ++ if (idx >= ARRAY_SIZE(cg->fman)) ++ goto bad_args; ++ clk = cg->fman[idx]; ++ break; ++ case 4: ++ pll = &cg->pll[PLATFORM_PLL]; ++ if (idx >= ARRAY_SIZE(pll->div)) ++ goto bad_args; ++ clk = pll->div[idx].clk; ++ break; ++ default: ++ goto bad_args; ++ } ++ ++ if (!clk) ++ return ERR_PTR(-ENOENT); ++ return clk; ++ ++bad_args: ++ pr_err("%s: Bad phandle args %u %u\n", __func__, type, idx); ++ return ERR_PTR(-EINVAL); + } + +-static void __init pltfrm_pll_init(struct device_node *np) ++#ifdef CONFIG_PPC ++#include ++ ++static const u32 a4510_svrs[] __initconst = { ++ (SVR_P2040 << 8) | 0x10, /* P2040 1.0 */ ++ (SVR_P2040 << 8) | 0x11, /* P2040 1.1 */ ++ (SVR_P2041 << 8) | 0x10, /* P2041 1.0 */ ++ (SVR_P2041 << 8) | 0x11, /* P2041 1.1 */ ++ (SVR_P3041 << 8) | 0x10, /* P3041 1.0 */ ++ (SVR_P3041 << 8) | 0x11, /* P3041 1.1 */ ++ (SVR_P4040 << 8) | 0x20, /* P4040 2.0 */ ++ (SVR_P4080 << 8) | 0x20, /* P4080 2.0 */ ++ (SVR_P5010 << 8) | 0x10, /* P5010 1.0 */ ++ (SVR_P5010 << 8) | 0x20, /* P5010 2.0 */ ++ (SVR_P5020 << 8) | 0x10, /* P5020 1.0 */ ++ (SVR_P5021 << 8) | 0x10, /* P5021 1.0 */ ++ (SVR_P5040 << 8) | 0x10, /* P5040 1.0 */ ++}; ++ ++#define SVR_SECURITY 0x80000 /* The Security (E) bit */ ++ ++static bool __init has_erratum_a4510(void) + { +- void __iomem *base; +- uint32_t mult; +- const char *parent_name, *clk_name; +- int i, _errno; +- struct clk_onecell_data *cod; +- +- base = of_iomap(np, 0); +- if (!base) { +- pr_err("%s(): %s: of_iomap() failed\n", __func__, np->name); +- return; ++ u32 svr = mfspr(SPRN_SVR); ++ int i; ++ ++ svr &= ~SVR_SECURITY; ++ ++ for (i = 0; i < ARRAY_SIZE(a4510_svrs); i++) { ++ if (svr == a4510_svrs[i]) ++ return true; + } + +- /* Get the multiple of PLL */ +- mult = ioread32be(base); ++ return false; ++} ++#else ++static bool __init has_erratum_a4510(void) ++{ ++ return false; ++} ++#endif + +- iounmap(base); ++static void __init clockgen_init(struct device_node *np) ++{ ++ int i, ret; ++ bool is_old_ls1021a = false; + +- /* Check if this PLL is disabled */ +- if (mult & PLL_KILL) { +- pr_debug("%s(): %s: Disabled\n", __func__, np->name); ++ /* May have already been called by a legacy probe */ ++ if (clockgen.node) + return; +- } +- mult = (mult & GENMASK(6, 1)) >> 1; + +- parent_name = of_clk_get_parent_name(np, 0); +- if (!parent_name) { +- pr_err("%s(): %s: of_clk_get_parent_name() failed\n", +- __func__, np->name); ++ clockgen.node = np; ++ clockgen.regs = of_iomap(np, 0); ++ if (!clockgen.regs && ++ of_device_is_compatible(of_root, "fsl,ls1021a")) { ++ /* Compatibility hack for old, broken device trees */ ++ clockgen.regs = ioremap(0x1ee1000, 0x1000); ++ is_old_ls1021a = true; ++ } ++ if (!clockgen.regs) { ++ pr_err("%s(): %s: of_iomap() failed\n", __func__, np->name); + return; + } + +- i = of_property_count_strings(np, "clock-output-names"); +- if (i < 0) { +- pr_err("%s(): %s: of_property_count_strings(clock-output-names) = %d\n", +- __func__, np->name, i); +- return; ++ for (i = 0; i < ARRAY_SIZE(chipinfo); i++) { ++ if (of_device_is_compatible(np, chipinfo[i].compat)) ++ break; ++ if (is_old_ls1021a && ++ !strcmp(chipinfo[i].compat, "fsl,ls1021a-clockgen")) ++ break; + } + +- cod = kmalloc(sizeof(*cod) + i * sizeof(struct clk *), GFP_KERNEL); +- if (!cod) +- return; +- cod->clks = (struct clk **)(cod + 1); +- cod->clk_num = i; +- +- for (i = 0; i < cod->clk_num; i++) { +- _errno = of_property_read_string_index(np, "clock-output-names", +- i, &clk_name); +- if (_errno < 0) { +- pr_err("%s(): %s: of_property_read_string_index(clock-output-names) = %d\n", +- __func__, np->name, _errno); +- goto return_clk_unregister; +- } ++ if (i == ARRAY_SIZE(chipinfo)) { ++ pr_err("%s: unknown clockgen node %s\n", __func__, ++ np->full_name); ++ goto err; ++ } ++ clockgen.info = chipinfo[i]; ++ ++ if (clockgen.info.guts_compat) { ++ struct device_node *guts; + +- cod->clks[i] = clk_register_fixed_factor(NULL, clk_name, +- parent_name, 0, mult, 1 + i); +- if (IS_ERR(cod->clks[i])) { +- pr_err("%s(): %s: clk_register_fixed_factor(%s) = %ld\n", +- __func__, np->name, +- clk_name, PTR_ERR(cod->clks[i])); +- goto return_clk_unregister; ++ guts = of_find_compatible_node(NULL, NULL, ++ clockgen.info.guts_compat); ++ if (guts) { ++ clockgen.guts = of_iomap(guts, 0); ++ if (!clockgen.guts) { ++ pr_err("%s: Couldn't map %s regs\n", __func__, ++ guts->full_name); ++ } + } ++ + } + +- _errno = of_clk_add_provider(np, of_clk_src_onecell_get, cod); +- if (_errno < 0) { +- pr_err("%s(): %s: of_clk_add_provider() = %d\n", +- __func__, np->name, _errno); +- goto return_clk_unregister; ++ if (has_erratum_a4510()) ++ clockgen.info.flags |= CG_CMUX_GE_PLAT; ++ ++ clockgen.sysclk = create_sysclk("cg-sysclk"); ++ create_plls(&clockgen); ++ create_muxes(&clockgen); ++ ++ if (clockgen.info.init_periph) ++ clockgen.info.init_periph(&clockgen); ++ ++ ret = of_clk_add_provider(np, clockgen_clk_get, &clockgen); ++ if (ret) { ++ pr_err("%s: Couldn't register clk provider for node %s: %d\n", ++ __func__, np->name, ret); + } + + return; +- +-return_clk_unregister: +- while (--i >= 0) +- clk_unregister(cod->clks[i]); +- kfree(cod); ++err: ++ iounmap(clockgen.regs); ++ clockgen.regs = NULL; + } + ++CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init); ++CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init); ++CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init); ++ ++/* Legacy nodes */ + CLK_OF_DECLARE(qoriq_sysclk_1, "fsl,qoriq-sysclk-1.0", sysclk_init); + CLK_OF_DECLARE(qoriq_sysclk_2, "fsl,qoriq-sysclk-2.0", sysclk_init); + CLK_OF_DECLARE(qoriq_core_pll_1, "fsl,qoriq-core-pll-1.0", core_pll_init); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0006-clk-qoriq-Add-ls2080a-support.patch b/target/linux/layerscape-64b/patches-4.1/0006-clk-qoriq-Add-ls2080a-support.patch new file mode 100644 index 0000000..5081a0c --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0006-clk-qoriq-Add-ls2080a-support.patch @@ -0,0 +1,181 @@ +From c6a404c4471e7eeb25f3eb51b6327a2f3a5639e0 Mon Sep 17 00:00:00 2001 +From: Scott Wood +Date: Fri, 15 Jan 2016 07:34:26 +0000 +Subject: [PATCH 006/151] clk: qoriq: Add ls2080a support. + +LS2080A is the first implementation of the chassis 3 clockgen, which +has a different register layout than previous chips. It is also little +endian, unlike previous chips. + +Signed-off-by: Scott Wood +Acked-by: Stephen Boyd +(cherry picked from commit 9e19ca2f627e5a6ee7425c48cc30b7356995b691) +Signed-off-by: Scott Wood +--- + drivers/clk/Kconfig | 2 +- + drivers/clk/clk-qoriq.c | 77 +++++++++++++++++++++++++++++++++++++++++++------ + 2 files changed, 69 insertions(+), 10 deletions(-) + +diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig +index 9897f35..0f7a0a1 100644 +--- a/drivers/clk/Kconfig ++++ b/drivers/clk/Kconfig +@@ -104,7 +104,7 @@ config COMMON_CLK_AXI_CLKGEN + + config CLK_QORIQ + bool "Clock driver for Freescale QorIQ platforms" +- depends on (PPC_E500MC || ARM) && OF ++ depends on (PPC_E500MC || ARM || ARM64) && OF + ---help--- + This adds the clock driver support for Freescale QorIQ platforms + using common clock framework. +diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c +index 06281a3..8f9c93b 100644 +--- a/drivers/clk/clk-qoriq.c ++++ b/drivers/clk/clk-qoriq.c +@@ -68,7 +68,10 @@ struct clockgen; + * If not set, cmux freq must be >= platform pll/2 + */ + #define CG_CMUX_GE_PLAT 1 ++ + #define CG_PLL_8BIT 2 /* PLLCnGSR[CFG] is 8 bits, not 6 */ ++#define CG_VER3 4 /* version 3 cg: reg layout different */ ++#define CG_LITTLE_ENDIAN 8 + + struct clockgen_chipinfo { + const char *compat, *guts_compat; +@@ -94,6 +97,26 @@ struct clockgen { + + static struct clockgen clockgen; + ++static void cg_out(struct clockgen *cg, u32 val, u32 __iomem *reg) ++{ ++ if (cg->info.flags & CG_LITTLE_ENDIAN) ++ iowrite32(val, reg); ++ else ++ iowrite32be(val, reg); ++} ++ ++static u32 cg_in(struct clockgen *cg, u32 __iomem *reg) ++{ ++ u32 val; ++ ++ if (cg->info.flags & CG_LITTLE_ENDIAN) ++ val = ioread32(reg); ++ else ++ val = ioread32be(reg); ++ ++ return val; ++} ++ + static const struct clockgen_muxinfo p2041_cmux_grp1 = { + { + [0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 }, +@@ -429,6 +452,17 @@ static const struct clockgen_chipinfo chipinfo[] = { + .pll_mask = 0x03, + }, + { ++ .compat = "fsl,ls2080a-clockgen", ++ .cmux_groups = { ++ &clockgen2_cmux_cga12, &clockgen2_cmux_cgb ++ }, ++ .cmux_to_group = { ++ 0, 0, 1, 1, -1 ++ }, ++ .pll_mask = 0x37, ++ .flags = CG_VER3 | CG_LITTLE_ENDIAN, ++ }, ++ { + .compat = "fsl,p2041-clockgen", + .guts_compat = "fsl,qoriq-device-config-1.0", + .init_periph = p2041_init_periph, +@@ -575,7 +609,7 @@ static int mux_set_parent(struct clk_hw *hw, u8 idx) + return -EINVAL; + + clksel = hwc->parent_to_clksel[idx]; +- iowrite32be((clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg); ++ cg_out(hwc->cg, (clksel << CLKSEL_SHIFT) & CLKSEL_MASK, hwc->reg); + + return 0; + } +@@ -586,7 +620,7 @@ static u8 mux_get_parent(struct clk_hw *hw) + u32 clksel; + s8 ret; + +- clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT; ++ clksel = (cg_in(hwc->cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT; + + ret = hwc->clksel_to_parent[clksel]; + if (ret < 0) { +@@ -705,7 +739,7 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx) + * default clksel) may be inappropriately excluded on certain + * chips. + */ +- clksel = (ioread32be(hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT; ++ clksel = (cg_in(cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT; + div = get_pll_div(cg, hwc, clksel); + if (!div) + return NULL; +@@ -874,13 +908,36 @@ static void __init create_one_pll(struct clockgen *cg, int idx) + if (!(cg->info.pll_mask & (1 << idx))) + return; + +- if (idx == PLATFORM_PLL) +- reg = cg->regs + 0xc00; +- else +- reg = cg->regs + 0x800 + 0x20 * (idx - 1); ++ if (cg->info.flags & CG_VER3) { ++ switch (idx) { ++ case PLATFORM_PLL: ++ reg = cg->regs + 0x60080; ++ break; ++ case CGA_PLL1: ++ reg = cg->regs + 0x80; ++ break; ++ case CGA_PLL2: ++ reg = cg->regs + 0xa0; ++ break; ++ case CGB_PLL1: ++ reg = cg->regs + 0x10080; ++ break; ++ case CGB_PLL2: ++ reg = cg->regs + 0x100a0; ++ break; ++ default: ++ WARN_ONCE(1, "index %d\n", idx); ++ return; ++ } ++ } else { ++ if (idx == PLATFORM_PLL) ++ reg = cg->regs + 0xc00; ++ else ++ reg = cg->regs + 0x800 + 0x20 * (idx - 1); ++ } + + /* Get the multiple of PLL */ +- mult = ioread32be(reg); ++ mult = cg_in(cg, reg); + + /* Check if this PLL is disabled */ + if (mult & PLL_KILL) { +@@ -888,7 +945,8 @@ static void __init create_one_pll(struct clockgen *cg, int idx) + return; + } + +- if ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL) ++ if ((cg->info.flags & CG_VER3) || ++ ((cg->info.flags & CG_PLL_8BIT) && idx != PLATFORM_PLL)) + mult = (mult & GENMASK(8, 1)) >> 1; + else + mult = (mult & GENMASK(6, 1)) >> 1; +@@ -1169,6 +1227,7 @@ err: + CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init); + CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init); + CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init); ++CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init); + + /* Legacy nodes */ + CLK_OF_DECLARE(qoriq_sysclk_1, "fsl,qoriq-sysclk-1.0", sysclk_init); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0007-clk-qoriq-Add-ls1043a-support.patch b/target/linux/layerscape-64b/patches-4.1/0007-clk-qoriq-Add-ls1043a-support.patch new file mode 100644 index 0000000..fedf3cb --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0007-clk-qoriq-Add-ls1043a-support.patch @@ -0,0 +1,80 @@ +From b1399d9751ac9e6cc6f9daf185fc2caaeb2cca77 Mon Sep 17 00:00:00 2001 +From: Hou Zhiqiang +Date: Fri, 15 Jan 2016 07:34:28 +0000 +Subject: [PATCH 007/151] clk: qoriq: Add ls1043a support. + +Signed-off-by: Hou Zhiqiang +Acked-by: Stephen Boyd +Signed-off-by: Scott Wood +(cherry picked from commit e994412c5f19402a834f4b0d95e9159d1c7b0fb8) +Signed-off-by: Scott Wood +--- + drivers/clk/clk-qoriq.c | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c +index 8f9c93b..b189688 100644 +--- a/drivers/clk/clk-qoriq.c ++++ b/drivers/clk/clk-qoriq.c +@@ -244,6 +244,28 @@ static const struct clockgen_muxinfo clockgen2_cmux_cgb = { + }, + }; + ++static const struct clockgen_muxinfo ls1043a_hwa1 = { ++ { ++ {}, ++ {}, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 }, ++ { CLKSEL_VALID, CGA_PLL1, PLL_DIV3 }, ++ {}, ++ {}, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV2 }, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, ++ }, ++}; ++ ++static const struct clockgen_muxinfo ls1043a_hwa2 = { ++ { ++ {}, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV1 }, ++ {}, ++ { CLKSEL_VALID, CGA_PLL2, PLL_DIV3 }, ++ }, ++}; ++ + static const struct clockgen_muxinfo t1023_hwa1 = { + { + {}, +@@ -452,6 +474,21 @@ static const struct clockgen_chipinfo chipinfo[] = { + .pll_mask = 0x03, + }, + { ++ .compat = "fsl,ls1043a-clockgen", ++ .init_periph = t2080_init_periph, ++ .cmux_groups = { ++ &t1040_cmux ++ }, ++ .hwaccel = { ++ &ls1043a_hwa1, &ls1043a_hwa2 ++ }, ++ .cmux_to_group = { ++ 0, -1 ++ }, ++ .pll_mask = 0x07, ++ .flags = CG_PLL_8BIT, ++ }, ++ { + .compat = "fsl,ls2080a-clockgen", + .cmux_groups = { + &clockgen2_cmux_cga12, &clockgen2_cmux_cgb +@@ -1227,6 +1264,7 @@ err: + CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init); + CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init); + CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init); ++CLK_OF_DECLARE(qoriq_clockgen_ls1043a, "fsl,ls1043a-clockgen", clockgen_init); + CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init); + + /* Legacy nodes */ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0008-clk-qoriq-fix-memory-leak.patch b/target/linux/layerscape-64b/patches-4.1/0008-clk-qoriq-fix-memory-leak.patch new file mode 100644 index 0000000..bfdcbb9 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0008-clk-qoriq-fix-memory-leak.patch @@ -0,0 +1,36 @@ +From d95e65cb2998c6e066e3bf62d0b8ac546f0afa90 Mon Sep 17 00:00:00 2001 +From: Sudip Mukherjee +Date: Fri, 15 Jan 2016 07:34:29 +0000 +Subject: [PATCH 008/151] clk: qoriq: fix memory leak + +If get_pll_div() fails we exited by returning NULL but we missed +releasing hwc. + +Signed-off-by: Sudip Mukherjee +Fixes: 0dfc86b3173f ("clk: qoriq: Move chip-specific knowledge into driver") +Signed-off-by: Stephen Boyd +(cherry picked from commit 279104e3ade92b38198fdaead9e84bd80057693a) +Signed-off-by: Scott Wood +--- + drivers/clk/clk-qoriq.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c +index b189688..f8739d0 100644 +--- a/drivers/clk/clk-qoriq.c ++++ b/drivers/clk/clk-qoriq.c +@@ -778,8 +778,10 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx) + */ + clksel = (cg_in(cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT; + div = get_pll_div(cg, hwc, clksel); +- if (!div) ++ if (!div) { ++ kfree(hwc); + return NULL; ++ } + + pct80_rate = clk_get_rate(div->clk); + pct80_rate *= 8; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0009-dts-ls1043a-add-fman-bman-qman-ethernet-nodes.patch b/target/linux/layerscape-64b/patches-4.1/0009-dts-ls1043a-add-fman-bman-qman-ethernet-nodes.patch new file mode 100644 index 0000000..3dbaa0f --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0009-dts-ls1043a-add-fman-bman-qman-ethernet-nodes.patch @@ -0,0 +1,754 @@ +From 0e60f48b37d3979674cd01e3a2d461c4e1a9301a Mon Sep 17 00:00:00 2001 +From: Shaohui Xie +Date: Thu, 21 Jan 2016 11:27:15 +0800 +Subject: [PATCH 009/151] dts: ls1043a: add fman/bman/qman/ethernet nodes + +Signed-off-by: Shaohui Xie +--- + arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 461 +++++++++++++++++++++ + .../boot/dts/freescale/qoriq-bman1-portals.dtsi | 104 +++++ + .../boot/dts/freescale/qoriq-qman1-portals.dtsi | 136 ++++++ + 3 files changed, 701 insertions(+) + create mode 100644 arch/arm64/boot/dts/freescale/qoriq-bman1-portals.dtsi + create mode 100644 arch/arm64/boot/dts/freescale/qoriq-qman1-portals.dtsi + +diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +index cb00a84..5654173 100644 +--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +@@ -50,6 +50,16 @@ + #address-cells = <2>; + #size-cells = <2>; + ++ aliases { ++ ethernet0 = &fm1mac1; ++ ethernet1 = &fm1mac2; ++ ethernet2 = &fm1mac3; ++ ethernet3 = &fm1mac4; ++ ethernet4 = &fm1mac5; ++ ethernet5 = &fm1mac6; ++ ethernet6 = &fm1mac9; ++ }; ++ + cpus { + #address-cells = <2>; + #size-cells = <0>; +@@ -174,6 +184,323 @@ + bus-width = <4>; + }; + ++ qman: qman at 1880000 { ++ compatible = "fsl,qman"; ++ reg = <0x00 0x1880000 0x0 0x10000>; ++ interrupts = <0 45 0x4>; ++ }; ++ ++ bman: bman at 1890000 { ++ compatible = "fsl,bman"; ++ reg = <0x00 0x1890000 0x0 0x10000>; ++ interrupts = <0 45 0x4>; ++ }; ++ ++ fman0: fman at 1a00000 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ cell-index = <0>; ++ compatible = "fsl,fman", "simple-bus"; ++ ranges = <0x0 0x00 0x1a00000 0x100000>; ++ reg = <0x00 0x1a00000 0x0 0x100000>; ++ clock-frequency = <0>; ++ interrupts = <0 44 0x4>, ++ <0 45 0x4>; ++ ++ cc { ++ compatible = "fsl,fman-cc"; ++ }; ++ ++ muram at 0 { ++ compatible = "fsl,fman-muram"; ++ reg = <0x0 0x60000>; ++ }; ++ ++ bmi at 80000 { ++ compatible = "fsl,fman-bmi"; ++ reg = <0x80000 0x400>; ++ }; ++ ++ qmi at 80400 { ++ compatible = "fsl,fman-qmi"; ++ reg = <0x80400 0x400>; ++ }; ++ ++ fman0_oh1: port at 82000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x82000 0x1000>; ++ }; ++ ++ fman0_oh2: port at 83000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x83000 0x1000>; ++ }; ++ ++ fman0_oh3: port at 84000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x84000 0x1000>; ++ }; ++ ++ fman0_oh4: port at 85000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x85000 0x1000>; ++ }; ++ ++ fman0_oh5: port at 86000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x86000 0x1000>; ++ }; ++ ++ fman0_oh6: port at 87000 { ++ cell-index = <5>; ++ compatible = "fsl,fman-port-oh"; ++ reg = <0x87000 0x1000>; ++ }; ++ ++ policer at c0000 { ++ compatible = "fsl,fman-policer"; ++ reg = <0xc0000 0x1000>; ++ }; ++ ++ keygen at c1000 { ++ compatible = "fsl,fman-keygen"; ++ reg = <0xc1000 0x1000>; ++ }; ++ ++ dma at c2000 { ++ compatible = "fsl,fman-dma"; ++ reg = <0xc2000 0x1000>; ++ }; ++ ++ fpm at c3000 { ++ compatible = "fsl,fman-fpm"; ++ reg = <0xc3000 0x1000>; ++ }; ++ ++ parser at c7000 { ++ compatible = "fsl,fman-parser"; ++ reg = <0xc7000 0x1000>; ++ }; ++ ++ vsps at dc000 { ++ compatible = "fsl,fman-vsps"; ++ reg = <0xdc000 0x1000>; ++ }; ++ ++ mdio0: mdio at fc000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-mdio"; ++ reg = <0xfc000 0x1000>; ++ }; ++ ++ xmdio0: mdio at fd000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-mdio"; ++ reg = <0xfd000 0x1000>; ++ }; ++ ++ fman0_rx0: port at 88000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x88000 0x1000>; ++ }; ++ ++ fman0_tx0: port at a8000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xa8000 0x1000>; ++ }; ++ ++ fm1mac1: ethernet at e0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe0000 0x1000>; ++ fsl,port-handles = <&fman0_rx0 &fman0_tx0>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio at e1000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-mdio"; ++ reg = <0xe1000 0x1000>; ++ }; ++ ++ fman0_rx1: port at 89000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x89000 0x1000>; ++ }; ++ ++ fman0_tx1: port at a9000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xa9000 0x1000>; ++ }; ++ ++ fm1mac2: ethernet at e2000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe2000 0x1000>; ++ fsl,port-handles = <&fman0_rx1 &fman0_tx1>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio at e3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-mdio"; ++ reg = <0xe3000 0x1000>; ++ }; ++ ++ fman0_rx2: port at 8a000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8a000 0x1000>; ++ }; ++ ++ fman0_tx2: port at aa000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xaa000 0x1000>; ++ }; ++ ++ fm1mac3: ethernet at e4000 { ++ cell-index = <2>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe4000 0x1000>; ++ fsl,port-handles = <&fman0_rx2 &fman0_tx2>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio at e5000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-mdio"; ++ reg = <0xe5000 0x1000>; ++ }; ++ ++ fman0_rx3: port at 8b000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8b000 0x1000>; ++ }; ++ ++ fman0_tx3: port at ab000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xab000 0x1000>; ++ }; ++ ++ fm1mac4: ethernet at e6000 { ++ cell-index = <3>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe6000 0x1000>; ++ fsl,port-handles = <&fman0_rx3 &fman0_tx3>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio at e7000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-mdio"; ++ reg = <0xe7000 0x1000>; ++ }; ++ ++ fman0_rx4: port at 8c000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8c000 0x1000>; ++ }; ++ ++ fman0_tx4: port at ac000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xac000 0x1000>; ++ }; ++ ++ fm1mac5: ethernet at e8000 { ++ cell-index = <4>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe8000 0x1000>; ++ fsl,port-handles = <&fman0_rx4 &fman0_tx4>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio at e9000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-mdio"; ++ reg = <0xe9000 0x1000>; ++ }; ++ ++ fman0_rx5: port at 8d000 { ++ cell-index = <5>; ++ compatible = "fsl,fman-port-1g-rx"; ++ reg = <0x8d000 0x1000>; ++ }; ++ ++ fman0_tx5: port at ad000 { ++ cell-index = <5>; ++ compatible = "fsl,fman-port-1g-tx"; ++ reg = <0xad000 0x1000>; ++ }; ++ ++ fm1mac6: ethernet at ea000 { ++ cell-index = <5>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xea000 0x1000>; ++ fsl,port-handles = <&fman0_rx5 &fman0_tx5>; ++ ptimer-handle = <&ptp_timer0>; ++ }; ++ ++ mdio at eb000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-mdio"; ++ reg = <0xeb000 0x1000>; ++ }; ++ ++ fman0_10g_rx0: port at 90000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-10g-rx"; ++ reg = <0x90000 0x1000>; ++ }; ++ ++ fman0_10g_tx0: port at b0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-port-10g-tx"; ++ reg = <0xb0000 0x1000>; ++ fsl,qman-channel-id = <0x800>; ++ }; ++ ++ fm1mac9: ethernet at f0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xf0000 0x1000>; ++ fsl,port-handles = <&fman0_10g_rx0 &fman0_10g_tx0>; ++ }; ++ ++ mdio at f1000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-mdio"; ++ reg = <0xf1000 0x1000>; ++ }; ++ ++ ptp_timer0: rtc at fe000 { ++ compatible = "fsl,fman-rtc"; ++ reg = <0xfe000 0x1000>; ++ }; ++ }; ++ + dspi0: dspi at 2100000 { + compatible = "fsl,ls1043a-dspi", "fsl,ls1021a-v1.0-dspi"; + #address-cells = <1>; +@@ -522,4 +849,138 @@ + }; + }; + ++ fsl,dpaa { ++ compatible = "fsl,ls1043a-dpaa", "simple-bus", "fsl,dpaa"; ++ ethernet at 0 { ++ compatible = "fsl,dpa-ethernet"; ++ fsl,fman-mac = <&fm1mac1>; ++ }; ++ ethernet at 1 { ++ compatible = "fsl,dpa-ethernet"; ++ fsl,fman-mac = <&fm1mac2>; ++ }; ++ ethernet at 2 { ++ compatible = "fsl,dpa-ethernet"; ++ fsl,fman-mac = <&fm1mac3>; ++ }; ++ ethernet at 3 { ++ compatible = "fsl,dpa-ethernet"; ++ fsl,fman-mac = <&fm1mac4>; ++ }; ++ ethernet at 4 { ++ compatible = "fsl,dpa-ethernet"; ++ fsl,fman-mac = <&fm1mac5>; ++ }; ++ ethernet at 5 { ++ compatible = "fsl,dpa-ethernet"; ++ fsl,fman-mac = <&fm1mac6>; ++ }; ++ ethernet at 8 { ++ compatible = "fsl,dpa-ethernet"; ++ fsl,fman-mac = <&fm1mac9>; ++ }; ++ }; ++ ++ qportals: qman-portals at 500000000 { ++ ranges = <0x0 0x5 0x00000000 0x8000000>; ++ }; ++ bportals: bman-portals at 508000000 { ++ ranges = <0x0 0x5 0x08000000 0x8000000>; ++ }; ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ bman_fbpr: bman-fbpr { ++ size = <0 0x1000000>; ++ alignment = <0 0x1000000>; ++ }; ++ qman_fqd: qman-fqd { ++ size = <0 0x400000>; ++ alignment = <0 0x400000>; ++ }; ++ qman_pfdr: qman-pfdr { ++ size = <0 0x2000000>; ++ alignment = <0 0x2000000>; ++ }; ++ }; + }; ++ ++&fman0 { ++ /* offline - 1 */ ++ port at 82000 { ++ fsl,qman-channel-id = <0x809>; ++ }; ++ ++ /* tx - 10g - 2 */ ++ port at a8000 { ++ fsl,qman-channel-id = <0x802>; ++ }; ++ /* tx - 10g - 3 */ ++ port at a9000 { ++ fsl,qman-channel-id = <0x803>; ++ }; ++ /* tx - 1g - 2 */ ++ port at aa000 { ++ fsl,qman-channel-id = <0x804>; ++ }; ++ /* tx - 1g - 3 */ ++ port at ab000 { ++ fsl,qman-channel-id = <0x805>; ++ }; ++ /* tx - 1g - 4 */ ++ port at ac000 { ++ fsl,qman-channel-id = <0x806>; ++ }; ++ /* tx - 1g - 5 */ ++ port at ad000 { ++ fsl,qman-channel-id = <0x807>; ++ }; ++ /* tx - 10g - 0 */ ++ port at b0000 { ++ fsl,qman-channel-id = <0x800>; ++ }; ++ /* tx - 10g - 1 */ ++ port at b1000 { ++ fsl,qman-channel-id = <0x801>; ++ }; ++ /* offline - 2 */ ++ port at 83000 { ++ fsl,qman-channel-id = <0x80a>; ++ }; ++ /* offline - 3 */ ++ port at 84000 { ++ fsl,qman-channel-id = <0x80b>; ++ }; ++ /* offline - 4 */ ++ port at 85000 { ++ fsl,qman-channel-id = <0x80c>; ++ }; ++ /* offline - 5 */ ++ port at 86000 { ++ fsl,qman-channel-id = <0x80d>; ++ }; ++ /* offline - 6 */ ++ port at 87000 { ++ fsl,qman-channel-id = <0x80e>; ++ }; ++}; ++ ++&bman_fbpr { ++ compatible = "fsl,bman-fbpr"; ++ alloc-ranges = <0 0 0x10000 0>; ++}; ++ ++&qman_fqd { ++ compatible = "fsl,qman-fqd"; ++ alloc-ranges = <0 0 0x10000 0>; ++}; ++ ++&qman_pfdr { ++ compatible = "fsl,qman-pfdr"; ++ alloc-ranges = <0 0 0x10000 0>; ++}; ++ ++/include/ "qoriq-qman1-portals.dtsi" ++/include/ "qoriq-bman1-portals.dtsi" +diff --git a/arch/arm64/boot/dts/freescale/qoriq-bman1-portals.dtsi b/arch/arm64/boot/dts/freescale/qoriq-bman1-portals.dtsi +new file mode 100644 +index 0000000..b733ff0 +--- /dev/null ++++ b/arch/arm64/boot/dts/freescale/qoriq-bman1-portals.dtsi +@@ -0,0 +1,104 @@ ++/* ++ * QorIQ BMan Portal device tree stub for 10 portals ++ * ++ * Copyright 2011-2016 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. ++ */ ++ ++&bportals { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ bportal0: bman-portal at 0 { ++ cell-index = <0>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x0 0x4000 0x4000000 0x4000>; ++ interrupts = <0 173 0x4>; ++ }; ++ bportal1: bman-portal at 10000 { ++ cell-index = <1>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x10000 0x4000 0x4010000 0x4000>; ++ interrupts = <0 175 0x4>; ++ }; ++ bportal2: bman-portal at 20000 { ++ cell-index = <2>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x20000 0x4000 0x4020000 0x4000>; ++ interrupts = <0 177 0x4>; ++ }; ++ bportal3: bman-portal at 30000 { ++ cell-index = <3>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x30000 0x4000 0x4030000 0x4000>; ++ interrupts = <0 179 0x4>; ++ }; ++ bportal4: bman-portal at 40000 { ++ cell-index = <4>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x40000 0x4000 0x4040000 0x4000>; ++ interrupts = <0 181 0x4>; ++ }; ++ bportal5: bman-portal at 50000 { ++ cell-index = <5>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x50000 0x4000 0x4050000 0x4000>; ++ interrupts = <0 183 0x4>; ++ }; ++ bportal6: bman-portal at 60000 { ++ cell-index = <6>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x60000 0x4000 0x4060000 0x4000>; ++ interrupts = <0 185 0x4>; ++ }; ++ bportal7: bman-portal at 70000 { ++ cell-index = <7>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x70000 0x4000 0x4070000 0x4000>; ++ interrupts = <0 187 0x4>; ++ }; ++ bportal8: bman-portal at 80000 { ++ cell-index = <8>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x80000 0x4000 0x4080000 0x4000>; ++ interrupts = <0 189 0x4>; ++ }; ++/* bportal9: bman-portal at 90000 { ++ cell-index = <9>; ++ compatible = "fsl,bman-portal"; ++ reg = <0x90000 0x4000 0x4090000 0x4000>; ++ interrupts = <0 191 0x4>; ++ }; */ ++ bman-bpids at 0 { ++ compatible = "fsl,bpid-range"; ++ fsl,bpid-range = <32 32>; ++ }; ++ ++}; +diff --git a/arch/arm64/boot/dts/freescale/qoriq-qman1-portals.dtsi b/arch/arm64/boot/dts/freescale/qoriq-qman1-portals.dtsi +new file mode 100644 +index 0000000..f01b58b +--- /dev/null ++++ b/arch/arm64/boot/dts/freescale/qoriq-qman1-portals.dtsi +@@ -0,0 +1,136 @@ ++/* ++ * QorIQ QMan Portal device tree stub for 10 portals & 15 pool channels ++ * ++ * Copyright 2011-2016 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. ++ */ ++&qportals { ++ ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "simple-bus"; ++ qportal0: qman-portal at 0 { ++ cell-index = <0>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x0 0x4000 0x4000000 0x4000>; ++ interrupts = <0 172 0x4>; ++ fsl,qman-channel-id = <0x0>; ++ }; ++ ++ qportal1: qman-portal at 10000 { ++ cell-index = <1>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x10000 0x4000 0x4010000 0x4000>; ++ interrupts = <0 174 0x4>; ++ fsl,qman-channel-id = <1>; ++ }; ++ ++ qportal2: qman-portal at 20000 { ++ cell-index = <2>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x20000 0x4000 0x4020000 0x4000>; ++ interrupts = <0 176 0x4>; ++ fsl,qman-channel-id = <2>; ++ }; ++ ++ qportal3: qman-portal at 30000 { ++ cell-index = <3>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x30000 0x4000 0x4030000 0x4000>; ++ interrupts = <0 178 0x4>; ++ fsl,qman-channel-id = <3>; ++ }; ++ ++ qportal4: qman-portal at 40000 { ++ cell-index = <4>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x40000 0x4000 0x4040000 0x4000>; ++ interrupts = <0 180 0x4>; ++ fsl,qman-channel-id = <4>; ++ }; ++ ++ qportal5: qman-portal at 50000 { ++ cell-index = <5>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x50000 0x4000 0x4050000 0x4000>; ++ interrupts = <0 182 0x4>; ++ fsl,qman-channel-id = <5>; ++ }; ++ ++ qportal6: qman-portal at 60000 { ++ cell-index = <6>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x60000 0x4000 0x4060000 0x4000>; ++ interrupts = <0 184 0x4>; ++ fsl,qman-channel-id = <6>; ++ }; ++ ++ qportal7: qman-portal at 70000 { ++ cell-index = <7>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x70000 0x4000 0x4070000 0x4000>; ++ interrupts = <0 186 0x4>; ++ fsl,qman-channel-id = <7>; ++ }; ++ ++ qportal8: qman-portal at 80000 { ++ cell-index = <8>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x80000 0x4000 0x4080000 0x4000>; ++ interrupts = <0 188 0x4>; ++ fsl,qman-channel-id = <8>; ++ }; ++ ++/* qportal9: qman-portal at 90000 { ++ cell-index = <9>; ++ compatible = "fsl,qman-portal"; ++ reg = <0x90000 0x4000 0x4090000 0x4000>; ++ interrupts = <0 190 0x4>; ++ fsl,qman-channel-id = <9>; ++ }; */ ++ ++ qman-fqids at 0 { ++ compatible = "fsl,fqid-range"; ++ fsl,fqid-range = <256 256>; ++ }; ++ qman-fqids at 1 { ++ compatible = "fsl,fqid-range"; ++ fsl,fqid-range = <32768 32768>; ++ }; ++ qman-pools at 0 { ++ compatible = "fsl,pool-channel-range"; ++ fsl,pool-channel-range = <0x401 0xf>; ++ }; ++ qman-cgrids at 0 { ++ compatible = "fsl,cgrid-range"; ++ fsl,cgrid-range = <0 256>; ++ }; ++ ++}; +\ No newline at end of file +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0010-dts-ls1043ardb-add-mdio-phy-nodes.patch b/target/linux/layerscape-64b/patches-4.1/0010-dts-ls1043ardb-add-mdio-phy-nodes.patch new file mode 100644 index 0000000..ea90a2e --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0010-dts-ls1043ardb-add-mdio-phy-nodes.patch @@ -0,0 +1,86 @@ +From 923a43e7e2180ea46e4e4088560f763d39006c07 Mon Sep 17 00:00:00 2001 +From: Shaohui Xie +Date: Thu, 21 Jan 2016 11:29:22 +0800 +Subject: [PATCH 010/151] dts: ls1043ardb: add mdio & phy nodes + +Signed-off-by: Shaohui Xie +--- + arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts | 65 +++++++++++++++++++++++ + 1 file changed, 65 insertions(+) + +diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts +index c95a0e7..bba79bf 100644 +--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts +@@ -115,3 +115,68 @@ + &duart1 { + status = "okay"; + }; ++ ++&fman0 { ++ ethernet at e0000 { ++ phy-handle = <&qsgmii_phy1>; ++ phy-connection-type = "qsgmii"; ++ }; ++ ++ ethernet at e2000 { ++ phy-handle = <&qsgmii_phy2>; ++ phy-connection-type = "qsgmii"; ++ }; ++ ++ ethernet at e4000 { ++ phy-handle = <&rgmii_phy1>; ++ phy-connection-type = "rgmii"; ++ }; ++ ++ ethernet at e6000 { ++ phy-handle = <&rgmii_phy2>; ++ phy-connection-type = "rgmii"; ++ }; ++ ++ ethernet at e8000 { ++ phy-handle = <&qsgmii_phy3>; ++ phy-connection-type = "qsgmii"; ++ }; ++ ++ ethernet at ea000 { ++ phy-handle = <&qsgmii_phy4>; ++ phy-connection-type = "qsgmii"; ++ }; ++ ++ ethernet at f0000 { /* 10GEC1 */ ++ phy-handle = <&aqr105_phy>; ++ phy-connection-type = "xgmii"; ++ }; ++ ++ mdio at fc000 { ++ rgmii_phy1: ethernet-phy at 1 { ++ reg = <0x1>; ++ }; ++ rgmii_phy2: ethernet-phy at 2 { ++ reg = <0x2>; ++ }; ++ qsgmii_phy1: ethernet-phy at 3 { ++ reg = <0x4>; ++ }; ++ qsgmii_phy2: ethernet-phy at 4 { ++ reg = <0x5>; ++ }; ++ qsgmii_phy3: ethernet-phy at 5 { ++ reg = <0x6>; ++ }; ++ qsgmii_phy4: ethernet-phy at 6 { ++ reg = <0x7>; ++ }; ++ }; ++ ++ mdio at fd000 { ++ aqr105_phy: ethernet-phy at c { ++ compatible = "ethernet-phy-ieee802.3-c45"; ++ reg = <0x1>; ++ }; ++ }; ++}; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0011-arch-arm-add-ARM-specific-fucntions-required-for-ehc.patch b/target/linux/layerscape-64b/patches-4.1/0011-arch-arm-add-ARM-specific-fucntions-required-for-ehc.patch new file mode 100644 index 0000000..549a669 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0011-arch-arm-add-ARM-specific-fucntions-required-for-ehc.patch @@ -0,0 +1,86 @@ +From 81fc89888a98d76369b88506d45fc5f0ecb3e030 Mon Sep 17 00:00:00 2001 +From: Zhao Qiang +Date: Fri, 10 Oct 2014 10:38:48 +0800 +Subject: [PATCH 011/151] arch: arm: add ARM specific fucntions required for + ehci fsl driver + +Add below functions for ARM platform which are used by ehci fsl driver: +1. spin_event_timeout function +2. set/clear bits functions + +Signed-off-by: Zhao Qiang +Signed-off-by: Rajesh Bhagat +--- + arch/arm/include/asm/delay.h | 16 ++++++++++++++++ + arch/arm/include/asm/io.h | 28 ++++++++++++++++++++++++++++ + 2 files changed, 44 insertions(+) + +diff --git a/arch/arm/include/asm/delay.h b/arch/arm/include/asm/delay.h +index dff714d..a932f99 100644 +--- a/arch/arm/include/asm/delay.h ++++ b/arch/arm/include/asm/delay.h +@@ -57,6 +57,22 @@ extern void __bad_udelay(void); + __const_udelay((n) * UDELAY_MULT)) : \ + __udelay(n)) + ++#define spin_event_timeout(condition, timeout, delay) \ ++({ \ ++ typeof(condition) __ret; \ ++ int i = 0; \ ++ while (!(__ret = (condition)) && (i++ < timeout)) { \ ++ if (delay) \ ++ udelay(delay); \ ++ else \ ++ cpu_relax(); \ ++ udelay(1); \ ++ } \ ++ if (!__ret) \ ++ __ret = (condition); \ ++ __ret; \ ++}) ++ + /* Loop-based definitions for assembly code. */ + extern void __loop_delay(unsigned long loops); + extern void __loop_udelay(unsigned long usecs); +diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h +index db58deb..e242160 100644 +--- a/arch/arm/include/asm/io.h ++++ b/arch/arm/include/asm/io.h +@@ -227,6 +227,34 @@ extern int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr); + #endif + #endif + ++/* access ports */ ++#define setbits32(_addr, _v) iowrite32be(ioread32be(_addr) | (_v), (_addr)) ++#define clrbits32(_addr, _v) iowrite32be(ioread32be(_addr) & ~(_v), (_addr)) ++ ++#define setbits16(_addr, _v) iowrite16be(ioread16be(_addr) | (_v), (_addr)) ++#define clrbits16(_addr, _v) iowrite16be(ioread16be(_addr) & ~(_v), (_addr)) ++ ++#define setbits8(_addr, _v) iowrite8(ioread8(_addr) | (_v), (_addr)) ++#define clrbits8(_addr, _v) iowrite8(ioread8(_addr) & ~(_v), (_addr)) ++ ++/* Clear and set bits in one shot. These macros can be used to clear and ++ * set multiple bits in a register using a single read-modify-write. These ++ * macros can also be used to set a multiple-bit bit pattern using a mask, ++ * by specifying the mask in the 'clear' parameter and the new bit pattern ++ * in the 'set' parameter. ++ */ ++ ++#define clrsetbits_be32(addr, clear, set) \ ++ iowrite32be((ioread32be(addr) & ~(clear)) | (set), (addr)) ++#define clrsetbits_le32(addr, clear, set) \ ++ iowrite32le((ioread32le(addr) & ~(clear)) | (set), (addr)) ++#define clrsetbits_be16(addr, clear, set) \ ++ iowrite16be((ioread16be(addr) & ~(clear)) | (set), (addr)) ++#define clrsetbits_le16(addr, clear, set) \ ++ iowrite16le((ioread16le(addr) & ~(clear)) | (set), (addr)) ++#define clrsetbits_8(addr, clear, set) \ ++ iowrite8((ioread8(addr) & ~(clear)) | (set), (addr)) ++ + /* + * IO port access primitives + * ------------------------- +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0012-USB-Gadget-fsl-add-a-sanity-check-for-complete-handl.patch b/target/linux/layerscape-64b/patches-4.1/0012-USB-Gadget-fsl-add-a-sanity-check-for-complete-handl.patch new file mode 100644 index 0000000..384b3af --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0012-USB-Gadget-fsl-add-a-sanity-check-for-complete-handl.patch @@ -0,0 +1,36 @@ +From 6ddf7073e8dbae0827b33b863df65b86f9b03ece Mon Sep 17 00:00:00 2001 +From: Rajesh Bhagat +Date: Mon, 25 Jan 2016 16:11:46 +0530 +Subject: [PATCH 012/151] USB : Gadget : fsl: add a sanity check for complete + handler + +complete handler is replaced by usb_gadget_giveback_request by below commit, +which removed the sanity check which was added for fsl specific gadget driver. +usb: gadget: Refactor request completion (304f7e5e1d08fa2f5674c1323bd0ebd806c86b81). + +Above change is causing crash in fsl gadget driver, Hence adding the check back. + +Signed-off-by: Rajesh Bhagat +--- + drivers/usb/gadget/udc/fsl_udc_core.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c +index c60022b..75ddf1a 100644 +--- a/drivers/usb/gadget/udc/fsl_udc_core.c ++++ b/drivers/usb/gadget/udc/fsl_udc_core.c +@@ -198,7 +198,10 @@ __acquires(ep->udc->lock) + + spin_unlock(&ep->udc->lock); + +- usb_gadget_giveback_request(&ep->ep, &req->req); ++ /* this complete() should a func implemented by gadget layer, ++ * eg fsg->bulk_in_complete() */ ++ if (req->req.complete) ++ usb_gadget_giveback_request(&ep->ep, &req->req); + + spin_lock(&ep->udc->lock); + ep->stopped = stopped; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0013-usb-kconfig-remove-dependency-FSL_SOC-for-ehci-fsl-d.patch b/target/linux/layerscape-64b/patches-4.1/0013-usb-kconfig-remove-dependency-FSL_SOC-for-ehci-fsl-d.patch new file mode 100644 index 0000000..f3f18cc --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0013-usb-kconfig-remove-dependency-FSL_SOC-for-ehci-fsl-d.patch @@ -0,0 +1,30 @@ +From 3ad386c4e2386a85052edca9dfd261e122a2b026 Mon Sep 17 00:00:00 2001 +From: Rajesh Bhagat +Date: Thu, 14 Jan 2016 10:58:59 +0530 +Subject: [PATCH 013/151] usb: kconfig: remove dependency FSL_SOC for ehci fsl + driver + +CONFIG_USB_EHCI_FSL is not dependent on FSL_SOC, it can be built on +non-PPC platforms. + +Signed-off-by: Rajesh Bhagat +--- + drivers/usb/host/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +index 688698a..5e0ae5c 100644 +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -145,7 +145,7 @@ config XPS_USB_HCD_XILINX + + config USB_EHCI_FSL + bool "Support for Freescale PPC on-chip EHCI USB controller" +- depends on FSL_SOC ++ depends on USB_EHCI_HCD + select USB_EHCI_ROOT_HUB_TT + select USB_FSL_MPH_DR_OF if OF + ---help--- +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0014-arm-dts-ls1043a-Add-configure-gfladj-property-to-USB.patch b/target/linux/layerscape-64b/patches-4.1/0014-arm-dts-ls1043a-Add-configure-gfladj-property-to-USB.patch new file mode 100644 index 0000000..6960318 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0014-arm-dts-ls1043a-Add-configure-gfladj-property-to-USB.patch @@ -0,0 +1,38 @@ +From 31fa3f01c9b7146c0bc1d810b43045df58f1452d Mon Sep 17 00:00:00 2001 +From: Rajesh Bhagat +Date: Wed, 27 Jan 2016 11:37:25 +0530 +Subject: [PATCH 014/151] arm:dts:ls1043a : Add configure-gfladj property to + USB3 node + +Add "configure-gfladj" boolean property to USB3 node. This property +is used to determine whether frame length adjustent is required +or not + +Signed-off-by: Rajesh Bhagat +--- + arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +index 5654173..5c6fb76 100644 +--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +@@ -733,6 +733,7 @@ + reg = <0x0 0x3000000 0x0 0x10000>; + interrupts = <0 61 0x4>; + dr_mode = "host"; ++ configure-gfladj; + }; + + usb2: usb3 at 3100000 { +@@ -740,6 +741,7 @@ + reg = <0x0 0x3100000 0x0 0x10000>; + interrupts = <0 63 0x4>; + dr_mode = "host"; ++ configure-gfladj; + }; + + sata: sata at 3200000 { +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0015-powerpc-fsl-Move-fsl_guts.h-out-of-arch-powerpc.patch b/target/linux/layerscape-64b/patches-4.1/0015-powerpc-fsl-Move-fsl_guts.h-out-of-arch-powerpc.patch new file mode 100644 index 0000000..abc7d6b --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0015-powerpc-fsl-Move-fsl_guts.h-out-of-arch-powerpc.patch @@ -0,0 +1,637 @@ +From 4fa144cf81d35aa3e213bf6107ecefe042fb8e52 Mon Sep 17 00:00:00 2001 +From: Scott Wood +Date: Fri, 15 Jan 2016 07:34:24 +0000 +Subject: [PATCH 015/151] powerpc/fsl: Move fsl_guts.h out of arch/powerpc + +Freescale's Layerscape ARM chips use the same structure. + +Signed-off-by: Scott Wood +(cherry picked from commit 948486544713492f00ac8a9572909101ea892cb0) +Signed-off-by: Scott Wood +--- + arch/powerpc/include/asm/fsl_guts.h | 192 ----------------------------- + arch/powerpc/platforms/85xx/mpc85xx_mds.c | 2 +- + arch/powerpc/platforms/85xx/mpc85xx_rdb.c | 2 +- + arch/powerpc/platforms/85xx/p1022_ds.c | 2 +- + arch/powerpc/platforms/85xx/p1022_rdk.c | 2 +- + arch/powerpc/platforms/85xx/smp.c | 2 +- + arch/powerpc/platforms/85xx/twr_p102x.c | 2 +- + arch/powerpc/platforms/86xx/mpc8610_hpcd.c | 2 +- + drivers/iommu/fsl_pamu.c | 2 +- + include/linux/fsl/guts.h | 192 +++++++++++++++++++++++++++++ + sound/soc/fsl/mpc8610_hpcd.c | 2 +- + sound/soc/fsl/p1022_ds.c | 2 +- + sound/soc/fsl/p1022_rdk.c | 2 +- + 13 files changed, 203 insertions(+), 203 deletions(-) + delete mode 100644 arch/powerpc/include/asm/fsl_guts.h + create mode 100644 include/linux/fsl/guts.h + +diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h +deleted file mode 100644 +index 43b6bb1..0000000 +--- a/arch/powerpc/include/asm/fsl_guts.h ++++ /dev/null +@@ -1,192 +0,0 @@ +-/** +- * Freecale 85xx and 86xx Global Utilties register set +- * +- * Authors: Jeff Brown +- * Timur Tabi +- * +- * Copyright 2004,2007,2012 Freescale Semiconductor, Inc +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- */ +- +-#ifndef __ASM_POWERPC_FSL_GUTS_H__ +-#define __ASM_POWERPC_FSL_GUTS_H__ +-#ifdef __KERNEL__ +- +-/** +- * Global Utility Registers. +- * +- * Not all registers defined in this structure are available on all chips, so +- * you are expected to know whether a given register actually exists on your +- * chip before you access it. +- * +- * Also, some registers are similar on different chips but have slightly +- * different names. In these cases, one name is chosen to avoid extraneous +- * #ifdefs. +- */ +-struct ccsr_guts { +- __be32 porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */ +- __be32 porbmsr; /* 0x.0004 - POR Boot Mode Status Register */ +- __be32 porimpscr; /* 0x.0008 - POR I/O Impedance Status and Control Register */ +- __be32 pordevsr; /* 0x.000c - POR I/O Device Status Register */ +- __be32 pordbgmsr; /* 0x.0010 - POR Debug Mode Status Register */ +- __be32 pordevsr2; /* 0x.0014 - POR device status register 2 */ +- u8 res018[0x20 - 0x18]; +- __be32 porcir; /* 0x.0020 - POR Configuration Information Register */ +- u8 res024[0x30 - 0x24]; +- __be32 gpiocr; /* 0x.0030 - GPIO Control Register */ +- u8 res034[0x40 - 0x34]; +- __be32 gpoutdr; /* 0x.0040 - General-Purpose Output Data Register */ +- u8 res044[0x50 - 0x44]; +- __be32 gpindr; /* 0x.0050 - General-Purpose Input Data Register */ +- u8 res054[0x60 - 0x54]; +- __be32 pmuxcr; /* 0x.0060 - Alternate Function Signal Multiplex Control */ +- __be32 pmuxcr2; /* 0x.0064 - Alternate function signal multiplex control 2 */ +- __be32 dmuxcr; /* 0x.0068 - DMA Mux Control Register */ +- u8 res06c[0x70 - 0x6c]; +- __be32 devdisr; /* 0x.0070 - Device Disable Control */ +-#define CCSR_GUTS_DEVDISR_TB1 0x00001000 +-#define CCSR_GUTS_DEVDISR_TB0 0x00004000 +- __be32 devdisr2; /* 0x.0074 - Device Disable Control 2 */ +- u8 res078[0x7c - 0x78]; +- __be32 pmjcr; /* 0x.007c - 4 Power Management Jog Control Register */ +- __be32 powmgtcsr; /* 0x.0080 - Power Management Status and Control Register */ +- __be32 pmrccr; /* 0x.0084 - Power Management Reset Counter Configuration Register */ +- __be32 pmpdccr; /* 0x.0088 - Power Management Power Down Counter Configuration Register */ +- __be32 pmcdr; /* 0x.008c - 4Power management clock disable register */ +- __be32 mcpsumr; /* 0x.0090 - Machine Check Summary Register */ +- __be32 rstrscr; /* 0x.0094 - Reset Request Status and Control Register */ +- __be32 ectrstcr; /* 0x.0098 - Exception reset control register */ +- __be32 autorstsr; /* 0x.009c - Automatic reset status register */ +- __be32 pvr; /* 0x.00a0 - Processor Version Register */ +- __be32 svr; /* 0x.00a4 - System Version Register */ +- u8 res0a8[0xb0 - 0xa8]; +- __be32 rstcr; /* 0x.00b0 - Reset Control Register */ +- u8 res0b4[0xc0 - 0xb4]; +- __be32 iovselsr; /* 0x.00c0 - I/O voltage select status register +- Called 'elbcvselcr' on 86xx SOCs */ +- u8 res0c4[0x100 - 0xc4]; +- __be32 rcwsr[16]; /* 0x.0100 - Reset Control Word Status registers +- There are 16 registers */ +- u8 res140[0x224 - 0x140]; +- __be32 iodelay1; /* 0x.0224 - IO delay control register 1 */ +- __be32 iodelay2; /* 0x.0228 - IO delay control register 2 */ +- u8 res22c[0x604 - 0x22c]; +- __be32 pamubypenr; /* 0x.604 - PAMU bypass enable register */ +- u8 res608[0x800 - 0x608]; +- __be32 clkdvdr; /* 0x.0800 - Clock Divide Register */ +- u8 res804[0x900 - 0x804]; +- __be32 ircr; /* 0x.0900 - Infrared Control Register */ +- u8 res904[0x908 - 0x904]; +- __be32 dmacr; /* 0x.0908 - DMA Control Register */ +- u8 res90c[0x914 - 0x90c]; +- __be32 elbccr; /* 0x.0914 - eLBC Control Register */ +- u8 res918[0xb20 - 0x918]; +- __be32 ddr1clkdr; /* 0x.0b20 - DDR1 Clock Disable Register */ +- __be32 ddr2clkdr; /* 0x.0b24 - DDR2 Clock Disable Register */ +- __be32 ddrclkdr; /* 0x.0b28 - DDR Clock Disable Register */ +- u8 resb2c[0xe00 - 0xb2c]; +- __be32 clkocr; /* 0x.0e00 - Clock Out Select Register */ +- u8 rese04[0xe10 - 0xe04]; +- __be32 ddrdllcr; /* 0x.0e10 - DDR DLL Control Register */ +- u8 rese14[0xe20 - 0xe14]; +- __be32 lbcdllcr; /* 0x.0e20 - LBC DLL Control Register */ +- __be32 cpfor; /* 0x.0e24 - L2 charge pump fuse override register */ +- u8 rese28[0xf04 - 0xe28]; +- __be32 srds1cr0; /* 0x.0f04 - SerDes1 Control Register 0 */ +- __be32 srds1cr1; /* 0x.0f08 - SerDes1 Control Register 0 */ +- u8 resf0c[0xf2c - 0xf0c]; +- __be32 itcr; /* 0x.0f2c - Internal transaction control register */ +- u8 resf30[0xf40 - 0xf30]; +- __be32 srds2cr0; /* 0x.0f40 - SerDes2 Control Register 0 */ +- __be32 srds2cr1; /* 0x.0f44 - SerDes2 Control Register 0 */ +-} __attribute__ ((packed)); +- +- +-/* Alternate function signal multiplex control */ +-#define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x)) +- +-#ifdef CONFIG_PPC_86xx +- +-#define CCSR_GUTS_DMACR_DEV_SSI 0 /* DMA controller/channel set to SSI */ +-#define CCSR_GUTS_DMACR_DEV_IR 1 /* DMA controller/channel set to IR */ +- +-/* +- * Set the DMACR register in the GUTS +- * +- * The DMACR register determines the source of initiated transfers for each +- * channel on each DMA controller. Rather than have a bunch of repetitive +- * macros for the bit patterns, we just have a function that calculates +- * them. +- * +- * guts: Pointer to GUTS structure +- * co: The DMA controller (0 or 1) +- * ch: The channel on the DMA controller (0, 1, 2, or 3) +- * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx) +- */ +-static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts, +- unsigned int co, unsigned int ch, unsigned int device) +-{ +- unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch)); +- +- clrsetbits_be32(&guts->dmacr, 3 << shift, device << shift); +-} +- +-#define CCSR_GUTS_PMUXCR_LDPSEL 0x00010000 +-#define CCSR_GUTS_PMUXCR_SSI1_MASK 0x0000C000 /* Bitmask for SSI1 */ +-#define CCSR_GUTS_PMUXCR_SSI1_LA 0x00000000 /* Latched address */ +-#define CCSR_GUTS_PMUXCR_SSI1_HI 0x00004000 /* High impedance */ +-#define CCSR_GUTS_PMUXCR_SSI1_SSI 0x00008000 /* Used for SSI1 */ +-#define CCSR_GUTS_PMUXCR_SSI2_MASK 0x00003000 /* Bitmask for SSI2 */ +-#define CCSR_GUTS_PMUXCR_SSI2_LA 0x00000000 /* Latched address */ +-#define CCSR_GUTS_PMUXCR_SSI2_HI 0x00001000 /* High impedance */ +-#define CCSR_GUTS_PMUXCR_SSI2_SSI 0x00002000 /* Used for SSI2 */ +-#define CCSR_GUTS_PMUXCR_LA_22_25_LA 0x00000000 /* Latched Address */ +-#define CCSR_GUTS_PMUXCR_LA_22_25_HI 0x00000400 /* High impedance */ +-#define CCSR_GUTS_PMUXCR_DBGDRV 0x00000200 /* Signals not driven */ +-#define CCSR_GUTS_PMUXCR_DMA2_0 0x00000008 +-#define CCSR_GUTS_PMUXCR_DMA2_3 0x00000004 +-#define CCSR_GUTS_PMUXCR_DMA1_0 0x00000002 +-#define CCSR_GUTS_PMUXCR_DMA1_3 0x00000001 +- +-/* +- * Set the DMA external control bits in the GUTS +- * +- * The DMA external control bits in the PMUXCR are only meaningful for +- * channels 0 and 3. Any other channels are ignored. +- * +- * guts: Pointer to GUTS structure +- * co: The DMA controller (0 or 1) +- * ch: The channel on the DMA controller (0, 1, 2, or 3) +- * value: the new value for the bit (0 or 1) +- */ +-static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts, +- unsigned int co, unsigned int ch, unsigned int value) +-{ +- if ((ch == 0) || (ch == 3)) { +- unsigned int shift = 2 * (co + 1) - (ch & 1) - 1; +- +- clrsetbits_be32(&guts->pmuxcr, 1 << shift, value << shift); +- } +-} +- +-#define CCSR_GUTS_CLKDVDR_PXCKEN 0x80000000 +-#define CCSR_GUTS_CLKDVDR_SSICKEN 0x20000000 +-#define CCSR_GUTS_CLKDVDR_PXCKINV 0x10000000 +-#define CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT 25 +-#define CCSR_GUTS_CLKDVDR_PXCKDLY_MASK 0x06000000 +-#define CCSR_GUTS_CLKDVDR_PXCKDLY(x) \ +- (((x) & 3) << CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT) +-#define CCSR_GUTS_CLKDVDR_PXCLK_SHIFT 16 +-#define CCSR_GUTS_CLKDVDR_PXCLK_MASK 0x001F0000 +-#define CCSR_GUTS_CLKDVDR_PXCLK(x) (((x) & 31) << CCSR_GUTS_CLKDVDR_PXCLK_SHIFT) +-#define CCSR_GUTS_CLKDVDR_SSICLK_MASK 0x000000FF +-#define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK) +- +-#endif +- +-#endif +-#endif +diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c +index a392e94..f0be439 100644 +--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c ++++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -51,7 +52,6 @@ + #include + #include + #include +-#include + #include "smp.h" + + #include "mpc85xx.h" +diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c +index e358bed..50dcc00 100644 +--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c ++++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -27,7 +28,6 @@ + #include + #include + #include +-#include + + #include + #include +diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c +index 6ac986d..371df82 100644 +--- a/arch/powerpc/platforms/85xx/p1022_ds.c ++++ b/arch/powerpc/platforms/85xx/p1022_ds.c +@@ -16,6 +16,7 @@ + * kind, whether express or implied. + */ + ++#include + #include + #include + #include +@@ -25,7 +26,6 @@ + #include + #include + #include +-#include + #include + #include "smp.h" + +diff --git a/arch/powerpc/platforms/85xx/p1022_rdk.c b/arch/powerpc/platforms/85xx/p1022_rdk.c +index 680232d..5087bec 100644 +--- a/arch/powerpc/platforms/85xx/p1022_rdk.c ++++ b/arch/powerpc/platforms/85xx/p1022_rdk.c +@@ -12,6 +12,7 @@ + * kind, whether express or implied. + */ + ++#include + #include + #include + #include +@@ -21,7 +22,6 @@ + #include + #include + #include +-#include + #include "smp.h" + + #include "mpc85xx.h" +diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c +index 8631ac5..c88981f 100644 +--- a/arch/powerpc/platforms/85xx/smp.c ++++ b/arch/powerpc/platforms/85xx/smp.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -26,7 +27,6 @@ + #include + #include + #include +-#include + #include + #include + +diff --git a/arch/powerpc/platforms/85xx/twr_p102x.c b/arch/powerpc/platforms/85xx/twr_p102x.c +index 1eadb6d..2799120 100644 +--- a/arch/powerpc/platforms/85xx/twr_p102x.c ++++ b/arch/powerpc/platforms/85xx/twr_p102x.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -23,7 +24,6 @@ + #include + #include + #include +-#include + + #include + #include +diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c +index 55413a5..437a9c3 100644 +--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c ++++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -38,7 +39,6 @@ + #include + #include + #include +-#include + + #include "mpc86xx.h" + +diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c +index 2570f2a..a34355f 100644 +--- a/drivers/iommu/fsl_pamu.c ++++ b/drivers/iommu/fsl_pamu.c +@@ -20,11 +20,11 @@ + + #include "fsl_pamu.h" + ++#include + #include + #include + + #include +-#include + + /* define indexes for each operation mapping scenario */ + #define OMI_QMAN 0x00 +diff --git a/include/linux/fsl/guts.h b/include/linux/fsl/guts.h +new file mode 100644 +index 0000000..84d971f +--- /dev/null ++++ b/include/linux/fsl/guts.h +@@ -0,0 +1,192 @@ ++/** ++ * Freecale 85xx and 86xx Global Utilties register set ++ * ++ * Authors: Jeff Brown ++ * Timur Tabi ++ * ++ * Copyright 2004,2007,2012 Freescale Semiconductor, Inc ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++ ++#ifndef __FSL_GUTS_H__ ++#define __FSL_GUTS_H__ ++ ++#include ++ ++/** ++ * Global Utility Registers. ++ * ++ * Not all registers defined in this structure are available on all chips, so ++ * you are expected to know whether a given register actually exists on your ++ * chip before you access it. ++ * ++ * Also, some registers are similar on different chips but have slightly ++ * different names. In these cases, one name is chosen to avoid extraneous ++ * #ifdefs. ++ */ ++struct ccsr_guts { ++ __be32 porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */ ++ __be32 porbmsr; /* 0x.0004 - POR Boot Mode Status Register */ ++ __be32 porimpscr; /* 0x.0008 - POR I/O Impedance Status and Control Register */ ++ __be32 pordevsr; /* 0x.000c - POR I/O Device Status Register */ ++ __be32 pordbgmsr; /* 0x.0010 - POR Debug Mode Status Register */ ++ __be32 pordevsr2; /* 0x.0014 - POR device status register 2 */ ++ u8 res018[0x20 - 0x18]; ++ __be32 porcir; /* 0x.0020 - POR Configuration Information Register */ ++ u8 res024[0x30 - 0x24]; ++ __be32 gpiocr; /* 0x.0030 - GPIO Control Register */ ++ u8 res034[0x40 - 0x34]; ++ __be32 gpoutdr; /* 0x.0040 - General-Purpose Output Data Register */ ++ u8 res044[0x50 - 0x44]; ++ __be32 gpindr; /* 0x.0050 - General-Purpose Input Data Register */ ++ u8 res054[0x60 - 0x54]; ++ __be32 pmuxcr; /* 0x.0060 - Alternate Function Signal Multiplex Control */ ++ __be32 pmuxcr2; /* 0x.0064 - Alternate function signal multiplex control 2 */ ++ __be32 dmuxcr; /* 0x.0068 - DMA Mux Control Register */ ++ u8 res06c[0x70 - 0x6c]; ++ __be32 devdisr; /* 0x.0070 - Device Disable Control */ ++#define CCSR_GUTS_DEVDISR_TB1 0x00001000 ++#define CCSR_GUTS_DEVDISR_TB0 0x00004000 ++ __be32 devdisr2; /* 0x.0074 - Device Disable Control 2 */ ++ u8 res078[0x7c - 0x78]; ++ __be32 pmjcr; /* 0x.007c - 4 Power Management Jog Control Register */ ++ __be32 powmgtcsr; /* 0x.0080 - Power Management Status and Control Register */ ++ __be32 pmrccr; /* 0x.0084 - Power Management Reset Counter Configuration Register */ ++ __be32 pmpdccr; /* 0x.0088 - Power Management Power Down Counter Configuration Register */ ++ __be32 pmcdr; /* 0x.008c - 4Power management clock disable register */ ++ __be32 mcpsumr; /* 0x.0090 - Machine Check Summary Register */ ++ __be32 rstrscr; /* 0x.0094 - Reset Request Status and Control Register */ ++ __be32 ectrstcr; /* 0x.0098 - Exception reset control register */ ++ __be32 autorstsr; /* 0x.009c - Automatic reset status register */ ++ __be32 pvr; /* 0x.00a0 - Processor Version Register */ ++ __be32 svr; /* 0x.00a4 - System Version Register */ ++ u8 res0a8[0xb0 - 0xa8]; ++ __be32 rstcr; /* 0x.00b0 - Reset Control Register */ ++ u8 res0b4[0xc0 - 0xb4]; ++ __be32 iovselsr; /* 0x.00c0 - I/O voltage select status register ++ Called 'elbcvselcr' on 86xx SOCs */ ++ u8 res0c4[0x100 - 0xc4]; ++ __be32 rcwsr[16]; /* 0x.0100 - Reset Control Word Status registers ++ There are 16 registers */ ++ u8 res140[0x224 - 0x140]; ++ __be32 iodelay1; /* 0x.0224 - IO delay control register 1 */ ++ __be32 iodelay2; /* 0x.0228 - IO delay control register 2 */ ++ u8 res22c[0x604 - 0x22c]; ++ __be32 pamubypenr; /* 0x.604 - PAMU bypass enable register */ ++ u8 res608[0x800 - 0x608]; ++ __be32 clkdvdr; /* 0x.0800 - Clock Divide Register */ ++ u8 res804[0x900 - 0x804]; ++ __be32 ircr; /* 0x.0900 - Infrared Control Register */ ++ u8 res904[0x908 - 0x904]; ++ __be32 dmacr; /* 0x.0908 - DMA Control Register */ ++ u8 res90c[0x914 - 0x90c]; ++ __be32 elbccr; /* 0x.0914 - eLBC Control Register */ ++ u8 res918[0xb20 - 0x918]; ++ __be32 ddr1clkdr; /* 0x.0b20 - DDR1 Clock Disable Register */ ++ __be32 ddr2clkdr; /* 0x.0b24 - DDR2 Clock Disable Register */ ++ __be32 ddrclkdr; /* 0x.0b28 - DDR Clock Disable Register */ ++ u8 resb2c[0xe00 - 0xb2c]; ++ __be32 clkocr; /* 0x.0e00 - Clock Out Select Register */ ++ u8 rese04[0xe10 - 0xe04]; ++ __be32 ddrdllcr; /* 0x.0e10 - DDR DLL Control Register */ ++ u8 rese14[0xe20 - 0xe14]; ++ __be32 lbcdllcr; /* 0x.0e20 - LBC DLL Control Register */ ++ __be32 cpfor; /* 0x.0e24 - L2 charge pump fuse override register */ ++ u8 rese28[0xf04 - 0xe28]; ++ __be32 srds1cr0; /* 0x.0f04 - SerDes1 Control Register 0 */ ++ __be32 srds1cr1; /* 0x.0f08 - SerDes1 Control Register 0 */ ++ u8 resf0c[0xf2c - 0xf0c]; ++ __be32 itcr; /* 0x.0f2c - Internal transaction control register */ ++ u8 resf30[0xf40 - 0xf30]; ++ __be32 srds2cr0; /* 0x.0f40 - SerDes2 Control Register 0 */ ++ __be32 srds2cr1; /* 0x.0f44 - SerDes2 Control Register 0 */ ++} __attribute__ ((packed)); ++ ++ ++/* Alternate function signal multiplex control */ ++#define MPC85xx_PMUXCR_QE(x) (0x8000 >> (x)) ++ ++#ifdef CONFIG_PPC_86xx ++ ++#define CCSR_GUTS_DMACR_DEV_SSI 0 /* DMA controller/channel set to SSI */ ++#define CCSR_GUTS_DMACR_DEV_IR 1 /* DMA controller/channel set to IR */ ++ ++/* ++ * Set the DMACR register in the GUTS ++ * ++ * The DMACR register determines the source of initiated transfers for each ++ * channel on each DMA controller. Rather than have a bunch of repetitive ++ * macros for the bit patterns, we just have a function that calculates ++ * them. ++ * ++ * guts: Pointer to GUTS structure ++ * co: The DMA controller (0 or 1) ++ * ch: The channel on the DMA controller (0, 1, 2, or 3) ++ * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx) ++ */ ++static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts, ++ unsigned int co, unsigned int ch, unsigned int device) ++{ ++ unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch)); ++ ++ clrsetbits_be32(&guts->dmacr, 3 << shift, device << shift); ++} ++ ++#define CCSR_GUTS_PMUXCR_LDPSEL 0x00010000 ++#define CCSR_GUTS_PMUXCR_SSI1_MASK 0x0000C000 /* Bitmask for SSI1 */ ++#define CCSR_GUTS_PMUXCR_SSI1_LA 0x00000000 /* Latched address */ ++#define CCSR_GUTS_PMUXCR_SSI1_HI 0x00004000 /* High impedance */ ++#define CCSR_GUTS_PMUXCR_SSI1_SSI 0x00008000 /* Used for SSI1 */ ++#define CCSR_GUTS_PMUXCR_SSI2_MASK 0x00003000 /* Bitmask for SSI2 */ ++#define CCSR_GUTS_PMUXCR_SSI2_LA 0x00000000 /* Latched address */ ++#define CCSR_GUTS_PMUXCR_SSI2_HI 0x00001000 /* High impedance */ ++#define CCSR_GUTS_PMUXCR_SSI2_SSI 0x00002000 /* Used for SSI2 */ ++#define CCSR_GUTS_PMUXCR_LA_22_25_LA 0x00000000 /* Latched Address */ ++#define CCSR_GUTS_PMUXCR_LA_22_25_HI 0x00000400 /* High impedance */ ++#define CCSR_GUTS_PMUXCR_DBGDRV 0x00000200 /* Signals not driven */ ++#define CCSR_GUTS_PMUXCR_DMA2_0 0x00000008 ++#define CCSR_GUTS_PMUXCR_DMA2_3 0x00000004 ++#define CCSR_GUTS_PMUXCR_DMA1_0 0x00000002 ++#define CCSR_GUTS_PMUXCR_DMA1_3 0x00000001 ++ ++/* ++ * Set the DMA external control bits in the GUTS ++ * ++ * The DMA external control bits in the PMUXCR are only meaningful for ++ * channels 0 and 3. Any other channels are ignored. ++ * ++ * guts: Pointer to GUTS structure ++ * co: The DMA controller (0 or 1) ++ * ch: The channel on the DMA controller (0, 1, 2, or 3) ++ * value: the new value for the bit (0 or 1) ++ */ ++static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts, ++ unsigned int co, unsigned int ch, unsigned int value) ++{ ++ if ((ch == 0) || (ch == 3)) { ++ unsigned int shift = 2 * (co + 1) - (ch & 1) - 1; ++ ++ clrsetbits_be32(&guts->pmuxcr, 1 << shift, value << shift); ++ } ++} ++ ++#define CCSR_GUTS_CLKDVDR_PXCKEN 0x80000000 ++#define CCSR_GUTS_CLKDVDR_SSICKEN 0x20000000 ++#define CCSR_GUTS_CLKDVDR_PXCKINV 0x10000000 ++#define CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT 25 ++#define CCSR_GUTS_CLKDVDR_PXCKDLY_MASK 0x06000000 ++#define CCSR_GUTS_CLKDVDR_PXCKDLY(x) \ ++ (((x) & 3) << CCSR_GUTS_CLKDVDR_PXCKDLY_SHIFT) ++#define CCSR_GUTS_CLKDVDR_PXCLK_SHIFT 16 ++#define CCSR_GUTS_CLKDVDR_PXCLK_MASK 0x001F0000 ++#define CCSR_GUTS_CLKDVDR_PXCLK(x) (((x) & 31) << CCSR_GUTS_CLKDVDR_PXCLK_SHIFT) ++#define CCSR_GUTS_CLKDVDR_SSICLK_MASK 0x000000FF ++#define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK) ++ ++#endif ++ ++#endif +diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c +index 9621b91..6f236f1 100644 +--- a/sound/soc/fsl/mpc8610_hpcd.c ++++ b/sound/soc/fsl/mpc8610_hpcd.c +@@ -12,11 +12,11 @@ + + #include + #include ++#include + #include + #include + #include + #include +-#include + + #include "fsl_dma.h" + #include "fsl_ssi.h" +diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c +index 71c1a7d..747aab0 100644 +--- a/sound/soc/fsl/p1022_ds.c ++++ b/sound/soc/fsl/p1022_ds.c +@@ -11,12 +11,12 @@ + */ + + #include ++#include + #include + #include + #include + #include + #include +-#include + + #include "fsl_dma.h" + #include "fsl_ssi.h" +diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c +index ee29048..1dd49e5 100644 +--- a/sound/soc/fsl/p1022_rdk.c ++++ b/sound/soc/fsl/p1022_rdk.c +@@ -18,12 +18,12 @@ + */ + + #include ++#include + #include + #include + #include + #include + #include +-#include + + #include "fsl_dma.h" + #include "fsl_ssi.h" +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0016-driver-memory-Removal-of-deprecated-NO_IRQ.patch b/target/linux/layerscape-64b/patches-4.1/0016-driver-memory-Removal-of-deprecated-NO_IRQ.patch new file mode 100644 index 0000000..1dcb99d --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0016-driver-memory-Removal-of-deprecated-NO_IRQ.patch @@ -0,0 +1,29 @@ +From af33865c6ca19eb849e7d00c9c58037aed9d8c5d Mon Sep 17 00:00:00 2001 +From: Raghav Dogra +Date: Wed, 16 Dec 2015 16:11:31 +0530 +Subject: [PATCH 016/151] driver/memory: Removal of deprecated NO_IRQ + +Replacing the NO_IRQ macro with 0. If there is no interrupt, +returned value will be 0 regardless of what NO_IRQ is defined. + +Signed-off-by: Raghav Dogra +--- + drivers/memory/fsl_ifc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c +index 410c397..5f6d42d 100644 +--- a/drivers/memory/fsl_ifc.c ++++ b/drivers/memory/fsl_ifc.c +@@ -242,7 +242,7 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) + + /* get the Controller level irq */ + fsl_ifc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0); +- if (fsl_ifc_ctrl_dev->irq == NO_IRQ) { ++ if (fsl_ifc_ctrl_dev->irq == 0) { + dev_err(&dev->dev, "failed to get irq resource " + "for IFC\n"); + ret = -ENODEV; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0017-net-fsl-remove-dependency-FSL_SOC-for-Gianfar.patch b/target/linux/layerscape-64b/patches-4.1/0017-net-fsl-remove-dependency-FSL_SOC-for-Gianfar.patch new file mode 100644 index 0000000..7b8a1b0 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0017-net-fsl-remove-dependency-FSL_SOC-for-Gianfar.patch @@ -0,0 +1,36 @@ +From d08a08ee248e0f59ca61e38e537991baf1f2abe1 Mon Sep 17 00:00:00 2001 +From: Alison Wang +Date: Thu, 25 Jun 2015 11:34:38 +0800 +Subject: [PATCH 017/151] net/fsl: remove dependency FSL_SOC for Gianfar + +CONFIG_GIANFAR is not depended on FSL_SOC, it +can be built on non-PPC platforms. + +Signed-off-by: Alison Wang +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/freescale/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig +index 25e3425..e383dba 100644 +--- a/drivers/net/ethernet/freescale/Kconfig ++++ b/drivers/net/ethernet/freescale/Kconfig +@@ -85,12 +85,12 @@ config UGETH_TX_ON_DEMAND + + config GIANFAR + tristate "Gianfar Ethernet" +- depends on FSL_SOC + select FSL_PQ_MDIO + select PHYLIB + select CRC32 + ---help--- + This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx, +- and MPC86xx family of chips, and the FEC on the 8540. ++ and MPC86xx family of chips, the eTSEC on LS1021A and the FEC ++ on the 8540. + + endif # NET_VENDOR_FREESCALE +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0018-temp-QE-headers-are-needed-by-FMD.patch b/target/linux/layerscape-64b/patches-4.1/0018-temp-QE-headers-are-needed-by-FMD.patch new file mode 100644 index 0000000..98adc07 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0018-temp-QE-headers-are-needed-by-FMD.patch @@ -0,0 +1,1326 @@ +From b6c8e00238ca26861c85e2aeab1d8ecbd7b6ea43 Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Tue, 5 Jan 2016 15:41:28 +0200 +Subject: [PATCH 018/151] temp: QE headers are needed by FMD + +Signed-off-by: Madalin Bucur +--- + include/linux/fsl/immap_qe.h | 488 ++++++++++++++++++++++++++ + include/linux/fsl/qe.h | 810 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 1298 insertions(+) + create mode 100644 include/linux/fsl/immap_qe.h + create mode 100644 include/linux/fsl/qe.h + +diff --git a/include/linux/fsl/immap_qe.h b/include/linux/fsl/immap_qe.h +new file mode 100644 +index 0000000..bd1ebd4 +--- /dev/null ++++ b/include/linux/fsl/immap_qe.h +@@ -0,0 +1,488 @@ ++/* ++ * QUICC Engine (QE) Internal Memory Map. ++ * The Internal Memory Map for devices with QE on them. This ++ * is the superset of all QE devices (8360, etc.). ++ * Copyright (C) 2006. Freescale Semiconductor, Inc. All rights reserved. ++ * ++ * Authors: ++ * Shlomi Gridish ++ * Li Yang ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++#ifndef _ASM_POWERPC_IMMAP_QE_H ++#define _ASM_POWERPC_IMMAP_QE_H ++#ifdef __KERNEL__ ++ ++#include ++#include ++ ++#define QE_IMMAP_SIZE (1024 * 1024) /* 1MB from 1MB+IMMR */ ++ ++/* QE I-RAM */ ++struct qe_iram { ++ __be32 iadd; /* I-RAM Address Register */ ++ __be32 idata; /* I-RAM Data Register */ ++ u8 res0[0x04]; ++ __be32 iready; /* I-RAM Ready Register */ ++ u8 res1[0x70]; ++} __packed; ++ ++/* QE Interrupt Controller */ ++struct qe_ic_regs { ++ __be32 qicr; ++ __be32 qivec; ++ __be32 qripnr; ++ __be32 qipnr; ++ __be32 qipxcc; ++ __be32 qipycc; ++ __be32 qipwcc; ++ __be32 qipzcc; ++ __be32 qimr; ++ __be32 qrimr; ++ __be32 qicnr; ++ u8 res0[0x4]; ++ __be32 qiprta; ++ __be32 qiprtb; ++ u8 res1[0x4]; ++ __be32 qricr; ++ u8 res2[0x20]; ++ __be32 qhivec; ++ u8 res3[0x1C]; ++} __packed; ++ ++/* Communications Processor */ ++struct cp_qe { ++ __be32 cecr; /* QE command register */ ++ __be32 ceccr; /* QE controller configuration register */ ++ __be32 cecdr; /* QE command data register */ ++ u8 res0[0xA]; ++ __be16 ceter; /* QE timer event register */ ++ u8 res1[0x2]; ++ __be16 cetmr; /* QE timers mask register */ ++ __be32 cetscr; /* QE time-stamp timer control register */ ++ __be32 cetsr1; /* QE time-stamp register 1 */ ++ __be32 cetsr2; /* QE time-stamp register 2 */ ++ u8 res2[0x8]; ++ __be32 cevter; /* QE virtual tasks event register */ ++ __be32 cevtmr; /* QE virtual tasks mask register */ ++ __be16 cercr; /* QE RAM control register */ ++ u8 res3[0x2]; ++ u8 res4[0x24]; ++ __be16 ceexe1; /* QE external request 1 event register */ ++ u8 res5[0x2]; ++ __be16 ceexm1; /* QE external request 1 mask register */ ++ u8 res6[0x2]; ++ __be16 ceexe2; /* QE external request 2 event register */ ++ u8 res7[0x2]; ++ __be16 ceexm2; /* QE external request 2 mask register */ ++ u8 res8[0x2]; ++ __be16 ceexe3; /* QE external request 3 event register */ ++ u8 res9[0x2]; ++ __be16 ceexm3; /* QE external request 3 mask register */ ++ u8 res10[0x2]; ++ __be16 ceexe4; /* QE external request 4 event register */ ++ u8 res11[0x2]; ++ __be16 ceexm4; /* QE external request 4 mask register */ ++ u8 res12[0x3A]; ++ __be32 ceurnr; /* QE microcode revision number register */ ++ u8 res13[0x244]; ++} __packed; ++ ++/* QE Multiplexer */ ++struct qe_mux { ++ __be32 cmxgcr; /* CMX general clock route register */ ++ __be32 cmxsi1cr_l; /* CMX SI1 clock route low register */ ++ __be32 cmxsi1cr_h; /* CMX SI1 clock route high register */ ++ __be32 cmxsi1syr; /* CMX SI1 SYNC route register */ ++ __be32 cmxucr[4]; /* CMX UCCx clock route registers */ ++ __be32 cmxupcr; /* CMX UPC clock route register */ ++ u8 res0[0x1C]; ++} __packed; ++ ++/* QE Timers */ ++struct qe_timers { ++ u8 gtcfr1; /* Timer 1 and Timer 2 global config register*/ ++ u8 res0[0x3]; ++ u8 gtcfr2; /* Timer 3 and timer 4 global config register*/ ++ u8 res1[0xB]; ++ __be16 gtmdr1; /* Timer 1 mode register */ ++ __be16 gtmdr2; /* Timer 2 mode register */ ++ __be16 gtrfr1; /* Timer 1 reference register */ ++ __be16 gtrfr2; /* Timer 2 reference register */ ++ __be16 gtcpr1; /* Timer 1 capture register */ ++ __be16 gtcpr2; /* Timer 2 capture register */ ++ __be16 gtcnr1; /* Timer 1 counter */ ++ __be16 gtcnr2; /* Timer 2 counter */ ++ __be16 gtmdr3; /* Timer 3 mode register */ ++ __be16 gtmdr4; /* Timer 4 mode register */ ++ __be16 gtrfr3; /* Timer 3 reference register */ ++ __be16 gtrfr4; /* Timer 4 reference register */ ++ __be16 gtcpr3; /* Timer 3 capture register */ ++ __be16 gtcpr4; /* Timer 4 capture register */ ++ __be16 gtcnr3; /* Timer 3 counter */ ++ __be16 gtcnr4; /* Timer 4 counter */ ++ __be16 gtevr1; /* Timer 1 event register */ ++ __be16 gtevr2; /* Timer 2 event register */ ++ __be16 gtevr3; /* Timer 3 event register */ ++ __be16 gtevr4; /* Timer 4 event register */ ++ __be16 gtps; /* Timer 1 prescale register */ ++ u8 res2[0x46]; ++} __packed; ++ ++/* BRG */ ++struct qe_brg { ++ __be32 brgc[16]; /* BRG configuration registers */ ++ u8 res0[0x40]; ++} __packed; ++ ++/* SPI */ ++struct spi { ++ u8 res0[0x20]; ++ __be32 spmode; /* SPI mode register */ ++ u8 res1[0x2]; ++ u8 spie; /* SPI event register */ ++ u8 res2[0x1]; ++ u8 res3[0x2]; ++ u8 spim; /* SPI mask register */ ++ u8 res4[0x1]; ++ u8 res5[0x1]; ++ u8 spcom; /* SPI command register */ ++ u8 res6[0x2]; ++ __be32 spitd; /* SPI transmit data register (cpu mode) */ ++ __be32 spird; /* SPI receive data register (cpu mode) */ ++ u8 res7[0x8]; ++} __packed; ++ ++/* SI */ ++struct si1 { ++ __be16 sixmr1[4]; /* SI1 TDMx (x = A B C D) mode register */ ++ u8 siglmr1_h; /* SI1 global mode register high */ ++ u8 res0[0x1]; ++ u8 sicmdr1_h; /* SI1 command register high */ ++ u8 res2[0x1]; ++ u8 sistr1_h; /* SI1 status register high */ ++ u8 res3[0x1]; ++ __be16 sirsr1_h; /* SI1 RAM shadow address register high */ ++ u8 sitarc1; /* SI1 RAM counter Tx TDMA */ ++ u8 sitbrc1; /* SI1 RAM counter Tx TDMB */ ++ u8 sitcrc1; /* SI1 RAM counter Tx TDMC */ ++ u8 sitdrc1; /* SI1 RAM counter Tx TDMD */ ++ u8 sirarc1; /* SI1 RAM counter Rx TDMA */ ++ u8 sirbrc1; /* SI1 RAM counter Rx TDMB */ ++ u8 sircrc1; /* SI1 RAM counter Rx TDMC */ ++ u8 sirdrc1; /* SI1 RAM counter Rx TDMD */ ++ u8 res4[0x8]; ++ __be16 siemr1; /* SI1 TDME mode register 16 bits */ ++ __be16 sifmr1; /* SI1 TDMF mode register 16 bits */ ++ __be16 sigmr1; /* SI1 TDMG mode register 16 bits */ ++ __be16 sihmr1; /* SI1 TDMH mode register 16 bits */ ++ u8 siglmg1_l; /* SI1 global mode register low 8 bits */ ++ u8 res5[0x1]; ++ u8 sicmdr1_l; /* SI1 command register low 8 bits */ ++ u8 res6[0x1]; ++ u8 sistr1_l; /* SI1 status register low 8 bits */ ++ u8 res7[0x1]; ++ __be16 sirsr1_l; /* SI1 RAM shadow address register low 16 bits*/ ++ u8 siterc1; /* SI1 RAM counter Tx TDME 8 bits */ ++ u8 sitfrc1; /* SI1 RAM counter Tx TDMF 8 bits */ ++ u8 sitgrc1; /* SI1 RAM counter Tx TDMG 8 bits */ ++ u8 sithrc1; /* SI1 RAM counter Tx TDMH 8 bits */ ++ u8 sirerc1; /* SI1 RAM counter Rx TDME 8 bits */ ++ u8 sirfrc1; /* SI1 RAM counter Rx TDMF 8 bits */ ++ u8 sirgrc1; /* SI1 RAM counter Rx TDMG 8 bits */ ++ u8 sirhrc1; /* SI1 RAM counter Rx TDMH 8 bits */ ++ u8 res8[0x8]; ++ __be32 siml1; /* SI1 multiframe limit register */ ++ u8 siedm1; /* SI1 extended diagnostic mode register */ ++ u8 res9[0xBB]; ++} __packed; ++ ++/* SI Routing Tables */ ++struct sir { ++ u8 tx[0x400]; ++ u8 rx[0x400]; ++ u8 res0[0x800]; ++} __packed; ++ ++/* USB Controller */ ++struct qe_usb_ctlr { ++ u8 usb_usmod; ++ u8 usb_usadr; ++ u8 usb_uscom; ++ u8 res1[1]; ++ __be16 usb_usep[4]; ++ u8 res2[4]; ++ __be16 usb_usber; ++ u8 res3[2]; ++ __be16 usb_usbmr; ++ u8 res4[1]; ++ u8 usb_usbs; ++ __be16 usb_ussft; ++ u8 res5[2]; ++ __be16 usb_usfrn; ++ u8 res6[0x22]; ++} __packed; ++ ++/* MCC */ ++struct qe_mcc { ++ __be32 mcce; /* MCC event register */ ++ __be32 mccm; /* MCC mask register */ ++ __be32 mccf; /* MCC configuration register */ ++ __be32 merl; /* MCC emergency request level register */ ++ u8 res0[0xF0]; ++} __packed; ++ ++/* QE UCC Slow */ ++struct ucc_slow { ++ __be32 gumr_l; /* UCCx general mode register (low) */ ++ __be32 gumr_h; /* UCCx general mode register (high) */ ++ __be16 upsmr; /* UCCx protocol-specific mode register */ ++ u8 res0[0x2]; ++ __be16 utodr; /* UCCx transmit on demand register */ ++ __be16 udsr; /* UCCx data synchronization register */ ++ __be16 ucce; /* UCCx event register */ ++ u8 res1[0x2]; ++ __be16 uccm; /* UCCx mask register */ ++ u8 res2[0x1]; ++ u8 uccs; /* UCCx status register */ ++ u8 res3[0x24]; ++ __be16 utpt; ++ u8 res4[0x52]; ++ u8 guemr; /* UCC general extended mode register */ ++} __packed; ++ ++/* QE UCC Fast */ ++struct ucc_fast { ++ __be32 gumr; /* UCCx general mode register */ ++ __be32 upsmr; /* UCCx protocol-specific mode register */ ++ __be16 utodr; /* UCCx transmit on demand register */ ++ u8 res0[0x2]; ++ __be16 udsr; /* UCCx data synchronization register */ ++ u8 res1[0x2]; ++ __be32 ucce; /* UCCx event register */ ++ __be32 uccm; /* UCCx mask register */ ++ u8 uccs; /* UCCx status register */ ++ u8 res2[0x7]; ++ __be32 urfb; /* UCC receive FIFO base */ ++ __be16 urfs; /* UCC receive FIFO size */ ++ u8 res3[0x2]; ++ __be16 urfet; /* UCC receive FIFO emergency threshold */ ++ __be16 urfset; /* UCC receive FIFO special emergency ++ threshold */ ++ __be32 utfb; /* UCC transmit FIFO base */ ++ __be16 utfs; /* UCC transmit FIFO size */ ++ u8 res4[0x2]; ++ __be16 utfet; /* UCC transmit FIFO emergency threshold */ ++ u8 res5[0x2]; ++ __be16 utftt; /* UCC transmit FIFO transmit threshold */ ++ u8 res6[0x2]; ++ __be16 utpt; /* UCC transmit polling timer */ ++ u8 res7[0x2]; ++ __be32 urtry; /* UCC retry counter register */ ++ u8 res8[0x4C]; ++ u8 guemr; /* UCC general extended mode register */ ++} __packed; ++ ++struct ucc { ++ union { ++ struct ucc_slow slow; ++ struct ucc_fast fast; ++ u8 res[0x200]; /* UCC blocks are 512 bytes each */ ++ }; ++} __packed; ++ ++/* MultiPHY UTOPIA POS Controllers (UPC) */ ++struct upc { ++ __be32 upgcr; /* UTOPIA/POS general configuration register */ ++ __be32 uplpa; /* UTOPIA/POS last PHY address */ ++ __be32 uphec; /* ATM HEC register */ ++ __be32 upuc; /* UTOPIA/POS UCC configuration */ ++ __be32 updc1; /* UTOPIA/POS device 1 configuration */ ++ __be32 updc2; /* UTOPIA/POS device 2 configuration */ ++ __be32 updc3; /* UTOPIA/POS device 3 configuration */ ++ __be32 updc4; /* UTOPIA/POS device 4 configuration */ ++ __be32 upstpa; /* UTOPIA/POS STPA threshold */ ++ u8 res0[0xC]; ++ __be32 updrs1_h; /* UTOPIA/POS device 1 rate select */ ++ __be32 updrs1_l; /* UTOPIA/POS device 1 rate select */ ++ __be32 updrs2_h; /* UTOPIA/POS device 2 rate select */ ++ __be32 updrs2_l; /* UTOPIA/POS device 2 rate select */ ++ __be32 updrs3_h; /* UTOPIA/POS device 3 rate select */ ++ __be32 updrs3_l; /* UTOPIA/POS device 3 rate select */ ++ __be32 updrs4_h; /* UTOPIA/POS device 4 rate select */ ++ __be32 updrs4_l; /* UTOPIA/POS device 4 rate select */ ++ __be32 updrp1; /* UTOPIA/POS device 1 receive priority low */ ++ __be32 updrp2; /* UTOPIA/POS device 2 receive priority low */ ++ __be32 updrp3; /* UTOPIA/POS device 3 receive priority low */ ++ __be32 updrp4; /* UTOPIA/POS device 4 receive priority low */ ++ __be32 upde1; /* UTOPIA/POS device 1 event */ ++ __be32 upde2; /* UTOPIA/POS device 2 event */ ++ __be32 upde3; /* UTOPIA/POS device 3 event */ ++ __be32 upde4; /* UTOPIA/POS device 4 event */ ++ __be16 uprp1; ++ __be16 uprp2; ++ __be16 uprp3; ++ __be16 uprp4; ++ u8 res1[0x8]; ++ __be16 uptirr1_0; /* Device 1 transmit internal rate 0 */ ++ __be16 uptirr1_1; /* Device 1 transmit internal rate 1 */ ++ __be16 uptirr1_2; /* Device 1 transmit internal rate 2 */ ++ __be16 uptirr1_3; /* Device 1 transmit internal rate 3 */ ++ __be16 uptirr2_0; /* Device 2 transmit internal rate 0 */ ++ __be16 uptirr2_1; /* Device 2 transmit internal rate 1 */ ++ __be16 uptirr2_2; /* Device 2 transmit internal rate 2 */ ++ __be16 uptirr2_3; /* Device 2 transmit internal rate 3 */ ++ __be16 uptirr3_0; /* Device 3 transmit internal rate 0 */ ++ __be16 uptirr3_1; /* Device 3 transmit internal rate 1 */ ++ __be16 uptirr3_2; /* Device 3 transmit internal rate 2 */ ++ __be16 uptirr3_3; /* Device 3 transmit internal rate 3 */ ++ __be16 uptirr4_0; /* Device 4 transmit internal rate 0 */ ++ __be16 uptirr4_1; /* Device 4 transmit internal rate 1 */ ++ __be16 uptirr4_2; /* Device 4 transmit internal rate 2 */ ++ __be16 uptirr4_3; /* Device 4 transmit internal rate 3 */ ++ __be32 uper1; /* Device 1 port enable register */ ++ __be32 uper2; /* Device 2 port enable register */ ++ __be32 uper3; /* Device 3 port enable register */ ++ __be32 uper4; /* Device 4 port enable register */ ++ u8 res2[0x150]; ++} __packed; ++ ++/* SDMA */ ++struct sdma { ++ __be32 sdsr; /* Serial DMA status register */ ++ __be32 sdmr; /* Serial DMA mode register */ ++ __be32 sdtr1; /* SDMA system bus threshold register */ ++ __be32 sdtr2; /* SDMA secondary bus threshold register */ ++ __be32 sdhy1; /* SDMA system bus hysteresis register */ ++ __be32 sdhy2; /* SDMA secondary bus hysteresis register */ ++ __be32 sdta1; /* SDMA system bus address register */ ++ __be32 sdta2; /* SDMA secondary bus address register */ ++ __be32 sdtm1; /* SDMA system bus MSNUM register */ ++ __be32 sdtm2; /* SDMA secondary bus MSNUM register */ ++ u8 res0[0x10]; ++ __be32 sdaqr; /* SDMA address bus qualify register */ ++ __be32 sdaqmr; /* SDMA address bus qualify mask register */ ++ u8 res1[0x4]; ++ __be32 sdebcr; /* SDMA CAM entries base register */ ++ u8 res2[0x38]; ++} __packed; ++ ++/* Debug Space */ ++struct dbg { ++ __be32 bpdcr; /* Breakpoint debug command register */ ++ __be32 bpdsr; /* Breakpoint debug status register */ ++ __be32 bpdmr; /* Breakpoint debug mask register */ ++ __be32 bprmrr0; /* Breakpoint request mode risc register 0 */ ++ __be32 bprmrr1; /* Breakpoint request mode risc register 1 */ ++ u8 res0[0x8]; ++ __be32 bprmtr0; /* Breakpoint request mode trb register 0 */ ++ __be32 bprmtr1; /* Breakpoint request mode trb register 1 */ ++ u8 res1[0x8]; ++ __be32 bprmir; /* Breakpoint request mode immediate register */ ++ __be32 bprmsr; /* Breakpoint request mode serial register */ ++ __be32 bpemr; /* Breakpoint exit mode register */ ++ u8 res2[0x48]; ++} __packed; ++ ++/* ++ * RISC Special Registers (Trap and Breakpoint). These are described in ++ * the QE Developer's Handbook. ++ */ ++struct rsp { ++ __be32 tibcr[16]; /* Trap/instruction breakpoint control regs */ ++ u8 res0[64]; ++ __be32 ibcr0; ++ __be32 ibs0; ++ __be32 ibcnr0; ++ u8 res1[4]; ++ __be32 ibcr1; ++ __be32 ibs1; ++ __be32 ibcnr1; ++ __be32 npcr; ++ __be32 dbcr; ++ __be32 dbar; ++ __be32 dbamr; ++ __be32 dbsr; ++ __be32 dbcnr; ++ u8 res2[12]; ++ __be32 dbdr_h; ++ __be32 dbdr_l; ++ __be32 dbdmr_h; ++ __be32 dbdmr_l; ++ __be32 bsr; ++ __be32 bor; ++ __be32 bior; ++ u8 res3[4]; ++ __be32 iatr[4]; ++ __be32 eccr; /* Exception control configuration register */ ++ __be32 eicr; ++ u8 res4[0x100-0xf8]; ++} __packed; ++ ++struct qe_immap { ++ struct qe_iram iram; /* I-RAM */ ++ struct qe_ic_regs ic; /* Interrupt Controller */ ++ struct cp_qe cp; /* Communications Processor */ ++ struct qe_mux qmx; /* QE Multiplexer */ ++ struct qe_timers qet; /* QE Timers */ ++ struct spi spi[0x2]; /* spi */ ++ struct qe_mcc mcc; /* mcc */ ++ struct qe_brg brg; /* brg */ ++ struct qe_usb_ctlr usb; /* USB */ ++ struct si1 si1; /* SI */ ++ u8 res11[0x800]; ++ struct sir sir; /* SI Routing Tables */ ++ struct ucc ucc1; /* ucc1 */ ++ struct ucc ucc3; /* ucc3 */ ++ struct ucc ucc5; /* ucc5 */ ++ struct ucc ucc7; /* ucc7 */ ++ u8 res12[0x600]; ++ struct upc upc1; /* MultiPHY UTOPIA POS Ctrlr 1*/ ++ struct ucc ucc2; /* ucc2 */ ++ struct ucc ucc4; /* ucc4 */ ++ struct ucc ucc6; /* ucc6 */ ++ struct ucc ucc8; /* ucc8 */ ++ u8 res13[0x600]; ++ struct upc upc2; /* MultiPHY UTOPIA POS Ctrlr 2*/ ++ struct sdma sdma; /* SDMA */ ++ struct dbg dbg; /* 0x104080 - 0x1040FF ++ Debug Space */ ++ struct rsp rsp[0x2]; /* 0x104100 - 0x1042FF ++ RISC Special Registers ++ (Trap and Breakpoint) */ ++ u8 res14[0x300]; /* 0x104300 - 0x1045FF */ ++ u8 res15[0x3A00]; /* 0x104600 - 0x107FFF */ ++ u8 res16[0x8000]; /* 0x108000 - 0x110000 */ ++ u8 muram[0xC000]; /* 0x110000 - 0x11C000 ++ Multi-user RAM */ ++ u8 res17[0x24000]; /* 0x11C000 - 0x140000 */ ++ u8 res18[0xC0000]; /* 0x140000 - 0x200000 */ ++} __packed; ++ ++extern struct qe_immap __iomem *qe_immr; ++extern phys_addr_t get_qe_base(void); ++ ++/* ++ * Returns the offset within the QE address space of the given pointer. ++ * ++ * Note that the QE does not support 36-bit physical addresses, so if ++ * get_qe_base() returns a number above 4GB, the caller will probably fail. ++ */ ++static inline phys_addr_t immrbar_virt_to_phys(void *address) ++{ ++ void *q = (void *)qe_immr; ++ ++ /* Is it a MURAM address? */ ++ if ((address >= q) && (address < (q + QE_IMMAP_SIZE))) ++ return get_qe_base() + (address - q); ++ ++ /* It's an address returned by kmalloc */ ++ return virt_to_phys(address); ++} ++ ++#endif /* __KERNEL__ */ ++#endif /* _ASM_POWERPC_IMMAP_QE_H */ +diff --git a/include/linux/fsl/qe.h b/include/linux/fsl/qe.h +new file mode 100644 +index 0000000..ef4422c +--- /dev/null ++++ b/include/linux/fsl/qe.h +@@ -0,0 +1,810 @@ ++/* ++ * Copyright (C) 2006, 2012 Freescale Semiconductor, Inc. All rights reserved. ++ * ++ * Authors: Shlomi Gridish ++ * Li Yang ++ * ++ * Description: ++ * QUICC Engine (QE) external definitions and structure. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ */ ++#ifndef _ASM_POWERPC_QE_H ++#define _ASM_POWERPC_QE_H ++#ifdef __KERNEL__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define QE_NUM_OF_SNUM 256 /* There are 256 serial number in QE */ ++#define QE_NUM_OF_BRGS 16 ++#define QE_NUM_OF_PORTS 1024 ++ ++/* Memory partitions ++*/ ++#define MEM_PART_SYSTEM 0 ++#define MEM_PART_SECONDARY 1 ++#define MEM_PART_MURAM 2 ++ ++extern int siram_init_flag; ++ ++/* Clocks and BRGs */ ++enum qe_clock { ++ QE_CLK_NONE = 0, ++ QE_BRG1, /* Baud Rate Generator 1 */ ++ QE_BRG2, /* Baud Rate Generator 2 */ ++ QE_BRG3, /* Baud Rate Generator 3 */ ++ QE_BRG4, /* Baud Rate Generator 4 */ ++ QE_BRG5, /* Baud Rate Generator 5 */ ++ QE_BRG6, /* Baud Rate Generator 6 */ ++ QE_BRG7, /* Baud Rate Generator 7 */ ++ QE_BRG8, /* Baud Rate Generator 8 */ ++ QE_BRG9, /* Baud Rate Generator 9 */ ++ QE_BRG10, /* Baud Rate Generator 10 */ ++ QE_BRG11, /* Baud Rate Generator 11 */ ++ QE_BRG12, /* Baud Rate Generator 12 */ ++ QE_BRG13, /* Baud Rate Generator 13 */ ++ QE_BRG14, /* Baud Rate Generator 14 */ ++ QE_BRG15, /* Baud Rate Generator 15 */ ++ QE_BRG16, /* Baud Rate Generator 16 */ ++ QE_CLK1, /* Clock 1 */ ++ QE_CLK2, /* Clock 2 */ ++ QE_CLK3, /* Clock 3 */ ++ QE_CLK4, /* Clock 4 */ ++ QE_CLK5, /* Clock 5 */ ++ QE_CLK6, /* Clock 6 */ ++ QE_CLK7, /* Clock 7 */ ++ QE_CLK8, /* Clock 8 */ ++ QE_CLK9, /* Clock 9 */ ++ QE_CLK10, /* Clock 10 */ ++ QE_CLK11, /* Clock 11 */ ++ QE_CLK12, /* Clock 12 */ ++ QE_CLK13, /* Clock 13 */ ++ QE_CLK14, /* Clock 14 */ ++ QE_CLK15, /* Clock 15 */ ++ QE_CLK16, /* Clock 16 */ ++ QE_CLK17, /* Clock 17 */ ++ QE_CLK18, /* Clock 18 */ ++ QE_CLK19, /* Clock 19 */ ++ QE_CLK20, /* Clock 20 */ ++ QE_CLK21, /* Clock 21 */ ++ QE_CLK22, /* Clock 22 */ ++ QE_CLK23, /* Clock 23 */ ++ QE_CLK24, /* Clock 24 */ ++ QE_RSYNC_PIN, /* RSYNC from pin */ ++ QE_TSYNC_PIN, /* TSYNC from pin */ ++ QE_CLK_DUMMY ++}; ++ ++static inline bool qe_clock_is_brg(enum qe_clock clk) ++{ ++ return clk >= QE_BRG1 && clk <= QE_BRG16; ++} ++ ++extern spinlock_t cmxgcr_lock; ++ ++/* Export QE common operations */ ++#ifdef CONFIG_QUICC_ENGINE ++extern void qe_reset(void); ++#else ++static inline void qe_reset(void) {} ++#endif ++ ++/* QE PIO */ ++#define QE_PIO_PINS 32 ++ ++struct qe_pio_regs { ++ __be32 cpodr; /* Open drain register */ ++ __be32 cpdata; /* Data register */ ++ __be32 cpdir1; /* Direction register */ ++ __be32 cpdir2; /* Direction register */ ++ __be32 cppar1; /* Pin assignment register */ ++ __be32 cppar2; /* Pin assignment register */ ++#ifdef CONFIG_PPC_85xx ++ u8 pad[8]; ++#endif ++}; ++ ++#define QE_PIO_DIR_IN 2 ++#define QE_PIO_DIR_OUT 1 ++extern void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin, ++ int dir, int open_drain, int assignment, ++ int has_irq); ++#ifdef CONFIG_QUICC_ENGINE ++extern int par_io_init(struct device_node *np); ++extern int par_io_of_config(struct device_node *np); ++extern int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain, ++ int assignment, int has_irq); ++extern int par_io_data_set(u8 port, u8 pin, u8 val); ++#else ++static inline int par_io_init(struct device_node *np) { return -ENOSYS; } ++static inline int par_io_of_config(struct device_node *np) { return -ENOSYS; } ++static inline int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain, ++ int assignment, int has_irq) { return -ENOSYS; } ++static inline int par_io_data_set(u8 port, u8 pin, u8 val) { return -ENOSYS; } ++#endif /* CONFIG_QUICC_ENGINE */ ++ ++/* ++ * Pin multiplexing functions. ++ */ ++struct qe_pin; ++#ifdef CONFIG_QE_GPIO ++extern struct qe_pin *qe_pin_request(struct device_node *np, int index); ++extern void qe_pin_free(struct qe_pin *qe_pin); ++extern void qe_pin_set_gpio(struct qe_pin *qe_pin); ++extern void qe_pin_set_dedicated(struct qe_pin *pin); ++#else ++static inline struct qe_pin *qe_pin_request(struct device_node *np, int index) ++{ ++ return ERR_PTR(-ENOSYS); ++} ++static inline void qe_pin_free(struct qe_pin *qe_pin) {} ++static inline void qe_pin_set_gpio(struct qe_pin *qe_pin) {} ++static inline void qe_pin_set_dedicated(struct qe_pin *pin) {} ++#endif /* CONFIG_QE_GPIO */ ++ ++#ifdef CONFIG_QUICC_ENGINE ++int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input); ++#else ++static inline int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, ++ u32 cmd_input) ++{ ++ return -ENOSYS; ++} ++#endif /* CONFIG_QUICC_ENGINE */ ++ ++/* QE internal API */ ++enum qe_clock qe_clock_source(const char *source); ++unsigned int qe_get_brg_clk(void); ++int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier); ++int qe_get_snum(void); ++void qe_put_snum(u8 snum); ++unsigned int qe_get_num_of_risc(void); ++unsigned int qe_get_num_of_snums(void); ++ ++static inline int qe_alive_during_sleep(void) ++{ ++ /* ++ * MPC8568E reference manual says: ++ * ++ * "...power down sequence waits for all I/O interfaces to become idle. ++ * In some applications this may happen eventually without actively ++ * shutting down interfaces, but most likely, software will have to ++ * take steps to shut down the eTSEC, QUICC Engine Block, and PCI ++ * interfaces before issuing the command (either the write to the core ++ * MSR[WE] as described above or writing to POWMGTCSR) to put the ++ * device into sleep state." ++ * ++ * MPC8569E reference manual has a similar paragraph. ++ */ ++#ifdef CONFIG_PPC_85xx ++ return 0; ++#else ++ return 1; ++#endif ++} ++ ++int qe_muram_init(void); ++ ++#if defined(CONFIG_QUICC_ENGINE) ++unsigned long qe_muram_alloc(unsigned long size, unsigned long align); ++int qe_muram_free(unsigned long offset); ++unsigned long qe_muram_alloc_fixed(unsigned long offset, unsigned long size); ++void __iomem *qe_muram_addr(unsigned long offset); ++unsigned long qe_muram_offset(void __iomem *addr); ++dma_addr_t qe_muram_dma(void __iomem *addr); ++#else ++static inline unsigned long qe_muram_alloc(unsigned long size, ++ unsigned long align) ++{ ++ return -ENOSYS; ++} ++ ++static inline int qe_muram_free(unsigned long offset) ++{ ++ return -ENOSYS; ++} ++ ++static inline unsigned long qe_muram_alloc_fixed(unsigned long offset, ++ unsigned long size) ++{ ++ return -ENOSYS; ++} ++ ++static inline void __iomem *qe_muram_addr(unsigned long offset) ++{ ++ return NULL; ++} ++ ++static inline unsigned long qe_muram_offset(void __iomem *addr) ++{ ++ return -ENOSYS; ++} ++ ++static inline dma_addr_t qe_muram_dma(void __iomem *addr) ++{ ++ return 0; ++} ++#endif /* defined(CONFIG_QUICC_ENGINE) */ ++ ++/* Structure that defines QE firmware binary files. ++ * ++ * See Documentation/powerpc/qe_firmware.txt for a description of these ++ * fields. ++ */ ++struct qe_firmware { ++ struct qe_header { ++ __be32 length; /* Length of the entire structure, in bytes */ ++ u8 magic[3]; /* Set to { 'Q', 'E', 'F' } */ ++ u8 version; /* Version of this layout. First ver is '1' */ ++ } header; ++ u8 id[62]; /* Null-terminated identifier string */ ++ u8 split; /* 0 = shared I-RAM, 1 = split I-RAM */ ++ u8 count; /* Number of microcode[] structures */ ++ struct { ++ __be16 model; /* The SOC model */ ++ u8 major; /* The SOC revision major */ ++ u8 minor; /* The SOC revision minor */ ++ } __packed soc; ++ u8 padding[4]; /* Reserved, for alignment */ ++ __be64 extended_modes; /* Extended modes */ ++ __be32 vtraps[8]; /* Virtual trap addresses */ ++ u8 reserved[4]; /* Reserved, for future expansion */ ++ struct qe_microcode { ++ u8 id[32]; /* Null-terminated identifier */ ++ __be32 traps[16]; /* Trap addresses, 0 == ignore */ ++ __be32 eccr; /* The value for the ECCR register */ ++ __be32 iram_offset; /* Offset into I-RAM for the code */ ++ __be32 count; /* Number of 32-bit words of the code */ ++ __be32 code_offset; /* Offset of the actual microcode */ ++ u8 major; /* The microcode version major */ ++ u8 minor; /* The microcode version minor */ ++ u8 revision; /* The microcode version revision */ ++ u8 padding; /* Reserved, for alignment */ ++ u8 reserved[4]; /* Reserved, for future expansion */ ++ } __packed microcode[1]; ++ /* All microcode binaries should be located here */ ++ /* CRC32 should be located here, after the microcode binaries */ ++} __packed; ++ ++struct qe_firmware_info { ++ char id[64]; /* Firmware name */ ++ u32 vtraps[8]; /* Virtual trap addresses */ ++ u64 extended_modes; /* Extended modes */ ++}; ++ ++#ifdef CONFIG_QUICC_ENGINE ++/* Upload a firmware to the QE */ ++int qe_upload_firmware(const struct qe_firmware *firmware); ++#else ++static inline int qe_upload_firmware(const struct qe_firmware *firmware) ++{ ++ return -ENOSYS; ++} ++#endif /* CONFIG_QUICC_ENGINE */ ++ ++/* Obtain information on the uploaded firmware */ ++struct qe_firmware_info *qe_get_firmware_info(void); ++ ++/* QE USB */ ++int qe_usb_clock_set(enum qe_clock clk, int rate); ++ ++/* Buffer descriptors */ ++struct qe_bd { ++ __be16 status; ++ __be16 length; ++ __be32 buf; ++} __packed; ++ ++#define BD_STATUS_MASK 0xffff0000 ++#define BD_LENGTH_MASK 0x0000ffff ++ ++/* Buffer descriptor control/status used by serial ++ */ ++ ++#define BD_SC_EMPTY (0x8000) /* Receive is empty */ ++#define BD_SC_READY (0x8000) /* Transmit is ready */ ++#define BD_SC_WRAP (0x2000) /* Last buffer descriptor */ ++#define BD_SC_INTRPT (0x1000) /* Interrupt on change */ ++#define BD_SC_LAST (0x0800) /* Last buffer in frame */ ++#define BD_SC_TC (0x0400) /* Transmit CRC */ ++#define BD_SC_CM (0x0200) /* Continuous mode */ ++#define BD_SC_ID (0x0100) /* Rec'd too many idles */ ++#define BD_SC_P (0x0100) /* xmt preamble */ ++#define BD_SC_BR (0x0020) /* Break received */ ++#define BD_SC_FR (0x0010) /* Framing error */ ++#define BD_SC_PR (0x0008) /* Parity error */ ++#define BD_SC_NAK (0x0004) /* NAK - did not respond */ ++#define BD_SC_OV (0x0002) /* Overrun */ ++#define BD_SC_UN (0x0002) /* Underrun */ ++#define BD_SC_CD (0x0001) /* */ ++#define BD_SC_CL (0x0001) /* Collision */ ++ ++/* Alignment */ ++#define QE_INTR_TABLE_ALIGN 16 /* ??? */ ++#define QE_ALIGNMENT_OF_BD 8 ++#define QE_ALIGNMENT_OF_PRAM 64 ++ ++/* RISC allocation */ ++#define QE_RISC_ALLOCATION_RISC1 0x1 /* RISC 1 */ ++#define QE_RISC_ALLOCATION_RISC2 0x2 /* RISC 2 */ ++#define QE_RISC_ALLOCATION_RISC3 0x4 /* RISC 3 */ ++#define QE_RISC_ALLOCATION_RISC4 0x8 /* RISC 4 */ ++#define QE_RISC_ALLOCATION_RISC1_AND_RISC2 (QE_RISC_ALLOCATION_RISC1 | \ ++ QE_RISC_ALLOCATION_RISC2) ++#define QE_RISC_ALLOCATION_FOUR_RISCS (QE_RISC_ALLOCATION_RISC1 | \ ++ QE_RISC_ALLOCATION_RISC2 | \ ++ QE_RISC_ALLOCATION_RISC3 | \ ++ QE_RISC_ALLOCATION_RISC4) ++ ++/* QE extended filtering Table Lookup Key Size */ ++enum qe_fltr_tbl_lookup_key_size { ++ QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES ++ = 0x3f, /* LookupKey parsed by the Generate LookupKey ++ CMD is truncated to 8 bytes */ ++ QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES ++ = 0x5f, /* LookupKey parsed by the Generate LookupKey ++ CMD is truncated to 16 bytes */ ++}; ++ ++/* QE FLTR extended filtering Largest External Table Lookup Key Size */ ++enum qe_fltr_largest_external_tbl_lookup_key_size { ++ QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE ++ = 0x0,/* not used */ ++ QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES ++ = QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES, /* 8 bytes */ ++ QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES ++ = QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES, /* 16 bytes */ ++}; ++ ++/* structure representing QE parameter RAM */ ++struct qe_timer_tables { ++ u16 tm_base; /* QE timer table base adr */ ++ u16 tm_ptr; /* QE timer table pointer */ ++ u16 r_tmr; /* QE timer mode register */ ++ u16 r_tmv; /* QE timer valid register */ ++ u32 tm_cmd; /* QE timer cmd register */ ++ u32 tm_cnt; /* QE timer internal cnt */ ++} __packed; ++ ++#define QE_FLTR_TAD_SIZE 8 ++ ++/* QE extended filtering Termination Action Descriptor (TAD) */ ++struct qe_fltr_tad { ++ u8 serialized[QE_FLTR_TAD_SIZE]; ++} __packed; ++ ++/* Communication Direction */ ++enum comm_dir { ++ COMM_DIR_NONE = 0, ++ COMM_DIR_RX = 1, ++ COMM_DIR_TX = 2, ++ COMM_DIR_RX_AND_TX = 3 ++}; ++ ++/* QE CMXUCR Registers. ++ * There are two UCCs represented in each of the four CMXUCR registers. ++ * These values are for the UCC in the LSBs ++ */ ++#define QE_CMXUCR_MII_ENET_MNG 0x00007000 ++#define QE_CMXUCR_MII_ENET_MNG_SHIFT 12 ++#define QE_CMXUCR_GRANT 0x00008000 ++#define QE_CMXUCR_TSA 0x00004000 ++#define QE_CMXUCR_BKPT 0x00000100 ++#define QE_CMXUCR_TX_CLK_SRC_MASK 0x0000000F ++ ++/* QE CMXGCR Registers. ++*/ ++#define QE_CMXGCR_MII_ENET_MNG 0x00007000 ++#define QE_CMXGCR_MII_ENET_MNG_SHIFT 12 ++#define QE_CMXGCR_USBCS 0x0000000f ++#define QE_CMXGCR_USBCS_CLK3 0x1 ++#define QE_CMXGCR_USBCS_CLK5 0x2 ++#define QE_CMXGCR_USBCS_CLK7 0x3 ++#define QE_CMXGCR_USBCS_CLK9 0x4 ++#define QE_CMXGCR_USBCS_CLK13 0x5 ++#define QE_CMXGCR_USBCS_CLK17 0x6 ++#define QE_CMXGCR_USBCS_CLK19 0x7 ++#define QE_CMXGCR_USBCS_CLK21 0x8 ++#define QE_CMXGCR_USBCS_BRG9 0x9 ++#define QE_CMXGCR_USBCS_BRG10 0xa ++ ++/* QE CECR Commands. ++*/ ++#define QE_CR_FLG 0x00010000 ++#define QE_RESET 0x80000000 ++#define QE_INIT_TX_RX 0x00000000 ++#define QE_INIT_RX 0x00000001 ++#define QE_INIT_TX 0x00000002 ++#define QE_ENTER_HUNT_MODE 0x00000003 ++#define QE_STOP_TX 0x00000004 ++#define QE_GRACEFUL_STOP_TX 0x00000005 ++#define QE_RESTART_TX 0x00000006 ++#define QE_CLOSE_RX_BD 0x00000007 ++#define QE_SWITCH_COMMAND 0x00000007 ++#define QE_SET_GROUP_ADDRESS 0x00000008 ++#define QE_START_IDMA 0x00000009 ++#define QE_MCC_STOP_RX 0x00000009 ++#define QE_ATM_TRANSMIT 0x0000000a ++#define QE_HPAC_CLEAR_ALL 0x0000000b ++#define QE_GRACEFUL_STOP_RX 0x0000001a ++#define QE_RESTART_RX 0x0000001b ++#define QE_HPAC_SET_PRIORITY 0x0000010b ++#define QE_HPAC_STOP_TX 0x0000020b ++#define QE_HPAC_STOP_RX 0x0000030b ++#define QE_HPAC_GRACEFUL_STOP_TX 0x0000040b ++#define QE_HPAC_GRACEFUL_STOP_RX 0x0000050b ++#define QE_HPAC_START_TX 0x0000060b ++#define QE_HPAC_START_RX 0x0000070b ++#define QE_USB_STOP_TX 0x0000000a ++#define QE_USB_RESTART_TX 0x0000000c ++#define QE_QMC_STOP_TX 0x0000000c ++#define QE_QMC_STOP_RX 0x0000000d ++#define QE_SS7_SU_FIL_RESET 0x0000000e ++/* jonathbr added from here down for 83xx */ ++#define QE_RESET_BCS 0x0000000a ++#define QE_MCC_INIT_TX_RX_16 0x00000003 ++#define QE_MCC_STOP_TX 0x00000004 ++#define QE_MCC_INIT_TX_1 0x00000005 ++#define QE_MCC_INIT_RX_1 0x00000006 ++#define QE_MCC_RESET 0x00000007 ++#define QE_SET_TIMER 0x00000008 ++#define QE_RANDOM_NUMBER 0x0000000c ++#define QE_ATM_MULTI_THREAD_INIT 0x00000011 ++#define QE_ASSIGN_PAGE 0x00000012 ++#define QE_ADD_REMOVE_HASH_ENTRY 0x00000013 ++#define QE_START_FLOW_CONTROL 0x00000014 ++#define QE_STOP_FLOW_CONTROL 0x00000015 ++#define QE_ASSIGN_PAGE_TO_DEVICE 0x00000016 ++ ++#define QE_ASSIGN_RISC 0x00000010 ++#define QE_CR_MCN_NORMAL_SHIFT 6 ++#define QE_CR_MCN_USB_SHIFT 4 ++#define QE_CR_MCN_RISC_ASSIGN_SHIFT 8 ++#define QE_CR_SNUM_SHIFT 17 ++ ++/* QE CECR Sub Block - sub block of QE command. ++*/ ++#define QE_CR_SUBBLOCK_INVALID 0x00000000 ++#define QE_CR_SUBBLOCK_USB 0x03200000 ++#define QE_CR_SUBBLOCK_UCCFAST1 0x02000000 ++#define QE_CR_SUBBLOCK_UCCFAST2 0x02200000 ++#define QE_CR_SUBBLOCK_UCCFAST3 0x02400000 ++#define QE_CR_SUBBLOCK_UCCFAST4 0x02600000 ++#define QE_CR_SUBBLOCK_UCCFAST5 0x02800000 ++#define QE_CR_SUBBLOCK_UCCFAST6 0x02a00000 ++#define QE_CR_SUBBLOCK_UCCFAST7 0x02c00000 ++#define QE_CR_SUBBLOCK_UCCFAST8 0x02e00000 ++#define QE_CR_SUBBLOCK_UCCSLOW1 0x00000000 ++#define QE_CR_SUBBLOCK_UCCSLOW2 0x00200000 ++#define QE_CR_SUBBLOCK_UCCSLOW3 0x00400000 ++#define QE_CR_SUBBLOCK_UCCSLOW4 0x00600000 ++#define QE_CR_SUBBLOCK_UCCSLOW5 0x00800000 ++#define QE_CR_SUBBLOCK_UCCSLOW6 0x00a00000 ++#define QE_CR_SUBBLOCK_UCCSLOW7 0x00c00000 ++#define QE_CR_SUBBLOCK_UCCSLOW8 0x00e00000 ++#define QE_CR_SUBBLOCK_MCC1 0x03800000 ++#define QE_CR_SUBBLOCK_MCC2 0x03a00000 ++#define QE_CR_SUBBLOCK_MCC3 0x03000000 ++#define QE_CR_SUBBLOCK_IDMA1 0x02800000 ++#define QE_CR_SUBBLOCK_IDMA2 0x02a00000 ++#define QE_CR_SUBBLOCK_IDMA3 0x02c00000 ++#define QE_CR_SUBBLOCK_IDMA4 0x02e00000 ++#define QE_CR_SUBBLOCK_HPAC 0x01e00000 ++#define QE_CR_SUBBLOCK_SPI1 0x01400000 ++#define QE_CR_SUBBLOCK_SPI2 0x01600000 ++#define QE_CR_SUBBLOCK_RAND 0x01c00000 ++#define QE_CR_SUBBLOCK_TIMER 0x01e00000 ++#define QE_CR_SUBBLOCK_GENERAL 0x03c00000 ++ ++/* QE CECR Protocol - For non-MCC, specifies mode for QE CECR command */ ++#define QE_CR_PROTOCOL_UNSPECIFIED 0x00 /* For all other protocols */ ++#define QE_CR_PROTOCOL_HDLC_TRANSPARENT 0x00 ++#define QE_CR_PROTOCOL_QMC 0x02 ++#define QE_CR_PROTOCOL_UART 0x04 ++#define QE_CR_PROTOCOL_ATM_POS 0x0A ++#define QE_CR_PROTOCOL_ETHERNET 0x0C ++#define QE_CR_PROTOCOL_L2_SWITCH 0x0D ++ ++/* BRG configuration register */ ++#define QE_BRGC_ENABLE 0x00010000 ++#define QE_BRGC_DIVISOR_SHIFT 1 ++#define QE_BRGC_DIVISOR_MAX 0xFFF ++#define QE_BRGC_DIV16 1 ++ ++/* QE Timers registers */ ++#define QE_GTCFR1_PCAS 0x80 ++#define QE_GTCFR1_STP2 0x20 ++#define QE_GTCFR1_RST2 0x10 ++#define QE_GTCFR1_GM2 0x08 ++#define QE_GTCFR1_GM1 0x04 ++#define QE_GTCFR1_STP1 0x02 ++#define QE_GTCFR1_RST1 0x01 ++ ++/* SDMA registers */ ++#define QE_SDSR_BER1 0x02000000 ++#define QE_SDSR_BER2 0x01000000 ++ ++#define QE_SDMR_GLB_1_MSK 0x80000000 ++#define QE_SDMR_ADR_SEL 0x20000000 ++#define QE_SDMR_BER1_MSK 0x02000000 ++#define QE_SDMR_BER2_MSK 0x01000000 ++#define QE_SDMR_EB1_MSK 0x00800000 ++#define QE_SDMR_ER1_MSK 0x00080000 ++#define QE_SDMR_ER2_MSK 0x00040000 ++#define QE_SDMR_CEN_MASK 0x0000E000 ++#define QE_SDMR_SBER_1 0x00000200 ++#define QE_SDMR_SBER_2 0x00000200 ++#define QE_SDMR_EB1_PR_MASK 0x000000C0 ++#define QE_SDMR_ER1_PR 0x00000008 ++ ++#define QE_SDMR_CEN_SHIFT 13 ++#define QE_SDMR_EB1_PR_SHIFT 6 ++ ++#define QE_SDTM_MSNUM_SHIFT 24 ++ ++#define QE_SDEBCR_BA_MASK 0x01FFFFFF ++ ++/* Communication Processor */ ++#define QE_CP_CERCR_MEE 0x8000 /* Multi-user RAM ECC enable */ ++#define QE_CP_CERCR_IEE 0x4000 /* Instruction RAM ECC enable */ ++#define QE_CP_CERCR_CIR 0x0800 /* Common instruction RAM */ ++ ++/* I-RAM */ ++#define QE_IRAM_IADD_AIE 0x80000000 /* Auto Increment Enable */ ++#define QE_IRAM_IADD_BADDR 0x00080000 /* Base Address */ ++#define QE_IRAM_READY 0x80000000 /* Ready */ ++ ++/* UPC */ ++#define UPGCR_PROTOCOL 0x80000000 /* protocol ul2 or pl2 */ ++#define UPGCR_TMS 0x40000000 /* Transmit master/slave mode */ ++#define UPGCR_RMS 0x20000000 /* Receive master/slave mode */ ++#define UPGCR_ADDR 0x10000000 /* Master MPHY Addr multiplexing */ ++#define UPGCR_DIAG 0x01000000 /* Diagnostic mode */ ++ ++/* UCC GUEMR register */ ++#define UCC_GUEMR_MODE_MASK_RX 0x02 ++#define UCC_GUEMR_MODE_FAST_RX 0x02 ++#define UCC_GUEMR_MODE_SLOW_RX 0x00 ++#define UCC_GUEMR_MODE_MASK_TX 0x01 ++#define UCC_GUEMR_MODE_FAST_TX 0x01 ++#define UCC_GUEMR_MODE_SLOW_TX 0x00 ++#define UCC_GUEMR_MODE_MASK (UCC_GUEMR_MODE_MASK_RX | UCC_GUEMR_MODE_MASK_TX) ++#define UCC_GUEMR_SET_RESERVED3 0x10 /* Bit 3 in the guemr is reserved but ++ must be set 1 */ ++ ++/* structure representing UCC SLOW parameter RAM */ ++struct ucc_slow_pram { ++ __be16 rbase; /* RX BD base address */ ++ __be16 tbase; /* TX BD base address */ ++ u8 rbmr; /* RX bus mode register (same as CPM's RFCR) */ ++ u8 tbmr; /* TX bus mode register (same as CPM's TFCR) */ ++ __be16 mrblr; /* Rx buffer length */ ++ __be32 rstate; /* Rx internal state */ ++ __be32 rptr; /* Rx internal data pointer */ ++ __be16 rbptr; /* rb BD Pointer */ ++ __be16 rcount; /* Rx internal byte count */ ++ __be32 rtemp; /* Rx temp */ ++ __be32 tstate; /* Tx internal state */ ++ __be32 tptr; /* Tx internal data pointer */ ++ __be16 tbptr; /* Tx BD pointer */ ++ __be16 tcount; /* Tx byte count */ ++ __be32 ttemp; /* Tx temp */ ++ __be32 rcrc; /* temp receive CRC */ ++ __be32 tcrc; /* temp transmit CRC */ ++} __packed; ++ ++/* General UCC SLOW Mode Register (GUMRH & GUMRL) */ ++#define UCC_SLOW_GUMR_H_SAM_QMC 0x00000000 ++#define UCC_SLOW_GUMR_H_SAM_SATM 0x00008000 ++#define UCC_SLOW_GUMR_H_REVD 0x00002000 ++#define UCC_SLOW_GUMR_H_TRX 0x00001000 ++#define UCC_SLOW_GUMR_H_TTX 0x00000800 ++#define UCC_SLOW_GUMR_H_CDP 0x00000400 ++#define UCC_SLOW_GUMR_H_CTSP 0x00000200 ++#define UCC_SLOW_GUMR_H_CDS 0x00000100 ++#define UCC_SLOW_GUMR_H_CTSS 0x00000080 ++#define UCC_SLOW_GUMR_H_TFL 0x00000040 ++#define UCC_SLOW_GUMR_H_RFW 0x00000020 ++#define UCC_SLOW_GUMR_H_TXSY 0x00000010 ++#define UCC_SLOW_GUMR_H_4SYNC 0x00000004 ++#define UCC_SLOW_GUMR_H_8SYNC 0x00000008 ++#define UCC_SLOW_GUMR_H_16SYNC 0x0000000c ++#define UCC_SLOW_GUMR_H_RTSM 0x00000002 ++#define UCC_SLOW_GUMR_H_RSYN 0x00000001 ++ ++#define UCC_SLOW_GUMR_L_TCI 0x10000000 ++#define UCC_SLOW_GUMR_L_RINV 0x02000000 ++#define UCC_SLOW_GUMR_L_TINV 0x01000000 ++#define UCC_SLOW_GUMR_L_TEND 0x00040000 ++#define UCC_SLOW_GUMR_L_TDCR_MASK 0x00030000 ++#define UCC_SLOW_GUMR_L_TDCR_32 0x00030000 ++#define UCC_SLOW_GUMR_L_TDCR_16 0x00020000 ++#define UCC_SLOW_GUMR_L_TDCR_8 0x00010000 ++#define UCC_SLOW_GUMR_L_TDCR_1 0x00000000 ++#define UCC_SLOW_GUMR_L_RDCR_MASK 0x0000c000 ++#define UCC_SLOW_GUMR_L_RDCR_32 0x0000c000 ++#define UCC_SLOW_GUMR_L_RDCR_16 0x00008000 ++#define UCC_SLOW_GUMR_L_RDCR_8 0x00004000 ++#define UCC_SLOW_GUMR_L_RDCR_1 0x00000000 ++#define UCC_SLOW_GUMR_L_RENC_NRZI 0x00000800 ++#define UCC_SLOW_GUMR_L_RENC_NRZ 0x00000000 ++#define UCC_SLOW_GUMR_L_TENC_NRZI 0x00000100 ++#define UCC_SLOW_GUMR_L_TENC_NRZ 0x00000000 ++#define UCC_SLOW_GUMR_L_DIAG_MASK 0x000000c0 ++#define UCC_SLOW_GUMR_L_DIAG_LE 0x000000c0 ++#define UCC_SLOW_GUMR_L_DIAG_ECHO 0x00000080 ++#define UCC_SLOW_GUMR_L_DIAG_LOOP 0x00000040 ++#define UCC_SLOW_GUMR_L_DIAG_NORM 0x00000000 ++#define UCC_SLOW_GUMR_L_ENR 0x00000020 ++#define UCC_SLOW_GUMR_L_ENT 0x00000010 ++#define UCC_SLOW_GUMR_L_MODE_MASK 0x0000000F ++#define UCC_SLOW_GUMR_L_MODE_BISYNC 0x00000008 ++#define UCC_SLOW_GUMR_L_MODE_AHDLC 0x00000006 ++#define UCC_SLOW_GUMR_L_MODE_UART 0x00000004 ++#define UCC_SLOW_GUMR_L_MODE_QMC 0x00000002 ++ ++/* General UCC FAST Mode Register */ ++#define UCC_FAST_GUMR_TCI 0x20000000 ++#define UCC_FAST_GUMR_TRX 0x10000000 ++#define UCC_FAST_GUMR_TTX 0x08000000 ++#define UCC_FAST_GUMR_CDP 0x04000000 ++#define UCC_FAST_GUMR_CTSP 0x02000000 ++#define UCC_FAST_GUMR_CDS 0x01000000 ++#define UCC_FAST_GUMR_CTSS 0x00800000 ++#define UCC_FAST_GUMR_TXSY 0x00020000 ++#define UCC_FAST_GUMR_RSYN 0x00010000 ++#define UCC_FAST_GUMR_RTSM 0x00002000 ++#define UCC_FAST_GUMR_REVD 0x00000400 ++#define UCC_FAST_GUMR_ENR 0x00000020 ++#define UCC_FAST_GUMR_ENT 0x00000010 ++ ++/* UART Slow UCC Event Register (UCCE) */ ++#define UCC_UART_UCCE_AB 0x0200 ++#define UCC_UART_UCCE_IDLE 0x0100 ++#define UCC_UART_UCCE_GRA 0x0080 ++#define UCC_UART_UCCE_BRKE 0x0040 ++#define UCC_UART_UCCE_BRKS 0x0020 ++#define UCC_UART_UCCE_CCR 0x0008 ++#define UCC_UART_UCCE_BSY 0x0004 ++#define UCC_UART_UCCE_TX 0x0002 ++#define UCC_UART_UCCE_RX 0x0001 ++ ++/* HDLC Slow UCC Event Register (UCCE) */ ++#define UCC_HDLC_UCCE_GLR 0x1000 ++#define UCC_HDLC_UCCE_GLT 0x0800 ++#define UCC_HDLC_UCCE_IDLE 0x0100 ++#define UCC_HDLC_UCCE_BRKE 0x0040 ++#define UCC_HDLC_UCCE_BRKS 0x0020 ++#define UCC_HDLC_UCCE_TXE 0x0010 ++#define UCC_HDLC_UCCE_RXF 0x0008 ++#define UCC_HDLC_UCCE_BSY 0x0004 ++#define UCC_HDLC_UCCE_TXB 0x0002 ++#define UCC_HDLC_UCCE_RXB 0x0001 ++ ++/* BISYNC Slow UCC Event Register (UCCE) */ ++#define UCC_BISYNC_UCCE_GRA 0x0080 ++#define UCC_BISYNC_UCCE_TXE 0x0010 ++#define UCC_BISYNC_UCCE_RCH 0x0008 ++#define UCC_BISYNC_UCCE_BSY 0x0004 ++#define UCC_BISYNC_UCCE_TXB 0x0002 ++#define UCC_BISYNC_UCCE_RXB 0x0001 ++ ++/* Transparent UCC Event Register (UCCE) */ ++#define UCC_TRANS_UCCE_GRA 0x0080 ++#define UCC_TRANS_UCCE_TXE 0x0010 ++#define UCC_TRANS_UCCE_RXF 0x0008 ++#define UCC_TRANS_UCCE_BSY 0x0004 ++#define UCC_TRANS_UCCE_TXB 0x0002 ++#define UCC_TRANS_UCCE_RXB 0x0001 ++ ++ ++/* Gigabit Ethernet Fast UCC Event Register (UCCE) */ ++#define UCC_GETH_UCCE_MPD 0x80000000 ++#define UCC_GETH_UCCE_SCAR 0x40000000 ++#define UCC_GETH_UCCE_GRA 0x20000000 ++#define UCC_GETH_UCCE_CBPR 0x10000000 ++#define UCC_GETH_UCCE_BSY 0x08000000 ++#define UCC_GETH_UCCE_RXC 0x04000000 ++#define UCC_GETH_UCCE_TXC 0x02000000 ++#define UCC_GETH_UCCE_TXE 0x01000000 ++#define UCC_GETH_UCCE_TXB7 0x00800000 ++#define UCC_GETH_UCCE_TXB6 0x00400000 ++#define UCC_GETH_UCCE_TXB5 0x00200000 ++#define UCC_GETH_UCCE_TXB4 0x00100000 ++#define UCC_GETH_UCCE_TXB3 0x00080000 ++#define UCC_GETH_UCCE_TXB2 0x00040000 ++#define UCC_GETH_UCCE_TXB1 0x00020000 ++#define UCC_GETH_UCCE_TXB0 0x00010000 ++#define UCC_GETH_UCCE_RXB7 0x00008000 ++#define UCC_GETH_UCCE_RXB6 0x00004000 ++#define UCC_GETH_UCCE_RXB5 0x00002000 ++#define UCC_GETH_UCCE_RXB4 0x00001000 ++#define UCC_GETH_UCCE_RXB3 0x00000800 ++#define UCC_GETH_UCCE_RXB2 0x00000400 ++#define UCC_GETH_UCCE_RXB1 0x00000200 ++#define UCC_GETH_UCCE_RXB0 0x00000100 ++#define UCC_GETH_UCCE_RXF7 0x00000080 ++#define UCC_GETH_UCCE_RXF6 0x00000040 ++#define UCC_GETH_UCCE_RXF5 0x00000020 ++#define UCC_GETH_UCCE_RXF4 0x00000010 ++#define UCC_GETH_UCCE_RXF3 0x00000008 ++#define UCC_GETH_UCCE_RXF2 0x00000004 ++#define UCC_GETH_UCCE_RXF1 0x00000002 ++#define UCC_GETH_UCCE_RXF0 0x00000001 ++ ++/* UCC Protocol Specific Mode Register (UPSMR), when used for UART */ ++#define UCC_UART_UPSMR_FLC 0x8000 ++#define UCC_UART_UPSMR_SL 0x4000 ++#define UCC_UART_UPSMR_CL_MASK 0x3000 ++#define UCC_UART_UPSMR_CL_8 0x3000 ++#define UCC_UART_UPSMR_CL_7 0x2000 ++#define UCC_UART_UPSMR_CL_6 0x1000 ++#define UCC_UART_UPSMR_CL_5 0x0000 ++#define UCC_UART_UPSMR_UM_MASK 0x0c00 ++#define UCC_UART_UPSMR_UM_NORMAL 0x0000 ++#define UCC_UART_UPSMR_UM_MAN_MULTI 0x0400 ++#define UCC_UART_UPSMR_UM_AUTO_MULTI 0x0c00 ++#define UCC_UART_UPSMR_FRZ 0x0200 ++#define UCC_UART_UPSMR_RZS 0x0100 ++#define UCC_UART_UPSMR_SYN 0x0080 ++#define UCC_UART_UPSMR_DRT 0x0040 ++#define UCC_UART_UPSMR_PEN 0x0010 ++#define UCC_UART_UPSMR_RPM_MASK 0x000c ++#define UCC_UART_UPSMR_RPM_ODD 0x0000 ++#define UCC_UART_UPSMR_RPM_LOW 0x0004 ++#define UCC_UART_UPSMR_RPM_EVEN 0x0008 ++#define UCC_UART_UPSMR_RPM_HIGH 0x000C ++#define UCC_UART_UPSMR_TPM_MASK 0x0003 ++#define UCC_UART_UPSMR_TPM_ODD 0x0000 ++#define UCC_UART_UPSMR_TPM_LOW 0x0001 ++#define UCC_UART_UPSMR_TPM_EVEN 0x0002 ++#define UCC_UART_UPSMR_TPM_HIGH 0x0003 ++ ++/* UCC Protocol Specific Mode Register (UPSMR), when used for Ethernet */ ++#define UCC_GETH_UPSMR_FTFE 0x80000000 ++#define UCC_GETH_UPSMR_PTPE 0x40000000 ++#define UCC_GETH_UPSMR_ECM 0x04000000 ++#define UCC_GETH_UPSMR_HSE 0x02000000 ++#define UCC_GETH_UPSMR_PRO 0x00400000 ++#define UCC_GETH_UPSMR_CAP 0x00200000 ++#define UCC_GETH_UPSMR_RSH 0x00100000 ++#define UCC_GETH_UPSMR_RPM 0x00080000 ++#define UCC_GETH_UPSMR_R10M 0x00040000 ++#define UCC_GETH_UPSMR_RLPB 0x00020000 ++#define UCC_GETH_UPSMR_TBIM 0x00010000 ++#define UCC_GETH_UPSMR_RES1 0x00002000 ++#define UCC_GETH_UPSMR_RMM 0x00001000 ++#define UCC_GETH_UPSMR_CAM 0x00000400 ++#define UCC_GETH_UPSMR_BRO 0x00000200 ++#define UCC_GETH_UPSMR_SMM 0x00000080 ++#define UCC_GETH_UPSMR_SGMM 0x00000020 ++ ++/* UCC Transmit On Demand Register (UTODR) */ ++#define UCC_SLOW_TOD 0x8000 ++#define UCC_FAST_TOD 0x8000 ++ ++/* UCC Bus Mode Register masks */ ++/* Not to be confused with the Bundle Mode Register */ ++#define UCC_BMR_GBL 0x20 ++#define UCC_BMR_BO_BE 0x10 ++#define UCC_BMR_CETM 0x04 ++#define UCC_BMR_DTB 0x02 ++#define UCC_BMR_BDB 0x01 ++ ++/* Function code masks */ ++#define FC_GBL 0x20 ++#define FC_DTB_LCL 0x02 ++#define UCC_FAST_FUNCTION_CODE_GBL 0x20 ++#define UCC_FAST_FUNCTION_CODE_DTB_LCL 0x02 ++#define UCC_FAST_FUNCTION_CODE_BDB_LCL 0x01 ++ ++#endif /* __KERNEL__ */ ++#endif /* _ASM_POWERPC_QE_H */ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0019-fmd-add-SDK1.9-codebase.patch b/target/linux/layerscape-64b/patches-4.1/0019-fmd-add-SDK1.9-codebase.patch new file mode 100644 index 0000000..7221a56 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0019-fmd-add-SDK1.9-codebase.patch @@ -0,0 +1,115016 @@ +From 47d8021852df758e17bb3e0d6840468c2f68facc Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Wed, 16 Dec 2015 21:46:52 +0200 +Subject: [PATCH 019/151] fmd: add SDK1.9 codebase + +Moved to the sdk_fman folder and renamed Kconfig option to FSL_SDK_FMAN to +allow for the upstreamable FMan driver to be added in the same tree. +Added changes needed to adapt to the new kernel. + +Signed-off-by: Mandy Lavi +Signed-off-by: Madalin Bucur +--- + drivers/net/ethernet/freescale/Kconfig | 1 + + drivers/net/ethernet/freescale/Makefile | 1 + + drivers/net/ethernet/freescale/sdk_fman/Kconfig | 146 + + drivers/net/ethernet/freescale/sdk_fman/Makefile | 11 + + .../freescale/sdk_fman/Peripherals/FM/HC/Makefile | 15 + + .../freescale/sdk_fman/Peripherals/FM/HC/hc.c | 1232 ++++ + .../freescale/sdk_fman/Peripherals/FM/MAC/Makefile | 25 + + .../freescale/sdk_fman/Peripherals/FM/MAC/dtsec.c | 1463 ++++ + .../freescale/sdk_fman/Peripherals/FM/MAC/dtsec.h | 228 + + .../sdk_fman/Peripherals/FM/MAC/dtsec_mii_acc.c | 97 + + .../sdk_fman/Peripherals/FM/MAC/dtsec_mii_acc.h | 42 + + .../freescale/sdk_fman/Peripherals/FM/MAC/fm_mac.c | 646 ++ + .../freescale/sdk_fman/Peripherals/FM/MAC/fm_mac.h | 224 + + .../sdk_fman/Peripherals/FM/MAC/fman_crc32.c | 119 + + .../sdk_fman/Peripherals/FM/MAC/fman_crc32.h | 43 + + .../sdk_fman/Peripherals/FM/MAC/fman_dtsec.c | 845 +++ + .../Peripherals/FM/MAC/fman_dtsec_mii_acc.c | 163 + + .../sdk_fman/Peripherals/FM/MAC/fman_memac.c | 511 ++ + .../Peripherals/FM/MAC/fman_memac_mii_acc.c | 213 + + .../sdk_fman/Peripherals/FM/MAC/fman_tgec.c | 367 + + .../freescale/sdk_fman/Peripherals/FM/MAC/memac.c | 1088 +++ + .../freescale/sdk_fman/Peripherals/FM/MAC/memac.h | 110 + + .../sdk_fman/Peripherals/FM/MAC/memac_mii_acc.c | 78 + + .../sdk_fman/Peripherals/FM/MAC/memac_mii_acc.h | 73 + + .../freescale/sdk_fman/Peripherals/FM/MAC/tgec.c | 974 +++ + .../freescale/sdk_fman/Peripherals/FM/MAC/tgec.h | 151 + + .../sdk_fman/Peripherals/FM/MAC/tgec_mii_acc.c | 139 + + .../sdk_fman/Peripherals/FM/MAC/tgec_mii_acc.h | 80 + + .../sdk_fman/Peripherals/FM/MACSEC/Makefile | 15 + + .../sdk_fman/Peripherals/FM/MACSEC/fm_macsec.c | 237 + + .../sdk_fman/Peripherals/FM/MACSEC/fm_macsec.h | 203 + + .../Peripherals/FM/MACSEC/fm_macsec_guest.c | 59 + + .../Peripherals/FM/MACSEC/fm_macsec_master.c | 1031 +++ + .../Peripherals/FM/MACSEC/fm_macsec_master.h | 479 ++ + .../Peripherals/FM/MACSEC/fm_macsec_secy.c | 883 +++ + .../Peripherals/FM/MACSEC/fm_macsec_secy.h | 144 + + .../freescale/sdk_fman/Peripherals/FM/Makefile | 23 + + .../freescale/sdk_fman/Peripherals/FM/Pcd/Makefile | 23 + + .../freescale/sdk_fman/Peripherals/FM/Pcd/crc64.h | 360 + + .../freescale/sdk_fman/Peripherals/FM/Pcd/fm_cc.c | 7533 ++++++++++++++++++++ + .../freescale/sdk_fman/Peripherals/FM/Pcd/fm_cc.h | 399 ++ + .../freescale/sdk_fman/Peripherals/FM/Pcd/fm_kg.c | 3242 +++++++++ + .../freescale/sdk_fman/Peripherals/FM/Pcd/fm_kg.h | 206 + + .../sdk_fman/Peripherals/FM/Pcd/fm_manip.c | 5564 +++++++++++++++ + .../sdk_fman/Peripherals/FM/Pcd/fm_manip.h | 553 ++ + .../freescale/sdk_fman/Peripherals/FM/Pcd/fm_pcd.c | 2094 ++++++ + .../freescale/sdk_fman/Peripherals/FM/Pcd/fm_pcd.h | 543 ++ + .../sdk_fman/Peripherals/FM/Pcd/fm_pcd_ipc.h | 280 + + .../sdk_fman/Peripherals/FM/Pcd/fm_plcr.c | 1846 +++++ + .../sdk_fman/Peripherals/FM/Pcd/fm_plcr.h | 165 + + .../freescale/sdk_fman/Peripherals/FM/Pcd/fm_prs.c | 420 ++ + .../freescale/sdk_fman/Peripherals/FM/Pcd/fm_prs.h | 316 + + .../sdk_fman/Peripherals/FM/Pcd/fm_replic.c | 984 +++ + .../sdk_fman/Peripherals/FM/Pcd/fm_replic.h | 101 + + .../sdk_fman/Peripherals/FM/Pcd/fman_kg.c | 888 +++ + .../sdk_fman/Peripherals/FM/Pcd/fman_prs.c | 129 + + .../sdk_fman/Peripherals/FM/Port/Makefile | 15 + + .../sdk_fman/Peripherals/FM/Port/fm_port.c | 6436 +++++++++++++++++ + .../sdk_fman/Peripherals/FM/Port/fm_port.h | 999 +++ + .../sdk_fman/Peripherals/FM/Port/fm_port_dsar.h | 494 ++ + .../sdk_fman/Peripherals/FM/Port/fm_port_im.c | 753 ++ + .../sdk_fman/Peripherals/FM/Port/fman_port.c | 1568 ++++ + .../freescale/sdk_fman/Peripherals/FM/Rtc/Makefile | 15 + + .../freescale/sdk_fman/Peripherals/FM/Rtc/fm_rtc.c | 692 ++ + .../freescale/sdk_fman/Peripherals/FM/Rtc/fm_rtc.h | 96 + + .../sdk_fman/Peripherals/FM/Rtc/fman_rtc.c | 334 + + .../freescale/sdk_fman/Peripherals/FM/SP/Makefile | 15 + + .../freescale/sdk_fman/Peripherals/FM/SP/fm_sp.c | 757 ++ + .../freescale/sdk_fman/Peripherals/FM/SP/fm_sp.h | 85 + + .../freescale/sdk_fman/Peripherals/FM/SP/fman_sp.c | 197 + + .../freescale/sdk_fman/Peripherals/FM/fm.c | 5191 ++++++++++++++ + .../freescale/sdk_fman/Peripherals/FM/fm.h | 646 ++ + .../freescale/sdk_fman/Peripherals/FM/fm_ipc.h | 465 ++ + .../freescale/sdk_fman/Peripherals/FM/fm_muram.c | 174 + + .../freescale/sdk_fman/Peripherals/FM/fman.c | 1399 ++++ + .../sdk_fman/Peripherals/FM/inc/fm_common.h | 1203 ++++ + .../freescale/sdk_fman/Peripherals/FM/inc/fm_hc.h | 93 + + .../sdk_fman/Peripherals/FM/inc/fm_sp_common.h | 117 + + .../net/ethernet/freescale/sdk_fman/etc/Makefile | 12 + + .../net/ethernet/freescale/sdk_fman/etc/error.c | 95 + + drivers/net/ethernet/freescale/sdk_fman/etc/list.c | 71 + + .../net/ethernet/freescale/sdk_fman/etc/memcpy.c | 601 ++ + drivers/net/ethernet/freescale/sdk_fman/etc/mm.c | 1155 +++ + drivers/net/ethernet/freescale/sdk_fman/etc/mm.h | 105 + + .../net/ethernet/freescale/sdk_fman/etc/sprint.c | 81 + + .../ethernet/freescale/sdk_fman/fmanv3h_dflags.h | 57 + + .../ethernet/freescale/sdk_fman/fmanv3l_dflags.h | 56 + + .../sdk_fman/inc/Peripherals/crc_mac_addr_ext.h | 364 + + .../freescale/sdk_fman/inc/Peripherals/dpaa_ext.h | 207 + + .../freescale/sdk_fman/inc/Peripherals/fm_ext.h | 1705 +++++ + .../sdk_fman/inc/Peripherals/fm_mac_ext.h | 846 +++ + .../sdk_fman/inc/Peripherals/fm_macsec_ext.h | 1271 ++++ + .../sdk_fman/inc/Peripherals/fm_muram_ext.h | 170 + + .../sdk_fman/inc/Peripherals/fm_pcd_ext.h | 3972 +++++++++++ + .../sdk_fman/inc/Peripherals/fm_port_ext.h | 2608 +++++++ + .../sdk_fman/inc/Peripherals/fm_rtc_ext.h | 619 ++ + .../sdk_fman/inc/Peripherals/fm_vsp_ext.h | 411 ++ + .../sdk_fman/inc/Peripherals/mii_acc_ext.h | 76 + + .../net/ethernet/freescale/sdk_fman/inc/core_ext.h | 86 + + .../freescale/sdk_fman/inc/cores/e500v2_ext.h | 476 ++ + .../freescale/sdk_fman/inc/cores/ppc_ext.h | 141 + + .../ethernet/freescale/sdk_fman/inc/ddr_std_ext.h | 77 + + .../ethernet/freescale/sdk_fman/inc/debug_ext.h | 233 + + .../ethernet/freescale/sdk_fman/inc/endian_ext.h | 447 ++ + .../net/ethernet/freescale/sdk_fman/inc/enet_ext.h | 205 + + .../ethernet/freescale/sdk_fman/inc/error_ext.h | 529 ++ + .../ethernet/freescale/sdk_fman/inc/etc/list_ext.h | 358 + + .../ethernet/freescale/sdk_fman/inc/etc/mem_ext.h | 318 + + .../freescale/sdk_fman/inc/etc/memcpy_ext.h | 174 + + .../ethernet/freescale/sdk_fman/inc/etc/mm_ext.h | 310 + + .../freescale/sdk_fman/inc/etc/sprint_ext.h | 118 + + .../sdk_fman/inc/flib/common/arch/ppc_access.h | 37 + + .../freescale/sdk_fman/inc/flib/common/general.h | 51 + + .../freescale/sdk_fman/inc/flib/fman_common.h | 78 + + .../freescale/sdk_fman/inc/flib/fsl_enet.h | 273 + + .../freescale/sdk_fman/inc/flib/fsl_fman.h | 825 +++ + .../freescale/sdk_fman/inc/flib/fsl_fman_dtsec.h | 1096 +++ + .../sdk_fman/inc/flib/fsl_fman_dtsec_mii_acc.h | 107 + + .../freescale/sdk_fman/inc/flib/fsl_fman_kg.h | 514 ++ + .../freescale/sdk_fman/inc/flib/fsl_fman_memac.h | 427 ++ + .../sdk_fman/inc/flib/fsl_fman_memac_mii_acc.h | 78 + + .../freescale/sdk_fman/inc/flib/fsl_fman_port.h | 593 ++ + .../freescale/sdk_fman/inc/flib/fsl_fman_prs.h | 102 + + .../freescale/sdk_fman/inc/flib/fsl_fman_rtc.h | 449 ++ + .../freescale/sdk_fman/inc/flib/fsl_fman_sp.h | 138 + + .../freescale/sdk_fman/inc/flib/fsl_fman_tgec.h | 479 ++ + .../integrations/FMANV3H/dpaa_integration_ext.h | 290 + + .../sdk_fman/inc/integrations/FMANV3H/part_ext.h | 71 + + .../integrations/FMANV3H/part_integration_ext.h | 304 + + .../integrations/FMANV3L/dpaa_integration_ext.h | 292 + + .../sdk_fman/inc/integrations/FMANV3L/part_ext.h | 59 + + .../integrations/FMANV3L/part_integration_ext.h | 304 + + .../inc/integrations/P1023/dpaa_integration_ext.h | 213 + + .../sdk_fman/inc/integrations/P1023/part_ext.h | 82 + + .../inc/integrations/P1023/part_integration_ext.h | 635 ++ + .../P3040_P4080_P5020/dpaa_integration_ext.h | 276 + + .../inc/integrations/P3040_P4080_P5020/part_ext.h | 83 + + .../P3040_P4080_P5020/part_integration_ext.h | 336 + + .../net/ethernet/freescale/sdk_fman/inc/math_ext.h | 99 + + .../net/ethernet/freescale/sdk_fman/inc/ncsw_ext.h | 435 ++ + .../net/ethernet/freescale/sdk_fman/inc/net_ext.h | 430 ++ + .../net/ethernet/freescale/sdk_fman/inc/std_ext.h | 48 + + .../ethernet/freescale/sdk_fman/inc/stdarg_ext.h | 49 + + .../ethernet/freescale/sdk_fman/inc/stdlib_ext.h | 162 + + .../ethernet/freescale/sdk_fman/inc/string_ext.h | 56 + + .../ethernet/freescale/sdk_fman/inc/types_ext.h | 104 + + .../ethernet/freescale/sdk_fman/inc/xx_common.h | 56 + + .../net/ethernet/freescale/sdk_fman/inc/xx_ext.h | 791 ++ + .../net/ethernet/freescale/sdk_fman/ncsw_config.mk | 47 + + .../net/ethernet/freescale/sdk_fman/p1023_dflags.h | 65 + + .../freescale/sdk_fman/p3040_4080_5020_dflags.h | 62 + + .../net/ethernet/freescale/sdk_fman/src/Makefile | 11 + + .../freescale/sdk_fman/src/inc/system/sys_ext.h | 118 + + .../freescale/sdk_fman/src/inc/system/sys_io_ext.h | 46 + + .../freescale/sdk_fman/src/inc/types_linux.h | 200 + + .../sdk_fman/src/inc/wrapper/fsl_fman_test.h | 84 + + .../sdk_fman/src/inc/wrapper/lnxwrp_exp_sym.h | 127 + + .../sdk_fman/src/inc/wrapper/lnxwrp_fm_ext.h | 163 + + .../sdk_fman/src/inc/wrapper/lnxwrp_fsl_fman.h | 919 +++ + .../ethernet/freescale/sdk_fman/src/inc/xx/xx.h | 50 + + .../freescale/sdk_fman/src/system/Makefile | 10 + + .../freescale/sdk_fman/src/system/sys_io.c | 171 + + .../freescale/sdk_fman/src/wrapper/Makefile | 19 + + .../freescale/sdk_fman/src/wrapper/fman_test.c | 1665 +++++ + .../freescale/sdk_fman/src/wrapper/lnxwrp_fm.c | 2753 +++++++ + .../freescale/sdk_fman/src/wrapper/lnxwrp_fm.h | 294 + + .../sdk_fman/src/wrapper/lnxwrp_fm_port.c | 1424 ++++ + .../sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c | 4799 +++++++++++++ + .../sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.c | 1296 ++++ + .../sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.h | 755 ++ + .../sdk_fman/src/wrapper/lnxwrp_resources.h | 121 + + .../sdk_fman/src/wrapper/lnxwrp_resources_ut.c | 191 + + .../sdk_fman/src/wrapper/lnxwrp_resources_ut.h | 144 + + .../sdk_fman/src/wrapper/lnxwrp_resources_ut.make | 28 + + .../freescale/sdk_fman/src/wrapper/lnxwrp_sysfs.c | 60 + + .../freescale/sdk_fman/src/wrapper/lnxwrp_sysfs.h | 60 + + .../sdk_fman/src/wrapper/lnxwrp_sysfs_fm.c | 1855 +++++ + .../sdk_fman/src/wrapper/lnxwrp_sysfs_fm.h | 136 + + .../sdk_fman/src/wrapper/lnxwrp_sysfs_fm_port.c | 1255 ++++ + .../sdk_fman/src/wrapper/lnxwrp_sysfs_fm_port.h | 56 + + .../ethernet/freescale/sdk_fman/src/xx/Makefile | 11 + + .../freescale/sdk_fman/src/xx/module_strings.c | 45 + + .../ethernet/freescale/sdk_fman/src/xx/udivdi3.c | 132 + + .../ethernet/freescale/sdk_fman/src/xx/xx_linux.c | 887 +++ + include/uapi/linux/fmd/Kbuild | 5 + + include/uapi/linux/fmd/Peripherals/Kbuild | 4 + + include/uapi/linux/fmd/Peripherals/fm_ioctls.h | 628 ++ + include/uapi/linux/fmd/Peripherals/fm_pcd_ioctls.h | 3084 ++++++++ + .../uapi/linux/fmd/Peripherals/fm_port_ioctls.h | 948 +++ + .../uapi/linux/fmd/Peripherals/fm_test_ioctls.h | 208 + + include/uapi/linux/fmd/integrations/Kbuild | 1 + + .../linux/fmd/integrations/integration_ioctls.h | 56 + + include/uapi/linux/fmd/ioctls.h | 96 + + include/uapi/linux/fmd/net_ioctls.h | 430 ++ + 194 files changed, 113444 insertions(+) + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Kconfig + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Makefile + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/HC/Makefile + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/HC/hc.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/Makefile + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec_mii_acc.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec_mii_acc.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fm_mac.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fm_mac.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_crc32.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_crc32.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_dtsec.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_dtsec_mii_acc.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_memac.c + create mode 100755 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_memac_mii_acc.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_tgec.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/memac.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/memac.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/memac_mii_acc.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/memac_mii_acc.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/tgec.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/tgec.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/tgec_mii_acc.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/tgec_mii_acc.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/Makefile + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_guest.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_master.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_master.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_secy.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_secy.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Makefile + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/Makefile + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/crc64.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_cc.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_cc.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_kg.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_kg.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_manip.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_manip.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_pcd.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_pcd.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_pcd_ipc.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_plcr.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_plcr.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_prs.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_prs.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_replic.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_replic.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fman_kg.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fman_prs.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/Makefile + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fm_port.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fm_port.h + create mode 100755 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fm_port_dsar.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fm_port_im.c + create mode 100755 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fman_port.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Rtc/Makefile + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Rtc/fm_rtc.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Rtc/fm_rtc.h + create mode 100755 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Rtc/fman_rtc.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/SP/Makefile + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/SP/fm_sp.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/SP/fm_sp.h + create mode 100755 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/SP/fman_sp.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm_ipc.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm_muram.c + create mode 100755 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fman.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc/fm_common.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc/fm_hc.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc/fm_sp_common.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/etc/Makefile + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/etc/error.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/etc/list.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/etc/memcpy.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/etc/mm.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/etc/mm.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/etc/sprint.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/fmanv3h_dflags.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/fmanv3l_dflags.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/crc_mac_addr_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/dpaa_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_mac_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_macsec_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_muram_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_pcd_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_port_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_rtc_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_vsp_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/mii_acc_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/core_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/cores/e500v2_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/cores/ppc_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/ddr_std_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/debug_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/endian_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/enet_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/error_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/etc/list_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/etc/mem_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/etc/memcpy_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/etc/mm_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/etc/sprint_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/flib/common/arch/ppc_access.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/flib/common/general.h + create mode 100755 drivers/net/ethernet/freescale/sdk_fman/inc/flib/fman_common.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_enet.h + create mode 100755 drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_dtsec.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_dtsec_mii_acc.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_kg.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_memac.h + create mode 100755 drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_memac_mii_acc.h + create mode 100755 drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_port.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_prs.h + create mode 100755 drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_rtc.h + create mode 100755 drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_sp.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_tgec.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3H/dpaa_integration_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3H/part_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3H/part_integration_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3L/dpaa_integration_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3L/part_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3L/part_integration_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P1023/dpaa_integration_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P1023/part_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P1023/part_integration_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P3040_P4080_P5020/dpaa_integration_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P3040_P4080_P5020/part_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P3040_P4080_P5020/part_integration_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/math_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/ncsw_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/net_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/std_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/stdarg_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/stdlib_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/string_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/types_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/xx_common.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/xx_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/p1023_dflags.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/p3040_4080_5020_dflags.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/Makefile + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/inc/system/sys_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/inc/system/sys_io_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/inc/types_linux.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/inc/wrapper/fsl_fman_test.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/inc/wrapper/lnxwrp_exp_sym.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/inc/wrapper/lnxwrp_fm_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/inc/wrapper/lnxwrp_fsl_fman.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/inc/xx/xx.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/system/Makefile + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/system/sys_io.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/Makefile + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/fman_test.c + create mode 100755 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm_port.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_resources.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_resources_ut.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_resources_ut.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_resources_ut.make + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs_fm.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs_fm.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs_fm_port.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs_fm_port.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/xx/Makefile + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/xx/module_strings.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/xx/udivdi3.c + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/xx/xx_linux.c + create mode 100644 include/uapi/linux/fmd/Kbuild + create mode 100644 include/uapi/linux/fmd/Peripherals/Kbuild + create mode 100644 include/uapi/linux/fmd/Peripherals/fm_ioctls.h + create mode 100644 include/uapi/linux/fmd/Peripherals/fm_pcd_ioctls.h + create mode 100644 include/uapi/linux/fmd/Peripherals/fm_port_ioctls.h + create mode 100644 include/uapi/linux/fmd/Peripherals/fm_test_ioctls.h + create mode 100644 include/uapi/linux/fmd/integrations/Kbuild + create mode 100644 include/uapi/linux/fmd/integrations/integration_ioctls.h + create mode 100644 include/uapi/linux/fmd/ioctls.h + create mode 100644 include/uapi/linux/fmd/net_ioctls.h + +diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig +index e383dba..536662c 100644 +--- a/drivers/net/ethernet/freescale/Kconfig ++++ b/drivers/net/ethernet/freescale/Kconfig +@@ -93,4 +93,5 @@ config GIANFAR + and MPC86xx family of chips, the eTSEC on LS1021A and the FEC + on the 8540. + ++source "drivers/net/ethernet/freescale/sdk_fman/Kconfig" + endif # NET_VENDOR_FREESCALE +diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile +index 71debd1..aa64c4e 100644 +--- a/drivers/net/ethernet/freescale/Makefile ++++ b/drivers/net/ethernet/freescale/Makefile +@@ -17,3 +17,4 @@ gianfar_driver-objs := gianfar.o \ + gianfar_ethtool.o + obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o + ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o ++obj-$(if $(CONFIG_FSL_SDK_FMAN),y) += sdk_fman/ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Kconfig b/drivers/net/ethernet/freescale/sdk_fman/Kconfig +new file mode 100644 +index 0000000..e56e3ec +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Kconfig +@@ -0,0 +1,146 @@ ++menu "Frame Manager support" ++ ++menuconfig FSL_SDK_FMAN ++ bool "Freescale Frame Manager (datapath) support - SDK driver" ++ depends on FSL_SOC && FSL_BMAN && FSL_QMAN ++ default y ++ ---help--- ++ If unsure, say Y. ++ ++if FSL_SDK_FMAN ++ ++config FSL_SDK_FMAN_TEST ++ bool "FMan test module" ++ default n ++ select FSL_DPAA_HOOKS ++ ---help--- ++ This option compiles test code for FMan. ++ ++menu "FMAN Processor support" ++choice ++ depends on FSL_SDK_FMAN ++ prompt "Processor Type" ++ ++config FMAN_P3040_P4080_P5020 ++ bool "P3040 P4080 5020" ++ ++config FMAN_P1023 ++ bool "P1023" ++ ++config FMAN_V3H ++ bool "FmanV3H" ++ ---help--- ++ Choose "FmanV3H" for Fman rev3H: ++ B4860, T4240, T4160, etc ++ ++config FMAN_V3L ++ bool "FmanV3L" ++ ---help--- ++ Choose "FmanV3L" for Fman rev3L: ++ T1040, T1042, T1020, T1022, T1023, T1024, etc ++ ++endchoice ++endmenu ++ ++config FMAN_MIB_CNT_OVF_IRQ_EN ++ bool "Enable the dTSEC MIB counters overflow interrupt" ++ default n ++ ---help--- ++ Enable the dTSEC MIB counters overflow interrupt to get ++ accurate MIB counters values. Enabled it compensates ++ for the counters overflow but reduces performance and ++ triggers error messages in HV setups. ++ ++config FSL_FM_MAX_FRAME_SIZE ++ int "Maximum L2 frame size" ++ depends on FSL_SDK_FMAN ++ range 64 9600 ++ default "1522" ++ help ++ Configure this in relation to the maximum possible MTU of your ++ network configuration. In particular, one would need to ++ increase this value in order to use jumbo frames. ++ FSL_FM_MAX_FRAME_SIZE must accommodate the Ethernet FCS (4 bytes) ++ and one ETH+VLAN header (18 bytes), to a total of 22 bytes in ++ excess of the desired L3 MTU. ++ ++ Note that having too large a FSL_FM_MAX_FRAME_SIZE (much larger ++ than the actual MTU) may lead to buffer exhaustion, especially ++ in the case of badly fragmented datagrams on the Rx path. ++ Conversely, having a FSL_FM_MAX_FRAME_SIZE smaller than the actual ++ MTU will lead to frames being dropped. ++ ++ This can be overridden by specifying "fsl_fm_max_frm" in ++ the kernel bootargs: ++ * in Hypervisor-based scenarios, by adding a "chosen" node ++ with the "bootargs" property specifying ++ "fsl_fm_max_frm="; ++ * in non-Hypervisor-based scenarios, via u-boot's env, by ++ modifying the "bootargs" env variable. ++ ++config FSL_FM_RX_EXTRA_HEADROOM ++ int "Add extra headroom at beginning of data buffers" ++ depends on FSL_SDK_FMAN ++ range 16 384 ++ default "64" ++ help ++ Configure this to tell the Frame Manager to reserve some extra ++ space at the beginning of a data buffer on the receive path, ++ before Internal Context fields are copied. This is in addition ++ to the private data area already reserved for driver internal ++ use. The provided value must be a multiple of 16. ++ ++ This setting can be overridden by specifying ++ "fsl_fm_rx_extra_headroom" in the kernel bootargs: ++ * in Hypervisor-based scenarios, by adding a "chosen" node ++ with the "bootargs" property specifying ++ "fsl_fm_rx_extra_headroom="; ++ * in non-Hypervisor-based scenarios, via u-boot's env, by ++ modifying the "bootargs" env variable. ++ ++config FMAN_PFC ++ bool "FMan PFC support (EXPERIMENTAL)" ++ depends on ( FMAN_V3H || FMAN_V3L ) && FSL_SDK_FMAN ++ default n ++ ---help--- ++ This option enables PFC support on FMan v3 ports. ++ Data Center Bridging defines Classes of Service that are ++ flow-controlled using PFC pause frames. ++ ++if FMAN_PFC ++config FMAN_PFC_COS_COUNT ++ int "Number of PFC Classes of Service" ++ depends on FMAN_PFC && FSL_SDK_FMAN ++ range 1 4 ++ default "3" ++ ---help --- ++ The number of Classes of Service controlled by PFC. ++ ++config FMAN_PFC_QUANTA_0 ++ int "The pause quanta for PFC CoS 0" ++ depends on FMAN_PFC && FSL_SDK_FMAN ++ range 0 65535 ++ default "65535" ++ ++config FMAN_PFC_QUANTA_1 ++ int "The pause quanta for PFC CoS 1" ++ depends on FMAN_PFC && FSL_SDK_FMAN ++ range 0 65535 ++ default "65535" ++ ++config FMAN_PFC_QUANTA_2 ++ int "The pause quanta for PFC CoS 2" ++ depends on FMAN_PFC && FSL_SDK_FMAN ++ range 0 65535 ++ default "65535" ++ ++config FMAN_PFC_QUANTA_3 ++ int "The pause quanta for PFC CoS 3" ++ depends on FMAN_PFC && FSL_SDK_FMAN ++ range 0 65535 ++ default "65535" ++endif ++ ++endif # FSL_SDK_FMAN ++ ++endmenu +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Makefile b/drivers/net/ethernet/freescale/sdk_fman/Makefile +new file mode 100644 +index 0000000..25ce7e6 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Makefile +@@ -0,0 +1,11 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++ccflags-y += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk ++# ++obj-y += etc/ ++obj-y += Peripherals/FM/ ++obj-y += src/ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/HC/Makefile b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/HC/Makefile +new file mode 100644 +index 0000000..d0e7672 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/HC/Makefile +@@ -0,0 +1,15 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++ccflags-y += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk ++ ++NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc ++ ++ccflags-y += -I$(NCSW_FM_INC) ++ ++obj-y += fsl-ncsw-Hc.o ++ ++fsl-ncsw-Hc-objs := hc.o +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/HC/hc.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/HC/hc.c +new file mode 100644 +index 0000000..363c8f9 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/HC/hc.c +@@ -0,0 +1,1232 @@ ++/* ++ * Copyright 2008-2012 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 "std_ext.h" ++#include "error_ext.h" ++#include "sprint_ext.h" ++#include "string_ext.h" ++ ++#include "fm_common.h" ++#include "fm_hc.h" ++ ++ ++/**************************************************************************//** ++ @Description defaults ++*//***************************************************************************/ ++#define DEFAULT_dataMemId 0 ++ ++#define HC_HCOR_OPCODE_PLCR_PRFL 0x0 ++#define HC_HCOR_OPCODE_KG_SCM 0x1 ++#define HC_HCOR_OPCODE_SYNC 0x2 ++#define HC_HCOR_OPCODE_CC 0x3 ++#define HC_HCOR_OPCODE_CC_AGE_MASK 0x4 ++#define HC_HCOR_OPCODE_CC_CAPWAP_REASSM_TIMEOUT 0x5 ++#define HC_HCOR_OPCODE_CC_REASSM_TIMEOUT 0x10 ++#define HC_HCOR_OPCODE_CC_IP_FRAG_INITIALIZATION 0x11 ++#define HC_HCOR_OPCODE_CC_UPDATE_WITH_AGING 0x13 ++#define HC_HCOR_ACTION_REG_REASSM_TIMEOUT_ACTIVE_SHIFT 24 ++#define HC_HCOR_EXTRA_REG_REASSM_TIMEOUT_TSBS_SHIFT 24 ++#define HC_HCOR_EXTRA_REG_CC_AGING_ADD 0x80000000 ++#define HC_HCOR_EXTRA_REG_CC_AGING_REMOVE 0x40000000 ++#define HC_HCOR_EXTRA_REG_CC_AGING_CHANGE_MASK 0xC0000000 ++#define HC_HCOR_EXTRA_REG_CC_REMOVE_INDX_SHIFT 24 ++#define HC_HCOR_EXTRA_REG_CC_REMOVE_INDX_MASK 0x1F000000 ++#define HC_HCOR_ACTION_REG_REASSM_TIMEOUT_RES_SHIFT 16 ++#define HC_HCOR_ACTION_REG_REASSM_TIMEOUT_RES_MASK 0xF ++#define HC_HCOR_ACTION_REG_IP_FRAG_SCRATCH_POOL_CMD_SHIFT 24 ++#define HC_HCOR_ACTION_REG_IP_FRAG_SCRATCH_POOL_BPID 16 ++ ++#define HC_HCOR_GBL 0x20000000 ++ ++#define HC_HCOR_KG_SCHEME_COUNTER 0x00000400 ++ ++#if (DPAA_VERSION == 10) ++#define HC_HCOR_KG_SCHEME_REGS_MASK 0xFFFFF800 ++#else ++#define HC_HCOR_KG_SCHEME_REGS_MASK 0xFFFFFE00 ++#endif /* (DPAA_VERSION == 10) */ ++ ++#define SIZE_OF_HC_FRAME_PORT_REGS (sizeof(t_HcFrame)-sizeof(struct fman_kg_scheme_regs)+sizeof(t_FmPcdKgPortRegs)) ++#define SIZE_OF_HC_FRAME_SCHEME_REGS sizeof(t_HcFrame) ++#define SIZE_OF_HC_FRAME_PROFILES_REGS (sizeof(t_HcFrame)-sizeof(struct fman_kg_scheme_regs)+sizeof(t_FmPcdPlcrProfileRegs)) ++#define SIZE_OF_HC_FRAME_PROFILE_CNT (sizeof(t_HcFrame)-sizeof(t_FmPcdPlcrProfileRegs)+sizeof(uint32_t)) ++#define SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC 16 ++ ++#define HC_CMD_POOL_SIZE (INTG_MAX_NUM_OF_CORES) ++ ++#define BUILD_FD(len) \ ++do { \ ++ memset(&fmFd, 0, sizeof(t_DpaaFD)); \ ++ DPAA_FD_SET_ADDR(&fmFd, p_HcFrame); \ ++ DPAA_FD_SET_OFFSET(&fmFd, 0); \ ++ DPAA_FD_SET_LENGTH(&fmFd, len); \ ++} while (0) ++ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++typedef struct t_FmPcdKgPortRegs { ++ volatile uint32_t spReg; ++ volatile uint32_t cppReg; ++} t_FmPcdKgPortRegs; ++ ++typedef struct t_HcFrame { ++ volatile uint32_t opcode; ++ volatile uint32_t actionReg; ++ volatile uint32_t extraReg; ++ volatile uint32_t commandSequence; ++ union { ++ struct fman_kg_scheme_regs schemeRegs; ++ struct fman_kg_scheme_regs schemeRegsWithoutCounter; ++ t_FmPcdPlcrProfileRegs profileRegs; ++ volatile uint32_t singleRegForWrite; /* for writing SP, CPP, profile counter */ ++ t_FmPcdKgPortRegs portRegsForRead; ++ volatile uint32_t clsPlanEntries[CLS_PLAN_NUM_PER_GRP]; ++ t_FmPcdCcCapwapReassmTimeoutParams ccCapwapReassmTimeout; ++ t_FmPcdCcReassmTimeoutParams ccReassmTimeout; ++ } hcSpecificData; ++} t_HcFrame; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++typedef struct t_FmHc { ++ t_Handle h_FmPcd; ++ t_Handle h_HcPortDev; ++ t_FmPcdQmEnqueueCallback *f_QmEnqueue; /**< A callback for enqueuing frames to the QM */ ++ t_Handle h_QmArg; /**< A handle to the QM module */ ++ uint8_t dataMemId; /**< Memory partition ID for data buffers */ ++ ++ uint32_t seqNum[HC_CMD_POOL_SIZE]; /* FIFO of seqNum to use when ++ taking buffer */ ++ uint32_t nextSeqNumLocation; /* seqNum location in seqNum[] for next buffer */ ++ volatile bool enqueued[HC_CMD_POOL_SIZE]; /* HC is active - frame is enqueued ++ and not confirmed yet */ ++ t_HcFrame *p_Frm[HC_CMD_POOL_SIZE]; ++} t_FmHc; ++ ++ ++static t_Error FillBufPool(t_FmHc *p_FmHc) ++{ ++ uint32_t i; ++ ++ ASSERT_COND(p_FmHc); ++ ++ for (i = 0; i < HC_CMD_POOL_SIZE; i++) ++ { ++#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 ++ p_FmHc->p_Frm[i] = (t_HcFrame *)XX_MallocSmart((sizeof(t_HcFrame) + (16 - (sizeof(t_FmHc) % 16))), ++ p_FmHc->dataMemId, ++ 16); ++#else ++ p_FmHc->p_Frm[i] = (t_HcFrame *)XX_MallocSmart(sizeof(t_HcFrame), ++ p_FmHc->dataMemId, ++ 16); ++#endif /* FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 */ ++ if (!p_FmHc->p_Frm[i]) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM HC frames!")); ++ } ++ ++ /* Initialize FIFO of seqNum to use during GetBuf */ ++ for (i = 0; i < HC_CMD_POOL_SIZE; i++) ++ { ++ p_FmHc->seqNum[i] = i; ++ } ++ p_FmHc->nextSeqNumLocation = 0; ++ ++ return E_OK; ++} ++ ++static __inline__ t_HcFrame * GetBuf(t_FmHc *p_FmHc, uint32_t *p_SeqNum) ++{ ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_FmHc); ++ ++ intFlags = FmPcdLock(p_FmHc->h_FmPcd); ++ ++ if (p_FmHc->nextSeqNumLocation == HC_CMD_POOL_SIZE) ++ { ++ /* No more buffers */ ++ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags); ++ return NULL; ++ } ++ ++ *p_SeqNum = p_FmHc->seqNum[p_FmHc->nextSeqNumLocation]; ++ p_FmHc->nextSeqNumLocation++; ++ ++ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags); ++ return p_FmHc->p_Frm[*p_SeqNum]; ++} ++ ++static __inline__ void PutBuf(t_FmHc *p_FmHc, t_HcFrame *p_Buf, uint32_t seqNum) ++{ ++ uint32_t intFlags; ++ ++ UNUSED(p_Buf); ++ ++ intFlags = FmPcdLock(p_FmHc->h_FmPcd); ++ ASSERT_COND(p_FmHc->nextSeqNumLocation); ++ p_FmHc->nextSeqNumLocation--; ++ p_FmHc->seqNum[p_FmHc->nextSeqNumLocation] = seqNum; ++ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags); ++} ++ ++static __inline__ t_Error EnQFrm(t_FmHc *p_FmHc, t_DpaaFD *p_FmFd, uint32_t seqNum) ++{ ++ t_Error err = E_OK; ++ uint32_t intFlags; ++ uint32_t timeout=100; ++ ++ intFlags = FmPcdLock(p_FmHc->h_FmPcd); ++ ASSERT_COND(!p_FmHc->enqueued[seqNum]); ++ p_FmHc->enqueued[seqNum] = TRUE; ++ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags); ++ DBG(TRACE, ("Send Hc, SeqNum %d, buff at 0x%x, fd offset 0x%x", ++ seqNum, ++ DPAA_FD_GET_ADDR(p_FmFd), ++ DPAA_FD_GET_OFFSET(p_FmFd))); ++ err = p_FmHc->f_QmEnqueue(p_FmHc->h_QmArg, (void *)p_FmFd); ++ if (err) ++ RETURN_ERROR(MINOR, err, ("HC enqueue failed")); ++ ++ while (p_FmHc->enqueued[seqNum] && --timeout) ++ XX_UDelay(100); ++ ++ if (!timeout) ++ RETURN_ERROR(MINOR, E_TIMEOUT, ("HC Callback, timeout exceeded")); ++ ++ return err; ++} ++ ++ ++t_Handle FmHcConfigAndInit(t_FmHcParams *p_FmHcParams) ++{ ++ t_FmHc *p_FmHc; ++ t_FmPortParams fmPortParam; ++ t_Error err; ++ ++ p_FmHc = (t_FmHc *)XX_Malloc(sizeof(t_FmHc)); ++ if (!p_FmHc) ++ { ++ REPORT_ERROR(MINOR, E_NO_MEMORY, ("HC obj")); ++ return NULL; ++ } ++ memset(p_FmHc,0,sizeof(t_FmHc)); ++ ++ p_FmHc->h_FmPcd = p_FmHcParams->h_FmPcd; ++ p_FmHc->f_QmEnqueue = p_FmHcParams->params.f_QmEnqueue; ++ p_FmHc->h_QmArg = p_FmHcParams->params.h_QmArg; ++ p_FmHc->dataMemId = DEFAULT_dataMemId; ++ ++ err = FillBufPool(p_FmHc); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ FmHcFree(p_FmHc); ++ return NULL; ++ } ++ ++ if (!FmIsMaster(p_FmHcParams->h_Fm)) ++ return (t_Handle)p_FmHc; ++ ++ memset(&fmPortParam, 0, sizeof(fmPortParam)); ++ fmPortParam.baseAddr = p_FmHcParams->params.portBaseAddr; ++ fmPortParam.portType = e_FM_PORT_TYPE_OH_HOST_COMMAND; ++ fmPortParam.portId = p_FmHcParams->params.portId; ++ fmPortParam.liodnBase = p_FmHcParams->params.liodnBase; ++ fmPortParam.h_Fm = p_FmHcParams->h_Fm; ++ ++ fmPortParam.specificParams.nonRxParams.errFqid = p_FmHcParams->params.errFqid; ++ fmPortParam.specificParams.nonRxParams.dfltFqid = p_FmHcParams->params.confFqid; ++ fmPortParam.specificParams.nonRxParams.qmChannel = p_FmHcParams->params.qmChannel; ++ ++ p_FmHc->h_HcPortDev = FM_PORT_Config(&fmPortParam); ++ if (!p_FmHc->h_HcPortDev) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("FM HC port!")); ++ XX_Free(p_FmHc); ++ return NULL; ++ } ++ ++ err = FM_PORT_ConfigMaxFrameLength(p_FmHc->h_HcPortDev, ++ (uint16_t)sizeof(t_HcFrame)); ++ ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MAJOR, err, ("FM HC port init!")); ++ FmHcFree(p_FmHc); ++ return NULL; ++ } ++ ++ /* final init */ ++ err = FM_PORT_Init(p_FmHc->h_HcPortDev); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MAJOR, err, ("FM HC port init!")); ++ FmHcFree(p_FmHc); ++ return NULL; ++ } ++ ++ err = FM_PORT_Enable(p_FmHc->h_HcPortDev); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MAJOR, err, ("FM HC port enable!")); ++ FmHcFree(p_FmHc); ++ return NULL; ++ } ++ ++ return (t_Handle)p_FmHc; ++} ++ ++void FmHcFree(t_Handle h_FmHc) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ int i; ++ ++ if (!p_FmHc) ++ return; ++ ++ for (i=0; ip_Frm[i]) ++ XX_FreeSmart(p_FmHc->p_Frm[i]); ++ else ++ break; ++ ++ if (p_FmHc->h_HcPortDev) ++ FM_PORT_Free(p_FmHc->h_HcPortDev); ++ ++ XX_Free(p_FmHc); ++} ++ ++/*****************************************************************************/ ++t_Error FmHcSetFramesDataMemory(t_Handle h_FmHc, ++ uint8_t memId) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ int i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmHc, E_INVALID_HANDLE); ++ ++ p_FmHc->dataMemId = memId; ++ ++ for (i=0; ip_Frm[i]) ++ XX_FreeSmart(p_FmHc->p_Frm[i]); ++ ++ return FillBufPool(p_FmHc); ++} ++ ++void FmHcTxConf(t_Handle h_FmHc, t_DpaaFD *p_Fd) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_FmHc); ++ ++ intFlags = FmPcdLock(p_FmHc->h_FmPcd); ++ p_HcFrame = (t_HcFrame *)PTR_MOVE(DPAA_FD_GET_ADDR(p_Fd), DPAA_FD_GET_OFFSET(p_Fd)); ++ ++ DBG(TRACE, ("Hc Conf, SeqNum %d, FD at 0x%x, fd offset 0x%x", ++ p_HcFrame->commandSequence, DPAA_FD_GET_ADDR(p_Fd), DPAA_FD_GET_OFFSET(p_Fd))); ++ ++ if (!(p_FmHc->enqueued[p_HcFrame->commandSequence])) ++ REPORT_ERROR(MINOR, E_INVALID_FRAME, ("Not an Host-Command frame received!")); ++ else ++ p_FmHc->enqueued[p_HcFrame->commandSequence] = FALSE; ++ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags); ++} ++ ++t_Error FmHcPcdKgSetScheme(t_Handle h_FmHc, ++ t_Handle h_Scheme, ++ struct fman_kg_scheme_regs *p_SchemeRegs, ++ bool updateCounter) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_Error err = E_OK; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint8_t physicalSchemeId; ++ uint32_t seqNum; ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ ++ physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme); ++ ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, updateCounter); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK; ++ memcpy(&p_HcFrame->hcSpecificData.schemeRegs, p_SchemeRegs, sizeof(struct fman_kg_scheme_regs)); ++ if (!updateCounter) ++ { ++ p_HcFrame->hcSpecificData.schemeRegs.kgse_dv0 = p_SchemeRegs->kgse_dv0; ++ p_HcFrame->hcSpecificData.schemeRegs.kgse_dv1 = p_SchemeRegs->kgse_dv1; ++ p_HcFrame->hcSpecificData.schemeRegs.kgse_ccbs = p_SchemeRegs->kgse_ccbs; ++ p_HcFrame->hcSpecificData.schemeRegs.kgse_mv = p_SchemeRegs->kgse_mv; ++ } ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FmHcPcdKgDeleteScheme(t_Handle h_FmHc, t_Handle h_Scheme) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_Error err = E_OK; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint8_t physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme); ++ uint32_t seqNum; ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, TRUE); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK; ++ memset(&p_HcFrame->hcSpecificData.schemeRegs, 0, sizeof(struct fman_kg_scheme_regs)); ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FmHcPcdKgCcGetSetParams(t_Handle h_FmHc, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_Error err = E_OK; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint8_t relativeSchemeId; ++ uint8_t physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme); ++ uint32_t tmpReg32 = 0; ++ uint32_t seqNum; ++ ++ /* Scheme is locked by calling routine */ ++ /* WARNING - this lock will not be efficient if other HC routine will attempt to change ++ * "kgse_mode" or "kgse_om" without locking scheme ! ++ */ ++ ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmHc->h_FmPcd, physicalSchemeId); ++ if ( relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ ++ if (!FmPcdKgGetRequiredActionFlag(p_FmHc->h_FmPcd, relativeSchemeId) || ++ !(FmPcdKgGetRequiredAction(p_FmHc->h_FmPcd, relativeSchemeId) & requiredAction)) ++ { ++ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) && ++ (FmPcdKgGetNextEngine(p_FmHc->h_FmPcd, relativeSchemeId) == e_FM_PCD_PLCR)) ++ { ++ if ((FmPcdKgIsDirectPlcr(p_FmHc->h_FmPcd, relativeSchemeId) == FALSE) || ++ (FmPcdKgIsDistrOnPlcrProfile(p_FmHc->h_FmPcd, relativeSchemeId) == TRUE)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("In this situation PP can not be with distribution and has to be shared")); ++ err = FmPcdPlcrCcGetSetParams(p_FmHc->h_FmPcd, FmPcdKgGetRelativeProfileId(p_FmHc->h_FmPcd, relativeSchemeId), requiredAction); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ else /* From here we deal with KG-Schemes only */ ++ { ++ /* Pre change general code */ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK; ++ p_HcFrame->commandSequence = seqNum; ++ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC); ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ /* specific change */ ++ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) && ++ ((FmPcdKgGetNextEngine(p_FmHc->h_FmPcd, relativeSchemeId) == e_FM_PCD_DONE) && ++ (FmPcdKgGetDoneAction(p_FmHc->h_FmPcd, relativeSchemeId) == e_FM_PCD_ENQ_FRAME))) ++ { ++ tmpReg32 = p_HcFrame->hcSpecificData.schemeRegs.kgse_mode; ++ ASSERT_COND(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)); ++ p_HcFrame->hcSpecificData.schemeRegs.kgse_mode = tmpReg32 | NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; ++ } ++ ++ if ((requiredAction & UPDATE_KG_NIA_CC_WA) && ++ (FmPcdKgGetNextEngine(p_FmHc->h_FmPcd, relativeSchemeId) == e_FM_PCD_CC)) ++ { ++ tmpReg32 = p_HcFrame->hcSpecificData.schemeRegs.kgse_mode; ++ ASSERT_COND(tmpReg32 & (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC)); ++ tmpReg32 &= ~NIA_FM_CTL_AC_CC; ++ p_HcFrame->hcSpecificData.schemeRegs.kgse_mode = tmpReg32 | NIA_FM_CTL_AC_PRE_CC; ++ } ++ ++ if (requiredAction & UPDATE_KG_OPT_MODE) ++ p_HcFrame->hcSpecificData.schemeRegs.kgse_om = value; ++ ++ if (requiredAction & UPDATE_KG_NIA) ++ { ++ tmpReg32 = p_HcFrame->hcSpecificData.schemeRegs.kgse_mode; ++ tmpReg32 &= ~(NIA_ENG_MASK | NIA_AC_MASK); ++ tmpReg32 |= value; ++ p_HcFrame->hcSpecificData.schemeRegs.kgse_mode = tmpReg32; ++ } ++ ++ /* Post change general code */ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ } ++ ++ return E_OK; ++} ++ ++uint32_t FmHcPcdKgGetSchemeCounter(t_Handle h_FmHc, t_Handle h_Scheme) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_Error err; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint32_t retVal; ++ uint8_t relativeSchemeId; ++ uint8_t physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme); ++ uint32_t seqNum; ++ ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmHc->h_FmPcd, physicalSchemeId); ++ if ( relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ return 0; ++ } ++ ++ /* first read scheme and check that it is valid */ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ { ++ REPORT_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ return 0; ++ } ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ if (err != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return 0; ++ } ++ ++ if (!FmPcdKgHwSchemeIsValid(p_HcFrame->hcSpecificData.schemeRegs.kgse_mode)) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is invalid")); ++ return 0; ++ } ++ ++ retVal = p_HcFrame->hcSpecificData.schemeRegs.kgse_spc; ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ return retVal; ++} ++ ++t_Error FmHcPcdKgSetSchemeCounter(t_Handle h_FmHc, t_Handle h_Scheme, uint32_t value) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_Error err = E_OK; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint8_t relativeSchemeId, physicalSchemeId; ++ uint32_t seqNum; ++ ++ physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme); ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmHc->h_FmPcd, physicalSchemeId); ++ if ( relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ ++ /* first read scheme and check that it is valid */ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, TRUE); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_COUNTER; ++ /* write counter */ ++ p_HcFrame->hcSpecificData.singleRegForWrite = value; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ return err; ++} ++ ++t_Error FmHcPcdKgSetClsPlan(t_Handle h_FmHc, t_FmPcdKgInterModuleClsPlanSet *p_Set) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint8_t i, idx; ++ uint32_t seqNum; ++ t_Error err = E_OK; ++ ++ ASSERT_COND(p_FmHc); ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ ++ for (i = p_Set->baseEntry; i < (p_Set->baseEntry+p_Set->numOfClsPlanEntries); i+=8) ++ { ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildWriteClsPlanBlockActionReg((uint8_t)(i / CLS_PLAN_NUM_PER_GRP)); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK; ++ ++ idx = (uint8_t)(i - p_Set->baseEntry); ++ ASSERT_COND(idx < FM_PCD_MAX_NUM_OF_CLS_PLANS); ++ memcpy(&p_HcFrame->hcSpecificData.clsPlanEntries, &p_Set->vectors[idx], CLS_PLAN_NUM_PER_GRP*sizeof(uint32_t)); ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ } ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ return err; ++} ++ ++t_Error FmHcPcdKgDeleteClsPlan(t_Handle h_FmHc, uint8_t grpId) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet; ++ ++ p_ClsPlanSet = (t_FmPcdKgInterModuleClsPlanSet *)XX_Malloc(sizeof(t_FmPcdKgInterModuleClsPlanSet)); ++ if (!p_ClsPlanSet) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Classification plan set")); ++ ++ memset(p_ClsPlanSet, 0, sizeof(t_FmPcdKgInterModuleClsPlanSet)); ++ ++ p_ClsPlanSet->baseEntry = FmPcdKgGetClsPlanGrpBase(p_FmHc->h_FmPcd, grpId); ++ p_ClsPlanSet->numOfClsPlanEntries = FmPcdKgGetClsPlanGrpSize(p_FmHc->h_FmPcd, grpId); ++ ASSERT_COND(p_ClsPlanSet->numOfClsPlanEntries <= FM_PCD_MAX_NUM_OF_CLS_PLANS); ++ ++ if (FmHcPcdKgSetClsPlan(p_FmHc, p_ClsPlanSet) != E_OK) ++ { ++ XX_Free(p_ClsPlanSet); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ } ++ ++ XX_Free(p_ClsPlanSet); ++ FmPcdKgDestroyClsPlanGrp(p_FmHc->h_FmPcd, grpId); ++ ++ return E_OK; ++} ++ ++t_Error FmHcPcdCcCapwapTimeoutReassm(t_Handle h_FmHc, t_FmPcdCcCapwapReassmTimeoutParams *p_CcCapwapReassmTimeoutParams ) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ t_Error err; ++ uint32_t seqNum; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0); ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_CC_CAPWAP_REASSM_TIMEOUT); ++ memcpy(&p_HcFrame->hcSpecificData.ccCapwapReassmTimeout, p_CcCapwapReassmTimeoutParams, sizeof(t_FmPcdCcCapwapReassmTimeoutParams)); ++ p_HcFrame->commandSequence = seqNum; ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ return err; ++} ++ ++t_Error FmHcPcdCcIpFragScratchPollCmd(t_Handle h_FmHc, bool fill, t_FmPcdCcFragScratchPoolCmdParams *p_FmPcdCcFragScratchPoolCmdParams) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ t_Error err; ++ uint32_t seqNum; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0); ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_CC_IP_FRAG_INITIALIZATION); ++ p_HcFrame->actionReg = (uint32_t)(((fill == TRUE) ? 0 : 1) << HC_HCOR_ACTION_REG_IP_FRAG_SCRATCH_POOL_CMD_SHIFT); ++ p_HcFrame->actionReg |= p_FmPcdCcFragScratchPoolCmdParams->bufferPoolId << HC_HCOR_ACTION_REG_IP_FRAG_SCRATCH_POOL_BPID; ++ if (fill == TRUE) ++ { ++ p_HcFrame->extraReg = p_FmPcdCcFragScratchPoolCmdParams->numOfBuffers; ++ } ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ p_FmPcdCcFragScratchPoolCmdParams->numOfBuffers = p_HcFrame->extraReg; ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ return E_OK; ++} ++ ++t_Error FmHcPcdCcTimeoutReassm(t_Handle h_FmHc, t_FmPcdCcReassmTimeoutParams *p_CcReassmTimeoutParams, uint8_t *p_Result) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ t_Error err; ++ uint32_t seqNum; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0); ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_CC_REASSM_TIMEOUT); ++ p_HcFrame->actionReg = (uint32_t)((p_CcReassmTimeoutParams->activate ? 0 : 1) << HC_HCOR_ACTION_REG_REASSM_TIMEOUT_ACTIVE_SHIFT); ++ p_HcFrame->extraReg = (p_CcReassmTimeoutParams->tsbs << HC_HCOR_EXTRA_REG_REASSM_TIMEOUT_TSBS_SHIFT) | p_CcReassmTimeoutParams->iprcpt; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ *p_Result = (uint8_t) ++ ((p_HcFrame->actionReg >> HC_HCOR_ACTION_REG_REASSM_TIMEOUT_RES_SHIFT) & HC_HCOR_ACTION_REG_REASSM_TIMEOUT_RES_MASK); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ return E_OK; ++} ++ ++t_Error FmHcPcdPlcrCcGetSetParams(t_Handle h_FmHc,uint16_t absoluteProfileId, uint32_t requiredAction) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ t_Error err; ++ uint32_t tmpReg32 = 0; ++ uint32_t requiredActionTmp, requiredActionFlag; ++ uint32_t seqNum; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0); ++ ++ /* Profile is locked by calling routine */ ++ /* WARNING - this lock will not be efficient if other HC routine will attempt to change ++ * "fmpl_pegnia" "fmpl_peynia" or "fmpl_pernia" without locking Profile ! ++ */ ++ ++ requiredActionTmp = FmPcdPlcrGetRequiredAction(p_FmHc->h_FmPcd, absoluteProfileId); ++ requiredActionFlag = FmPcdPlcrGetRequiredActionFlag(p_FmHc->h_FmPcd, absoluteProfileId); ++ ++ if (!requiredActionFlag || !(requiredActionTmp & requiredAction)) ++ { ++ if (requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) ++ { ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ /* first read scheme and check that it is valid */ ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL); ++ p_HcFrame->actionReg = FmPcdPlcrBuildReadPlcrActionReg(absoluteProfileId); ++ p_HcFrame->extraReg = 0x00008000; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC); ++ ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ tmpReg32 = p_HcFrame->hcSpecificData.profileRegs.fmpl_pegnia; ++ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("Next engine of this policer profile has to be assigned to FM_PCD_DONE")); ++ } ++ ++ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; ++ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL); ++ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId); ++ p_HcFrame->actionReg |= FmPcdPlcrBuildNiaProfileReg(TRUE, FALSE, FALSE); ++ p_HcFrame->extraReg = 0x00008000; ++ p_HcFrame->hcSpecificData.singleRegForWrite = tmpReg32; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_PROFILE_CNT); ++ ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ tmpReg32 = p_HcFrame->hcSpecificData.profileRegs.fmpl_peynia; ++ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE")); ++ } ++ ++ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; ++ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL); ++ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId); ++ p_HcFrame->actionReg |= FmPcdPlcrBuildNiaProfileReg(FALSE, TRUE, FALSE); ++ p_HcFrame->extraReg = 0x00008000; ++ p_HcFrame->hcSpecificData.singleRegForWrite = tmpReg32; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_PROFILE_CNT); ++ ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ tmpReg32 = p_HcFrame->hcSpecificData.profileRegs.fmpl_pernia; ++ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE")); ++ } ++ ++ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; ++ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL); ++ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId); ++ p_HcFrame->actionReg |= FmPcdPlcrBuildNiaProfileReg(FALSE, FALSE, TRUE); ++ p_HcFrame->extraReg = 0x00008000; ++ p_HcFrame->hcSpecificData.singleRegForWrite = tmpReg32; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_PROFILE_CNT); ++ ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ } ++ } ++ ++ return E_OK; ++} ++ ++t_Error FmHcPcdPlcrSetProfile(t_Handle h_FmHc, t_Handle h_Profile, t_FmPcdPlcrProfileRegs *p_PlcrRegs) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_Error err = E_OK; ++ uint16_t profileIndx; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint32_t seqNum; ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ ++ profileIndx = FmPcdPlcrProfileGetAbsoluteId(h_Profile); ++ ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL); ++ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionRegs(profileIndx); ++ p_HcFrame->extraReg = 0x00008000; ++ memcpy(&p_HcFrame->hcSpecificData.profileRegs, p_PlcrRegs, sizeof(t_FmPcdPlcrProfileRegs)); ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FmHcPcdPlcrDeleteProfile(t_Handle h_FmHc, t_Handle h_Profile) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ uint16_t absoluteProfileId = FmPcdPlcrProfileGetAbsoluteId(h_Profile); ++ t_Error err = E_OK; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint32_t seqNum; ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL); ++ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId); ++ p_HcFrame->actionReg |= 0x00008000; ++ p_HcFrame->extraReg = 0x00008000; ++ memset(&p_HcFrame->hcSpecificData.profileRegs, 0, sizeof(t_FmPcdPlcrProfileRegs)); ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FmHcPcdPlcrSetProfileCounter(t_Handle h_FmHc, t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter, uint32_t value) ++{ ++ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ uint16_t absoluteProfileId = FmPcdPlcrProfileGetAbsoluteId(h_Profile); ++ t_Error err = E_OK; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint32_t seqNum; ++ ++ /* first read scheme and check that it is valid */ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL); ++ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId); ++ p_HcFrame->actionReg |= FmPcdPlcrBuildCounterProfileReg(counter); ++ p_HcFrame->extraReg = 0x00008000; ++ p_HcFrame->hcSpecificData.singleRegForWrite = value; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_PROFILE_CNT); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++uint32_t FmHcPcdPlcrGetProfileCounter(t_Handle h_FmHc, t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ uint16_t absoluteProfileId = FmPcdPlcrProfileGetAbsoluteId(h_Profile); ++ t_Error err; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ uint32_t retVal = 0; ++ uint32_t seqNum; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0); ++ ++ /* first read scheme and check that it is valid */ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ { ++ REPORT_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ return 0; ++ } ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL); ++ p_HcFrame->actionReg = FmPcdPlcrBuildReadPlcrActionReg(absoluteProfileId); ++ p_HcFrame->extraReg = 0x00008000; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ if (err != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return 0; ++ } ++ ++ switch (counter) ++ { ++ case e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER: ++ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_pegpc; ++ break; ++ case e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER: ++ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_peypc; ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER: ++ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_perpc; ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER: ++ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_perypc; ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER: ++ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_perrpc; ++ break; ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ return retVal; ++} ++ ++t_Error FmHcKgWriteSp(t_Handle h_FmHc, uint8_t hardwarePortId, uint32_t spReg, bool add) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ t_Error err = E_OK; ++ uint32_t seqNum; ++ ++ ASSERT_COND(p_FmHc); ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ /* first read SP register */ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildReadPortSchemeBindActionReg(hardwarePortId); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_PORT_REGS); ++ ++ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK) ++ { ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ /* spReg is the first reg, so we can use it both for read and for write */ ++ if (add) ++ p_HcFrame->hcSpecificData.portRegsForRead.spReg |= spReg; ++ else ++ p_HcFrame->hcSpecificData.portRegsForRead.spReg &= ~spReg; ++ ++ p_HcFrame->actionReg = FmPcdKgBuildWritePortSchemeBindActionReg(hardwarePortId); ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FmHcKgWriteCpp(t_Handle h_FmHc, uint8_t hardwarePortId, uint32_t cppReg) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ t_Error err = E_OK; ++ uint32_t seqNum; ++ ++ ASSERT_COND(p_FmHc); ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ /* first read SP register */ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM); ++ p_HcFrame->actionReg = FmPcdKgBuildWritePortClsPlanBindActionReg(hardwarePortId); ++ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK; ++ p_HcFrame->hcSpecificData.singleRegForWrite = cppReg; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FmHcPcdCcDoDynamicChange(t_Handle h_FmHc, uint32_t oldAdAddrOffset, uint32_t newAdAddrOffset) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ t_Error err = E_OK; ++ uint32_t seqNum; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmHc, E_INVALID_HANDLE); ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_CC); ++ p_HcFrame->actionReg = newAdAddrOffset; ++ p_HcFrame->actionReg |= 0xc0000000; ++ p_HcFrame->extraReg = oldAdAddrOffset; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FmHcPcdSync(t_Handle h_FmHc) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ t_HcFrame *p_HcFrame; ++ t_DpaaFD fmFd; ++ t_Error err = E_OK; ++ uint32_t seqNum; ++ ++ ASSERT_COND(p_FmHc); ++ ++ p_HcFrame = GetBuf(p_FmHc, &seqNum); ++ if (!p_HcFrame) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object")); ++ memset(p_HcFrame, 0, sizeof(t_HcFrame)); ++ /* first read SP register */ ++ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_SYNC); ++ p_HcFrame->actionReg = 0; ++ p_HcFrame->extraReg = 0; ++ p_HcFrame->commandSequence = seqNum; ++ ++ BUILD_FD(sizeof(t_HcFrame)); ++ ++ err = EnQFrm(p_FmHc, &fmFd, seqNum); ++ ++ PutBuf(p_FmHc, p_HcFrame, seqNum); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Handle FmHcGetPort(t_Handle h_FmHc) ++{ ++ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; ++ return p_FmHc->h_HcPortDev; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/Makefile b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/Makefile +new file mode 100644 +index 0000000..823f6ad +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/Makefile +@@ -0,0 +1,25 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++ccflags-y += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk ++ ++NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc ++ ++ccflags-y += -I$(NCSW_FM_INC) ++ ++obj-y += fsl-ncsw-MAC.o ++ ++fsl-ncsw-MAC-objs := dtsec.o dtsec_mii_acc.o fm_mac.o tgec.o tgec_mii_acc.o \ ++ fman_dtsec.o fman_dtsec_mii_acc.o fman_memac.o \ ++ fman_tgec.o fman_crc32.o ++ ++ifeq ($(CONFIG_FMAN_V3H),y) ++fsl-ncsw-MAC-objs += memac.o memac_mii_acc.o fman_memac_mii_acc.o ++endif ++ifeq ($(CONFIG_FMAN_V3L),y) ++fsl-ncsw-MAC-objs += memac.o memac_mii_acc.o fman_memac_mii_acc.o ++endif ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec.c +new file mode 100644 +index 0000000..5ae65f8 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec.c +@@ -0,0 +1,1463 @@ ++/* ++ * Copyright 2008-2013 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. ++ */ ++ ++/****************************************************************************** ++ @File dtsec.c ++ ++ @Description FMan dTSEC driver ++*//***************************************************************************/ ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "xx_ext.h" ++#include "endian_ext.h" ++#include "debug_ext.h" ++#include "crc_mac_addr_ext.h" ++ ++#include "fm_common.h" ++#include "dtsec.h" ++#include "fsl_fman_dtsec.h" ++#include "fsl_fman_dtsec_mii_acc.h" ++ ++/*****************************************************************************/ ++/* Internal routines */ ++/*****************************************************************************/ ++ ++static t_Error CheckInitParameters(t_Dtsec *p_Dtsec) ++{ ++ if (ENET_SPEED_FROM_MODE(p_Dtsec->enetMode) >= e_ENET_SPEED_10000) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet 1G MAC driver only supports 1G or lower speeds")); ++ if (p_Dtsec->macId >= FM_MAX_NUM_OF_1G_MACS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("macId can not be greater than the number of 1G MACs")); ++ if (p_Dtsec->addr == 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC Must have a valid MAC Address")); ++ if ((ENET_SPEED_FROM_MODE(p_Dtsec->enetMode) >= e_ENET_SPEED_1000) && ++ p_Dtsec->p_DtsecDriverParam->halfdup_on) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC 1G can't work in half duplex")); ++ if (p_Dtsec->p_DtsecDriverParam->halfdup_on && (p_Dtsec->p_DtsecDriverParam)->loopback) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("LoopBack is not supported in halfDuplex mode")); ++#ifdef FM_RX_PREAM_4_ERRATA_DTSEC_A001 ++ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev <= 6) /* fixed for rev3 */ ++ if (p_Dtsec->p_DtsecDriverParam->rx_preamble) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("preambleRxEn")); ++#endif /* FM_RX_PREAM_4_ERRATA_DTSEC_A001 */ ++ if (((p_Dtsec->p_DtsecDriverParam)->tx_preamble || (p_Dtsec->p_DtsecDriverParam)->rx_preamble) &&( (p_Dtsec->p_DtsecDriverParam)->preamble_len != 0x7)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Preamble length should be 0x7 bytes")); ++ if ((p_Dtsec->p_DtsecDriverParam)->halfdup_on && ++ (p_Dtsec->p_DtsecDriverParam->tx_time_stamp_en || p_Dtsec->p_DtsecDriverParam->rx_time_stamp_en)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dTSEC in half duplex mode has to be with 1588 timeStamping diable")); ++ if ((p_Dtsec->p_DtsecDriverParam)->rx_flow && (p_Dtsec->p_DtsecDriverParam)->rx_ctrl_acc ) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Receive control frame are not passed to the system memory so it can not be accept ")); ++ if ((p_Dtsec->p_DtsecDriverParam)->rx_prepend > MAX_PACKET_ALIGNMENT) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("packetAlignmentPadding can't be greater than %d ",MAX_PACKET_ALIGNMENT )); ++ if (((p_Dtsec->p_DtsecDriverParam)->non_back_to_back_ipg1 > MAX_INTER_PACKET_GAP) || ++ ((p_Dtsec->p_DtsecDriverParam)->non_back_to_back_ipg2 > MAX_INTER_PACKET_GAP) || ++ ((p_Dtsec->p_DtsecDriverParam)->back_to_back_ipg > MAX_INTER_PACKET_GAP)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inter packet gap can't be greater than %d ",MAX_INTER_PACKET_GAP )); ++ if ((p_Dtsec->p_DtsecDriverParam)->halfdup_alt_backoff_val > MAX_INTER_PALTERNATE_BEB) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("alternateBackoffVal can't be greater than %d ",MAX_INTER_PALTERNATE_BEB )); ++ if ((p_Dtsec->p_DtsecDriverParam)->halfdup_retransmit > MAX_RETRANSMISSION) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("maxRetransmission can't be greater than %d ",MAX_RETRANSMISSION )); ++ if ((p_Dtsec->p_DtsecDriverParam)->halfdup_coll_window > MAX_COLLISION_WINDOW) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("collisionWindow can't be greater than %d ",MAX_COLLISION_WINDOW )); ++ ++ /* If Auto negotiation process is disabled, need to */ ++ /* Set up the PHY using the MII Management Interface */ ++ if (p_Dtsec->p_DtsecDriverParam->tbipa > MAX_PHYS) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("PHY address (should be 0-%d)", MAX_PHYS)); ++ if (!p_Dtsec->f_Exception) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("uninitialized f_Exception")); ++ if (!p_Dtsec->f_Event) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("uninitialized f_Event")); ++ ++#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002 ++ if (p_Dtsec->p_DtsecDriverParam->rx_len_check) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!")); ++#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */ ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static uint32_t GetMacAddrHashCode(uint64_t ethAddr) ++{ ++ uint32_t crc; ++ ++ /* CRC calculation */ ++ GET_MAC_ADDR_CRC(ethAddr, crc); ++ ++ crc = GetMirror32(crc); ++ ++ return crc; ++} ++ ++/* ......................................................................... */ ++ ++static void UpdateStatistics(t_Dtsec *p_Dtsec) ++{ ++ uint32_t car1, car2; ++ ++ fman_dtsec_get_clear_carry_regs(p_Dtsec->p_MemMap, &car1, &car2); ++ ++ if (car1) ++ { ++ if (car1 & CAR1_TR64) ++ p_Dtsec->internalStatistics.tr64 += VAL22BIT; ++ if (car1 & CAR1_TR127) ++ p_Dtsec->internalStatistics.tr127 += VAL22BIT; ++ if (car1 & CAR1_TR255) ++ p_Dtsec->internalStatistics.tr255 += VAL22BIT; ++ if (car1 & CAR1_TR511) ++ p_Dtsec->internalStatistics.tr511 += VAL22BIT; ++ if (car1 & CAR1_TRK1) ++ p_Dtsec->internalStatistics.tr1k += VAL22BIT; ++ if (car1 & CAR1_TRMAX) ++ p_Dtsec->internalStatistics.trmax += VAL22BIT; ++ if (car1 & CAR1_TRMGV) ++ p_Dtsec->internalStatistics.trmgv += VAL22BIT; ++ if (car1 & CAR1_RBYT) ++ p_Dtsec->internalStatistics.rbyt += (uint64_t)VAL32BIT; ++ if (car1 & CAR1_RPKT) ++ p_Dtsec->internalStatistics.rpkt += VAL22BIT; ++ if (car1 & CAR1_RMCA) ++ p_Dtsec->internalStatistics.rmca += VAL22BIT; ++ if (car1 & CAR1_RBCA) ++ p_Dtsec->internalStatistics.rbca += VAL22BIT; ++ if (car1 & CAR1_RXPF) ++ p_Dtsec->internalStatistics.rxpf += VAL16BIT; ++ if (car1 & CAR1_RALN) ++ p_Dtsec->internalStatistics.raln += VAL16BIT; ++ if (car1 & CAR1_RFLR) ++ p_Dtsec->internalStatistics.rflr += VAL16BIT; ++ if (car1 & CAR1_RCDE) ++ p_Dtsec->internalStatistics.rcde += VAL16BIT; ++ if (car1 & CAR1_RCSE) ++ p_Dtsec->internalStatistics.rcse += VAL16BIT; ++ if (car1 & CAR1_RUND) ++ p_Dtsec->internalStatistics.rund += VAL16BIT; ++ if (car1 & CAR1_ROVR) ++ p_Dtsec->internalStatistics.rovr += VAL16BIT; ++ if (car1 & CAR1_RFRG) ++ p_Dtsec->internalStatistics.rfrg += VAL16BIT; ++ if (car1 & CAR1_RJBR) ++ p_Dtsec->internalStatistics.rjbr += VAL16BIT; ++ if (car1 & CAR1_RDRP) ++ p_Dtsec->internalStatistics.rdrp += VAL16BIT; ++ } ++ if (car2) ++ { ++ if (car2 & CAR2_TFCS) ++ p_Dtsec->internalStatistics.tfcs += VAL12BIT; ++ if (car2 & CAR2_TBYT) ++ p_Dtsec->internalStatistics.tbyt += (uint64_t)VAL32BIT; ++ if (car2 & CAR2_TPKT) ++ p_Dtsec->internalStatistics.tpkt += VAL22BIT; ++ if (car2 & CAR2_TMCA) ++ p_Dtsec->internalStatistics.tmca += VAL22BIT; ++ if (car2 & CAR2_TBCA) ++ p_Dtsec->internalStatistics.tbca += VAL22BIT; ++ if (car2 & CAR2_TXPF) ++ p_Dtsec->internalStatistics.txpf += VAL16BIT; ++ if (car2 & CAR2_TDRP) ++ p_Dtsec->internalStatistics.tdrp += VAL16BIT; ++ } ++} ++ ++/* .............................................................................. */ ++ ++static uint16_t DtsecGetMaxFrameLength(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Dtsec, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE, 0); ++ ++ return fman_dtsec_get_max_frame_len(p_Dtsec->p_MemMap); ++} ++ ++/* .............................................................................. */ ++ ++static void DtsecIsr(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ uint32_t event; ++ struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap; ++ ++ /* do not handle MDIO events */ ++ event = fman_dtsec_get_event(p_DtsecMemMap, (uint32_t)(~(DTSEC_IMASK_MMRDEN | DTSEC_IMASK_MMWREN))); ++ ++ event &= fman_dtsec_get_interrupt_mask(p_DtsecMemMap); ++ ++ fman_dtsec_ack_event(p_DtsecMemMap, event); ++ ++ if (event & DTSEC_IMASK_BREN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_BAB_RX); ++ if (event & DTSEC_IMASK_RXCEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_RX_CTL); ++ if (event & DTSEC_IMASK_MSROEN) ++ UpdateStatistics(p_Dtsec); ++ if (event & DTSEC_IMASK_GTSCEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET); ++ if (event & DTSEC_IMASK_BTEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_BAB_TX); ++ if (event & DTSEC_IMASK_TXCEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_CTL); ++ if (event & DTSEC_IMASK_TXEEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_ERR); ++ if (event & DTSEC_IMASK_LCEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_LATE_COL); ++ if (event & DTSEC_IMASK_CRLEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_COL_RET_LMT); ++ if (event & DTSEC_IMASK_XFUNEN) ++ { ++#ifdef FM_TX_LOCKUP_ERRATA_DTSEC6 ++ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2) ++ { ++ uint32_t tpkt1, tmpReg1, tpkt2, tmpReg2, i; ++ /* a. Write 0x00E0_0C00 to DTSEC_ID */ ++ /* This is a read only regidter */ ++ ++ /* b. Read and save the value of TPKT */ ++ tpkt1 = GET_UINT32(p_DtsecMemMap->tpkt); ++ ++ /* c. Read the register at dTSEC address offset 0x32C */ ++ tmpReg1 = GET_UINT32(*(uint32_t*)((uint8_t*)p_DtsecMemMap + 0x32c)); ++ ++ /* d. Compare bits [9:15] to bits [25:31] of the register at address offset 0x32C. */ ++ if ((tmpReg1 & 0x007F0000) != (tmpReg1 & 0x0000007F)) ++ { ++ /* If they are not equal, save the value of this register and wait for at least ++ * MAXFRM*16 ns */ ++ XX_UDelay((uint32_t)(MIN(DtsecGetMaxFrameLength(p_Dtsec)*16/1000, 1))); ++ } ++ ++ /* e. Read and save TPKT again and read the register at dTSEC address offset ++ 0x32C again*/ ++ tpkt2 = GET_UINT32(p_DtsecMemMap->tpkt); ++ tmpReg2 = GET_UINT32(*(uint32_t*)((uint8_t*)p_DtsecMemMap + 0x32c)); ++ ++ /* f. Compare the value of TPKT saved in step b to value read in step e. Also ++ compare bits [9:15] of the register at offset 0x32C saved in step d to the value ++ of bits [9:15] saved in step e. If the two registers values are unchanged, then ++ the transmit portion of the dTSEC controller is locked up and the user should ++ proceed to the recover sequence. */ ++ if ((tpkt1 == tpkt2) && ((tmpReg1 & 0x007F0000) == (tmpReg2 & 0x007F0000))) ++ { ++ /* recover sequence */ ++ ++ /* a.Write a 1 to RCTRL[GRS]*/ ++ ++ WRITE_UINT32(p_DtsecMemMap->rctrl, GET_UINT32(p_DtsecMemMap->rctrl) | RCTRL_GRS); ++ ++ /* b.Wait until IEVENT[GRSC]=1, or at least 100 us has elapsed. */ ++ for (i = 0 ; i < 100 ; i++ ) ++ { ++ if (GET_UINT32(p_DtsecMemMap->ievent) & DTSEC_IMASK_GRSCEN) ++ break; ++ XX_UDelay(1); ++ } ++ if (GET_UINT32(p_DtsecMemMap->ievent) & DTSEC_IMASK_GRSCEN) ++ WRITE_UINT32(p_DtsecMemMap->ievent, DTSEC_IMASK_GRSCEN); ++ else ++ DBG(INFO,("Rx lockup due to dTSEC Tx lockup")); ++ ++ /* c.Write a 1 to bit n of FM_RSTC (offset 0x0CC of FPM)*/ ++ FmResetMac(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MAC_1G, p_Dtsec->fmMacControllerDriver.macId); ++ ++ /* d.Wait 4 Tx clocks (32 ns) */ ++ XX_UDelay(1); ++ ++ /* e.Write a 0 to bit n of FM_RSTC. */ ++ /* cleared by FMAN */ ++ } ++ } ++#endif /* FM_TX_LOCKUP_ERRATA_DTSEC6 */ ++ ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_FIFO_UNDRN); ++ } ++ if (event & DTSEC_IMASK_MAGEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_MAG_PCKT); ++ if (event & DTSEC_IMASK_GRSCEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET); ++ if (event & DTSEC_IMASK_TDPEEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_DATA_ERR); ++ if (event & DTSEC_IMASK_RDPEEN) ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_RX_DATA_ERR); ++ ++ /* - masked interrupts */ ++ ASSERT_COND(!(event & DTSEC_IMASK_ABRTEN)); ++ ASSERT_COND(!(event & DTSEC_IMASK_IFERREN)); ++} ++ ++static void DtsecMdioIsr(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ uint32_t event; ++ struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap; ++ ++ event = GET_UINT32(p_DtsecMemMap->ievent); ++ /* handle only MDIO events */ ++ event &= (DTSEC_IMASK_MMRDEN | DTSEC_IMASK_MMWREN); ++ if (event) ++ { ++ event &= GET_UINT32(p_DtsecMemMap->imask); ++ ++ WRITE_UINT32(p_DtsecMemMap->ievent, event); ++ ++ if (event & DTSEC_IMASK_MMRDEN) ++ p_Dtsec->f_Event(p_Dtsec->h_App, e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET); ++ if (event & DTSEC_IMASK_MMWREN) ++ p_Dtsec->f_Event(p_Dtsec->h_App, e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET); ++ } ++} ++ ++static void Dtsec1588Isr(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ uint32_t event; ++ struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap; ++ ++ if (p_Dtsec->ptpTsuEnabled) ++ { ++ event = fman_dtsec_check_and_clear_tmr_event(p_DtsecMemMap); ++ ++ if (event) ++ { ++ ASSERT_COND(event & TMR_PEVENT_TSRE); ++ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_1588_TS_RX_ERR); ++ } ++ } ++} ++ ++/* ........................................................................... */ ++ ++static void FreeInitResources(t_Dtsec *p_Dtsec) ++{ ++ if (p_Dtsec->mdioIrq != NO_IRQ) ++ { ++ XX_DisableIntr(p_Dtsec->mdioIrq); ++ XX_FreeIntr(p_Dtsec->mdioIrq); ++ } ++ FmUnregisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Dtsec->macId, e_FM_INTR_TYPE_ERR); ++ FmUnregisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Dtsec->macId, e_FM_INTR_TYPE_NORMAL); ++ ++ /* release the driver's group hash table */ ++ FreeHashTable(p_Dtsec->p_MulticastAddrHash); ++ p_Dtsec->p_MulticastAddrHash = NULL; ++ ++ /* release the driver's individual hash table */ ++ FreeHashTable(p_Dtsec->p_UnicastAddrHash); ++ p_Dtsec->p_UnicastAddrHash = NULL; ++} ++ ++/* ........................................................................... */ ++ ++static t_Error GracefulStop(t_Dtsec *p_Dtsec, e_CommMode mode) ++{ ++ struct dtsec_regs *p_MemMap; ++ ++ ASSERT_COND(p_Dtsec); ++ ++ p_MemMap = p_Dtsec->p_MemMap; ++ ASSERT_COND(p_MemMap); ++ ++ /* Assert the graceful transmit stop bit */ ++ if (mode & e_COMM_MODE_RX) ++ { ++ fman_dtsec_stop_rx(p_MemMap); ++ ++#ifdef FM_GRS_ERRATA_DTSEC_A002 ++ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2) ++ XX_UDelay(100); ++#else /* FM_GRS_ERRATA_DTSEC_A002 */ ++#ifdef FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 ++ XX_UDelay(10); ++#endif /* FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 */ ++#endif /* FM_GRS_ERRATA_DTSEC_A002 */ ++ } ++ ++ if (mode & e_COMM_MODE_TX) ++#if defined(FM_GTS_ERRATA_DTSEC_A004) || defined(FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012) ++ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2) ++ DBG(INFO, ("GTS not supported due to DTSEC_A004 errata.")); ++#else /* not defined(FM_GTS_ERRATA_DTSEC_A004) ||... */ ++#ifdef FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 ++ DBG(INFO, ("GTS not supported due to DTSEC_A0014 errata.")); ++#else /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */ ++ fman_dtsec_stop_tx(p_MemMap); ++#endif /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */ ++#endif /* defined(FM_GTS_ERRATA_DTSEC_A004) ||... */ ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error GracefulRestart(t_Dtsec *p_Dtsec, e_CommMode mode) ++{ ++ struct dtsec_regs *p_MemMap; ++ ++ ASSERT_COND(p_Dtsec); ++ p_MemMap = p_Dtsec->p_MemMap; ++ ASSERT_COND(p_MemMap); ++ ++ /* clear the graceful receive stop bit */ ++ if (mode & e_COMM_MODE_TX) ++ fman_dtsec_start_tx(p_MemMap); ++ ++ if (mode & e_COMM_MODE_RX) ++ fman_dtsec_start_rx(p_MemMap); ++ ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* dTSEC Configs modification functions */ ++/*****************************************************************************/ ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecConfigLoopback(t_Handle h_Dtsec, bool newVal) ++{ ++ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->p_DtsecDriverParam->loopback = newVal; ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecConfigMaxFrameLength(t_Handle h_Dtsec, uint16_t newVal) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->p_DtsecDriverParam->maximum_frame = newVal; ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecConfigPadAndCrc(t_Handle h_Dtsec, bool newVal) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->p_DtsecDriverParam->tx_pad_crc = newVal; ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecConfigHalfDuplex(t_Handle h_Dtsec, bool newVal) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->p_DtsecDriverParam->halfdup_on = newVal; ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecConfigTbiPhyAddr(t_Handle h_Dtsec, uint8_t newVal) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->p_DtsecDriverParam->tbi_phy_addr = newVal; ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecConfigLengthCheck(t_Handle h_Dtsec, bool newVal) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->p_DtsecDriverParam->rx_len_check = newVal; ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecConfigException(t_Handle h_Dtsec, e_FmMacExceptions exception, bool enable) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ if (exception != e_FM_MAC_EX_1G_1588_TS_RX_ERR) ++ { ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_Dtsec->exceptions |= bitMask; ++ else ++ p_Dtsec->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ } ++ else ++ { ++ if (!p_Dtsec->ptpTsuEnabled) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exception valid for 1588 only")); ++ ++ if (enable) ++ p_Dtsec->enTsuErrExeption = TRUE; ++ else ++ p_Dtsec->enTsuErrExeption = FALSE; ++ } ++ ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* dTSEC Run Time API functions */ ++/*****************************************************************************/ ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecEnable(t_Handle h_Dtsec, e_CommMode mode) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ fman_dtsec_enable(p_Dtsec->p_MemMap, ++ (bool)!!(mode & e_COMM_MODE_RX), ++ (bool)!!(mode & e_COMM_MODE_TX)); ++ ++ GracefulRestart(p_Dtsec, mode); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecDisable (t_Handle h_Dtsec, e_CommMode mode) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ GracefulStop(p_Dtsec, mode); ++ ++ fman_dtsec_disable(p_Dtsec->p_MemMap, ++ (bool)!!(mode & e_COMM_MODE_RX), ++ (bool)!!(mode & e_COMM_MODE_TX)); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecSetTxPauseFrames(t_Handle h_Dtsec, ++ uint8_t priority, ++ uint16_t pauseTime, ++ uint16_t threshTime) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ UNUSED(priority);UNUSED(threshTime); ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++#ifdef FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 ++ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2) ++ if (0 < pauseTime && pauseTime <= 320) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ++ ("This pause-time value of %d is illegal due to errata dTSEC-A003!" ++ " value should be greater than 320.")); ++#endif /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 */ ++ ++ fman_dtsec_set_tx_pause_frames(p_Dtsec->p_MemMap, pauseTime); ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++/* backward compatibility. will be removed in the future. */ ++static t_Error DtsecTxMacPause(t_Handle h_Dtsec, uint16_t pauseTime) ++{ ++ return DtsecSetTxPauseFrames(h_Dtsec, 0, pauseTime, 0); ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecRxIgnoreMacPause(t_Handle h_Dtsec, bool en) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ bool accept_pause = !en; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ fman_dtsec_handle_rx_pause(p_Dtsec->p_MemMap, accept_pause); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecEnable1588TimeStamp(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->ptpTsuEnabled = TRUE; ++ fman_dtsec_set_ts(p_Dtsec->p_MemMap, TRUE); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecDisable1588TimeStamp(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->ptpTsuEnabled = FALSE; ++ fman_dtsec_set_ts(p_Dtsec->p_MemMap, FALSE); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecGetStatistics(t_Handle h_Dtsec, t_FmMacStatistics *p_Statistics) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ struct dtsec_regs *p_DtsecMemMap; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER); ++ ++ p_DtsecMemMap = p_Dtsec->p_MemMap; ++ ++ if (p_Dtsec->statisticsLevel == e_FM_MAC_NONE_STATISTICS) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Statistics disabled")); ++ ++ memset(p_Statistics, 0xff, sizeof(t_FmMacStatistics)); ++ ++ if (p_Dtsec->statisticsLevel == e_FM_MAC_FULL_STATISTICS) ++ { ++ p_Statistics->eStatPkts64 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR64) ++ + p_Dtsec->internalStatistics.tr64; ++ p_Statistics->eStatPkts65to127 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR127) ++ + p_Dtsec->internalStatistics.tr127; ++ p_Statistics->eStatPkts128to255 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR255) ++ + p_Dtsec->internalStatistics.tr255; ++ p_Statistics->eStatPkts256to511 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR511) ++ + p_Dtsec->internalStatistics.tr511; ++ p_Statistics->eStatPkts512to1023 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR1K) ++ + p_Dtsec->internalStatistics.tr1k; ++ p_Statistics->eStatPkts1024to1518 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TRMAX) ++ + p_Dtsec->internalStatistics.trmax; ++ p_Statistics->eStatPkts1519to1522 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TRMGV) ++ + p_Dtsec->internalStatistics.trmgv; ++ ++ /* MIB II */ ++ p_Statistics->ifInOctets = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RBYT) ++ + p_Dtsec->internalStatistics.rbyt; ++ p_Statistics->ifInPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RPKT) ++ + p_Dtsec->internalStatistics.rpkt; ++ p_Statistics->ifInUcastPkts = 0; ++ p_Statistics->ifInMcastPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RMCA) ++ + p_Dtsec->internalStatistics.rmca; ++ p_Statistics->ifInBcastPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RBCA) ++ + p_Dtsec->internalStatistics.rbca; ++ p_Statistics->ifOutOctets = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TBYT) ++ + p_Dtsec->internalStatistics.tbyt; ++ p_Statistics->ifOutPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TPKT) ++ + p_Dtsec->internalStatistics.tpkt; ++ p_Statistics->ifOutUcastPkts = 0; ++ p_Statistics->ifOutMcastPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TMCA) ++ + p_Dtsec->internalStatistics.tmca; ++ p_Statistics->ifOutBcastPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TBCA) ++ + p_Dtsec->internalStatistics.tbca; ++ } ++ ++ p_Statistics->eStatFragments = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RFRG) ++ + p_Dtsec->internalStatistics.rfrg; ++ p_Statistics->eStatJabbers = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RJBR) ++ + p_Dtsec->internalStatistics.rjbr; ++ p_Statistics->eStatsDropEvents = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RDRP) ++ + p_Dtsec->internalStatistics.rdrp; ++ p_Statistics->eStatCRCAlignErrors = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RALN) ++ + p_Dtsec->internalStatistics.raln; ++ p_Statistics->eStatUndersizePkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RUND) ++ + p_Dtsec->internalStatistics.rund; ++ p_Statistics->eStatOversizePkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_ROVR) ++ + p_Dtsec->internalStatistics.rovr; ++ p_Statistics->reStatPause = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RXPF) ++ + p_Dtsec->internalStatistics.rxpf; ++ p_Statistics->teStatPause = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TXPF) ++ + p_Dtsec->internalStatistics.txpf; ++ p_Statistics->ifInDiscards = p_Statistics->eStatsDropEvents; ++ p_Statistics->ifInErrors = p_Statistics->eStatsDropEvents + p_Statistics->eStatCRCAlignErrors ++ + fman_dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RFLR) + p_Dtsec->internalStatistics.rflr ++ + fman_dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RCDE) + p_Dtsec->internalStatistics.rcde ++ + fman_dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RCSE) + p_Dtsec->internalStatistics.rcse; ++ ++ p_Statistics->ifOutDiscards = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TDRP) ++ + p_Dtsec->internalStatistics.tdrp; ++ p_Statistics->ifOutErrors = p_Statistics->ifOutDiscards /**< Number of frames transmitted with error: */ ++ + fman_dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_TFCS) ++ + p_Dtsec->internalStatistics.tfcs; ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecModifyMacAddress (t_Handle h_Dtsec, t_EnetAddr *p_EnetAddr) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ /* Initialize MAC Station Address registers (1 & 2) */ ++ /* Station address have to be swapped (big endian to little endian */ ++ p_Dtsec->addr = ENET_ADDR_TO_UINT64(*p_EnetAddr); ++ fman_dtsec_set_mac_address(p_Dtsec->p_MemMap, (uint8_t *)(*p_EnetAddr)); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecResetCounters (t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ /* clear HW counters */ ++ fman_dtsec_reset_stat(p_Dtsec->p_MemMap); ++ ++ /* clear SW counters holding carries */ ++ memset(&p_Dtsec->internalStatistics, 0, sizeof(t_InternalStatistics)); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecAddExactMatchMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *) h_Dtsec; ++ uint64_t ethAddr; ++ uint8_t paddrNum; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ if (ethAddr & GROUP_ADDRESS) ++ /* Multicast address has no effect in PADDR */ ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Multicast address")); ++ ++ /* Make sure no PADDR contains this address */ ++ for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++) ++ if (p_Dtsec->indAddrRegUsed[paddrNum]) ++ if (p_Dtsec->paddr[paddrNum] == ethAddr) ++ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG); ++ ++ /* Find first unused PADDR */ ++ for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++) ++ if (!(p_Dtsec->indAddrRegUsed[paddrNum])) ++ { ++ /* mark this PADDR as used */ ++ p_Dtsec->indAddrRegUsed[paddrNum] = TRUE; ++ /* store address */ ++ p_Dtsec->paddr[paddrNum] = ethAddr; ++ ++ /* put in hardware */ ++ fman_dtsec_add_addr_in_paddr(p_Dtsec->p_MemMap, (uint64_t)PTR_TO_UINT(ðAddr), paddrNum); ++ p_Dtsec->numOfIndAddrInRegs++; ++ ++ return E_OK; ++ } ++ ++ /* No free PADDR */ ++ RETURN_ERROR(MAJOR, E_FULL, NO_MSG); ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecDelExactMatchMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *) h_Dtsec; ++ uint64_t ethAddr; ++ uint8_t paddrNum; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ /* Find used PADDR containing this address */ ++ for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++) ++ { ++ if ((p_Dtsec->indAddrRegUsed[paddrNum]) && ++ (p_Dtsec->paddr[paddrNum] == ethAddr)) ++ { ++ /* mark this PADDR as not used */ ++ p_Dtsec->indAddrRegUsed[paddrNum] = FALSE; ++ /* clear in hardware */ ++ fman_dtsec_clear_addr_in_paddr(p_Dtsec->p_MemMap, paddrNum); ++ p_Dtsec->numOfIndAddrInRegs--; ++ ++ return E_OK; ++ } ++ } ++ ++ RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG); ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecAddHashMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ t_EthHashEntry *p_HashEntry; ++ uint64_t ethAddr; ++ int32_t bucket; ++ uint32_t crc; ++ bool mcast, ghtx; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ ghtx = (bool)((fman_dtsec_get_rctrl(p_Dtsec->p_MemMap) & RCTRL_GHTX) ? TRUE : FALSE); ++ mcast = (bool)((ethAddr & MAC_GROUP_ADDRESS) ? TRUE : FALSE); ++ ++ if (ghtx && !mcast) /* Cannot handle unicast mac addr when GHTX is on */ ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Could not compute hash bucket")); ++ ++ crc = GetMacAddrHashCode(ethAddr); ++ ++ /* considering the 9 highest order bits in crc H[8:0]: ++ * if ghtx = 0 H[8:6] (highest order 3 bits) identify the hash register ++ * and H[5:1] (next 5 bits) identify the hash bit ++ * if ghts = 1 H[8:5] (highest order 4 bits) identify the hash register ++ * and H[4:0] (next 5 bits) identify the hash bit. ++ * ++ * In bucket index output the low 5 bits identify the hash register bit, ++ * while the higher 4 bits identify the hash register ++ */ ++ ++ if (ghtx) ++ bucket = (int32_t)((crc >> 23) & 0x1ff); ++ else { ++ bucket = (int32_t)((crc >> 24) & 0xff); ++ /* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */ ++ if (mcast) ++ bucket += 0x100; ++ } ++ ++ fman_dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, TRUE); ++ ++ /* Create element to be added to the driver hash table */ ++ p_HashEntry = (t_EthHashEntry *)XX_Malloc(sizeof(t_EthHashEntry)); ++ p_HashEntry->addr = ethAddr; ++ INIT_LIST(&p_HashEntry->node); ++ ++ if (ethAddr & MAC_GROUP_ADDRESS) ++ /* Group Address */ ++ LIST_AddToTail(&(p_HashEntry->node), &(p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket])); ++ else ++ LIST_AddToTail(&(p_HashEntry->node), &(p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket])); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecDelHashMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ t_List *p_Pos; ++ t_EthHashEntry *p_HashEntry = NULL; ++ uint64_t ethAddr; ++ int32_t bucket; ++ uint32_t crc; ++ bool mcast, ghtx; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ ghtx = (bool)((fman_dtsec_get_rctrl(p_Dtsec->p_MemMap) & RCTRL_GHTX) ? TRUE : FALSE); ++ mcast = (bool)((ethAddr & MAC_GROUP_ADDRESS) ? TRUE : FALSE); ++ ++ if (ghtx && !mcast) /* Cannot handle unicast mac addr when GHTX is on */ ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Could not compute hash bucket")); ++ ++ crc = GetMacAddrHashCode(ethAddr); ++ ++ if (ghtx) ++ bucket = (int32_t)((crc >> 23) & 0x1ff); ++ else { ++ bucket = (int32_t)((crc >> 24) & 0xff); ++ /* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */ ++ if (mcast) ++ bucket += 0x100; ++ } ++ ++ if (ethAddr & MAC_GROUP_ADDRESS) ++ { ++ /* Group Address */ ++ LIST_FOR_EACH(p_Pos, &(p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket])) ++ { ++ p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos); ++ if (p_HashEntry->addr == ethAddr) ++ { ++ LIST_DelAndInit(&p_HashEntry->node); ++ XX_Free(p_HashEntry); ++ break; ++ } ++ } ++ if (LIST_IsEmpty(&p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket])) ++ fman_dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, FALSE); ++ } ++ else ++ { ++ /* Individual Address */ ++ LIST_FOR_EACH(p_Pos, &(p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket])) ++ { ++ p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos); ++ if (p_HashEntry->addr == ethAddr) ++ { ++ LIST_DelAndInit(&p_HashEntry->node); ++ XX_Free(p_HashEntry); ++ break; ++ } ++ } ++ if (LIST_IsEmpty(&p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket])) ++ fman_dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, FALSE); ++ } ++ ++ /* address does not exist */ ++ ASSERT_COND(p_HashEntry != NULL); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecSetPromiscuous(t_Handle h_Dtsec, bool newVal) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ fman_dtsec_set_uc_promisc(p_Dtsec->p_MemMap, newVal); ++ fman_dtsec_set_mc_promisc(p_Dtsec->p_MemMap, newVal); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecSetStatistics(t_Handle h_Dtsec, e_FmMacStatisticsLevel statisticsLevel) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->statisticsLevel = statisticsLevel; ++ ++ err = (t_Error)fman_dtsec_set_stat_level(p_Dtsec->p_MemMap, ++ (enum dtsec_stat_level)statisticsLevel); ++ if (err != E_OK) ++ return err; ++ ++ switch (statisticsLevel) ++ { ++ case (e_FM_MAC_NONE_STATISTICS): ++ p_Dtsec->exceptions &= ~DTSEC_IMASK_MSROEN; ++ break; ++ case (e_FM_MAC_PARTIAL_STATISTICS): ++ p_Dtsec->exceptions |= DTSEC_IMASK_MSROEN; ++ break; ++ case (e_FM_MAC_FULL_STATISTICS): ++ p_Dtsec->exceptions |= DTSEC_IMASK_MSROEN; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecSetWakeOnLan(t_Handle h_Dtsec, bool en) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ fman_dtsec_set_wol(p_Dtsec->p_MemMap, en); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecAdjustLink(t_Handle h_Dtsec, e_EnetSpeed speed, bool fullDuplex) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ int err; ++ enum enet_interface enet_interface; ++ enum enet_speed enet_speed; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ p_Dtsec->enetMode = MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode), speed); ++ enet_interface = (enum enet_interface) ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode); ++ enet_speed = (enum enet_speed) ENET_SPEED_FROM_MODE(p_Dtsec->enetMode); ++ p_Dtsec->halfDuplex = !fullDuplex; ++ ++ err = fman_dtsec_adjust_link(p_Dtsec->p_MemMap, enet_interface, enet_speed, fullDuplex); ++ ++ if (err == -EINVAL) ++ RETURN_ERROR(MAJOR, E_CONFLICT, ("Ethernet interface does not support Half Duplex mode")); ++ ++ return (t_Error)err; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecRestartAutoneg(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ uint16_t tmpReg16; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ DTSEC_MII_ReadPhyReg(p_Dtsec, p_Dtsec->tbi_phy_addr, 0, &tmpReg16); ++ ++ tmpReg16 &= ~( PHY_CR_SPEED0 | PHY_CR_SPEED1 ); ++ tmpReg16 |= (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1); ++ ++ DTSEC_MII_WritePhyReg(p_Dtsec, p_Dtsec->tbi_phy_addr, 0, tmpReg16); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecGetId(t_Handle h_Dtsec, uint32_t *macId) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ *macId = p_Dtsec->macId; ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecGetVersion(t_Handle h_Dtsec, uint32_t *macVersion) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ *macVersion = fman_dtsec_get_revision(p_Dtsec->p_MemMap); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecSetException(t_Handle h_Dtsec, e_FmMacExceptions exception, bool enable) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ ++ if (exception != e_FM_MAC_EX_1G_1588_TS_RX_ERR) ++ { ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_Dtsec->exceptions |= bitMask; ++ else ++ p_Dtsec->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ if (enable) ++ fman_dtsec_enable_interrupt(p_Dtsec->p_MemMap, bitMask); ++ else ++ fman_dtsec_disable_interrupt(p_Dtsec->p_MemMap, bitMask); ++ } ++ else ++ { ++ if (!p_Dtsec->ptpTsuEnabled) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exception valid for 1588 only")); ++ ++ if (enable) ++ { ++ p_Dtsec->enTsuErrExeption = TRUE; ++ fman_dtsec_enable_tmr_interrupt(p_Dtsec->p_MemMap); ++ } ++ else ++ { ++ p_Dtsec->enTsuErrExeption = FALSE; ++ fman_dtsec_disable_tmr_interrupt(p_Dtsec->p_MemMap); ++ } ++ } ++ ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* dTSEC Init & Free API */ ++/*****************************************************************************/ ++ ++/* .............................................................................. */ ++ ++static t_Error DtsecInit(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ struct dtsec_cfg *p_DtsecDriverParam; ++ t_Error err; ++ uint16_t maxFrmLn; ++ enum enet_interface enet_interface; ++ enum enet_speed enet_speed; ++ t_EnetAddr ethAddr; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE); ++ ++ FM_GetRevision(p_Dtsec->fmMacControllerDriver.h_Fm, &p_Dtsec->fmMacControllerDriver.fmRevInfo); ++ CHECK_INIT_PARAMETERS(p_Dtsec, CheckInitParameters); ++ ++ p_DtsecDriverParam = p_Dtsec->p_DtsecDriverParam; ++ p_Dtsec->halfDuplex = p_DtsecDriverParam->halfdup_on; ++ ++ enet_interface = (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode); ++ enet_speed = (enum enet_speed)ENET_SPEED_FROM_MODE(p_Dtsec->enetMode); ++ MAKE_ENET_ADDR_FROM_UINT64(p_Dtsec->addr, ethAddr); ++ ++ err = (t_Error)fman_dtsec_init(p_Dtsec->p_MemMap, ++ p_DtsecDriverParam, ++ enet_interface, ++ enet_speed, ++ (uint8_t*)ethAddr, ++ p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev, ++ p_Dtsec->fmMacControllerDriver.fmRevInfo.minorRev, ++ p_Dtsec->exceptions); ++ if (err) ++ { ++ FreeInitResources(p_Dtsec); ++ RETURN_ERROR(MAJOR, err, ("This DTSEC version does not support the required i/f mode")); ++ } ++ ++ if (ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode) == e_ENET_IF_SGMII) ++ { ++ uint16_t tmpReg16; ++ ++ /* Configure the TBI PHY Control Register */ ++ tmpReg16 = PHY_TBICON_CLK_SEL | PHY_TBICON_SRESET; ++ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 17, tmpReg16); ++ ++ tmpReg16 = PHY_TBICON_CLK_SEL; ++ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 17, tmpReg16); ++ ++ tmpReg16 = (PHY_CR_PHY_RESET | PHY_CR_ANE | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1); ++ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 0, tmpReg16); ++ ++ if (p_Dtsec->enetMode & ENET_IF_SGMII_BASEX) ++ tmpReg16 = PHY_TBIANA_1000X; ++ else ++ tmpReg16 = PHY_TBIANA_SGMII; ++ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 4, tmpReg16); ++ ++ tmpReg16 = (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1); ++ ++ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 0, tmpReg16); ++ } ++ ++ /* Max Frame Length */ ++ maxFrmLn = fman_dtsec_get_max_frame_len(p_Dtsec->p_MemMap); ++ err = FmSetMacMaxFrame(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MAC_1G, ++ p_Dtsec->fmMacControllerDriver.macId, maxFrmLn); ++ if (err) ++ RETURN_ERROR(MINOR,err, NO_MSG); ++ ++ p_Dtsec->p_MulticastAddrHash = AllocHashTable(EXTENDED_HASH_TABLE_SIZE); ++ if (!p_Dtsec->p_MulticastAddrHash) { ++ FreeInitResources(p_Dtsec); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MC hash table is FAILED")); ++ } ++ ++ p_Dtsec->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE); ++ if (!p_Dtsec->p_UnicastAddrHash) ++ { ++ FreeInitResources(p_Dtsec); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("UC hash table is FAILED")); ++ } ++ ++ /* register err intr handler for dtsec to FPM (err)*/ ++ FmRegisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm, ++ e_FM_MOD_1G_MAC, ++ p_Dtsec->macId, ++ e_FM_INTR_TYPE_ERR, ++ DtsecIsr, ++ p_Dtsec); ++ /* register 1588 intr handler for TMR to FPM (normal)*/ ++ FmRegisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm, ++ e_FM_MOD_1G_MAC, ++ p_Dtsec->macId, ++ e_FM_INTR_TYPE_NORMAL, ++ Dtsec1588Isr, ++ p_Dtsec); ++ /* register normal intr handler for dtsec to main interrupt controller. */ ++ if (p_Dtsec->mdioIrq != NO_IRQ) ++ { ++ XX_SetIntr(p_Dtsec->mdioIrq, DtsecMdioIsr, p_Dtsec); ++ XX_EnableIntr(p_Dtsec->mdioIrq); ++ } ++ ++ XX_Free(p_DtsecDriverParam); ++ p_Dtsec->p_DtsecDriverParam = NULL; ++ ++ err = DtsecSetStatistics(h_Dtsec, e_FM_MAC_FULL_STATISTICS); ++ if (err) ++ { ++ FreeInitResources(p_Dtsec); ++ RETURN_ERROR(MAJOR, err, ("Undefined statistics level")); ++ } ++ ++ return E_OK; ++} ++ ++/* ........................................................................... */ ++ ++static t_Error DtsecFree(t_Handle h_Dtsec) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ ++ if (p_Dtsec->p_DtsecDriverParam) ++ { ++ /* Called after config */ ++ XX_Free(p_Dtsec->p_DtsecDriverParam); ++ p_Dtsec->p_DtsecDriverParam = NULL; ++ } ++ else ++ /* Called after init */ ++ FreeInitResources(p_Dtsec); ++ ++ XX_Free(p_Dtsec); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver) ++{ ++ p_FmMacControllerDriver->f_FM_MAC_Init = DtsecInit; ++ p_FmMacControllerDriver->f_FM_MAC_Free = DtsecFree; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetStatistics = DtsecSetStatistics; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback = DtsecConfigLoopback; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength = DtsecConfigMaxFrameLength; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigWan = NULL; /* Not supported on dTSEC */ ++ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc = DtsecConfigPadAndCrc; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex = DtsecConfigHalfDuplex; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck = DtsecConfigLengthCheck; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigTbiPhyAddr = DtsecConfigTbiPhyAddr; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigException = DtsecConfigException; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit = NULL; ++ ++ p_FmMacControllerDriver->f_FM_MAC_Enable = DtsecEnable; ++ p_FmMacControllerDriver->f_FM_MAC_Disable = DtsecDisable; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetException = DtsecSetException; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous = DtsecSetPromiscuous; ++ p_FmMacControllerDriver->f_FM_MAC_AdjustLink = DtsecAdjustLink; ++ p_FmMacControllerDriver->f_FM_MAC_SetWakeOnLan = DtsecSetWakeOnLan; ++ p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg = DtsecRestartAutoneg; ++ ++ p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp = DtsecEnable1588TimeStamp; ++ p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp = DtsecDisable1588TimeStamp; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames = DtsecTxMacPause; ++ p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames = DtsecSetTxPauseFrames; ++ p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames = DtsecRxIgnoreMacPause; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ResetCounters = DtsecResetCounters; ++ p_FmMacControllerDriver->f_FM_MAC_GetStatistics = DtsecGetStatistics; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr = DtsecModifyMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr = DtsecAddHashMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr = DtsecDelHashMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr = DtsecAddExactMatchMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr = DtsecDelExactMatchMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_GetId = DtsecGetId; ++ p_FmMacControllerDriver->f_FM_MAC_GetVersion = DtsecGetVersion; ++ p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength = DtsecGetMaxFrameLength; ++ ++ p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg = DTSEC_MII_WritePhyReg; ++ p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg = DTSEC_MII_ReadPhyReg; ++ ++} ++ ++ ++/*****************************************************************************/ ++/* dTSEC Config Main Entry */ ++/*****************************************************************************/ ++ ++/* .............................................................................. */ ++ ++t_Handle DTSEC_Config(t_FmMacParams *p_FmMacParam) ++{ ++ t_Dtsec *p_Dtsec; ++ struct dtsec_cfg *p_DtsecDriverParam; ++ uintptr_t baseAddr; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL); ++ ++ baseAddr = p_FmMacParam->baseAddr; ++ ++ /* allocate memory for the UCC GETH data structure. */ ++ p_Dtsec = (t_Dtsec *)XX_Malloc(sizeof(t_Dtsec)); ++ if (!p_Dtsec) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("dTSEC driver structure")); ++ return NULL; ++ } ++ memset(p_Dtsec, 0, sizeof(t_Dtsec)); ++ InitFmMacControllerDriver(&p_Dtsec->fmMacControllerDriver); ++ ++ /* allocate memory for the dTSEC driver parameters data structure. */ ++ p_DtsecDriverParam = (struct dtsec_cfg *) XX_Malloc(sizeof(struct dtsec_cfg)); ++ if (!p_DtsecDriverParam) ++ { ++ XX_Free(p_Dtsec); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("dTSEC driver parameters")); ++ return NULL; ++ } ++ memset(p_DtsecDriverParam, 0, sizeof(struct dtsec_cfg)); ++ ++ /* Plant parameter structure pointer */ ++ p_Dtsec->p_DtsecDriverParam = p_DtsecDriverParam; ++ ++ fman_dtsec_defconfig(p_DtsecDriverParam); ++ ++ p_Dtsec->p_MemMap = (struct dtsec_regs *)UINT_TO_PTR(baseAddr); ++ p_Dtsec->p_MiiMemMap = (struct dtsec_mii_reg *)UINT_TO_PTR(baseAddr + DTSEC_TO_MII_OFFSET); ++ p_Dtsec->addr = ENET_ADDR_TO_UINT64(p_FmMacParam->addr); ++ p_Dtsec->enetMode = p_FmMacParam->enetMode; ++ p_Dtsec->macId = p_FmMacParam->macId; ++ p_Dtsec->exceptions = DEFAULT_exceptions; ++ p_Dtsec->mdioIrq = p_FmMacParam->mdioIrq; ++ p_Dtsec->f_Exception = p_FmMacParam->f_Exception; ++ p_Dtsec->f_Event = p_FmMacParam->f_Event; ++ p_Dtsec->h_App = p_FmMacParam->h_App; ++ p_Dtsec->ptpTsuEnabled = p_Dtsec->p_DtsecDriverParam->ptp_tsu_en; ++ p_Dtsec->enTsuErrExeption = p_Dtsec->p_DtsecDriverParam->ptp_exception_en; ++ p_Dtsec->tbi_phy_addr = p_Dtsec->p_DtsecDriverParam->tbi_phy_addr; ++ ++ return p_Dtsec; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec.h +new file mode 100644 +index 0000000..c26f40c +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec.h +@@ -0,0 +1,228 @@ ++/* ++ * Copyright 2008-2013 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. ++ */ ++ ++/****************************************************************************** ++ @File dtsec.h ++ ++ @Description FM dTSEC ... ++*//***************************************************************************/ ++#ifndef __DTSEC_H ++#define __DTSEC_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++#include "enet_ext.h" ++ ++#include "dtsec_mii_acc.h" ++#include "fm_mac.h" ++ ++ ++#define DEFAULT_exceptions \ ++ ((uint32_t)(DTSEC_IMASK_BREN | \ ++ DTSEC_IMASK_RXCEN | \ ++ DTSEC_IMASK_BTEN | \ ++ DTSEC_IMASK_TXCEN | \ ++ DTSEC_IMASK_TXEEN | \ ++ DTSEC_IMASK_ABRTEN | \ ++ DTSEC_IMASK_LCEN | \ ++ DTSEC_IMASK_CRLEN | \ ++ DTSEC_IMASK_XFUNEN | \ ++ DTSEC_IMASK_IFERREN | \ ++ DTSEC_IMASK_MAGEN | \ ++ DTSEC_IMASK_TDPEEN | \ ++ DTSEC_IMASK_RDPEEN)) ++ ++#define GET_EXCEPTION_FLAG(bitMask, exception) switch (exception){ \ ++ case e_FM_MAC_EX_1G_BAB_RX: \ ++ bitMask = DTSEC_IMASK_BREN; break; \ ++ case e_FM_MAC_EX_1G_RX_CTL: \ ++ bitMask = DTSEC_IMASK_RXCEN; break; \ ++ case e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET: \ ++ bitMask = DTSEC_IMASK_GTSCEN ; break; \ ++ case e_FM_MAC_EX_1G_BAB_TX: \ ++ bitMask = DTSEC_IMASK_BTEN ; break; \ ++ case e_FM_MAC_EX_1G_TX_CTL: \ ++ bitMask = DTSEC_IMASK_TXCEN ; break; \ ++ case e_FM_MAC_EX_1G_TX_ERR: \ ++ bitMask = DTSEC_IMASK_TXEEN ; break; \ ++ case e_FM_MAC_EX_1G_LATE_COL: \ ++ bitMask = DTSEC_IMASK_LCEN ; break; \ ++ case e_FM_MAC_EX_1G_COL_RET_LMT: \ ++ bitMask = DTSEC_IMASK_CRLEN ; break; \ ++ case e_FM_MAC_EX_1G_TX_FIFO_UNDRN: \ ++ bitMask = DTSEC_IMASK_XFUNEN ; break; \ ++ case e_FM_MAC_EX_1G_MAG_PCKT: \ ++ bitMask = DTSEC_IMASK_MAGEN ; break; \ ++ case e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET: \ ++ bitMask = DTSEC_IMASK_MMRDEN; break; \ ++ case e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET: \ ++ bitMask = DTSEC_IMASK_MMWREN ; break; \ ++ case e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET: \ ++ bitMask = DTSEC_IMASK_GRSCEN; break; \ ++ case e_FM_MAC_EX_1G_TX_DATA_ERR: \ ++ bitMask = DTSEC_IMASK_TDPEEN; break; \ ++ case e_FM_MAC_EX_1G_RX_MIB_CNT_OVFL: \ ++ bitMask = DTSEC_IMASK_MSROEN ; break; \ ++ default: bitMask = 0;break;} ++ ++ ++#define MAX_PACKET_ALIGNMENT 31 ++#define MAX_INTER_PACKET_GAP 0x7f ++#define MAX_INTER_PALTERNATE_BEB 0x0f ++#define MAX_RETRANSMISSION 0x0f ++#define MAX_COLLISION_WINDOW 0x03ff ++ ++ ++/********************* From mac ext ******************************************/ ++typedef uint32_t t_ErrorDisable; ++ ++#define ERROR_DISABLE_TRANSMIT 0x00400000 ++#define ERROR_DISABLE_LATE_COLLISION 0x00040000 ++#define ERROR_DISABLE_COLLISION_RETRY_LIMIT 0x00020000 ++#define ERROR_DISABLE_TxFIFO_UNDERRUN 0x00010000 ++#define ERROR_DISABLE_TxABORT 0x00008000 ++#define ERROR_DISABLE_INTERFACE 0x00004000 ++#define ERROR_DISABLE_TxDATA_PARITY 0x00000002 ++#define ERROR_DISABLE_RxDATA_PARITY 0x00000001 ++ ++/*****************************************************************************/ ++#define DTSEC_NUM_OF_PADDRS 15 /* number of pattern match registers (entries) */ ++ ++#define GROUP_ADDRESS 0x0000010000000000LL /* Group address bit indication */ ++ ++#define HASH_TABLE_SIZE 256 /* Hash table size (= 32 bits * 8 regs) */ ++ ++#define HASH_TABLE_SIZE 256 /* Hash table size (32 bits * 8 regs) */ ++#define EXTENDED_HASH_TABLE_SIZE 512 /* Extended Hash table size (32 bits * 16 regs) */ ++ ++#define DTSEC_TO_MII_OFFSET 0x1000 /* number of pattern match registers (entries) */ ++ ++#define MAX_PHYS 32 /* maximum number of phys */ ++ ++#define VAL32BIT 0x100000000LL ++#define VAL22BIT 0x00400000 ++#define VAL16BIT 0x00010000 ++#define VAL12BIT 0x00001000 ++ ++/* CAR1/2 bits */ ++#define CAR1_TR64 0x80000000 ++#define CAR1_TR127 0x40000000 ++#define CAR1_TR255 0x20000000 ++#define CAR1_TR511 0x10000000 ++#define CAR1_TRK1 0x08000000 ++#define CAR1_TRMAX 0x04000000 ++#define CAR1_TRMGV 0x02000000 ++ ++#define CAR1_RBYT 0x00010000 ++#define CAR1_RPKT 0x00008000 ++#define CAR1_RMCA 0x00002000 ++#define CAR1_RBCA 0x00001000 ++#define CAR1_RXPF 0x00000400 ++#define CAR1_RALN 0x00000100 ++#define CAR1_RFLR 0x00000080 ++#define CAR1_RCDE 0x00000040 ++#define CAR1_RCSE 0x00000020 ++#define CAR1_RUND 0x00000010 ++#define CAR1_ROVR 0x00000008 ++#define CAR1_RFRG 0x00000004 ++#define CAR1_RJBR 0x00000002 ++#define CAR1_RDRP 0x00000001 ++ ++#define CAR2_TFCS 0x00040000 ++#define CAR2_TBYT 0x00002000 ++#define CAR2_TPKT 0x00001000 ++#define CAR2_TMCA 0x00000800 ++#define CAR2_TBCA 0x00000400 ++#define CAR2_TXPF 0x00000200 ++#define CAR2_TDRP 0x00000001 ++ ++typedef struct t_InternalStatistics ++{ ++ uint64_t tr64; ++ uint64_t tr127; ++ uint64_t tr255; ++ uint64_t tr511; ++ uint64_t tr1k; ++ uint64_t trmax; ++ uint64_t trmgv; ++ uint64_t rfrg; ++ uint64_t rjbr; ++ uint64_t rdrp; ++ uint64_t raln; ++ uint64_t rund; ++ uint64_t rovr; ++ uint64_t rxpf; ++ uint64_t txpf; ++ uint64_t rbyt; ++ uint64_t rpkt; ++ uint64_t rmca; ++ uint64_t rbca; ++ uint64_t rflr; ++ uint64_t rcde; ++ uint64_t rcse; ++ uint64_t tbyt; ++ uint64_t tpkt; ++ uint64_t tmca; ++ uint64_t tbca; ++ uint64_t tdrp; ++ uint64_t tfcs; ++} t_InternalStatistics; ++ ++typedef struct { ++ t_FmMacControllerDriver fmMacControllerDriver; ++ t_Handle h_App; /**< Handle to the upper layer application */ ++ struct dtsec_regs *p_MemMap; /**< pointer to dTSEC memory mapped registers. */ ++ struct dtsec_mii_reg *p_MiiMemMap; /**< pointer to dTSEC MII memory mapped registers. */ ++ uint64_t addr; /**< MAC address of device; */ ++ e_EnetMode enetMode; /**< Ethernet physical interface */ ++ t_FmMacExceptionCallback *f_Exception; ++ int mdioIrq; ++ t_FmMacExceptionCallback *f_Event; ++ bool indAddrRegUsed[DTSEC_NUM_OF_PADDRS]; /**< Whether a particular individual address recognition register is being used */ ++ uint64_t paddr[DTSEC_NUM_OF_PADDRS]; /**< MAC address for particular individual address recognition register */ ++ uint8_t numOfIndAddrInRegs; /**< Number of individual addresses in registers for this station. */ ++ bool halfDuplex; ++ t_InternalStatistics internalStatistics; ++ t_EthHash *p_MulticastAddrHash; /* pointer to driver's global address hash table */ ++ t_EthHash *p_UnicastAddrHash; /* pointer to driver's individual address hash table */ ++ uint8_t macId; ++ uint8_t tbi_phy_addr; ++ uint32_t exceptions; ++ bool ptpTsuEnabled; ++ bool enTsuErrExeption; ++ e_FmMacStatisticsLevel statisticsLevel; ++ struct dtsec_cfg *p_DtsecDriverParam; ++} t_Dtsec; ++ ++ ++#endif /* __DTSEC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec_mii_acc.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec_mii_acc.c +new file mode 100644 +index 0000000..87da25f +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec_mii_acc.c +@@ -0,0 +1,97 @@ ++/* ++ * Copyright 2008-2013 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File dtsec_mii_acc.c ++ ++ @Description FM dtsec MII register access MAC ... ++*//***************************************************************************/ ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "fm_mac.h" ++#include "dtsec.h" ++#include "fsl_fman_dtsec_mii_acc.h" ++ ++ ++/*****************************************************************************/ ++t_Error DTSEC_MII_WritePhyReg(t_Handle h_Dtsec, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t data) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ struct dtsec_mii_reg *miiregs; ++ uint16_t dtsec_freq; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_MiiMemMap, E_INVALID_HANDLE); ++ ++ dtsec_freq = (uint16_t)(p_Dtsec->fmMacControllerDriver.clkFreq >> 1); ++ miiregs = p_Dtsec->p_MiiMemMap; ++ ++ err = (t_Error)fman_dtsec_mii_write_reg(miiregs, phyAddr, reg, data, dtsec_freq); ++ ++ return err; ++} ++ ++/*****************************************************************************/ ++t_Error DTSEC_MII_ReadPhyReg(t_Handle h_Dtsec, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t *p_Data) ++{ ++ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec; ++ struct dtsec_mii_reg *miiregs; ++ uint16_t dtsec_freq; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_MiiMemMap, E_INVALID_HANDLE); ++ ++ dtsec_freq = (uint16_t)(p_Dtsec->fmMacControllerDriver.clkFreq >> 1); ++ miiregs = p_Dtsec->p_MiiMemMap; ++ ++ err = fman_dtsec_mii_read_reg(miiregs, phyAddr, reg, p_Data, dtsec_freq); ++ ++ if (*p_Data == 0xffff) ++ RETURN_ERROR(MINOR, E_NO_DEVICE, ++ ("Read wrong data (0xffff): phyAddr 0x%x, reg 0x%x", ++ phyAddr, reg)); ++ if (err) ++ RETURN_ERROR(MINOR, (t_Error)err, NO_MSG); ++ ++ return E_OK; ++} ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec_mii_acc.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec_mii_acc.h +new file mode 100644 +index 0000000..75cc658 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/dtsec_mii_acc.h +@@ -0,0 +1,42 @@ ++/* ++ * Copyright 2008-2013 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 __DTSEC_MII_ACC_H ++#define __DTSEC_MII_ACC_H ++ ++#include "std_ext.h" ++ ++ ++t_Error DTSEC_MII_WritePhyReg(t_Handle h_Dtsec, uint8_t phyAddr, uint8_t reg, uint16_t data); ++t_Error DTSEC_MII_ReadPhyReg(t_Handle h_Dtsec, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data); ++ ++#endif /* __DTSEC_MII_ACC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fm_mac.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fm_mac.c +new file mode 100644 +index 0000000..a76ca6a +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fm_mac.c +@@ -0,0 +1,646 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_mac.c ++ ++ @Description FM MAC ... ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "string_ext.h" ++#include "sprint_ext.h" ++#include "error_ext.h" ++#include "fm_ext.h" ++ ++#include "fm_common.h" ++#include "fm_mac.h" ++ ++ ++/* ......................................................................... */ ++ ++t_Handle FM_MAC_Config (t_FmMacParams *p_FmMacParam) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver; ++ uint16_t fmClkFreq; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_INVALID_HANDLE, NULL); ++ ++ fmClkFreq = FmGetClockFreq(p_FmMacParam->h_Fm); ++ if (fmClkFreq == 0) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Can't get clock for MAC!")); ++ return NULL; ++ } ++ ++#if (DPAA_VERSION == 10) ++ if (ENET_SPEED_FROM_MODE(p_FmMacParam->enetMode) < e_ENET_SPEED_10000) ++ p_FmMacControllerDriver = (t_FmMacControllerDriver *)DTSEC_Config(p_FmMacParam); ++ else ++#if FM_MAX_NUM_OF_10G_MACS > 0 ++ p_FmMacControllerDriver = (t_FmMacControllerDriver *)TGEC_Config(p_FmMacParam); ++#else ++ p_FmMacControllerDriver = NULL; ++#endif /* FM_MAX_NUM_OF_10G_MACS > 0 */ ++#else ++ p_FmMacControllerDriver = (t_FmMacControllerDriver *)MEMAC_Config(p_FmMacParam); ++#endif /* (DPAA_VERSION == 10) */ ++ ++ if (!p_FmMacControllerDriver) ++ return NULL; ++ ++ p_FmMacControllerDriver->h_Fm = p_FmMacParam->h_Fm; ++ p_FmMacControllerDriver->enetMode = p_FmMacParam->enetMode; ++ p_FmMacControllerDriver->macId = p_FmMacParam->macId; ++ p_FmMacControllerDriver->resetOnInit = DEFAULT_resetOnInit; ++ ++ p_FmMacControllerDriver->clkFreq = fmClkFreq; ++ ++ return (t_Handle)p_FmMacControllerDriver; ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_Init (t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->resetOnInit && ++ !p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit && ++ (FmResetMac(p_FmMacControllerDriver->h_Fm, ++ ((ENET_INTERFACE_FROM_MODE(p_FmMacControllerDriver->enetMode) == e_ENET_IF_XGMII) ? ++ e_FM_MAC_10G : e_FM_MAC_1G), ++ p_FmMacControllerDriver->macId) != E_OK)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't reset MAC!")); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_Init) ++ return p_FmMacControllerDriver->f_FM_MAC_Init(h_FmMac); ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_Free (t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_Free) ++ return p_FmMacControllerDriver->f_FM_MAC_Free(h_FmMac); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigResetOnInit (t_Handle h_FmMac, bool enable) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit(h_FmMac, enable); ++ ++ p_FmMacControllerDriver->resetOnInit = enable; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigLoopback (t_Handle h_FmMac, bool newVal) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback(h_FmMac, newVal); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigMaxFrameLength (t_Handle h_FmMac, uint16_t newVal) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength(h_FmMac, newVal); ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigWan (t_Handle h_FmMac, bool flag) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigWan) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigWan(h_FmMac, flag); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigPadAndCrc (t_Handle h_FmMac, bool newVal) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc(h_FmMac, newVal); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigHalfDuplex (t_Handle h_FmMac, bool newVal) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex(h_FmMac,newVal); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigTbiPhyAddr (t_Handle h_FmMac, uint8_t newVal) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigTbiPhyAddr) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigTbiPhyAddr(h_FmMac,newVal); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigLengthCheck (t_Handle h_FmMac, bool newVal) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck(h_FmMac,newVal); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigException (t_Handle h_FmMac, e_FmMacExceptions ex, bool enable) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigException) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigException(h_FmMac, ex, enable); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ConfigSkipFman11Workaround (t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ConfigSkipFman11Workaround) ++ return p_FmMacControllerDriver->f_FM_MAC_ConfigSkipFman11Workaround(h_FmMac); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++ ++/*****************************************************************************/ ++/* Run Time Control */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_Enable (t_Handle h_FmMac, e_CommMode mode) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_Enable) ++ return p_FmMacControllerDriver->f_FM_MAC_Enable(h_FmMac, mode); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_Disable (t_Handle h_FmMac, e_CommMode mode) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_Disable) ++ return p_FmMacControllerDriver->f_FM_MAC_Disable(h_FmMac, mode); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_Enable1588TimeStamp (t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp) ++ return p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp(h_FmMac); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_Disable1588TimeStamp (t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp) ++ return p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp(h_FmMac); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_SetTxAutoPauseFrames(t_Handle h_FmMac, ++ uint16_t pauseTime) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames) ++ return p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames(h_FmMac, ++ pauseTime); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_SetTxPauseFrames(t_Handle h_FmMac, ++ uint8_t priority, ++ uint16_t pauseTime, ++ uint16_t threshTime) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames) ++ return p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames(h_FmMac, ++ priority, ++ pauseTime, ++ threshTime); ++ ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_SetRxIgnorePauseFrames (t_Handle h_FmMac, bool en) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames) ++ return p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames(h_FmMac, en); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_SetWakeOnLan (t_Handle h_FmMac, bool en) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_SetWakeOnLan) ++ return p_FmMacControllerDriver->f_FM_MAC_SetWakeOnLan(h_FmMac, en); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ResetCounters (t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ResetCounters) ++ return p_FmMacControllerDriver->f_FM_MAC_ResetCounters(h_FmMac); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_SetException(t_Handle h_FmMac, e_FmMacExceptions ex, bool enable) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_SetException) ++ return p_FmMacControllerDriver->f_FM_MAC_SetException(h_FmMac, ex, enable); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_SetStatistics (t_Handle h_FmMac, e_FmMacStatisticsLevel statisticsLevel) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_SetStatistics) ++ return p_FmMacControllerDriver->f_FM_MAC_SetStatistics(h_FmMac, statisticsLevel); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_GetStatistics (t_Handle h_FmMac, t_FmMacStatistics *p_Statistics) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_GetStatistics) ++ return p_FmMacControllerDriver->f_FM_MAC_GetStatistics(h_FmMac, p_Statistics); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_ModifyMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr) ++ return p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr(h_FmMac, p_EnetAddr); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_AddHashMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr) ++ return p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr(h_FmMac, p_EnetAddr); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_RemoveHashMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr) ++ return p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr(h_FmMac, p_EnetAddr); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_AddExactMatchMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr) ++ return p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr(h_FmMac, p_EnetAddr); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_RemovelExactMatchMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr) ++ return p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr(h_FmMac, p_EnetAddr); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_GetVesrion (t_Handle h_FmMac, uint32_t *macVresion) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_GetVersion) ++ return p_FmMacControllerDriver->f_FM_MAC_GetVersion(h_FmMac, macVresion); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++ ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_GetId (t_Handle h_FmMac, uint32_t *macId) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_GetId) ++ return p_FmMacControllerDriver->f_FM_MAC_GetId(h_FmMac, macId); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_SetPromiscuous (t_Handle h_FmMac, bool newVal) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous) ++ return p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous(h_FmMac, newVal); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_AdjustLink(t_Handle h_FmMac, e_EnetSpeed speed, bool fullDuplex) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_AdjustLink) ++ return p_FmMacControllerDriver->f_FM_MAC_AdjustLink(h_FmMac, speed, fullDuplex); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_RestartAutoneg(t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg) ++ return p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg(h_FmMac); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_MII_WritePhyReg (t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t data) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg) ++ return p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg(h_FmMac, phyAddr, reg, data); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++t_Error FM_MAC_MII_ReadPhyReg(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg) ++ return p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg(h_FmMac, phyAddr, reg, p_Data); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++uint16_t FM_MAC_GetMaxFrameLength(t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmMacControllerDriver, E_INVALID_HANDLE, 0); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength) ++ return p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength(h_FmMac); ++ ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++ return 0; ++} ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++/*****************************************************************************/ ++t_Error FM_MAC_DumpRegs(t_Handle h_FmMac) ++{ ++ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacControllerDriver->f_FM_MAC_DumpRegs) ++ return p_FmMacControllerDriver->f_FM_MAC_DumpRegs(h_FmMac); ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++#endif /* (defined(DEBUG_ERRORS) && ... */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fm_mac.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fm_mac.h +new file mode 100644 +index 0000000..0d7b8d2 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fm_mac.h +@@ -0,0 +1,224 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_mac.h ++ ++ @Description FM MAC ... ++*//***************************************************************************/ ++#ifndef __FM_MAC_H ++#define __FM_MAC_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++#include "fm_mac_ext.h" ++#include "fm_common.h" ++ ++ ++#define __ERR_MODULE__ MODULE_FM_MAC ++ ++/**************************************************************************//** ++ @Description defaults ++*//***************************************************************************/ ++ ++ ++#define DEFAULT_halfDuplex FALSE ++#define DEFAULT_padAndCrcEnable TRUE ++#define DEFAULT_resetOnInit FALSE ++ ++ ++typedef struct { ++ uint64_t addr; /* Ethernet Address */ ++ t_List node; ++} t_EthHashEntry; ++#define ETH_HASH_ENTRY_OBJ(ptr) LIST_OBJECT(ptr, t_EthHashEntry, node) ++ ++typedef struct { ++ uint16_t size; ++ t_List *p_Lsts; ++} t_EthHash; ++ ++typedef struct { ++ t_Error (*f_FM_MAC_Init) (t_Handle h_FmMac); ++ t_Error (*f_FM_MAC_Free) (t_Handle h_FmMac); ++ ++ t_Error (*f_FM_MAC_SetStatistics) (t_Handle h_FmMac, e_FmMacStatisticsLevel statisticsLevel); ++ t_Error (*f_FM_MAC_ConfigLoopback) (t_Handle h_FmMac, bool newVal); ++ t_Error (*f_FM_MAC_ConfigMaxFrameLength) (t_Handle h_FmMac, uint16_t newVal); ++ t_Error (*f_FM_MAC_ConfigWan) (t_Handle h_FmMac, bool flag); ++ t_Error (*f_FM_MAC_ConfigPadAndCrc) (t_Handle h_FmMac, bool newVal); ++ t_Error (*f_FM_MAC_ConfigHalfDuplex) (t_Handle h_FmMac, bool newVal); ++ t_Error (*f_FM_MAC_ConfigLengthCheck) (t_Handle h_FmMac, bool newVal); ++ t_Error (*f_FM_MAC_ConfigTbiPhyAddr) (t_Handle h_FmMac, uint8_t newVal); ++ t_Error (*f_FM_MAC_ConfigException) (t_Handle h_FmMac, e_FmMacExceptions, bool enable); ++ t_Error (*f_FM_MAC_ConfigResetOnInit) (t_Handle h_FmMac, bool enable); ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++ t_Error (*f_FM_MAC_ConfigSkipFman11Workaround) (t_Handle h_FmMac); ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++ t_Error (*f_FM_MAC_SetException) (t_Handle h_FmMac, e_FmMacExceptions ex, bool enable); ++ ++ t_Error (*f_FM_MAC_Enable) (t_Handle h_FmMac, e_CommMode mode); ++ t_Error (*f_FM_MAC_Disable) (t_Handle h_FmMac, e_CommMode mode); ++ t_Error (*f_FM_MAC_Enable1588TimeStamp) (t_Handle h_FmMac); ++ t_Error (*f_FM_MAC_Disable1588TimeStamp) (t_Handle h_FmMac); ++ t_Error (*f_FM_MAC_Reset) (t_Handle h_FmMac, bool wait); ++ ++ t_Error (*f_FM_MAC_SetTxAutoPauseFrames) (t_Handle h_FmMac, ++ uint16_t pauseTime); ++ t_Error (*f_FM_MAC_SetTxPauseFrames) (t_Handle h_FmMac, ++ uint8_t priority, ++ uint16_t pauseTime, ++ uint16_t threshTime); ++ t_Error (*f_FM_MAC_SetRxIgnorePauseFrames) (t_Handle h_FmMac, bool en); ++ ++ t_Error (*f_FM_MAC_ResetCounters) (t_Handle h_FmMac); ++ t_Error (*f_FM_MAC_GetStatistics) (t_Handle h_FmMac, t_FmMacStatistics *p_Statistics); ++ ++ t_Error (*f_FM_MAC_ModifyMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ t_Error (*f_FM_MAC_AddHashMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ t_Error (*f_FM_MAC_RemoveHashMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ t_Error (*f_FM_MAC_AddExactMatchMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ t_Error (*f_FM_MAC_RemovelExactMatchMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ ++ t_Error (*f_FM_MAC_SetPromiscuous) (t_Handle h_FmMac, bool newVal); ++ t_Error (*f_FM_MAC_AdjustLink) (t_Handle h_FmMac, e_EnetSpeed speed, bool fullDuplex); ++ t_Error (*f_FM_MAC_RestartAutoneg) (t_Handle h_FmMac); ++ ++ t_Error (*f_FM_MAC_SetWakeOnLan) (t_Handle h_FmMac, bool en); ++ ++ t_Error (*f_FM_MAC_GetId) (t_Handle h_FmMac, uint32_t *macId); ++ ++ t_Error (*f_FM_MAC_GetVersion) (t_Handle h_FmMac, uint32_t *macVersion); ++ ++ uint16_t (*f_FM_MAC_GetMaxFrameLength) (t_Handle h_FmMac); ++ ++ t_Error (*f_FM_MAC_MII_WritePhyReg)(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t data); ++ t_Error (*f_FM_MAC_MII_ReadPhyReg)(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data); ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_Error (*f_FM_MAC_DumpRegs) (t_Handle h_FmMac); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ t_Handle h_Fm; ++ t_FmRevisionInfo fmRevInfo; ++ e_EnetMode enetMode; ++ uint8_t macId; ++ bool resetOnInit; ++ uint16_t clkFreq; ++} t_FmMacControllerDriver; ++ ++ ++#if (DPAA_VERSION == 10) ++t_Handle DTSEC_Config(t_FmMacParams *p_FmMacParam); ++t_Handle TGEC_Config(t_FmMacParams *p_FmMacParams); ++#else ++t_Handle MEMAC_Config(t_FmMacParams *p_FmMacParam); ++#endif /* (DPAA_VERSION == 10) */ ++uint16_t FM_MAC_GetMaxFrameLength(t_Handle FmMac); ++ ++ ++/* ........................................................................... */ ++ ++static __inline__ t_EthHashEntry *DequeueAddrFromHashEntry(t_List *p_AddrLst) ++{ ++ t_EthHashEntry *p_HashEntry = NULL; ++ if (!LIST_IsEmpty(p_AddrLst)) ++ { ++ p_HashEntry = ETH_HASH_ENTRY_OBJ(p_AddrLst->p_Next); ++ LIST_DelAndInit(&p_HashEntry->node); ++ } ++ return p_HashEntry; ++} ++ ++/* ........................................................................... */ ++ ++static __inline__ void FreeHashTable(t_EthHash *p_Hash) ++{ ++ t_EthHashEntry *p_HashEntry; ++ int i = 0; ++ ++ if (p_Hash) ++ { ++ if (p_Hash->p_Lsts) ++ { ++ for (i=0; isize; i++) ++ { ++ p_HashEntry = DequeueAddrFromHashEntry(&p_Hash->p_Lsts[i]); ++ while (p_HashEntry) ++ { ++ XX_Free(p_HashEntry); ++ p_HashEntry = DequeueAddrFromHashEntry(&p_Hash->p_Lsts[i]); ++ } ++ } ++ ++ XX_Free(p_Hash->p_Lsts); ++ } ++ ++ XX_Free(p_Hash); ++ } ++} ++ ++/* ........................................................................... */ ++ ++static __inline__ t_EthHash * AllocHashTable(uint16_t size) ++{ ++ uint32_t i; ++ t_EthHash *p_Hash; ++ ++ /* Allocate address hash table */ ++ p_Hash = (t_EthHash *)XX_Malloc(sizeof(t_EthHash)); ++ if (!p_Hash) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Address hash table")); ++ return NULL; ++ } ++ p_Hash->size = size; ++ ++ p_Hash->p_Lsts = (t_List *)XX_Malloc(p_Hash->size*sizeof(t_List)); ++ if (!p_Hash->p_Lsts) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Address hash table")); ++ XX_Free(p_Hash); ++ return NULL; ++ } ++ ++ for (i=0 ; isize; i++) ++ INIT_LIST(&p_Hash->p_Lsts[i]); ++ ++ return p_Hash; ++} ++ ++ ++#endif /* __FM_MAC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_crc32.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_crc32.c +new file mode 100644 +index 0000000..b6a4ca2 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_crc32.c +@@ -0,0 +1,119 @@ ++/* ++ * Copyright 2008-2012 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 "fman_crc32.h" ++#include "common/general.h" ++ ++ ++/* precomputed CRC values for address hashing */ ++static const uint32_t crc_tbl[256] = { ++ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, ++ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, ++ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, ++ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, ++ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, ++ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, ++ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, ++ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, ++ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, ++ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, ++ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, ++ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, ++ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, ++ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, ++ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, ++ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, ++ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, ++ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, ++ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, ++ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, ++ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, ++ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, ++ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, ++ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, ++ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, ++ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, ++ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, ++ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, ++ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, ++ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, ++ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, ++ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, ++ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, ++ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, ++ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, ++ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, ++ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, ++ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, ++ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, ++ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, ++ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, ++ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, ++ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d ++}; ++ ++/* Get the mirrored value of a byte size number. (0x11010011 --> 0x11001011) */ ++static inline uint8_t get_mirror8(uint8_t n) ++{ ++ uint8_t mirror[16] = { ++ 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e, ++ 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f ++ }; ++ return (uint8_t)(((mirror[n & 0x0f] << 4) | (mirror[n >> 4]))); ++} ++ ++static inline uint32_t get_mirror32(uint32_t n) ++{ ++ return ((uint32_t)get_mirror8((uint8_t)(n))<<24) | ++ ((uint32_t)get_mirror8((uint8_t)(n>>8))<<16) | ++ ((uint32_t)get_mirror8((uint8_t)(n>>16))<<8) | ++ ((uint32_t)get_mirror8((uint8_t)(n>>24))); ++} ++ ++uint32_t get_mac_addr_crc(uint64_t _addr) ++{ ++ uint32_t i; ++ uint8_t data; ++ uint32_t crc; ++ ++ /* CRC calculation */ ++ crc = 0xffffffff; ++ for (i = 0; i < 6; i++) { ++ data = (uint8_t)(_addr >> ((5-i)*8)); ++ crc = crc ^ data; ++ crc = crc_tbl[crc&0xff] ^ (crc>>8); ++ } ++ ++ crc = get_mirror32(crc); ++ return crc; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_crc32.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_crc32.h +new file mode 100644 +index 0000000..6e32fdc +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_crc32.h +@@ -0,0 +1,43 @@ ++/* ++ * Copyright 2008-2012 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 __FMAN_CRC32_H ++#define __FMAN_CRC32_H ++ ++#include "common/general.h" ++ ++ ++uint32_t get_mac_addr_crc(uint64_t _addr); ++ ++ ++#endif /* __FMAN_CRC32_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_dtsec.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_dtsec.c +new file mode 100644 +index 0000000..5b09286 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_dtsec.c +@@ -0,0 +1,845 @@ ++/* ++ * Copyright 2008-2012 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 "fsl_fman_dtsec.h" ++ ++ ++void fman_dtsec_stop_rx(struct dtsec_regs *regs) ++{ ++ /* Assert the graceful stop bit */ ++ iowrite32be(ioread32be(®s->rctrl) | RCTRL_GRS, ®s->rctrl); ++} ++ ++void fman_dtsec_stop_tx(struct dtsec_regs *regs) ++{ ++ /* Assert the graceful stop bit */ ++ iowrite32be(ioread32be(®s->tctrl) | DTSEC_TCTRL_GTS, ®s->tctrl); ++} ++ ++void fman_dtsec_start_tx(struct dtsec_regs *regs) ++{ ++ /* clear the graceful stop bit */ ++ iowrite32be(ioread32be(®s->tctrl) & ~DTSEC_TCTRL_GTS, ®s->tctrl); ++} ++ ++void fman_dtsec_start_rx(struct dtsec_regs *regs) ++{ ++ /* clear the graceful stop bit */ ++ iowrite32be(ioread32be(®s->rctrl) & ~RCTRL_GRS, ®s->rctrl); ++} ++ ++void fman_dtsec_defconfig(struct dtsec_cfg *cfg) ++{ ++ cfg->halfdup_on = DEFAULT_HALFDUP_ON; ++ cfg->halfdup_retransmit = DEFAULT_HALFDUP_RETRANSMIT; ++ cfg->halfdup_coll_window = DEFAULT_HALFDUP_COLL_WINDOW; ++ cfg->halfdup_excess_defer = DEFAULT_HALFDUP_EXCESS_DEFER; ++ cfg->halfdup_no_backoff = DEFAULT_HALFDUP_NO_BACKOFF; ++ cfg->halfdup_bp_no_backoff = DEFAULT_HALFDUP_BP_NO_BACKOFF; ++ cfg->halfdup_alt_backoff_val = DEFAULT_HALFDUP_ALT_BACKOFF_VAL; ++ cfg->halfdup_alt_backoff_en = DEFAULT_HALFDUP_ALT_BACKOFF_EN; ++ cfg->rx_drop_bcast = DEFAULT_RX_DROP_BCAST; ++ cfg->rx_short_frm = DEFAULT_RX_SHORT_FRM; ++ cfg->rx_len_check = DEFAULT_RX_LEN_CHECK; ++ cfg->tx_pad_crc = DEFAULT_TX_PAD_CRC; ++ cfg->tx_crc = DEFAULT_TX_CRC; ++ cfg->rx_ctrl_acc = DEFAULT_RX_CTRL_ACC; ++ cfg->tx_pause_time = DEFAULT_TX_PAUSE_TIME; ++ cfg->tbipa = DEFAULT_TBIPA; /* PHY address 0 is reserved (DPAA RM)*/ ++ cfg->rx_prepend = DEFAULT_RX_PREPEND; ++ cfg->ptp_tsu_en = DEFAULT_PTP_TSU_EN; ++ cfg->ptp_exception_en = DEFAULT_PTP_EXCEPTION_EN; ++ cfg->preamble_len = DEFAULT_PREAMBLE_LEN; ++ cfg->rx_preamble = DEFAULT_RX_PREAMBLE; ++ cfg->tx_preamble = DEFAULT_TX_PREAMBLE; ++ cfg->loopback = DEFAULT_LOOPBACK; ++ cfg->rx_time_stamp_en = DEFAULT_RX_TIME_STAMP_EN; ++ cfg->tx_time_stamp_en = DEFAULT_TX_TIME_STAMP_EN; ++ cfg->rx_flow = DEFAULT_RX_FLOW; ++ cfg->tx_flow = DEFAULT_TX_FLOW; ++ cfg->rx_group_hash_exd = DEFAULT_RX_GROUP_HASH_EXD; ++ cfg->tx_pause_time_extd = DEFAULT_TX_PAUSE_TIME_EXTD; ++ cfg->rx_promisc = DEFAULT_RX_PROMISC; ++ cfg->non_back_to_back_ipg1 = DEFAULT_NON_BACK_TO_BACK_IPG1; ++ cfg->non_back_to_back_ipg2 = DEFAULT_NON_BACK_TO_BACK_IPG2; ++ cfg->min_ifg_enforcement = DEFAULT_MIN_IFG_ENFORCEMENT; ++ cfg->back_to_back_ipg = DEFAULT_BACK_TO_BACK_IPG; ++ cfg->maximum_frame = DEFAULT_MAXIMUM_FRAME; ++ cfg->tbi_phy_addr = DEFAULT_TBI_PHY_ADDR; ++ cfg->wake_on_lan = DEFAULT_WAKE_ON_LAN; ++} ++ ++int fman_dtsec_init(struct dtsec_regs *regs, struct dtsec_cfg *cfg, ++ enum enet_interface iface_mode, ++ enum enet_speed iface_speed, ++ uint8_t *macaddr, ++ uint8_t fm_rev_maj, ++ uint8_t fm_rev_min, ++ uint32_t exception_mask) ++{ ++ bool is_rgmii = FALSE; ++ bool is_sgmii = FALSE; ++ bool is_qsgmii = FALSE; ++ int i; ++ uint32_t tmp; ++ ++UNUSED(fm_rev_maj);UNUSED(fm_rev_min); ++ ++ /* let's start with a soft reset */ ++ iowrite32be(MACCFG1_SOFT_RESET, ®s->maccfg1); ++ iowrite32be(0, ®s->maccfg1); ++ ++ /*************dtsec_id2******************/ ++ tmp = ioread32be(®s->tsec_id2); ++ ++ /* check RGMII support */ ++ if (iface_mode == E_ENET_IF_RGMII || ++ iface_mode == E_ENET_IF_RMII) ++ if (tmp & DTSEC_ID2_INT_REDUCED_OFF) ++ return -EINVAL; ++ ++ if (iface_mode == E_ENET_IF_SGMII || ++ iface_mode == E_ENET_IF_MII) ++ if (tmp & DTSEC_ID2_INT_REDUCED_OFF) ++ return -EINVAL; ++ ++ /***************ECNTRL************************/ ++ ++ is_rgmii = (bool)((iface_mode == E_ENET_IF_RGMII) ? TRUE : FALSE); ++ is_sgmii = (bool)((iface_mode == E_ENET_IF_SGMII) ? TRUE : FALSE); ++ is_qsgmii = (bool)((iface_mode == E_ENET_IF_QSGMII) ? TRUE : FALSE); ++ ++ tmp = 0; ++ if (is_rgmii || iface_mode == E_ENET_IF_GMII) ++ tmp |= DTSEC_ECNTRL_GMIIM; ++ if (is_sgmii) ++ tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM); ++ if (is_qsgmii) ++ tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM | ++ DTSEC_ECNTRL_QSGMIIM); ++ if (is_rgmii) ++ tmp |= DTSEC_ECNTRL_RPM; ++ if (iface_speed == E_ENET_SPEED_100) ++ tmp |= DTSEC_ECNTRL_R100M; ++ ++ iowrite32be(tmp, ®s->ecntrl); ++ /***************ECNTRL************************/ ++ ++ /***************TCTRL************************/ ++ tmp = 0; ++ if (cfg->halfdup_on) ++ tmp |= DTSEC_TCTRL_THDF; ++ if (cfg->tx_time_stamp_en) ++ tmp |= DTSEC_TCTRL_TTSE; ++ ++ iowrite32be(tmp, ®s->tctrl); ++ ++ /***************TCTRL************************/ ++ ++ /***************PTV************************/ ++ tmp = 0; ++ ++#ifdef FM_SHORT_PAUSE_TIME_ERRATA_DTSEC1 ++ if ((fm_rev_maj == 1) && (fm_rev_min == 0)) ++ cfg->tx_pause_time += 2; ++#endif /* FM_SHORT_PAUSE_TIME_ERRATA_DTSEC1 */ ++ ++ if (cfg->tx_pause_time) ++ tmp |= cfg->tx_pause_time; ++ if (cfg->tx_pause_time_extd) ++ tmp |= cfg->tx_pause_time_extd << PTV_PTE_OFST; ++ iowrite32be(tmp, ®s->ptv); ++ ++ /***************RCTRL************************/ ++ tmp = 0; ++ tmp |= ((uint32_t)(cfg->rx_prepend & 0x0000001f)) << 16; ++ if (cfg->rx_ctrl_acc) ++ tmp |= RCTRL_CFA; ++ if (cfg->rx_group_hash_exd) ++ tmp |= RCTRL_GHTX; ++ if (cfg->rx_time_stamp_en) ++ tmp |= RCTRL_RTSE; ++ if (cfg->rx_drop_bcast) ++ tmp |= RCTRL_BC_REJ; ++ if (cfg->rx_short_frm) ++ tmp |= RCTRL_RSF; ++ if (cfg->rx_promisc) ++ tmp |= RCTRL_PROM; ++ ++ iowrite32be(tmp, ®s->rctrl); ++ /***************RCTRL************************/ ++ ++ /* ++ * Assign a Phy Address to the TBI (TBIPA). ++ * Done also in cases where TBI is not selected to avoid conflict with ++ * the external PHY's Physical address ++ */ ++ iowrite32be(cfg->tbipa, ®s->tbipa); ++ ++ /***************TMR_CTL************************/ ++ iowrite32be(0, ®s->tmr_ctrl); ++ ++ if (cfg->ptp_tsu_en) { ++ tmp = 0; ++ tmp |= TMR_PEVENT_TSRE; ++ iowrite32be(tmp, ®s->tmr_pevent); ++ ++ if (cfg->ptp_exception_en) { ++ tmp = 0; ++ tmp |= TMR_PEMASK_TSREEN; ++ iowrite32be(tmp, ®s->tmr_pemask); ++ } ++ } ++ ++ /***************MACCFG1***********************/ ++ tmp = 0; ++ if (cfg->loopback) ++ tmp |= MACCFG1_LOOPBACK; ++ if (cfg->rx_flow) ++ tmp |= MACCFG1_RX_FLOW; ++ if (cfg->tx_flow) ++ tmp |= MACCFG1_TX_FLOW; ++ iowrite32be(tmp, ®s->maccfg1); ++ ++ /***************MACCFG1***********************/ ++ ++ /***************MACCFG2***********************/ ++ tmp = 0; ++ ++ if (iface_speed < E_ENET_SPEED_1000) ++ tmp |= MACCFG2_NIBBLE_MODE; ++ else if (iface_speed == E_ENET_SPEED_1000) ++ tmp |= MACCFG2_BYTE_MODE; ++ ++ tmp |= ((uint32_t) cfg->preamble_len & 0x0000000f) ++ << PREAMBLE_LENGTH_SHIFT; ++ ++ if (cfg->rx_preamble) ++ tmp |= MACCFG2_PRE_AM_Rx_EN; ++ if (cfg->tx_preamble) ++ tmp |= MACCFG2_PRE_AM_Tx_EN; ++ if (cfg->rx_len_check) ++ tmp |= MACCFG2_LENGTH_CHECK; ++ if (cfg->tx_pad_crc) ++ tmp |= MACCFG2_PAD_CRC_EN; ++ if (cfg->tx_crc) ++ tmp |= MACCFG2_CRC_EN; ++ if (!cfg->halfdup_on) ++ tmp |= MACCFG2_FULL_DUPLEX; ++ iowrite32be(tmp, ®s->maccfg2); ++ ++ /***************MACCFG2***********************/ ++ ++ /***************IPGIFG************************/ ++ tmp = (((cfg->non_back_to_back_ipg1 << ++ IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT) ++ & IPGIFG_NON_BACK_TO_BACK_IPG_1) ++ | ((cfg->non_back_to_back_ipg2 << ++ IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT) ++ & IPGIFG_NON_BACK_TO_BACK_IPG_2) ++ | ((cfg->min_ifg_enforcement << ++ IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT) ++ & IPGIFG_MIN_IFG_ENFORCEMENT) ++ | (cfg->back_to_back_ipg & IPGIFG_BACK_TO_BACK_IPG)); ++ iowrite32be(tmp, ®s->ipgifg); ++ ++ /***************IPGIFG************************/ ++ ++ /***************HAFDUP************************/ ++ tmp = 0; ++ ++ if (cfg->halfdup_alt_backoff_en) ++ tmp = (uint32_t)(HAFDUP_ALT_BEB | ++ ((cfg->halfdup_alt_backoff_val & 0x0000000f) ++ << HAFDUP_ALTERNATE_BEB_TRUNCATION_SHIFT)); ++ if (cfg->halfdup_bp_no_backoff) ++ tmp |= HAFDUP_BP_NO_BACKOFF; ++ if (cfg->halfdup_no_backoff) ++ tmp |= HAFDUP_NO_BACKOFF; ++ if (cfg->halfdup_excess_defer) ++ tmp |= HAFDUP_EXCESS_DEFER; ++ tmp |= ((cfg->halfdup_retransmit << HAFDUP_RETRANSMISSION_MAX_SHIFT) ++ & HAFDUP_RETRANSMISSION_MAX); ++ tmp |= (cfg->halfdup_coll_window & HAFDUP_COLLISION_WINDOW); ++ ++ iowrite32be(tmp, ®s->hafdup); ++ /***************HAFDUP************************/ ++ ++ /***************MAXFRM************************/ ++ /* Initialize MAXFRM */ ++ iowrite32be(cfg->maximum_frame, ®s->maxfrm); ++ ++ /***************MAXFRM************************/ ++ ++ /***************CAM1************************/ ++ iowrite32be(0xffffffff, ®s->cam1); ++ iowrite32be(0xffffffff, ®s->cam2); ++ ++ /***************IMASK************************/ ++ iowrite32be(exception_mask, ®s->imask); ++ /***************IMASK************************/ ++ ++ /***************IEVENT************************/ ++ iowrite32be(0xffffffff, ®s->ievent); ++ ++ /***************MACSTNADDR1/2*****************/ ++ ++ tmp = (uint32_t)((macaddr[5] << 24) | ++ (macaddr[4] << 16) | ++ (macaddr[3] << 8) | ++ macaddr[2]); ++ iowrite32be(tmp, ®s->macstnaddr1); ++ ++ tmp = (uint32_t)((macaddr[1] << 24) | ++ (macaddr[0] << 16)); ++ iowrite32be(tmp, ®s->macstnaddr2); ++ ++ /***************MACSTNADDR1/2*****************/ ++ ++ /*****************HASH************************/ ++ for (i = 0; i < NUM_OF_HASH_REGS ; i++) { ++ /* Initialize IADDRx */ ++ iowrite32be(0, ®s->igaddr[i]); ++ /* Initialize GADDRx */ ++ iowrite32be(0, ®s->gaddr[i]); ++ } ++ ++ fman_dtsec_reset_stat(regs); ++ ++ return 0; ++} ++ ++uint16_t fman_dtsec_get_max_frame_len(struct dtsec_regs *regs) ++{ ++ return (uint16_t)ioread32be(®s->maxfrm); ++} ++ ++void fman_dtsec_set_max_frame_len(struct dtsec_regs *regs, uint16_t length) ++{ ++ iowrite32be(length, ®s->maxfrm); ++} ++ ++void fman_dtsec_set_mac_address(struct dtsec_regs *regs, uint8_t *adr) ++{ ++ uint32_t tmp; ++ ++ tmp = (uint32_t)((adr[5] << 24) | ++ (adr[4] << 16) | ++ (adr[3] << 8) | ++ adr[2]); ++ iowrite32be(tmp, ®s->macstnaddr1); ++ ++ tmp = (uint32_t)((adr[1] << 24) | ++ (adr[0] << 16)); ++ iowrite32be(tmp, ®s->macstnaddr2); ++} ++ ++void fman_dtsec_get_mac_address(struct dtsec_regs *regs, uint8_t *macaddr) ++{ ++ uint32_t tmp1, tmp2; ++ ++ tmp1 = ioread32be(®s->macstnaddr1); ++ tmp2 = ioread32be(®s->macstnaddr2); ++ ++ macaddr[0] = (uint8_t)((tmp2 & 0x00ff0000) >> 16); ++ macaddr[1] = (uint8_t)((tmp2 & 0xff000000) >> 24); ++ macaddr[2] = (uint8_t)(tmp1 & 0x000000ff); ++ macaddr[3] = (uint8_t)((tmp1 & 0x0000ff00) >> 8); ++ macaddr[4] = (uint8_t)((tmp1 & 0x00ff0000) >> 16); ++ macaddr[5] = (uint8_t)((tmp1 & 0xff000000) >> 24); ++} ++ ++void fman_dtsec_set_hash_table(struct dtsec_regs *regs, uint32_t crc, bool mcast, bool ghtx) ++{ ++ int32_t bucket; ++ if (ghtx) ++ bucket = (int32_t)((crc >> 23) & 0x1ff); ++ else { ++ bucket = (int32_t)((crc >> 24) & 0xff); ++ /* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */ ++ if (mcast) ++ bucket += 0x100; ++ } ++ fman_dtsec_set_bucket(regs, bucket, TRUE); ++} ++ ++void fman_dtsec_set_bucket(struct dtsec_regs *regs, int bucket, bool enable) ++{ ++ int reg_idx = (bucket >> 5) & 0xf; ++ int bit_idx = bucket & 0x1f; ++ uint32_t bit_mask = 0x80000000 >> bit_idx; ++ uint32_t *reg; ++ ++ if (reg_idx > 7) ++ reg = ®s->gaddr[reg_idx-8]; ++ else ++ reg = ®s->igaddr[reg_idx]; ++ ++ if (enable) ++ iowrite32be(ioread32be(reg) | bit_mask, reg); ++ else ++ iowrite32be(ioread32be(reg) & (~bit_mask), reg); ++} ++ ++void fman_dtsec_reset_filter_table(struct dtsec_regs *regs, bool mcast, bool ucast) ++{ ++ int i; ++ bool ghtx; ++ ++ ghtx = (bool)((ioread32be(®s->rctrl) & RCTRL_GHTX) ? TRUE : FALSE); ++ ++ if (ucast || (ghtx && mcast)) { ++ for (i = 0; i < NUM_OF_HASH_REGS; i++) ++ iowrite32be(0, ®s->igaddr[i]); ++ } ++ if (mcast) { ++ for (i = 0; i < NUM_OF_HASH_REGS; i++) ++ iowrite32be(0, ®s->gaddr[i]); ++ } ++} ++ ++int fman_dtsec_set_tbi_phy_addr(struct dtsec_regs *regs, ++ uint8_t addr) ++{ ++ if (addr > 0 && addr < 32) ++ iowrite32be(addr, ®s->tbipa); ++ else ++ return -EINVAL; ++ ++ return 0; ++} ++ ++void fman_dtsec_set_wol(struct dtsec_regs *regs, bool en) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->maccfg2); ++ if (en) ++ tmp |= MACCFG2_MAGIC_PACKET_EN; ++ else ++ tmp &= ~MACCFG2_MAGIC_PACKET_EN; ++ iowrite32be(tmp, ®s->maccfg2); ++} ++ ++int fman_dtsec_adjust_link(struct dtsec_regs *regs, ++ enum enet_interface iface_mode, ++ enum enet_speed speed, bool full_dx) ++{ ++ uint32_t tmp; ++ ++ UNUSED(iface_mode); ++ ++ if ((speed == E_ENET_SPEED_1000) && !full_dx) ++ return -EINVAL; ++ ++ tmp = ioread32be(®s->maccfg2); ++ if (!full_dx) ++ tmp &= ~MACCFG2_FULL_DUPLEX; ++ else ++ tmp |= MACCFG2_FULL_DUPLEX; ++ ++ tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE); ++ if (speed < E_ENET_SPEED_1000) ++ tmp |= MACCFG2_NIBBLE_MODE; ++ else if (speed == E_ENET_SPEED_1000) ++ tmp |= MACCFG2_BYTE_MODE; ++ iowrite32be(tmp, ®s->maccfg2); ++ ++ tmp = ioread32be(®s->ecntrl); ++ if (speed == E_ENET_SPEED_100) ++ tmp |= DTSEC_ECNTRL_R100M; ++ else ++ tmp &= ~DTSEC_ECNTRL_R100M; ++ iowrite32be(tmp, ®s->ecntrl); ++ ++ return 0; ++} ++ ++void fman_dtsec_set_uc_promisc(struct dtsec_regs *regs, bool enable) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->rctrl); ++ ++ if (enable) ++ tmp |= RCTRL_UPROM; ++ else ++ tmp &= ~RCTRL_UPROM; ++ ++ iowrite32be(tmp, ®s->rctrl); ++} ++ ++void fman_dtsec_set_mc_promisc(struct dtsec_regs *regs, bool enable) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->rctrl); ++ ++ if (enable) ++ tmp |= RCTRL_MPROM; ++ else ++ tmp &= ~RCTRL_MPROM; ++ ++ iowrite32be(tmp, ®s->rctrl); ++} ++ ++bool fman_dtsec_get_clear_carry_regs(struct dtsec_regs *regs, ++ uint32_t *car1, uint32_t *car2) ++{ ++ /* read carry registers */ ++ *car1 = ioread32be(®s->car1); ++ *car2 = ioread32be(®s->car2); ++ /* clear carry registers */ ++ if (*car1) ++ iowrite32be(*car1, ®s->car1); ++ if (*car2) ++ iowrite32be(*car2, ®s->car2); ++ ++ return (bool)((*car1 | *car2) ? TRUE : FALSE); ++} ++ ++void fman_dtsec_reset_stat(struct dtsec_regs *regs) ++{ ++ /* clear HW counters */ ++ iowrite32be(ioread32be(®s->ecntrl) | ++ DTSEC_ECNTRL_CLRCNT, ®s->ecntrl); ++} ++ ++int fman_dtsec_set_stat_level(struct dtsec_regs *regs, enum dtsec_stat_level level) ++{ ++ switch (level) { ++ case E_MAC_STAT_NONE: ++ iowrite32be(0xffffffff, ®s->cam1); ++ iowrite32be(0xffffffff, ®s->cam2); ++ iowrite32be(ioread32be(®s->ecntrl) & ~DTSEC_ECNTRL_STEN, ++ ®s->ecntrl); ++ iowrite32be(ioread32be(®s->imask) & ~DTSEC_IMASK_MSROEN, ++ ®s->imask); ++ break; ++ case E_MAC_STAT_PARTIAL: ++ iowrite32be(CAM1_ERRORS_ONLY, ®s->cam1); ++ iowrite32be(CAM2_ERRORS_ONLY, ®s->cam2); ++ iowrite32be(ioread32be(®s->ecntrl) | DTSEC_ECNTRL_STEN, ++ ®s->ecntrl); ++ iowrite32be(ioread32be(®s->imask) | DTSEC_IMASK_MSROEN, ++ ®s->imask); ++ break; ++ case E_MAC_STAT_MIB_GRP1: ++ iowrite32be((uint32_t)~CAM1_MIB_GRP_1, ®s->cam1); ++ iowrite32be((uint32_t)~CAM2_MIB_GRP_1, ®s->cam2); ++ iowrite32be(ioread32be(®s->ecntrl) | DTSEC_ECNTRL_STEN, ++ ®s->ecntrl); ++ iowrite32be(ioread32be(®s->imask) | DTSEC_IMASK_MSROEN, ++ ®s->imask); ++ break; ++ case E_MAC_STAT_FULL: ++ iowrite32be(0, ®s->cam1); ++ iowrite32be(0, ®s->cam2); ++ iowrite32be(ioread32be(®s->ecntrl) | DTSEC_ECNTRL_STEN, ++ ®s->ecntrl); ++ iowrite32be(ioread32be(®s->imask) | DTSEC_IMASK_MSROEN, ++ ®s->imask); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++void fman_dtsec_set_ts(struct dtsec_regs *regs, bool en) ++{ ++ if (en) { ++ iowrite32be(ioread32be(®s->rctrl) | RCTRL_RTSE, ++ ®s->rctrl); ++ iowrite32be(ioread32be(®s->tctrl) | DTSEC_TCTRL_TTSE, ++ ®s->tctrl); ++ } else { ++ iowrite32be(ioread32be(®s->rctrl) & ~RCTRL_RTSE, ++ ®s->rctrl); ++ iowrite32be(ioread32be(®s->tctrl) & ~DTSEC_TCTRL_TTSE, ++ ®s->tctrl); ++ } ++} ++ ++void fman_dtsec_enable(struct dtsec_regs *regs, bool apply_rx, bool apply_tx) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->maccfg1); ++ ++ if (apply_rx) ++ tmp |= MACCFG1_RX_EN ; ++ ++ if (apply_tx) ++ tmp |= MACCFG1_TX_EN ; ++ ++ iowrite32be(tmp, ®s->maccfg1); ++} ++ ++void fman_dtsec_clear_addr_in_paddr(struct dtsec_regs *regs, uint8_t paddr_num) ++{ ++ iowrite32be(0, ®s->macaddr[paddr_num].exact_match1); ++ iowrite32be(0, ®s->macaddr[paddr_num].exact_match2); ++} ++ ++void fman_dtsec_add_addr_in_paddr(struct dtsec_regs *regs, ++ uint64_t addr, ++ uint8_t paddr_num) ++{ ++ uint32_t tmp; ++ ++ tmp = (uint32_t)(addr); ++ /* swap */ ++ tmp = (((tmp & 0x000000FF) << 24) | ++ ((tmp & 0x0000FF00) << 8) | ++ ((tmp & 0x00FF0000) >> 8) | ++ ((tmp & 0xFF000000) >> 24)); ++ iowrite32be(tmp, ®s->macaddr[paddr_num].exact_match1); ++ ++ tmp = (uint32_t)(addr>>32); ++ /* swap */ ++ tmp = (((tmp & 0x000000FF) << 24) | ++ ((tmp & 0x0000FF00) << 8) | ++ ((tmp & 0x00FF0000) >> 8) | ++ ((tmp & 0xFF000000) >> 24)); ++ iowrite32be(tmp, ®s->macaddr[paddr_num].exact_match2); ++} ++ ++void fman_dtsec_disable(struct dtsec_regs *regs, bool apply_rx, bool apply_tx) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->maccfg1); ++ ++ if (apply_rx) ++ tmp &= ~MACCFG1_RX_EN; ++ ++ if (apply_tx) ++ tmp &= ~MACCFG1_TX_EN; ++ ++ iowrite32be(tmp, ®s->maccfg1); ++} ++ ++void fman_dtsec_set_tx_pause_frames(struct dtsec_regs *regs, uint16_t time) ++{ ++ uint32_t ptv = 0; ++ ++ /* fixme: don't enable tx pause for half-duplex */ ++ ++ if (time) { ++ ptv = ioread32be(®s->ptv); ++ ptv &= 0xffff0000; ++ ptv |= time & 0x0000ffff; ++ iowrite32be(ptv, ®s->ptv); ++ ++ /* trigger the transmission of a flow-control pause frame */ ++ iowrite32be(ioread32be(®s->maccfg1) | MACCFG1_TX_FLOW, ++ ®s->maccfg1); ++ } else ++ iowrite32be(ioread32be(®s->maccfg1) & ~MACCFG1_TX_FLOW, ++ ®s->maccfg1); ++} ++ ++void fman_dtsec_handle_rx_pause(struct dtsec_regs *regs, bool en) ++{ ++ uint32_t tmp; ++ ++ /* todo: check if mac is set to full-duplex */ ++ ++ tmp = ioread32be(®s->maccfg1); ++ if (en) ++ tmp |= MACCFG1_RX_FLOW; ++ else ++ tmp &= ~MACCFG1_RX_FLOW; ++ iowrite32be(tmp, ®s->maccfg1); ++} ++ ++uint32_t fman_dtsec_get_rctrl(struct dtsec_regs *regs) ++{ ++ return ioread32be(®s->rctrl); ++} ++ ++uint32_t fman_dtsec_get_revision(struct dtsec_regs *regs) ++{ ++ return ioread32be(®s->tsec_id); ++} ++ ++uint32_t fman_dtsec_get_event(struct dtsec_regs *regs, uint32_t ev_mask) ++{ ++ return ioread32be(®s->ievent) & ev_mask; ++} ++ ++void fman_dtsec_ack_event(struct dtsec_regs *regs, uint32_t ev_mask) ++{ ++ iowrite32be(ev_mask, ®s->ievent); ++} ++ ++uint32_t fman_dtsec_get_interrupt_mask(struct dtsec_regs *regs) ++{ ++ return ioread32be(®s->imask); ++} ++ ++uint32_t fman_dtsec_check_and_clear_tmr_event(struct dtsec_regs *regs) ++{ ++ uint32_t event; ++ ++ event = ioread32be(®s->tmr_pevent); ++ event &= ioread32be(®s->tmr_pemask); ++ ++ if (event) ++ iowrite32be(event, ®s->tmr_pevent); ++ return event; ++} ++ ++void fman_dtsec_enable_tmr_interrupt(struct dtsec_regs *regs) ++{ ++ iowrite32be(ioread32be(®s->tmr_pemask) | TMR_PEMASK_TSREEN, ++ ®s->tmr_pemask); ++} ++ ++void fman_dtsec_disable_tmr_interrupt(struct dtsec_regs *regs) ++{ ++ iowrite32be(ioread32be(®s->tmr_pemask) & ~TMR_PEMASK_TSREEN, ++ ®s->tmr_pemask); ++} ++ ++void fman_dtsec_enable_interrupt(struct dtsec_regs *regs, uint32_t ev_mask) ++{ ++ iowrite32be(ioread32be(®s->imask) | ev_mask, ®s->imask); ++} ++ ++void fman_dtsec_disable_interrupt(struct dtsec_regs *regs, uint32_t ev_mask) ++{ ++ iowrite32be(ioread32be(®s->imask) & ~ev_mask, ®s->imask); ++} ++ ++uint32_t fman_dtsec_get_stat_counter(struct dtsec_regs *regs, ++ enum dtsec_stat_counters reg_name) ++{ ++ uint32_t ret_val; ++ ++ switch (reg_name) { ++ case E_DTSEC_STAT_TR64: ++ ret_val = ioread32be(®s->tr64); ++ break; ++ case E_DTSEC_STAT_TR127: ++ ret_val = ioread32be(®s->tr127); ++ break; ++ case E_DTSEC_STAT_TR255: ++ ret_val = ioread32be(®s->tr255); ++ break; ++ case E_DTSEC_STAT_TR511: ++ ret_val = ioread32be(®s->tr511); ++ break; ++ case E_DTSEC_STAT_TR1K: ++ ret_val = ioread32be(®s->tr1k); ++ break; ++ case E_DTSEC_STAT_TRMAX: ++ ret_val = ioread32be(®s->trmax); ++ break; ++ case E_DTSEC_STAT_TRMGV: ++ ret_val = ioread32be(®s->trmgv); ++ break; ++ case E_DTSEC_STAT_RBYT: ++ ret_val = ioread32be(®s->rbyt); ++ break; ++ case E_DTSEC_STAT_RPKT: ++ ret_val = ioread32be(®s->rpkt); ++ break; ++ case E_DTSEC_STAT_RMCA: ++ ret_val = ioread32be(®s->rmca); ++ break; ++ case E_DTSEC_STAT_RBCA: ++ ret_val = ioread32be(®s->rbca); ++ break; ++ case E_DTSEC_STAT_RXPF: ++ ret_val = ioread32be(®s->rxpf); ++ break; ++ case E_DTSEC_STAT_RALN: ++ ret_val = ioread32be(®s->raln); ++ break; ++ case E_DTSEC_STAT_RFLR: ++ ret_val = ioread32be(®s->rflr); ++ break; ++ case E_DTSEC_STAT_RCDE: ++ ret_val = ioread32be(®s->rcde); ++ break; ++ case E_DTSEC_STAT_RCSE: ++ ret_val = ioread32be(®s->rcse); ++ break; ++ case E_DTSEC_STAT_RUND: ++ ret_val = ioread32be(®s->rund); ++ break; ++ case E_DTSEC_STAT_ROVR: ++ ret_val = ioread32be(®s->rovr); ++ break; ++ case E_DTSEC_STAT_RFRG: ++ ret_val = ioread32be(®s->rfrg); ++ break; ++ case E_DTSEC_STAT_RJBR: ++ ret_val = ioread32be(®s->rjbr); ++ break; ++ case E_DTSEC_STAT_RDRP: ++ ret_val = ioread32be(®s->rdrp); ++ break; ++ case E_DTSEC_STAT_TFCS: ++ ret_val = ioread32be(®s->tfcs); ++ break; ++ case E_DTSEC_STAT_TBYT: ++ ret_val = ioread32be(®s->tbyt); ++ break; ++ case E_DTSEC_STAT_TPKT: ++ ret_val = ioread32be(®s->tpkt); ++ break; ++ case E_DTSEC_STAT_TMCA: ++ ret_val = ioread32be(®s->tmca); ++ break; ++ case E_DTSEC_STAT_TBCA: ++ ret_val = ioread32be(®s->tbca); ++ break; ++ case E_DTSEC_STAT_TXPF: ++ ret_val = ioread32be(®s->txpf); ++ break; ++ case E_DTSEC_STAT_TNCL: ++ ret_val = ioread32be(®s->tncl); ++ break; ++ case E_DTSEC_STAT_TDRP: ++ ret_val = ioread32be(®s->tdrp); ++ break; ++ default: ++ ret_val = 0; ++ } ++ ++ return ret_val; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_dtsec_mii_acc.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_dtsec_mii_acc.c +new file mode 100644 +index 0000000..8819f8f +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_dtsec_mii_acc.c +@@ -0,0 +1,163 @@ ++/* ++ * Copyright 2008-2013 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 "common/general.h" ++#include "fsl_fman_dtsec_mii_acc.h" ++ ++ ++/** ++ * dtsec_mii_get_div() - calculates the value of the dtsec mii divider ++ * @dtsec_freq: dtsec clock frequency (in Mhz) ++ * ++ * This function calculates the dtsec mii clock divider that determines ++ * the MII MDC clock. MII MDC clock will be set to work in the range ++ * of 1.5 to 2.5Mhz ++ * The output of this function is the value of MIIMCFG[MgmtClk] which ++ * implicitly determines the divider value. ++ * Note: the dTSEC system clock is equal to 1/2 of the FMan clock. ++ * ++ * The table below which reflects dtsec_mii_get_div() functionality ++ * shows the relations among dtsec_freq, MgmtClk, actual divider ++ * and the MII frequency: ++ * ++ * dtsec freq MgmtClk div MII freq Mhz ++ * [0.....80] 1 (1/4)(1/8) [0 to 2.5] ++ * [81...120] 2 (1/6)(1/8) [1.6 to 2.5] ++ * [121..160] 3 (1/8)(1/8) [1.8 to 2.5] ++ * [161..200] 4 (1/10)(1/8) [2.0 to 2.5] ++ * [201..280] 5 (1/14)(1/8) [1.8 to 2.5] ++ * [281..400] 6 (1/20)(1/8) [1.1 to 2.5] ++ * [401..560] 7 (1/28)(1/8) [1.8 to 2.5] ++ * [560..frq] 7 (1/28)(1/8) [frq/224] ++ * ++ * Returns: the MIIMCFG[MgmtClk] appropriate value ++ */ ++ ++static uint8_t dtsec_mii_get_div(uint16_t dtsec_freq) ++{ ++ uint16_t mgmt_clk; ++ ++ if (dtsec_freq < 80) mgmt_clk = 1; ++ else if (dtsec_freq < 120) mgmt_clk = 2; ++ else if (dtsec_freq < 160) mgmt_clk = 3; ++ else if (dtsec_freq < 200) mgmt_clk = 4; ++ else if (dtsec_freq < 280) mgmt_clk = 5; ++ else if (dtsec_freq < 400) mgmt_clk = 6; ++ else mgmt_clk = 7; ++ ++ return (uint8_t)mgmt_clk; ++} ++ ++void fman_dtsec_mii_reset(struct dtsec_mii_reg *regs) ++{ ++ /* Reset the management interface */ ++ iowrite32be(ioread32be(®s->miimcfg) | MIIMCFG_RESET_MGMT, ++ ®s->miimcfg); ++ iowrite32be(ioread32be(®s->miimcfg) & ~MIIMCFG_RESET_MGMT, ++ ®s->miimcfg); ++} ++ ++ ++int fman_dtsec_mii_write_reg(struct dtsec_mii_reg *regs, uint8_t addr, ++ uint8_t reg, uint16_t data, uint16_t dtsec_freq) ++{ ++ uint32_t tmp; ++ ++ /* Setup the MII Mgmt clock speed */ ++ iowrite32be((uint32_t)dtsec_mii_get_div(dtsec_freq), ®s->miimcfg); ++ wmb(); ++ ++ /* Stop the MII management read cycle */ ++ iowrite32be(0, ®s->miimcom); ++ /* Dummy read to make sure MIIMCOM is written */ ++ tmp = ioread32be(®s->miimcom); ++ wmb(); ++ ++ /* Setting up MII Management Address Register */ ++ tmp = (uint32_t)((addr << MIIMADD_PHY_ADDR_SHIFT) | reg); ++ iowrite32be(tmp, ®s->miimadd); ++ wmb(); ++ ++ /* Setting up MII Management Control Register with data */ ++ iowrite32be((uint32_t)data, ®s->miimcon); ++ /* Dummy read to make sure MIIMCON is written */ ++ tmp = ioread32be(®s->miimcon); ++ wmb(); ++ ++ /* Wait until MII management write is complete */ ++ /* todo: a timeout could be useful here */ ++ while ((ioread32be(®s->miimind)) & MIIMIND_BUSY) ++ /* busy wait */; ++ ++ return 0; ++} ++ ++int fman_dtsec_mii_read_reg(struct dtsec_mii_reg *regs, uint8_t addr, ++ uint8_t reg, uint16_t *data, uint16_t dtsec_freq) ++{ ++ uint32_t tmp; ++ ++ /* Setup the MII Mgmt clock speed */ ++ iowrite32be((uint32_t)dtsec_mii_get_div(dtsec_freq), ®s->miimcfg); ++ wmb(); ++ ++ /* Setting up the MII Management Address Register */ ++ tmp = (uint32_t)((addr << MIIMADD_PHY_ADDR_SHIFT) | reg); ++ iowrite32be(tmp, ®s->miimadd); ++ wmb(); ++ ++ /* Perform an MII management read cycle */ ++ iowrite32be(MIIMCOM_READ_CYCLE, ®s->miimcom); ++ /* Dummy read to make sure MIIMCOM is written */ ++ tmp = ioread32be(®s->miimcom); ++ wmb(); ++ ++ /* Wait until MII management read is complete */ ++ /* todo: a timeout could be useful here */ ++ while ((ioread32be(®s->miimind)) & MIIMIND_BUSY) ++ /* busy wait */; ++ ++ /* Read MII management status */ ++ *data = (uint16_t)ioread32be(®s->miimstat); ++ wmb(); ++ ++ iowrite32be(0, ®s->miimcom); ++ /* Dummy read to make sure MIIMCOM is written */ ++ tmp = ioread32be(®s->miimcom); ++ ++ if (*data == 0xffff) ++ return -ENXIO; ++ ++ return 0; ++} ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_memac.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_memac.c +new file mode 100644 +index 0000000..00995a1 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_memac.c +@@ -0,0 +1,511 @@ ++/* ++ * Copyright 2008-2012 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 "fsl_fman_memac.h" ++ ++ ++uint32_t fman_memac_get_event(struct memac_regs *regs, uint32_t ev_mask) ++{ ++ return ioread32be(®s->ievent) & ev_mask; ++} ++ ++uint32_t fman_memac_get_interrupt_mask(struct memac_regs *regs) ++{ ++ return ioread32be(®s->imask); ++} ++ ++void fman_memac_ack_event(struct memac_regs *regs, uint32_t ev_mask) ++{ ++ iowrite32be(ev_mask, ®s->ievent); ++} ++ ++void fman_memac_set_promiscuous(struct memac_regs *regs, bool val) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ ++ if (val) ++ tmp |= CMD_CFG_PROMIS_EN; ++ else ++ tmp &= ~CMD_CFG_PROMIS_EN; ++ ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++void fman_memac_clear_addr_in_paddr(struct memac_regs *regs, ++ uint8_t paddr_num) ++{ ++ if (paddr_num == 0) { ++ iowrite32be(0, ®s->mac_addr0.mac_addr_l); ++ iowrite32be(0, ®s->mac_addr0.mac_addr_u); ++ } else { ++ iowrite32be(0x0, ®s->mac_addr[paddr_num - 1].mac_addr_l); ++ iowrite32be(0x0, ®s->mac_addr[paddr_num - 1].mac_addr_u); ++ } ++} ++ ++void fman_memac_add_addr_in_paddr(struct memac_regs *regs, ++ uint8_t *adr, ++ uint8_t paddr_num) ++{ ++ uint32_t tmp0, tmp1; ++ ++ tmp0 = (uint32_t)(adr[0] | ++ adr[1] << 8 | ++ adr[2] << 16 | ++ adr[3] << 24); ++ tmp1 = (uint32_t)(adr[4] | adr[5] << 8); ++ ++ if (paddr_num == 0) { ++ iowrite32be(tmp0, ®s->mac_addr0.mac_addr_l); ++ iowrite32be(tmp1, ®s->mac_addr0.mac_addr_u); ++ } else { ++ iowrite32be(tmp0, ®s->mac_addr[paddr_num-1].mac_addr_l); ++ iowrite32be(tmp1, ®s->mac_addr[paddr_num-1].mac_addr_u); ++ } ++} ++ ++void fman_memac_enable(struct memac_regs *regs, bool apply_rx, bool apply_tx) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ ++ if (apply_rx) ++ tmp |= CMD_CFG_RX_EN; ++ ++ if (apply_tx) ++ tmp |= CMD_CFG_TX_EN; ++ ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++void fman_memac_disable(struct memac_regs *regs, bool apply_rx, bool apply_tx) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ ++ if (apply_rx) ++ tmp &= ~CMD_CFG_RX_EN; ++ ++ if (apply_tx) ++ tmp &= ~CMD_CFG_TX_EN; ++ ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++void fman_memac_reset_stat(struct memac_regs *regs) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->statn_config); ++ ++ tmp |= STATS_CFG_CLR; ++ ++ iowrite32be(tmp, ®s->statn_config); ++ ++ while (ioread32be(®s->statn_config) & STATS_CFG_CLR); ++} ++ ++void fman_memac_reset(struct memac_regs *regs) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ ++ tmp |= CMD_CFG_SW_RESET; ++ ++ iowrite32be(tmp, ®s->command_config); ++ ++ while (ioread32be(®s->command_config) & CMD_CFG_SW_RESET); ++} ++ ++int fman_memac_init(struct memac_regs *regs, ++ struct memac_cfg *cfg, ++ enum enet_interface enet_interface, ++ enum enet_speed enet_speed, ++ bool slow_10g_if, ++ uint32_t exceptions) ++{ ++ uint32_t tmp; ++ ++ /* Config */ ++ tmp = 0; ++ if (cfg->wan_mode_enable) ++ tmp |= CMD_CFG_WAN_MODE; ++ if (cfg->promiscuous_mode_enable) ++ tmp |= CMD_CFG_PROMIS_EN; ++ if (cfg->pause_forward_enable) ++ tmp |= CMD_CFG_PAUSE_FWD; ++ if (cfg->pause_ignore) ++ tmp |= CMD_CFG_PAUSE_IGNORE; ++ if (cfg->tx_addr_ins_enable) ++ tmp |= CMD_CFG_TX_ADDR_INS; ++ if (cfg->loopback_enable) ++ tmp |= CMD_CFG_LOOPBACK_EN; ++ if (cfg->cmd_frame_enable) ++ tmp |= CMD_CFG_CNT_FRM_EN; ++ if (cfg->send_idle_enable) ++ tmp |= CMD_CFG_SEND_IDLE; ++ if (cfg->no_length_check_enable) ++ tmp |= CMD_CFG_NO_LEN_CHK; ++ if (cfg->rx_sfd_any) ++ tmp |= CMD_CFG_SFD_ANY; ++ if (cfg->pad_enable) ++ tmp |= CMD_CFG_TX_PAD_EN; ++ if (cfg->wake_on_lan) ++ tmp |= CMD_CFG_MG; ++ ++ tmp |= CMD_CFG_CRC_FWD; ++ ++ iowrite32be(tmp, ®s->command_config); ++ ++ /* Max Frame Length */ ++ iowrite32be((uint32_t)cfg->max_frame_length, ®s->maxfrm); ++ ++ /* Pause Time */ ++ iowrite32be((uint32_t)cfg->pause_quanta, ®s->pause_quanta[0]); ++ iowrite32be((uint32_t)0, ®s->pause_thresh[0]); ++ ++ /* IF_MODE */ ++ tmp = 0; ++ switch (enet_interface) { ++ case E_ENET_IF_XGMII: ++ case E_ENET_IF_XFI: ++ tmp |= IF_MODE_XGMII; ++ break; ++ default: ++ tmp |= IF_MODE_GMII; ++ if (enet_interface == E_ENET_IF_RGMII && !cfg->loopback_enable) ++ tmp |= IF_MODE_RGMII | IF_MODE_RGMII_AUTO; ++ } ++ iowrite32be(tmp, ®s->if_mode); ++ ++ /* TX_FIFO_SECTIONS */ ++ tmp = 0; ++ if (enet_interface == E_ENET_IF_XGMII || ++ enet_interface == E_ENET_IF_XFI) { ++ if(slow_10g_if) { ++ tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G | ++ TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G); ++ } else { ++ tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_10G | ++ TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G); ++ } ++ } else { ++ tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_1G | ++ TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G); ++ } ++ iowrite32be(tmp, ®s->tx_fifo_sections); ++ ++ /* clear all pending events and set-up interrupts */ ++ fman_memac_ack_event(regs, 0xffffffff); ++ fman_memac_set_exception(regs, exceptions, TRUE); ++ ++ return 0; ++} ++ ++void fman_memac_set_exception(struct memac_regs *regs, uint32_t val, bool enable) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->imask); ++ if (enable) ++ tmp |= val; ++ else ++ tmp &= ~val; ++ ++ iowrite32be(tmp, ®s->imask); ++} ++ ++void fman_memac_reset_filter_table(struct memac_regs *regs) ++{ ++ uint32_t i; ++ for (i = 0; i < 64; i++) ++ iowrite32be(i & ~HASH_CTRL_MCAST_EN, ®s->hashtable_ctrl); ++} ++ ++void fman_memac_set_hash_table_entry(struct memac_regs *regs, uint32_t crc) ++{ ++ iowrite32be(crc | HASH_CTRL_MCAST_EN, ®s->hashtable_ctrl); ++} ++ ++void fman_memac_set_hash_table(struct memac_regs *regs, uint32_t val) ++{ ++ iowrite32be(val, ®s->hashtable_ctrl); ++} ++ ++uint16_t fman_memac_get_max_frame_len(struct memac_regs *regs) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->maxfrm); ++ ++ return(uint16_t)tmp; ++} ++ ++ ++void fman_memac_set_tx_pause_frames(struct memac_regs *regs, ++ uint8_t priority, ++ uint16_t pause_time, ++ uint16_t thresh_time) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->tx_fifo_sections); ++ ++ if (priority == 0xff) { ++ GET_TX_EMPTY_DEFAULT_VALUE(tmp); ++ iowrite32be(tmp, ®s->tx_fifo_sections); ++ ++ tmp = ioread32be(®s->command_config); ++ tmp &= ~CMD_CFG_PFC_MODE; ++ priority = 0; ++ } else { ++ GET_TX_EMPTY_PFC_VALUE(tmp); ++ iowrite32be(tmp, ®s->tx_fifo_sections); ++ ++ tmp = ioread32be(®s->command_config); ++ tmp |= CMD_CFG_PFC_MODE; ++ } ++ ++ iowrite32be(tmp, ®s->command_config); ++ ++ tmp = ioread32be(®s->pause_quanta[priority / 2]); ++ if (priority % 2) ++ tmp &= 0x0000FFFF; ++ else ++ tmp &= 0xFFFF0000; ++ tmp |= ((uint32_t)pause_time << (16 * (priority % 2))); ++ iowrite32be(tmp, ®s->pause_quanta[priority / 2]); ++ ++ tmp = ioread32be(®s->pause_thresh[priority / 2]); ++ if (priority % 2) ++ tmp &= 0x0000FFFF; ++ else ++ tmp &= 0xFFFF0000; ++ tmp |= ((uint32_t)thresh_time<<(16 * (priority % 2))); ++ iowrite32be(tmp, ®s->pause_thresh[priority / 2]); ++} ++ ++void fman_memac_set_rx_ignore_pause_frames(struct memac_regs *regs,bool enable) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ if (enable) ++ tmp |= CMD_CFG_PAUSE_IGNORE; ++ else ++ tmp &= ~CMD_CFG_PAUSE_IGNORE; ++ ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++void fman_memac_set_wol(struct memac_regs *regs, bool enable) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ ++ if (enable) ++ tmp |= CMD_CFG_MG; ++ else ++ tmp &= ~CMD_CFG_MG; ++ ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++#define GET_MEMAC_CNTR_64(bn) \ ++ (ioread32be(®s->bn ## _l) | \ ++ ((uint64_t)ioread32be(®s->bn ## _u) << 32)) ++ ++uint64_t fman_memac_get_counter(struct memac_regs *regs, ++ enum memac_counters reg_name) ++{ ++ uint64_t ret_val; ++ ++ switch (reg_name) { ++ case E_MEMAC_COUNTER_R64: ++ ret_val = GET_MEMAC_CNTR_64(r64); ++ break; ++ case E_MEMAC_COUNTER_R127: ++ ret_val = GET_MEMAC_CNTR_64(r127); ++ break; ++ case E_MEMAC_COUNTER_R255: ++ ret_val = GET_MEMAC_CNTR_64(r255); ++ break; ++ case E_MEMAC_COUNTER_R511: ++ ret_val = GET_MEMAC_CNTR_64(r511); ++ break; ++ case E_MEMAC_COUNTER_R1023: ++ ret_val = GET_MEMAC_CNTR_64(r1023); ++ break; ++ case E_MEMAC_COUNTER_R1518: ++ ret_val = GET_MEMAC_CNTR_64(r1518); ++ break; ++ case E_MEMAC_COUNTER_R1519X: ++ ret_val = GET_MEMAC_CNTR_64(r1519x); ++ break; ++ case E_MEMAC_COUNTER_RFRG: ++ ret_val = GET_MEMAC_CNTR_64(rfrg); ++ break; ++ case E_MEMAC_COUNTER_RJBR: ++ ret_val = GET_MEMAC_CNTR_64(rjbr); ++ break; ++ case E_MEMAC_COUNTER_RDRP: ++ ret_val = GET_MEMAC_CNTR_64(rdrp); ++ break; ++ case E_MEMAC_COUNTER_RALN: ++ ret_val = GET_MEMAC_CNTR_64(raln); ++ break; ++ case E_MEMAC_COUNTER_TUND: ++ ret_val = GET_MEMAC_CNTR_64(tund); ++ break; ++ case E_MEMAC_COUNTER_ROVR: ++ ret_val = GET_MEMAC_CNTR_64(rovr); ++ break; ++ case E_MEMAC_COUNTER_RXPF: ++ ret_val = GET_MEMAC_CNTR_64(rxpf); ++ break; ++ case E_MEMAC_COUNTER_TXPF: ++ ret_val = GET_MEMAC_CNTR_64(txpf); ++ break; ++ case E_MEMAC_COUNTER_ROCT: ++ ret_val = GET_MEMAC_CNTR_64(roct); ++ break; ++ case E_MEMAC_COUNTER_RMCA: ++ ret_val = GET_MEMAC_CNTR_64(rmca); ++ break; ++ case E_MEMAC_COUNTER_RBCA: ++ ret_val = GET_MEMAC_CNTR_64(rbca); ++ break; ++ case E_MEMAC_COUNTER_RPKT: ++ ret_val = GET_MEMAC_CNTR_64(rpkt); ++ break; ++ case E_MEMAC_COUNTER_RUCA: ++ ret_val = GET_MEMAC_CNTR_64(ruca); ++ break; ++ case E_MEMAC_COUNTER_RERR: ++ ret_val = GET_MEMAC_CNTR_64(rerr); ++ break; ++ case E_MEMAC_COUNTER_TOCT: ++ ret_val = GET_MEMAC_CNTR_64(toct); ++ break; ++ case E_MEMAC_COUNTER_TMCA: ++ ret_val = GET_MEMAC_CNTR_64(tmca); ++ break; ++ case E_MEMAC_COUNTER_TBCA: ++ ret_val = GET_MEMAC_CNTR_64(tbca); ++ break; ++ case E_MEMAC_COUNTER_TUCA: ++ ret_val = GET_MEMAC_CNTR_64(tuca); ++ break; ++ case E_MEMAC_COUNTER_TERR: ++ ret_val = GET_MEMAC_CNTR_64(terr); ++ break; ++ default: ++ ret_val = 0; ++ } ++ ++ return ret_val; ++} ++ ++void fman_memac_adjust_link(struct memac_regs *regs, ++ enum enet_interface iface_mode, ++ enum enet_speed speed, bool full_dx) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->if_mode); ++ ++ if (full_dx) ++ tmp &= ~IF_MODE_HD; ++ else ++ tmp |= IF_MODE_HD; ++ ++ if (iface_mode == E_ENET_IF_RGMII) { ++ /* Configure RGMII in manual mode */ ++ tmp &= ~IF_MODE_RGMII_AUTO; ++ tmp &= ~IF_MODE_RGMII_SP_MASK; ++ ++ if (full_dx) ++ tmp |= IF_MODE_RGMII_FD; ++ else ++ tmp &= ~IF_MODE_RGMII_FD; ++ ++ switch (speed) { ++ case E_ENET_SPEED_1000: ++ tmp |= IF_MODE_RGMII_1000; ++ break; ++ case E_ENET_SPEED_100: ++ tmp |= IF_MODE_RGMII_100; ++ break; ++ case E_ENET_SPEED_10: ++ tmp |= IF_MODE_RGMII_10; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ iowrite32be(tmp, ®s->if_mode); ++} ++ ++void fman_memac_defconfig(struct memac_cfg *cfg) ++{ ++ cfg->reset_on_init = FALSE; ++ cfg->wan_mode_enable = FALSE; ++ cfg->promiscuous_mode_enable = FALSE; ++ cfg->pause_forward_enable = FALSE; ++ cfg->pause_ignore = FALSE; ++ cfg->tx_addr_ins_enable = FALSE; ++ cfg->loopback_enable = FALSE; ++ cfg->cmd_frame_enable = FALSE; ++ cfg->rx_error_discard = FALSE; ++ cfg->send_idle_enable = FALSE; ++ cfg->no_length_check_enable = TRUE; ++ cfg->lgth_check_nostdr = FALSE; ++ cfg->time_stamp_enable = FALSE; ++ cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH; ++ cfg->max_frame_length = DEFAULT_FRAME_LENGTH; ++ cfg->pause_quanta = DEFAULT_PAUSE_QUANTA; ++ cfg->pad_enable = TRUE; ++ cfg->phy_tx_ena_on = FALSE; ++ cfg->rx_sfd_any = FALSE; ++ cfg->rx_pbl_fwd = FALSE; ++ cfg->tx_pbl_fwd = FALSE; ++ cfg->debug_mode = FALSE; ++ cfg->wake_on_lan = FALSE; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_memac_mii_acc.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_memac_mii_acc.c +new file mode 100755 +index 0000000..ccda11e +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_memac_mii_acc.c +@@ -0,0 +1,213 @@ ++/* ++ * Copyright 2008-2013 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 "fsl_fman_memac_mii_acc.h" ++ ++static void write_phy_reg_10g(struct memac_mii_access_mem_map *mii_regs, ++ uint8_t phy_addr, uint8_t reg, uint16_t data) ++{ ++ uint32_t tmp_reg; ++ ++ tmp_reg = ioread32be(&mii_regs->mdio_cfg); ++ /* Leave only MDIO_CLK_DIV bits set on */ ++ tmp_reg &= MDIO_CFG_CLK_DIV_MASK; ++ /* Set maximum MDIO_HOLD value to allow phy to see ++ change of data signal */ ++ tmp_reg |= MDIO_CFG_HOLD_MASK; ++ /* Add 10G interface mode */ ++ tmp_reg |= MDIO_CFG_ENC45; ++ iowrite32be(tmp_reg, &mii_regs->mdio_cfg); ++ ++ /* Wait for command completion */ ++ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) ++ udelay(1); ++ ++ /* Specify phy and register to be accessed */ ++ iowrite32be(phy_addr, &mii_regs->mdio_ctrl); ++ iowrite32be(reg, &mii_regs->mdio_addr); ++ wmb(); ++ ++ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) ++ udelay(1); ++ ++ /* Write data */ ++ iowrite32be(data, &mii_regs->mdio_data); ++ wmb(); ++ ++ /* Wait for write transaction end */ ++ while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY) ++ udelay(1); ++} ++ ++static uint32_t read_phy_reg_10g(struct memac_mii_access_mem_map *mii_regs, ++ uint8_t phy_addr, uint8_t reg, uint16_t *data) ++{ ++ uint32_t tmp_reg; ++ ++ tmp_reg = ioread32be(&mii_regs->mdio_cfg); ++ /* Leave only MDIO_CLK_DIV bits set on */ ++ tmp_reg &= MDIO_CFG_CLK_DIV_MASK; ++ /* Set maximum MDIO_HOLD value to allow phy to see ++ change of data signal */ ++ tmp_reg |= MDIO_CFG_HOLD_MASK; ++ /* Add 10G interface mode */ ++ tmp_reg |= MDIO_CFG_ENC45; ++ iowrite32be(tmp_reg, &mii_regs->mdio_cfg); ++ ++ /* Wait for command completion */ ++ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) ++ udelay(1); ++ ++ /* Specify phy and register to be accessed */ ++ iowrite32be(phy_addr, &mii_regs->mdio_ctrl); ++ iowrite32be(reg, &mii_regs->mdio_addr); ++ wmb(); ++ ++ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) ++ udelay(1); ++ ++ /* Read cycle */ ++ tmp_reg = phy_addr; ++ tmp_reg |= MDIO_CTL_READ; ++ iowrite32be(tmp_reg, &mii_regs->mdio_ctrl); ++ wmb(); ++ ++ /* Wait for data to be available */ ++ while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY) ++ udelay(1); ++ ++ *data = (uint16_t)ioread32be(&mii_regs->mdio_data); ++ ++ /* Check if there was an error */ ++ return ioread32be(&mii_regs->mdio_cfg); ++} ++ ++static void write_phy_reg_1g(struct memac_mii_access_mem_map *mii_regs, ++ uint8_t phy_addr, uint8_t reg, uint16_t data) ++{ ++ uint32_t tmp_reg; ++ ++ /* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */ ++ tmp_reg = ioread32be(&mii_regs->mdio_cfg); ++ tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK); ++ iowrite32be(tmp_reg, &mii_regs->mdio_cfg); ++ ++ /* Wait for command completion */ ++ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) ++ udelay(1); ++ ++ /* Write transaction */ ++ tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT); ++ tmp_reg |= reg; ++ iowrite32be(tmp_reg, &mii_regs->mdio_ctrl); ++ ++ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) ++ udelay(1); ++ ++ iowrite32be(data, &mii_regs->mdio_data); ++ ++ wmb(); ++ ++ /* Wait for write transaction to end */ ++ while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY) ++ udelay(1); ++} ++ ++static uint32_t read_phy_reg_1g(struct memac_mii_access_mem_map *mii_regs, ++ uint8_t phy_addr, uint8_t reg, uint16_t *data) ++{ ++ uint32_t tmp_reg; ++ ++ /* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */ ++ tmp_reg = ioread32be(&mii_regs->mdio_cfg); ++ tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK); ++ iowrite32be(tmp_reg, &mii_regs->mdio_cfg); ++ ++ /* Wait for command completion */ ++ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) ++ udelay(1); ++ ++ /* Read transaction */ ++ tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT); ++ tmp_reg |= reg; ++ tmp_reg |= MDIO_CTL_READ; ++ iowrite32be(tmp_reg, &mii_regs->mdio_ctrl); ++ ++ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY) ++ udelay(1); ++ ++ /* Wait for data to be available */ ++ while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY) ++ udelay(1); ++ ++ *data = (uint16_t)ioread32be(&mii_regs->mdio_data); ++ ++ /* Check error */ ++ return ioread32be(&mii_regs->mdio_cfg); ++} ++ ++/*****************************************************************************/ ++int fman_memac_mii_write_phy_reg(struct memac_mii_access_mem_map *mii_regs, ++ uint8_t phy_addr, uint8_t reg, uint16_t data, ++ enum enet_speed enet_speed) ++{ ++ /* Figure out interface type - 10G vs 1G. ++ In 10G interface both phy_addr and devAddr present. */ ++ if (enet_speed == E_ENET_SPEED_10000) ++ write_phy_reg_10g(mii_regs, phy_addr, reg, data); ++ else ++ write_phy_reg_1g(mii_regs, phy_addr, reg, data); ++ ++ return 0; ++} ++ ++/*****************************************************************************/ ++int fman_memac_mii_read_phy_reg(struct memac_mii_access_mem_map *mii_regs, ++ uint8_t phy_addr, uint8_t reg, uint16_t *data, ++ enum enet_speed enet_speed) ++{ ++ uint32_t ans; ++ /* Figure out interface type - 10G vs 1G. ++ In 10G interface both phy_addr and devAddr present. */ ++ if (enet_speed == E_ENET_SPEED_10000) ++ ans = read_phy_reg_10g(mii_regs, phy_addr, reg, data); ++ else ++ ans = read_phy_reg_1g(mii_regs, phy_addr, reg, data); ++ ++ if (ans & MDIO_CFG_READ_ERR) ++ return -EINVAL; ++ return 0; ++} ++ ++/* ......................................................................... */ ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_tgec.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_tgec.c +new file mode 100644 +index 0000000..fff9d5d +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/fman_tgec.c +@@ -0,0 +1,367 @@ ++/* ++ * Copyright 2008-2012 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 "fsl_fman_tgec.h" ++ ++ ++void fman_tgec_set_mac_address(struct tgec_regs *regs, uint8_t *adr) ++{ ++ uint32_t tmp0, tmp1; ++ ++ tmp0 = (uint32_t)(adr[0] | ++ adr[1] << 8 | ++ adr[2] << 16 | ++ adr[3] << 24); ++ tmp1 = (uint32_t)(adr[4] | adr[5] << 8); ++ iowrite32be(tmp0, ®s->mac_addr_0); ++ iowrite32be(tmp1, ®s->mac_addr_1); ++} ++ ++void fman_tgec_reset_stat(struct tgec_regs *regs) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ ++ tmp |= CMD_CFG_STAT_CLR; ++ ++ iowrite32be(tmp, ®s->command_config); ++ ++ while (ioread32be(®s->command_config) & CMD_CFG_STAT_CLR) ; ++} ++ ++#define GET_TGEC_CNTR_64(bn) \ ++ (((uint64_t)ioread32be(®s->bn ## _u) << 32) | \ ++ ioread32be(®s->bn ## _l)) ++ ++uint64_t fman_tgec_get_counter(struct tgec_regs *regs, enum tgec_counters reg_name) ++{ ++ uint64_t ret_val; ++ ++ switch (reg_name) { ++ case E_TGEC_COUNTER_R64: ++ ret_val = GET_TGEC_CNTR_64(r64); ++ break; ++ case E_TGEC_COUNTER_R127: ++ ret_val = GET_TGEC_CNTR_64(r127); ++ break; ++ case E_TGEC_COUNTER_R255: ++ ret_val = GET_TGEC_CNTR_64(r255); ++ break; ++ case E_TGEC_COUNTER_R511: ++ ret_val = GET_TGEC_CNTR_64(r511); ++ break; ++ case E_TGEC_COUNTER_R1023: ++ ret_val = GET_TGEC_CNTR_64(r1023); ++ break; ++ case E_TGEC_COUNTER_R1518: ++ ret_val = GET_TGEC_CNTR_64(r1518); ++ break; ++ case E_TGEC_COUNTER_R1519X: ++ ret_val = GET_TGEC_CNTR_64(r1519x); ++ break; ++ case E_TGEC_COUNTER_TRFRG: ++ ret_val = GET_TGEC_CNTR_64(trfrg); ++ break; ++ case E_TGEC_COUNTER_TRJBR: ++ ret_val = GET_TGEC_CNTR_64(trjbr); ++ break; ++ case E_TGEC_COUNTER_RDRP: ++ ret_val = GET_TGEC_CNTR_64(rdrp); ++ break; ++ case E_TGEC_COUNTER_RALN: ++ ret_val = GET_TGEC_CNTR_64(raln); ++ break; ++ case E_TGEC_COUNTER_TRUND: ++ ret_val = GET_TGEC_CNTR_64(trund); ++ break; ++ case E_TGEC_COUNTER_TROVR: ++ ret_val = GET_TGEC_CNTR_64(trovr); ++ break; ++ case E_TGEC_COUNTER_RXPF: ++ ret_val = GET_TGEC_CNTR_64(rxpf); ++ break; ++ case E_TGEC_COUNTER_TXPF: ++ ret_val = GET_TGEC_CNTR_64(txpf); ++ break; ++ case E_TGEC_COUNTER_ROCT: ++ ret_val = GET_TGEC_CNTR_64(roct); ++ break; ++ case E_TGEC_COUNTER_RMCA: ++ ret_val = GET_TGEC_CNTR_64(rmca); ++ break; ++ case E_TGEC_COUNTER_RBCA: ++ ret_val = GET_TGEC_CNTR_64(rbca); ++ break; ++ case E_TGEC_COUNTER_RPKT: ++ ret_val = GET_TGEC_CNTR_64(rpkt); ++ break; ++ case E_TGEC_COUNTER_RUCA: ++ ret_val = GET_TGEC_CNTR_64(ruca); ++ break; ++ case E_TGEC_COUNTER_RERR: ++ ret_val = GET_TGEC_CNTR_64(rerr); ++ break; ++ case E_TGEC_COUNTER_TOCT: ++ ret_val = GET_TGEC_CNTR_64(toct); ++ break; ++ case E_TGEC_COUNTER_TMCA: ++ ret_val = GET_TGEC_CNTR_64(tmca); ++ break; ++ case E_TGEC_COUNTER_TBCA: ++ ret_val = GET_TGEC_CNTR_64(tbca); ++ break; ++ case E_TGEC_COUNTER_TUCA: ++ ret_val = GET_TGEC_CNTR_64(tuca); ++ break; ++ case E_TGEC_COUNTER_TERR: ++ ret_val = GET_TGEC_CNTR_64(terr); ++ break; ++ default: ++ ret_val = 0; ++ } ++ ++ return ret_val; ++} ++ ++void fman_tgec_enable(struct tgec_regs *regs, bool apply_rx, bool apply_tx) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ if (apply_rx) ++ tmp |= CMD_CFG_RX_EN; ++ if (apply_tx) ++ tmp |= CMD_CFG_TX_EN; ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++void fman_tgec_disable(struct tgec_regs *regs, bool apply_rx, bool apply_tx) ++{ ++ uint32_t tmp_reg_32; ++ ++ tmp_reg_32 = ioread32be(®s->command_config); ++ if (apply_rx) ++ tmp_reg_32 &= ~CMD_CFG_RX_EN; ++ if (apply_tx) ++ tmp_reg_32 &= ~CMD_CFG_TX_EN; ++ iowrite32be(tmp_reg_32, ®s->command_config); ++} ++ ++void fman_tgec_set_promiscuous(struct tgec_regs *regs, bool val) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ if (val) ++ tmp |= CMD_CFG_PROMIS_EN; ++ else ++ tmp &= ~CMD_CFG_PROMIS_EN; ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++void fman_tgec_reset_filter_table(struct tgec_regs *regs) ++{ ++ uint32_t i; ++ for (i = 0; i < 512; i++) ++ iowrite32be(i & ~TGEC_HASH_MCAST_EN, ®s->hashtable_ctrl); ++} ++ ++void fman_tgec_set_hash_table_entry(struct tgec_regs *regs, uint32_t crc) ++{ ++ uint32_t hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK; /* Take 9 MSB bits */ ++ iowrite32be(hash | TGEC_HASH_MCAST_EN, ®s->hashtable_ctrl); ++} ++ ++void fman_tgec_set_hash_table(struct tgec_regs *regs, uint32_t value) ++{ ++ iowrite32be(value, ®s->hashtable_ctrl); ++} ++ ++void fman_tgec_set_tx_pause_frames(struct tgec_regs *regs, uint16_t pause_time) ++{ ++ iowrite32be((uint32_t)pause_time, ®s->pause_quant); ++} ++ ++void fman_tgec_set_rx_ignore_pause_frames(struct tgec_regs *regs, bool en) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ if (en) ++ tmp |= CMD_CFG_PAUSE_IGNORE; ++ else ++ tmp &= ~CMD_CFG_PAUSE_IGNORE; ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++void fman_tgec_enable_1588_time_stamp(struct tgec_regs *regs, bool en) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->command_config); ++ if (en) ++ tmp |= CMD_CFG_EN_TIMESTAMP; ++ else ++ tmp &= ~CMD_CFG_EN_TIMESTAMP; ++ iowrite32be(tmp, ®s->command_config); ++} ++ ++uint32_t fman_tgec_get_event(struct tgec_regs *regs, uint32_t ev_mask) ++{ ++ return ioread32be(®s->ievent) & ev_mask; ++} ++ ++void fman_tgec_ack_event(struct tgec_regs *regs, uint32_t ev_mask) ++{ ++ iowrite32be(ev_mask, ®s->ievent); ++} ++ ++uint32_t fman_tgec_get_interrupt_mask(struct tgec_regs *regs) ++{ ++ return ioread32be(®s->imask); ++} ++ ++void fman_tgec_add_addr_in_paddr(struct tgec_regs *regs, uint8_t *adr) ++{ ++ uint32_t tmp0, tmp1; ++ ++ tmp0 = (uint32_t)(adr[0] | ++ adr[1] << 8 | ++ adr[2] << 16 | ++ adr[3] << 24); ++ tmp1 = (uint32_t)(adr[4] | adr[5] << 8); ++ iowrite32be(tmp0, ®s->mac_addr_2); ++ iowrite32be(tmp1, ®s->mac_addr_3); ++} ++ ++void fman_tgec_clear_addr_in_paddr(struct tgec_regs *regs) ++{ ++ iowrite32be(0, ®s->mac_addr_2); ++ iowrite32be(0, ®s->mac_addr_3); ++} ++ ++uint32_t fman_tgec_get_revision(struct tgec_regs *regs) ++{ ++ return ioread32be(®s->tgec_id); ++} ++ ++void fman_tgec_enable_interrupt(struct tgec_regs *regs, uint32_t ev_mask) ++{ ++ iowrite32be(ioread32be(®s->imask) | ev_mask, ®s->imask); ++} ++ ++void fman_tgec_disable_interrupt(struct tgec_regs *regs, uint32_t ev_mask) ++{ ++ iowrite32be(ioread32be(®s->imask) & ~ev_mask, ®s->imask); ++} ++ ++uint16_t fman_tgec_get_max_frame_len(struct tgec_regs *regs) ++{ ++ return (uint16_t) ioread32be(®s->maxfrm); ++} ++ ++void fman_tgec_defconfig(struct tgec_cfg *cfg) ++{ ++ cfg->wan_mode_enable = DEFAULT_WAN_MODE_ENABLE; ++ cfg->promiscuous_mode_enable = DEFAULT_PROMISCUOUS_MODE_ENABLE; ++ cfg->pause_forward_enable = DEFAULT_PAUSE_FORWARD_ENABLE; ++ cfg->pause_ignore = DEFAULT_PAUSE_IGNORE; ++ cfg->tx_addr_ins_enable = DEFAULT_TX_ADDR_INS_ENABLE; ++ cfg->loopback_enable = DEFAULT_LOOPBACK_ENABLE; ++ cfg->cmd_frame_enable = DEFAULT_CMD_FRAME_ENABLE; ++ cfg->rx_error_discard = DEFAULT_RX_ERROR_DISCARD; ++ cfg->send_idle_enable = DEFAULT_SEND_IDLE_ENABLE; ++ cfg->no_length_check_enable = DEFAULT_NO_LENGTH_CHECK_ENABLE; ++ cfg->lgth_check_nostdr = DEFAULT_LGTH_CHECK_NOSTDR; ++ cfg->time_stamp_enable = DEFAULT_TIME_STAMP_ENABLE; ++ cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH; ++ cfg->max_frame_length = DEFAULT_MAX_FRAME_LENGTH; ++ cfg->pause_quant = DEFAULT_PAUSE_QUANT; ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++ cfg->skip_fman11_workaround = FALSE; ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++} ++ ++int fman_tgec_init(struct tgec_regs *regs, struct tgec_cfg *cfg, ++ uint32_t exception_mask) ++{ ++ uint32_t tmp; ++ ++ /* Config */ ++ tmp = 0x40; /* CRC forward */ ++ if (cfg->wan_mode_enable) ++ tmp |= CMD_CFG_WAN_MODE; ++ if (cfg->promiscuous_mode_enable) ++ tmp |= CMD_CFG_PROMIS_EN; ++ if (cfg->pause_forward_enable) ++ tmp |= CMD_CFG_PAUSE_FWD; ++ if (cfg->pause_ignore) ++ tmp |= CMD_CFG_PAUSE_IGNORE; ++ if (cfg->tx_addr_ins_enable) ++ tmp |= CMD_CFG_TX_ADDR_INS; ++ if (cfg->loopback_enable) ++ tmp |= CMD_CFG_LOOPBACK_EN; ++ if (cfg->cmd_frame_enable) ++ tmp |= CMD_CFG_CMD_FRM_EN; ++ if (cfg->rx_error_discard) ++ tmp |= CMD_CFG_RX_ER_DISC; ++ if (cfg->send_idle_enable) ++ tmp |= CMD_CFG_SEND_IDLE; ++ if (cfg->no_length_check_enable) ++ tmp |= CMD_CFG_NO_LEN_CHK; ++ if (cfg->time_stamp_enable) ++ tmp |= CMD_CFG_EN_TIMESTAMP; ++ iowrite32be(tmp, ®s->command_config); ++ ++ /* Max Frame Length */ ++ iowrite32be((uint32_t)cfg->max_frame_length, ®s->maxfrm); ++ /* Pause Time */ ++ iowrite32be(cfg->pause_quant, ®s->pause_quant); ++ ++ /* clear all pending events and set-up interrupts */ ++ fman_tgec_ack_event(regs, 0xffffffff); ++ fman_tgec_enable_interrupt(regs, exception_mask); ++ ++ return 0; ++} ++ ++void fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007(struct tgec_regs *regs) ++{ ++ uint32_t tmp; ++ ++ /* restore the default tx ipg Length */ ++ tmp = (ioread32be(®s->tx_ipg_len) & ~TGEC_TX_IPG_LENGTH_MASK) | 12; ++ ++ iowrite32be(tmp, ®s->tx_ipg_len); ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/memac.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/memac.c +new file mode 100644 +index 0000000..b5aacc9 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/memac.c +@@ -0,0 +1,1088 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File memac.c ++ ++ @Description FM mEMAC driver ++*//***************************************************************************/ ++ ++#include "std_ext.h" ++#include "string_ext.h" ++#include "error_ext.h" ++#include "xx_ext.h" ++#include "endian_ext.h" ++#include "debug_ext.h" ++ ++#include "fm_common.h" ++#include "memac.h" ++ ++ ++/*****************************************************************************/ ++/* Internal routines */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++static uint32_t GetMacAddrHashCode(uint64_t ethAddr) ++{ ++ uint64_t mask1, mask2; ++ uint32_t xorVal = 0; ++ uint8_t i, j; ++ ++ for (i=0; i<6; i++) ++ { ++ mask1 = ethAddr & (uint64_t)0x01; ++ ethAddr >>= 1; ++ ++ for (j=0; j<7; j++) ++ { ++ mask2 = ethAddr & (uint64_t)0x01; ++ mask1 ^= mask2; ++ ethAddr >>= 1; ++ } ++ ++ xorVal |= (mask1 << (5-i)); ++ } ++ ++ return xorVal; ++} ++ ++/* ......................................................................... */ ++ ++static void SetupSgmiiInternalPhy(t_Memac *p_Memac, uint8_t phyAddr) ++{ ++ uint16_t tmpReg16; ++ e_EnetMode enetMode; ++ ++ /* In case the higher MACs are used (i.e. the MACs that should support 10G), ++ speed=10000 is provided for SGMII ports. Temporary modify enet mode ++ to 1G one, so MII functions can work correctly. */ ++ enetMode = p_Memac->enetMode; ++ ++ /* SGMII mode + AN enable */ ++ tmpReg16 = PHY_SGMII_IF_MODE_AN | PHY_SGMII_IF_MODE_SGMII; ++ if ((p_Memac->enetMode) == e_ENET_MODE_SGMII_2500) ++ tmpReg16 = PHY_SGMII_CR_PHY_RESET | PHY_SGMII_IF_SPEED_GIGABIT | PHY_SGMII_IF_MODE_SGMII; ++ ++ p_Memac->enetMode = MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_Memac->enetMode), e_ENET_SPEED_1000); ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x14, tmpReg16); ++ ++ /* Device ability according to SGMII specification */ ++ tmpReg16 = PHY_SGMII_DEV_ABILITY_SGMII; ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x4, tmpReg16); ++ ++ /* Adjust link timer for SGMII - ++ According to Cisco SGMII specification the timer should be 1.6 ms. ++ The link_timer register is configured in units of the clock. ++ - When running as 1G SGMII, Serdes clock is 125 MHz, so ++ unit = 1 / (125*10^6 Hz) = 8 ns. ++ 1.6 ms in units of 8 ns = 1.6ms / 8ns = 2 * 10^5 = 0x30d40 ++ - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so ++ unit = 1 / (312.5*10^6 Hz) = 3.2 ns. ++ 1.6 ms in units of 3.2 ns = 1.6ms / 3.2ns = 5 * 10^5 = 0x7a120. ++ Since link_timer value of 1G SGMII will be too short for 2.5 SGMII, ++ we always set up here a value of 2.5 SGMII. */ ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x13, 0x0007); ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x12, 0xa120); ++ ++ /* Restart AN */ ++ tmpReg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN; ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x0, tmpReg16); ++ ++ /* Restore original enet mode */ ++ p_Memac->enetMode = enetMode; ++} ++ ++/* ......................................................................... */ ++ ++static void SetupSgmiiInternalPhyBaseX(t_Memac *p_Memac, uint8_t phyAddr) ++{ ++ uint16_t tmpReg16; ++ e_EnetMode enetMode; ++ ++ /* In case the higher MACs are used (i.e. the MACs that should support 10G), ++ speed=10000 is provided for SGMII ports. Temporary modify enet mode ++ to 1G one, so MII functions can work correctly. */ ++ enetMode = p_Memac->enetMode; ++ p_Memac->enetMode = MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_Memac->enetMode), e_ENET_SPEED_1000); ++ ++ /* 1000BaseX mode */ ++ tmpReg16 = PHY_SGMII_IF_MODE_1000X; ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x14, tmpReg16); ++ ++ /* AN Device capability */ ++ tmpReg16 = PHY_SGMII_DEV_ABILITY_1000X; ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x4, tmpReg16); ++ ++ /* Adjust link timer for SGMII - ++ For Serdes 1000BaseX auto-negotiation the timer should be 10 ms. ++ The link_timer register is configured in units of the clock. ++ - When running as 1G SGMII, Serdes clock is 125 MHz, so ++ unit = 1 / (125*10^6 Hz) = 8 ns. ++ 10 ms in units of 8 ns = 10ms / 8ns = 1250000 = 0x1312d0 ++ - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so ++ unit = 1 / (312.5*10^6 Hz) = 3.2 ns. ++ 10 ms in units of 3.2 ns = 10ms / 3.2ns = 3125000 = 0x2faf08. ++ Since link_timer value of 1G SGMII will be too short for 2.5 SGMII, ++ we always set up here a value of 2.5 SGMII. */ ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x13, 0x002f); ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x12, 0xaf08); ++ ++ /* Restart AN */ ++ tmpReg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN; ++ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x0, tmpReg16); ++ ++ /* Restore original enet mode */ ++ p_Memac->enetMode = enetMode; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error CheckInitParameters(t_Memac *p_Memac) ++{ ++ e_FmMacType portType; ++ ++ portType = ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G); ++ ++#if (FM_MAX_NUM_OF_10G_MACS > 0) ++ if ((portType == e_FM_MAC_10G) && (p_Memac->macId >= FM_MAX_NUM_OF_10G_MACS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("10G MAC ID must be less than %d", FM_MAX_NUM_OF_10G_MACS)); ++#endif /* (FM_MAX_NUM_OF_10G_MACS > 0) */ ++ ++ if ((portType == e_FM_MAC_1G) && (p_Memac->macId >= FM_MAX_NUM_OF_1G_MACS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("1G MAC ID must be less than %d", FM_MAX_NUM_OF_1G_MACS)); ++ if (p_Memac->addr == 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC must have a valid MAC address")); ++ if (!p_Memac->f_Exception) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Uninitialized f_Exception")); ++ if (!p_Memac->f_Event) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Uninitialized f_Event")); ++#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002 ++ if (!p_Memac->p_MemacDriverParam->no_length_check_enable) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!")); ++#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */ ++ ++ return E_OK; ++} ++ ++/* ........................................................................... */ ++ ++static void MemacErrException(t_Handle h_Memac) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ uint32_t event, imask; ++ ++ event = fman_memac_get_event(p_Memac->p_MemMap, 0xffffffff); ++ imask = fman_memac_get_interrupt_mask(p_Memac->p_MemMap); ++ ++ /* Imask include both error and notification/event bits. ++ Leaving only error bits enabled by imask. ++ The imask error bits are shifted by 16 bits offset from ++ their corresponding location in the ievent - hence the >> 16 */ ++ event &= ((imask & MEMAC_ALL_ERRS_IMASK) >> 16); ++ ++ fman_memac_ack_event(p_Memac->p_MemMap, event); ++ ++ if (event & MEMAC_IEVNT_TS_ECC_ER) ++ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_TS_FIFO_ECC_ERR); ++ if (event & MEMAC_IEVNT_TX_ECC_ER) ++ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_1TX_ECC_ER); ++ if (event & MEMAC_IEVNT_RX_ECC_ER) ++ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_RX_ECC_ER); ++} ++ ++static void MemacException(t_Handle h_Memac) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ uint32_t event, imask; ++ ++ event = fman_memac_get_event(p_Memac->p_MemMap, 0xffffffff); ++ imask = fman_memac_get_interrupt_mask(p_Memac->p_MemMap); ++ ++ /* Imask include both error and notification/event bits. ++ Leaving only error bits enabled by imask. ++ The imask error bits are shifted by 16 bits offset from ++ their corresponding location in the ievent - hence the >> 16 */ ++ event &= ((imask & MEMAC_ALL_ERRS_IMASK) >> 16); ++ ++ fman_memac_ack_event(p_Memac->p_MemMap, event); ++ ++ if (event & MEMAC_IEVNT_MGI) ++ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_MAGIC_PACKET_INDICATION); ++} ++ ++/* ......................................................................... */ ++ ++static void FreeInitResources(t_Memac *p_Memac) ++{ ++ e_FmMacType portType; ++ ++ portType = ++ ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G); ++ ++ if (portType == e_FM_MAC_10G) ++ FmUnregisterIntr(p_Memac->fmMacControllerDriver.h_Fm, e_FM_MOD_10G_MAC, p_Memac->macId, e_FM_INTR_TYPE_ERR); ++ else ++ FmUnregisterIntr(p_Memac->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Memac->macId, e_FM_INTR_TYPE_ERR); ++ ++ /* release the driver's group hash table */ ++ FreeHashTable(p_Memac->p_MulticastAddrHash); ++ p_Memac->p_MulticastAddrHash = NULL; ++ ++ /* release the driver's individual hash table */ ++ FreeHashTable(p_Memac->p_UnicastAddrHash); ++ p_Memac->p_UnicastAddrHash = NULL; ++} ++ ++ ++/*****************************************************************************/ ++/* mEMAC API routines */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++static t_Error MemacEnable(t_Handle h_Memac, e_CommMode mode) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ fman_memac_enable(p_Memac->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX)); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacDisable (t_Handle h_Memac, e_CommMode mode) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ fman_memac_disable(p_Memac->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX)); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacSetPromiscuous(t_Handle h_Memac, bool newVal) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ fman_memac_set_promiscuous(p_Memac->p_MemMap, newVal); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error MemacAdjustLink(t_Handle h_Memac, e_EnetSpeed speed, bool fullDuplex) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ if ((speed >= e_ENET_SPEED_1000) && (!fullDuplex)) ++ RETURN_ERROR(MAJOR, E_CONFLICT, ++ ("Ethernet MAC 1G or 10G does not support half-duplex")); ++ ++ fman_memac_adjust_link(p_Memac->p_MemMap, ++ (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_Memac->enetMode), ++ (enum enet_speed)speed, ++ fullDuplex); ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* Memac Configs modification functions */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++static t_Error MemacConfigLoopback(t_Handle h_Memac, bool newVal) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ p_Memac->p_MemacDriverParam->loopback_enable = newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacConfigWan(t_Handle h_Memac, bool newVal) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ p_Memac->p_MemacDriverParam->wan_mode_enable = newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacConfigMaxFrameLength(t_Handle h_Memac, uint16_t newVal) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ p_Memac->p_MemacDriverParam->max_frame_length = newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacConfigPad(t_Handle h_Memac, bool newVal) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ p_Memac->p_MemacDriverParam->pad_enable = newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacConfigLengthCheck(t_Handle h_Memac, bool newVal) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ p_Memac->p_MemacDriverParam->no_length_check_enable = !newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacConfigException(t_Handle h_Memac, e_FmMacExceptions exception, bool enable) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_Memac->exceptions |= bitMask; ++ else ++ p_Memac->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacConfigResetOnInit(t_Handle h_Memac, bool enable) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ p_Memac->p_MemacDriverParam->reset_on_init = enable; ++ ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* Memac Run Time API functions */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++static t_Error MemacSetTxPauseFrames(t_Handle h_Memac, ++ uint8_t priority, ++ uint16_t pauseTime, ++ uint16_t threshTime) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ if (priority != 0xFF) ++ { ++ bool PortConfigured, PreFetchEnabled; ++ ++ if (FmGetTnumAgingPeriod(p_Memac->fmMacControllerDriver.h_Fm) == 0) ++ RETURN_ERROR(MAJOR, E_CONFLICT, ("For PFC operation, TNUM aging must be enabled")); ++ ++ FmGetPortPreFetchConfiguration(p_Memac->fmMacControllerDriver.h_Fm, ++ p_Memac->fmMacControllerDriver.macId, ++ &PortConfigured, ++ &PreFetchEnabled); ++ ++ if ((ENET_SPEED_FROM_MODE(p_Memac->fmMacControllerDriver.enetMode) == e_ENET_SPEED_1000) && !PortConfigured) ++ DBG(INFO, ("For PFC correct operation, prefetch must be configured on the FM Tx PORT")); ++ ++ if ((ENET_SPEED_FROM_MODE(p_Memac->fmMacControllerDriver.enetMode) == e_ENET_SPEED_1000) && PortConfigured && !PreFetchEnabled) ++ DBG(WARNING, ("For PFC correct operation, prefetch must be configured on the FM Tx PORT")); ++ } ++ ++ fman_memac_set_tx_pause_frames(p_Memac->p_MemMap, priority, pauseTime, threshTime); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacSetTxAutoPauseFrames(t_Handle h_Memac, ++ uint16_t pauseTime) ++{ ++ return MemacSetTxPauseFrames(h_Memac, FM_MAC_NO_PFC, pauseTime, 0); ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacSetRxIgnorePauseFrames(t_Handle h_Memac, bool en) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ fman_memac_set_rx_ignore_pause_frames(p_Memac->p_MemMap, en); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacSetWakeOnLan(t_Handle h_Memac, bool en) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ fman_memac_set_wol(p_Memac->p_MemMap, en); ++ ++ return E_OK; ++} ++ ++/* .............................................................................. */ ++ ++static t_Error MemacEnable1588TimeStamp(t_Handle h_Memac) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++UNUSED(p_Memac); ++DBG(WARNING, ("mEMAC has 1588 always enabled!")); ++ ++ return E_OK; ++} ++ ++/* Counters handling */ ++/* ......................................................................... */ ++ ++static t_Error MemacGetStatistics(t_Handle h_Memac, t_FmMacStatistics *p_Statistics) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER); ++ ++ p_Statistics->eStatPkts64 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R64); ++ p_Statistics->eStatPkts65to127 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R127); ++ p_Statistics->eStatPkts128to255 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R255); ++ p_Statistics->eStatPkts256to511 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R511); ++ p_Statistics->eStatPkts512to1023 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1023); ++ p_Statistics->eStatPkts1024to1518 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1518); ++ p_Statistics->eStatPkts1519to1522 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1519X); ++/* */ ++ p_Statistics->eStatFragments = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RFRG); ++ p_Statistics->eStatJabbers = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RJBR); ++ ++ p_Statistics->eStatsDropEvents = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RDRP); ++ p_Statistics->eStatCRCAlignErrors = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RALN); ++ ++ p_Statistics->eStatUndersizePkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TUND); ++ p_Statistics->eStatOversizePkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_ROVR); ++/* Pause */ ++ p_Statistics->reStatPause = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RXPF); ++ p_Statistics->teStatPause = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TXPF); ++ ++/* MIB II */ ++ p_Statistics->ifInOctets = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_ROCT); ++ p_Statistics->ifInUcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RUCA); ++ p_Statistics->ifInMcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RMCA); ++ p_Statistics->ifInBcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RBCA); ++ p_Statistics->ifInPkts = p_Statistics->ifInUcastPkts ++ + p_Statistics->ifInMcastPkts ++ + p_Statistics->ifInBcastPkts; ++ p_Statistics->ifInDiscards = 0; ++ p_Statistics->ifInErrors = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RERR); ++ ++ p_Statistics->ifOutOctets = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TOCT); ++ p_Statistics->ifOutUcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TUCA); ++ p_Statistics->ifOutMcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TMCA); ++ p_Statistics->ifOutBcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TBCA); ++ p_Statistics->ifOutPkts = p_Statistics->ifOutUcastPkts ++ + p_Statistics->ifOutMcastPkts ++ + p_Statistics->ifOutBcastPkts; ++ p_Statistics->ifOutDiscards = 0; ++ p_Statistics->ifOutErrors = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TERR); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacModifyMacAddress (t_Handle h_Memac, t_EnetAddr *p_EnetAddr) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ fman_memac_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t *)(*p_EnetAddr), 0); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacResetCounters (t_Handle h_Memac) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ fman_memac_reset_stat(p_Memac->p_MemMap); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacAddExactMatchMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr) ++{ ++ t_Memac *p_Memac = (t_Memac *) h_Memac; ++ uint64_t ethAddr; ++ uint8_t paddrNum; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ if (ethAddr & GROUP_ADDRESS) ++ /* Multicast address has no effect in PADDR */ ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Multicast address")); ++ ++ /* Make sure no PADDR contains this address */ ++ for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++) ++ if (p_Memac->indAddrRegUsed[paddrNum]) ++ if (p_Memac->paddr[paddrNum] == ethAddr) ++ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG); ++ ++ /* Find first unused PADDR */ ++ for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++) ++ if (!(p_Memac->indAddrRegUsed[paddrNum])) ++ { ++ /* mark this PADDR as used */ ++ p_Memac->indAddrRegUsed[paddrNum] = TRUE; ++ /* store address */ ++ p_Memac->paddr[paddrNum] = ethAddr; ++ ++ /* put in hardware */ ++ fman_memac_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t*)(*p_EthAddr), paddrNum); ++ p_Memac->numOfIndAddrInRegs++; ++ ++ return E_OK; ++ } ++ ++ /* No free PADDR */ ++ RETURN_ERROR(MAJOR, E_FULL, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacDelExactMatchMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr) ++{ ++ t_Memac *p_Memac = (t_Memac *) h_Memac; ++ uint64_t ethAddr; ++ uint8_t paddrNum; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ /* Find used PADDR containing this address */ ++ for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++) ++ { ++ if ((p_Memac->indAddrRegUsed[paddrNum]) && ++ (p_Memac->paddr[paddrNum] == ethAddr)) ++ { ++ /* mark this PADDR as not used */ ++ p_Memac->indAddrRegUsed[paddrNum] = FALSE; ++ /* clear in hardware */ ++ fman_memac_clear_addr_in_paddr(p_Memac->p_MemMap, paddrNum); ++ p_Memac->numOfIndAddrInRegs--; ++ ++ return E_OK; ++ } ++ } ++ ++ RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacGetId(t_Handle h_Memac, uint32_t *macId) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ *macId = p_Memac->macId; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++ ++static t_Error MemacAddHashMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ t_EthHashEntry *p_HashEntry; ++ uint32_t hash; ++ uint64_t ethAddr; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ if (!(ethAddr & GROUP_ADDRESS)) ++ /* Unicast addresses not supported in hash */ ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unicast Address")); ++ ++ hash = GetMacAddrHashCode(ethAddr) & HASH_CTRL_ADDR_MASK; ++ ++ /* Create element to be added to the driver hash table */ ++ p_HashEntry = (t_EthHashEntry *)XX_Malloc(sizeof(t_EthHashEntry)); ++ p_HashEntry->addr = ethAddr; ++ INIT_LIST(&p_HashEntry->node); ++ ++ LIST_AddToTail(&(p_HashEntry->node), &(p_Memac->p_MulticastAddrHash->p_Lsts[hash])); ++ fman_memac_set_hash_table(p_Memac->p_MemMap, (hash | HASH_CTRL_MCAST_EN)); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacDelHashMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ t_EthHashEntry *p_HashEntry = NULL; ++ t_List *p_Pos; ++ uint32_t hash; ++ uint64_t ethAddr; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ hash = GetMacAddrHashCode(ethAddr) & HASH_CTRL_ADDR_MASK; ++ ++ LIST_FOR_EACH(p_Pos, &(p_Memac->p_MulticastAddrHash->p_Lsts[hash])) ++ { ++ p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos); ++ if (p_HashEntry->addr == ethAddr) ++ { ++ LIST_DelAndInit(&p_HashEntry->node); ++ XX_Free(p_HashEntry); ++ break; ++ } ++ } ++ if (LIST_IsEmpty(&p_Memac->p_MulticastAddrHash->p_Lsts[hash])) ++ fman_memac_set_hash_table(p_Memac->p_MemMap, (hash & ~HASH_CTRL_MCAST_EN)); ++ ++ return E_OK; ++} ++ ++ ++/* ......................................................................... */ ++ ++static t_Error MemacSetException(t_Handle h_Memac, e_FmMacExceptions exception, bool enable) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_Memac->exceptions |= bitMask; ++ else ++ p_Memac->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ fman_memac_set_exception(p_Memac->p_MemMap, bitMask, enable); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static uint16_t MemacGetMaxFrameLength(t_Handle h_Memac) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Memac, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_Memac->p_MemacDriverParam, E_INVALID_STATE, 0); ++ ++ return fman_memac_get_max_frame_len(p_Memac->p_MemMap); ++} ++ ++ ++/*****************************************************************************/ ++/* mEMAC Init & Free API */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++void *g_MemacRegs; ++static t_Error MemacInit(t_Handle h_Memac) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ struct memac_cfg *p_MemacDriverParam; ++ enum enet_interface enet_interface; ++ enum enet_speed enet_speed; ++ uint8_t i, phyAddr; ++ t_EnetAddr ethAddr; ++ e_FmMacType portType; ++ t_Error err; ++ bool slow_10g_if = FALSE; ++ if (p_Memac->macId == 3) /* This is a quick WA */ ++ g_MemacRegs = p_Memac->p_MemMap; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE); ++ ++ FM_GetRevision(p_Memac->fmMacControllerDriver.h_Fm, &p_Memac->fmMacControllerDriver.fmRevInfo); ++ if (p_Memac->fmMacControllerDriver.fmRevInfo.majorRev == 6 && ++ p_Memac->fmMacControllerDriver.fmRevInfo.minorRev == 4) ++ slow_10g_if = TRUE; ++ ++ CHECK_INIT_PARAMETERS(p_Memac, CheckInitParameters); ++ ++ p_MemacDriverParam = p_Memac->p_MemacDriverParam; ++ ++ portType = ++ ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G); ++ ++ /* First, reset the MAC if desired. */ ++ if (p_MemacDriverParam->reset_on_init) ++ fman_memac_reset(p_Memac->p_MemMap); ++ ++ /* MAC Address */ ++ MAKE_ENET_ADDR_FROM_UINT64(p_Memac->addr, ethAddr); ++ fman_memac_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t*)ethAddr, 0); ++ ++ enet_interface = (enum enet_interface) ENET_INTERFACE_FROM_MODE(p_Memac->enetMode); ++ enet_speed = (enum enet_speed) ENET_SPEED_FROM_MODE(p_Memac->enetMode); ++ ++ fman_memac_init(p_Memac->p_MemMap, ++ p_Memac->p_MemacDriverParam, ++ enet_interface, ++ enet_speed, ++ slow_10g_if, ++ p_Memac->exceptions); ++ ++#ifdef FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 ++ { ++ uint32_t tmpReg = 0; ++ ++ FM_GetRevision(p_Memac->fmMacControllerDriver.h_Fm, &p_Memac->fmMacControllerDriver.fmRevInfo); ++ /* check the FMAN version - the bug exists only in rev1 */ ++ if ((p_Memac->fmMacControllerDriver.fmRevInfo.majorRev == 6) && ++ (p_Memac->fmMacControllerDriver.fmRevInfo.minorRev == 0)) ++ { ++ /* MAC strips CRC from received frames - this workaround should ++ decrease the likelihood of bug appearance ++ */ ++ tmpReg = GET_UINT32(p_Memac->p_MemMap->command_config); ++ tmpReg &= ~CMD_CFG_CRC_FWD; ++ WRITE_UINT32(p_Memac->p_MemMap->command_config, tmpReg); ++ /* DBG(WARNING, ("mEMAC strips CRC from received frames as part of A006320 errata workaround"));*/ ++ } ++ } ++#endif /* FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 */ ++ ++ if (ENET_INTERFACE_FROM_MODE(p_Memac->enetMode) == e_ENET_IF_SGMII) ++ { ++ /* Configure internal SGMII PHY */ ++ if (p_Memac->enetMode & ENET_IF_SGMII_BASEX) ++ SetupSgmiiInternalPhyBaseX(p_Memac, PHY_MDIO_ADDR); ++ else ++ SetupSgmiiInternalPhy(p_Memac, PHY_MDIO_ADDR); ++ } ++ else if (ENET_INTERFACE_FROM_MODE(p_Memac->enetMode) == e_ENET_IF_QSGMII) ++ { ++ /* Configure 4 internal SGMII PHYs */ ++ for (i = 0; i < 4; i++) ++ { ++ /* QSGMII PHY address occupies 3 upper bits of 5-bit ++ phyAddress; the lower 2 bits are used to extend ++ register address space and access each one of 4 ++ ports inside QSGMII. */ ++ phyAddr = (uint8_t)((PHY_MDIO_ADDR << 2) | i); ++ if (p_Memac->enetMode & ENET_IF_SGMII_BASEX) ++ SetupSgmiiInternalPhyBaseX(p_Memac, phyAddr); ++ else ++ SetupSgmiiInternalPhy(p_Memac, phyAddr); ++ } ++ } ++ ++ /* Max Frame Length */ ++ err = FmSetMacMaxFrame(p_Memac->fmMacControllerDriver.h_Fm, ++ portType, ++ p_Memac->fmMacControllerDriver.macId, ++ p_MemacDriverParam->max_frame_length); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("settings Mac max frame length is FAILED")); ++ ++ p_Memac->p_MulticastAddrHash = AllocHashTable(HASH_TABLE_SIZE); ++ if (!p_Memac->p_MulticastAddrHash) ++ { ++ FreeInitResources(p_Memac); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED")); ++ } ++ ++ p_Memac->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE); ++ if (!p_Memac->p_UnicastAddrHash) ++ { ++ FreeInitResources(p_Memac); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED")); ++ } ++ ++ FmRegisterIntr(p_Memac->fmMacControllerDriver.h_Fm, ++ (portType == e_FM_MAC_10G) ? e_FM_MOD_10G_MAC : e_FM_MOD_1G_MAC, ++ p_Memac->macId, ++ e_FM_INTR_TYPE_ERR, ++ MemacErrException, ++ p_Memac); ++ ++ FmRegisterIntr(p_Memac->fmMacControllerDriver.h_Fm, ++ (portType == e_FM_MAC_10G) ? e_FM_MOD_10G_MAC : e_FM_MOD_1G_MAC, ++ p_Memac->macId, ++ e_FM_INTR_TYPE_NORMAL, ++ MemacException, ++ p_Memac); ++ ++ XX_Free(p_MemacDriverParam); ++ p_Memac->p_MemacDriverParam = NULL; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error MemacFree(t_Handle h_Memac) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ ++ if (p_Memac->p_MemacDriverParam) ++ { ++ /* Called after config */ ++ XX_Free(p_Memac->p_MemacDriverParam); ++ p_Memac->p_MemacDriverParam = NULL; ++ } ++ else ++ /* Called after init */ ++ FreeInitResources(p_Memac); ++ ++ XX_Free(p_Memac); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver) ++{ ++ p_FmMacControllerDriver->f_FM_MAC_Init = MemacInit; ++ p_FmMacControllerDriver->f_FM_MAC_Free = MemacFree; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetStatistics = NULL; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback = MemacConfigLoopback; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength = MemacConfigMaxFrameLength; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigWan = MemacConfigWan; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc = MemacConfigPad; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex = NULL; /* half-duplex is detected automatically */ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck = MemacConfigLengthCheck; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigException = MemacConfigException; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit = MemacConfigResetOnInit; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetException = MemacSetException; ++ ++ p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp = MemacEnable1588TimeStamp; /* always enabled */ ++ p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp = NULL; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous = MemacSetPromiscuous; ++ p_FmMacControllerDriver->f_FM_MAC_AdjustLink = MemacAdjustLink; ++ p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg = NULL; ++ ++ p_FmMacControllerDriver->f_FM_MAC_Enable = MemacEnable; ++ p_FmMacControllerDriver->f_FM_MAC_Disable = MemacDisable; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames = MemacSetTxAutoPauseFrames; ++ p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames = MemacSetTxPauseFrames; ++ p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames = MemacSetRxIgnorePauseFrames; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetWakeOnLan = MemacSetWakeOnLan; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ResetCounters = MemacResetCounters; ++ p_FmMacControllerDriver->f_FM_MAC_GetStatistics = MemacGetStatistics; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr = MemacModifyMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr = MemacAddHashMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr = MemacDelHashMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr = MemacAddExactMatchMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr = MemacDelExactMatchMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_GetId = MemacGetId; ++ p_FmMacControllerDriver->f_FM_MAC_GetVersion = NULL; ++ p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength = MemacGetMaxFrameLength; ++ ++ p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg = MEMAC_MII_WritePhyReg; ++ p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg = MEMAC_MII_ReadPhyReg; ++} ++ ++ ++/*****************************************************************************/ ++/* mEMAC Config Main Entry */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++t_Handle MEMAC_Config(t_FmMacParams *p_FmMacParam) ++{ ++ t_Memac *p_Memac; ++ struct memac_cfg *p_MemacDriverParam; ++ uintptr_t baseAddr; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL); ++ ++ baseAddr = p_FmMacParam->baseAddr; ++ /* Allocate memory for the mEMAC data structure */ ++ p_Memac = (t_Memac *)XX_Malloc(sizeof(t_Memac)); ++ if (!p_Memac) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("mEMAC driver structure")); ++ return NULL; ++ } ++ memset(p_Memac, 0, sizeof(t_Memac)); ++ InitFmMacControllerDriver(&p_Memac->fmMacControllerDriver); ++ ++ /* Allocate memory for the mEMAC driver parameters data structure */ ++ p_MemacDriverParam = (struct memac_cfg *)XX_Malloc(sizeof(struct memac_cfg)); ++ if (!p_MemacDriverParam) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("mEMAC driver parameters")); ++ XX_Free(p_Memac); ++ return NULL; ++ } ++ memset(p_MemacDriverParam, 0, sizeof(struct memac_cfg)); ++ ++ /* Plant parameter structure pointer */ ++ p_Memac->p_MemacDriverParam = p_MemacDriverParam; ++ ++ fman_memac_defconfig(p_MemacDriverParam); ++ ++ p_Memac->addr = ENET_ADDR_TO_UINT64(p_FmMacParam->addr); ++ ++ p_Memac->p_MemMap = (struct memac_regs *)UINT_TO_PTR(baseAddr); ++ p_Memac->p_MiiMemMap = (struct memac_mii_access_mem_map*)UINT_TO_PTR(baseAddr + MEMAC_TO_MII_OFFSET); ++ ++ p_Memac->enetMode = p_FmMacParam->enetMode; ++ p_Memac->macId = p_FmMacParam->macId; ++ p_Memac->exceptions = MEMAC_default_exceptions; ++ p_Memac->f_Exception = p_FmMacParam->f_Exception; ++ p_Memac->f_Event = p_FmMacParam->f_Event; ++ p_Memac->h_App = p_FmMacParam->h_App; ++ ++ return p_Memac; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/memac.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/memac.h +new file mode 100644 +index 0000000..2fd89da +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/memac.h +@@ -0,0 +1,110 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File memac.h ++ ++ @Description FM Multirate Ethernet MAC (mEMAC) ++*//***************************************************************************/ ++#ifndef __MEMAC_H ++#define __MEMAC_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++ ++#include "fsl_fman_memac_mii_acc.h" ++#include "fm_mac.h" ++#include "fsl_fman_memac.h" ++ ++ ++#define MEMAC_default_exceptions \ ++ ((uint32_t)(MEMAC_IMASK_TSECC_ER | MEMAC_IMASK_TECC_ER | MEMAC_IMASK_RECC_ER | MEMAC_IMASK_MGI)) ++ ++#define GET_EXCEPTION_FLAG(bitMask, exception) switch (exception){ \ ++ case e_FM_MAC_EX_10G_1TX_ECC_ER: \ ++ bitMask = MEMAC_IMASK_TECC_ER; break; \ ++ case e_FM_MAC_EX_10G_RX_ECC_ER: \ ++ bitMask = MEMAC_IMASK_RECC_ER; break; \ ++ case e_FM_MAC_EX_TS_FIFO_ECC_ERR: \ ++ bitMask = MEMAC_IMASK_TSECC_ER; break; \ ++ case e_FM_MAC_EX_MAGIC_PACKET_INDICATION: \ ++ bitMask = MEMAC_IMASK_MGI; break; \ ++ default: bitMask = 0;break;} ++ ++ ++typedef struct ++{ ++ t_FmMacControllerDriver fmMacControllerDriver; /**< Upper Mac control block */ ++ t_Handle h_App; /**< Handle to the upper layer application */ ++ struct memac_regs *p_MemMap; /**< Pointer to MAC memory mapped registers */ ++ struct memac_mii_access_mem_map *p_MiiMemMap; /**< Pointer to MII memory mapped registers */ ++ uint64_t addr; /**< MAC address of device */ ++ e_EnetMode enetMode; /**< Ethernet physical interface */ ++ t_FmMacExceptionCallback *f_Exception; ++ int mdioIrq; ++ t_FmMacExceptionCallback *f_Event; ++ bool indAddrRegUsed[MEMAC_NUM_OF_PADDRS]; /**< Whether a particular individual address recognition register is being used */ ++ uint64_t paddr[MEMAC_NUM_OF_PADDRS]; /**< MAC address for particular individual address recognition register */ ++ uint8_t numOfIndAddrInRegs; /**< Number of individual addresses in registers for this station. */ ++ t_EthHash *p_MulticastAddrHash; /**< Pointer to driver's global address hash table */ ++ t_EthHash *p_UnicastAddrHash; /**< Pointer to driver's individual address hash table */ ++ bool debugMode; ++ uint8_t macId; ++ uint32_t exceptions; ++ struct memac_cfg *p_MemacDriverParam; ++} t_Memac; ++ ++ ++/* Internal PHY access */ ++#define PHY_MDIO_ADDR 0 ++ ++/* Internal PHY Registers - SGMII */ ++#define PHY_SGMII_CR_PHY_RESET 0x8000 ++#define PHY_SGMII_CR_RESET_AN 0x0200 ++#define PHY_SGMII_CR_DEF_VAL 0x1140 ++#define PHY_SGMII_DEV_ABILITY_SGMII 0x4001 ++#define PHY_SGMII_DEV_ABILITY_1000X 0x01A0 ++#define PHY_SGMII_IF_SPEED_GIGABIT 0x0008 ++#define PHY_SGMII_IF_MODE_AN 0x0002 ++#define PHY_SGMII_IF_MODE_SGMII 0x0001 ++#define PHY_SGMII_IF_MODE_1000X 0x0000 ++ ++ ++#define MEMAC_TO_MII_OFFSET 0x030 /* Offset from the MEM map to the MDIO mem map */ ++ ++t_Error MEMAC_MII_WritePhyReg(t_Handle h_Memac, uint8_t phyAddr, uint8_t reg, uint16_t data); ++t_Error MEMAC_MII_ReadPhyReg(t_Handle h_Memac, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data); ++ ++ ++#endif /* __MEMAC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/memac_mii_acc.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/memac_mii_acc.c +new file mode 100644 +index 0000000..56eaffb +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/memac_mii_acc.c +@@ -0,0 +1,78 @@ ++/* ++ * Copyright 2008-2012 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 "error_ext.h" ++#include "std_ext.h" ++#include "fm_mac.h" ++#include "memac.h" ++#include "xx_ext.h" ++ ++#include "fm_common.h" ++#include "memac_mii_acc.h" ++ ++ ++/*****************************************************************************/ ++t_Error MEMAC_MII_WritePhyReg(t_Handle h_Memac, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t data) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MiiMemMap, E_INVALID_HANDLE); ++ ++ return (t_Error)fman_memac_mii_write_phy_reg(p_Memac->p_MiiMemMap, ++ phyAddr, ++ reg, ++ data, ++ (enum enet_speed)ENET_SPEED_FROM_MODE(p_Memac->enetMode)); ++} ++ ++/*****************************************************************************/ ++t_Error MEMAC_MII_ReadPhyReg(t_Handle h_Memac, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t *p_Data) ++{ ++ t_Memac *p_Memac = (t_Memac *)h_Memac; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MiiMemMap, E_INVALID_HANDLE); ++ ++ return fman_memac_mii_read_phy_reg(p_Memac->p_MiiMemMap, ++ phyAddr, ++ reg, ++ p_Data, ++ (enum enet_speed)ENET_SPEED_FROM_MODE(p_Memac->enetMode)); ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/memac_mii_acc.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/memac_mii_acc.h +new file mode 100644 +index 0000000..325ec08 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/memac_mii_acc.h +@@ -0,0 +1,73 @@ ++/* ++ * Copyright 2008-2012 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 __MEMAC_MII_ACC_H ++#define __MEMAC_MII_ACC_H ++ ++#include "std_ext.h" ++ ++ ++/* MII Management Registers */ ++#define MDIO_CFG_CLK_DIV_MASK 0x0080ff80 ++#define MDIO_CFG_CLK_DIV_SHIFT 7 ++#define MDIO_CFG_HOLD_MASK 0x0000001c ++#define MDIO_CFG_ENC45 0x00000040 ++#define MDIO_CFG_READ_ERR 0x00000002 ++#define MDIO_CFG_BSY 0x00000001 ++ ++#define MDIO_CTL_PHY_ADDR_SHIFT 5 ++#define MDIO_CTL_READ 0x00008000 ++ ++#define MDIO_DATA_BSY 0x80000000 ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/*----------------------------------------------------*/ ++/* MII Configuration Control Memory Map Registers */ ++/*----------------------------------------------------*/ ++typedef struct t_MemacMiiAccessMemMap ++{ ++ volatile uint32_t mdio_cfg; /* 0x030 */ ++ volatile uint32_t mdio_ctrl; /* 0x034 */ ++ volatile uint32_t mdio_data; /* 0x038 */ ++ volatile uint32_t mdio_addr; /* 0x03c */ ++} t_MemacMiiAccessMemMap ; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++#endif /* __MEMAC_MII_ACC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/tgec.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/tgec.c +new file mode 100644 +index 0000000..bf12c5d +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/tgec.c +@@ -0,0 +1,974 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File tgec.c ++ ++ @Description FM 10G MAC ... ++*//***************************************************************************/ ++ ++#include "std_ext.h" ++#include "string_ext.h" ++#include "error_ext.h" ++#include "xx_ext.h" ++#include "endian_ext.h" ++#include "debug_ext.h" ++#include "crc_mac_addr_ext.h" ++ ++#include "fm_common.h" ++#include "fsl_fman_tgec.h" ++#include "tgec.h" ++ ++ ++/*****************************************************************************/ ++/* Internal routines */ ++/*****************************************************************************/ ++ ++static t_Error CheckInitParameters(t_Tgec *p_Tgec) ++{ ++ if (ENET_SPEED_FROM_MODE(p_Tgec->enetMode) < e_ENET_SPEED_10000) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet 10G MAC driver only support 10G speed")); ++#if (FM_MAX_NUM_OF_10G_MACS > 0) ++ if (p_Tgec->macId >= FM_MAX_NUM_OF_10G_MACS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("macId of 10G can not be greater than 0")); ++#endif /* (FM_MAX_NUM_OF_10G_MACS > 0) */ ++ ++ if (p_Tgec->addr == 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet 10G MAC Must have a valid MAC Address")); ++ if (!p_Tgec->f_Exception) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("uninitialized f_Exception")); ++ if (!p_Tgec->f_Event) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("uninitialized f_Event")); ++#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002 ++ if (!p_Tgec->p_TgecDriverParam->no_length_check_enable) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!")); ++#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static uint32_t GetMacAddrHashCode(uint64_t ethAddr) ++{ ++ uint32_t crc; ++ ++ /* CRC calculation */ ++ GET_MAC_ADDR_CRC(ethAddr, crc); ++ ++ crc = GetMirror32(crc); ++ ++ return crc; ++} ++ ++/* ......................................................................... */ ++ ++static void TgecErrException(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ uint32_t event; ++ struct tgec_regs *p_TgecMemMap = p_Tgec->p_MemMap; ++ ++ /* do not handle MDIO events */ ++ event = fman_tgec_get_event(p_TgecMemMap, ~(TGEC_IMASK_MDIO_SCAN_EVENT | TGEC_IMASK_MDIO_CMD_CMPL)); ++ event &= fman_tgec_get_interrupt_mask(p_TgecMemMap); ++ ++ fman_tgec_ack_event(p_TgecMemMap, event); ++ ++ if (event & TGEC_IMASK_REM_FAULT) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_REM_FAULT); ++ if (event & TGEC_IMASK_LOC_FAULT) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_LOC_FAULT); ++ if (event & TGEC_IMASK_TX_ECC_ER) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_1TX_ECC_ER); ++ if (event & TGEC_IMASK_TX_FIFO_UNFL) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_TX_FIFO_UNFL); ++ if (event & TGEC_IMASK_TX_FIFO_OVFL) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_TX_FIFO_OVFL); ++ if (event & TGEC_IMASK_TX_ER) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_TX_ER); ++ if (event & TGEC_IMASK_RX_FIFO_OVFL) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_FIFO_OVFL); ++ if (event & TGEC_IMASK_RX_ECC_ER) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_ECC_ER); ++ if (event & TGEC_IMASK_RX_JAB_FRM) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_JAB_FRM); ++ if (event & TGEC_IMASK_RX_OVRSZ_FRM) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_OVRSZ_FRM); ++ if (event & TGEC_IMASK_RX_RUNT_FRM) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_RUNT_FRM); ++ if (event & TGEC_IMASK_RX_FRAG_FRM) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_FRAG_FRM); ++ if (event & TGEC_IMASK_RX_LEN_ER) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_LEN_ER); ++ if (event & TGEC_IMASK_RX_CRC_ER) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_CRC_ER); ++ if (event & TGEC_IMASK_RX_ALIGN_ER) ++ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_ALIGN_ER); ++} ++ ++/* ......................................................................... */ ++ ++static void TgecException(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ uint32_t event; ++ struct tgec_regs *p_TgecMemMap = p_Tgec->p_MemMap; ++ ++ /* handle only MDIO events */ ++ event = fman_tgec_get_event(p_TgecMemMap, (TGEC_IMASK_MDIO_SCAN_EVENT | TGEC_IMASK_MDIO_CMD_CMPL)); ++ event &= fman_tgec_get_interrupt_mask(p_TgecMemMap); ++ ++ fman_tgec_ack_event(p_TgecMemMap, event); ++ ++ if (event & TGEC_IMASK_MDIO_SCAN_EVENT) ++ p_Tgec->f_Event(p_Tgec->h_App, e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO); ++ if (event & TGEC_IMASK_MDIO_CMD_CMPL) ++ p_Tgec->f_Event(p_Tgec->h_App, e_FM_MAC_EX_10G_MDIO_CMD_CMPL); ++} ++ ++/* ......................................................................... */ ++ ++static void FreeInitResources(t_Tgec *p_Tgec) ++{ ++ if (p_Tgec->mdioIrq != NO_IRQ) ++ { ++ XX_DisableIntr(p_Tgec->mdioIrq); ++ XX_FreeIntr(p_Tgec->mdioIrq); ++ } ++ ++ FmUnregisterIntr(p_Tgec->fmMacControllerDriver.h_Fm, e_FM_MOD_10G_MAC, p_Tgec->macId, e_FM_INTR_TYPE_ERR); ++ ++ /* release the driver's group hash table */ ++ FreeHashTable(p_Tgec->p_MulticastAddrHash); ++ p_Tgec->p_MulticastAddrHash = NULL; ++ ++ /* release the driver's individual hash table */ ++ FreeHashTable(p_Tgec->p_UnicastAddrHash); ++ p_Tgec->p_UnicastAddrHash = NULL; ++} ++ ++ ++/*****************************************************************************/ ++/* 10G MAC API routines */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++static t_Error TgecEnable(t_Handle h_Tgec, e_CommMode mode) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ fman_tgec_enable(p_Tgec->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX)); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecDisable (t_Handle h_Tgec, e_CommMode mode) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ fman_tgec_disable(p_Tgec->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX)); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecSetPromiscuous(t_Handle h_Tgec, bool newVal) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ fman_tgec_set_promiscuous(p_Tgec->p_MemMap, newVal); ++ ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* Tgec Configs modification functions */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++static t_Error TgecConfigLoopback(t_Handle h_Tgec, bool newVal) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ p_Tgec->p_TgecDriverParam->loopback_enable = newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecConfigWan(t_Handle h_Tgec, bool newVal) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ p_Tgec->p_TgecDriverParam->wan_mode_enable = newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecConfigMaxFrameLength(t_Handle h_Tgec, uint16_t newVal) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ p_Tgec->p_TgecDriverParam->max_frame_length = newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecConfigLengthCheck(t_Handle h_Tgec, bool newVal) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ UNUSED(newVal); ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ p_Tgec->p_TgecDriverParam->no_length_check_enable = !newVal; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecConfigException(t_Handle h_Tgec, e_FmMacExceptions exception, bool enable) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_Tgec->exceptions |= bitMask; ++ else ++ p_Tgec->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ return E_OK; ++} ++ ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++/* ......................................................................... */ ++ ++static t_Error TgecConfigSkipFman11Workaround(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ p_Tgec->p_TgecDriverParam->skip_fman11_workaround = TRUE; ++ ++ return E_OK; ++} ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++ ++/*****************************************************************************/ ++/* Tgec Run Time API functions */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++/* backward compatibility. will be removed in the future. */ ++static t_Error TgecTxMacPause(t_Handle h_Tgec, uint16_t pauseTime) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ fman_tgec_set_tx_pause_frames(p_Tgec->p_MemMap, pauseTime); ++ ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecSetTxPauseFrames(t_Handle h_Tgec, ++ uint8_t priority, ++ uint16_t pauseTime, ++ uint16_t threshTime) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ UNUSED(priority); UNUSED(threshTime); ++ ++ fman_tgec_set_tx_pause_frames(p_Tgec->p_MemMap, pauseTime); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecRxIgnoreMacPause(t_Handle h_Tgec, bool en) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ fman_tgec_set_rx_ignore_pause_frames(p_Tgec->p_MemMap, en); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecGetStatistics(t_Handle h_Tgec, t_FmMacStatistics *p_Statistics) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ struct tgec_regs *p_TgecMemMap; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER); ++ ++ p_TgecMemMap = p_Tgec->p_MemMap; ++ ++ p_Statistics->eStatPkts64 = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R64); ++ p_Statistics->eStatPkts65to127 = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R127); ++ p_Statistics->eStatPkts128to255 = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R255); ++ p_Statistics->eStatPkts256to511 = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R511); ++ p_Statistics->eStatPkts512to1023 = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R1023); ++ p_Statistics->eStatPkts1024to1518 = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R1518); ++ p_Statistics->eStatPkts1519to1522 = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R1519X); ++/* */ ++ p_Statistics->eStatFragments = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TRFRG); ++ p_Statistics->eStatJabbers = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TRJBR); ++ ++ p_Statistics->eStatsDropEvents = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RDRP); ++ p_Statistics->eStatCRCAlignErrors = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RALN); ++ ++ p_Statistics->eStatUndersizePkts = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TRUND); ++ p_Statistics->eStatOversizePkts = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TROVR); ++/* Pause */ ++ p_Statistics->reStatPause = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RXPF); ++ p_Statistics->teStatPause = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TXPF); ++ ++/* MIB II */ ++ p_Statistics->ifInOctets = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_ROCT); ++ p_Statistics->ifInUcastPkts = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RUCA); ++ p_Statistics->ifInMcastPkts = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RMCA); ++ p_Statistics->ifInBcastPkts = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RBCA); ++ p_Statistics->ifInPkts = p_Statistics->ifInUcastPkts ++ + p_Statistics->ifInMcastPkts ++ + p_Statistics->ifInBcastPkts; ++ p_Statistics->ifInDiscards = 0; ++ p_Statistics->ifInErrors = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RERR); ++ ++ p_Statistics->ifOutOctets = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TOCT); ++ p_Statistics->ifOutUcastPkts = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TUCA); ++ p_Statistics->ifOutMcastPkts = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TMCA); ++ p_Statistics->ifOutBcastPkts = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TBCA); ++ p_Statistics->ifOutPkts = p_Statistics->ifOutUcastPkts ++ + p_Statistics->ifOutMcastPkts ++ + p_Statistics->ifOutBcastPkts; ++ p_Statistics->ifOutDiscards = 0; ++ p_Statistics->ifOutErrors = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TERR); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecEnable1588TimeStamp(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ fman_tgec_enable_1588_time_stamp(p_Tgec->p_MemMap, 1); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecDisable1588TimeStamp(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ fman_tgec_enable_1588_time_stamp(p_Tgec->p_MemMap, 0); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecModifyMacAddress (t_Handle h_Tgec, t_EnetAddr *p_EnetAddr) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ p_Tgec->addr = ENET_ADDR_TO_UINT64(*p_EnetAddr); ++ fman_tgec_set_mac_address(p_Tgec->p_MemMap, (uint8_t *)(*p_EnetAddr)); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecResetCounters (t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ fman_tgec_reset_stat(p_Tgec->p_MemMap); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecAddExactMatchMacAddress(t_Handle h_Tgec, t_EnetAddr *p_EthAddr) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *) h_Tgec; ++ uint64_t ethAddr; ++ uint8_t paddrNum; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ if (ethAddr & GROUP_ADDRESS) ++ /* Multicast address has no effect in PADDR */ ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Multicast address")); ++ ++ /* Make sure no PADDR contains this address */ ++ for (paddrNum = 0; paddrNum < TGEC_NUM_OF_PADDRS; paddrNum++) ++ if (p_Tgec->indAddrRegUsed[paddrNum]) ++ if (p_Tgec->paddr[paddrNum] == ethAddr) ++ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG); ++ ++ /* Find first unused PADDR */ ++ for (paddrNum = 0; paddrNum < TGEC_NUM_OF_PADDRS; paddrNum++) ++ { ++ if (!(p_Tgec->indAddrRegUsed[paddrNum])) ++ { ++ /* mark this PADDR as used */ ++ p_Tgec->indAddrRegUsed[paddrNum] = TRUE; ++ /* store address */ ++ p_Tgec->paddr[paddrNum] = ethAddr; ++ ++ /* put in hardware */ ++ fman_tgec_add_addr_in_paddr(p_Tgec->p_MemMap, (uint8_t*)(*p_EthAddr)/* , paddrNum */); ++ p_Tgec->numOfIndAddrInRegs++; ++ ++ return E_OK; ++ } ++ } ++ ++ /* No free PADDR */ ++ RETURN_ERROR(MAJOR, E_FULL, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecDelExactMatchMacAddress(t_Handle h_Tgec, t_EnetAddr *p_EthAddr) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *) h_Tgec; ++ uint64_t ethAddr; ++ uint8_t paddrNum; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ /* Find used PADDR containing this address */ ++ for (paddrNum = 0; paddrNum < TGEC_NUM_OF_PADDRS; paddrNum++) ++ { ++ if ((p_Tgec->indAddrRegUsed[paddrNum]) && ++ (p_Tgec->paddr[paddrNum] == ethAddr)) ++ { ++ /* mark this PADDR as not used */ ++ p_Tgec->indAddrRegUsed[paddrNum] = FALSE; ++ /* clear in hardware */ ++ fman_tgec_clear_addr_in_paddr(p_Tgec->p_MemMap /*, paddrNum */); ++ p_Tgec->numOfIndAddrInRegs--; ++ ++ return E_OK; ++ } ++ } ++ ++ RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG); ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecAddHashMacAddress(t_Handle h_Tgec, t_EnetAddr *p_EthAddr) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ t_EthHashEntry *p_HashEntry; ++ uint32_t crc; ++ uint32_t hash; ++ uint64_t ethAddr; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr); ++ ++ if (!(ethAddr & GROUP_ADDRESS)) ++ /* Unicast addresses not supported in hash */ ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unicast Address")); ++ ++ /* CRC calculation */ ++ crc = GetMacAddrHashCode(ethAddr); ++ ++ hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK; /* Take 9 MSB bits */ ++ ++ /* Create element to be added to the driver hash table */ ++ p_HashEntry = (t_EthHashEntry *)XX_Malloc(sizeof(t_EthHashEntry)); ++ p_HashEntry->addr = ethAddr; ++ INIT_LIST(&p_HashEntry->node); ++ ++ LIST_AddToTail(&(p_HashEntry->node), &(p_Tgec->p_MulticastAddrHash->p_Lsts[hash])); ++ fman_tgec_set_hash_table(p_Tgec->p_MemMap, (hash | TGEC_HASH_MCAST_EN)); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecDelHashMacAddress(t_Handle h_Tgec, t_EnetAddr *p_EthAddr) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ t_EthHashEntry *p_HashEntry = NULL; ++ t_List *p_Pos; ++ uint32_t crc; ++ uint32_t hash; ++ uint64_t ethAddr; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ ethAddr = ((*(uint64_t *)p_EthAddr) >> 16); ++ ++ /* CRC calculation */ ++ crc = GetMacAddrHashCode(ethAddr); ++ ++ hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK; /* Take 9 MSB bits */ ++ ++ LIST_FOR_EACH(p_Pos, &(p_Tgec->p_MulticastAddrHash->p_Lsts[hash])) ++ { ++ p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos); ++ if (p_HashEntry->addr == ethAddr) ++ { ++ LIST_DelAndInit(&p_HashEntry->node); ++ XX_Free(p_HashEntry); ++ break; ++ } ++ } ++ if (LIST_IsEmpty(&p_Tgec->p_MulticastAddrHash->p_Lsts[hash])) ++ fman_tgec_set_hash_table(p_Tgec->p_MemMap, (hash & ~TGEC_HASH_MCAST_EN)); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecGetId(t_Handle h_Tgec, uint32_t *macId) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ UNUSED(p_Tgec); ++ UNUSED(macId); ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("TgecGetId Not Supported")); ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecGetVersion(t_Handle h_Tgec, uint32_t *macVersion) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ *macVersion = fman_tgec_get_revision(p_Tgec->p_MemMap); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecSetExcpetion(t_Handle h_Tgec, e_FmMacExceptions exception, bool enable) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_Tgec->exceptions |= bitMask; ++ else ++ p_Tgec->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ if (enable) ++ fman_tgec_enable_interrupt(p_Tgec->p_MemMap, bitMask); ++ else ++ fman_tgec_disable_interrupt(p_Tgec->p_MemMap, bitMask); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static uint16_t TgecGetMaxFrameLength(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Tgec, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE, 0); ++ ++ return fman_tgec_get_max_frame_len(p_Tgec->p_MemMap); ++} ++ ++/* ......................................................................... */ ++ ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++static t_Error TgecTxEccWorkaround(t_Tgec *p_Tgec) ++{ ++ t_Error err; ++ ++#if defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0) ++ XX_Print("Applying 10G TX ECC workaround (10GMAC-A004) ... "); ++#endif /* (DEBUG_ERRORS > 0) */ ++ /* enable and set promiscuous */ ++ fman_tgec_enable(p_Tgec->p_MemMap, TRUE, TRUE); ++ fman_tgec_set_promiscuous(p_Tgec->p_MemMap, TRUE); ++ err = Fm10GTxEccWorkaround(p_Tgec->fmMacControllerDriver.h_Fm, p_Tgec->macId); ++ /* disable */ ++ fman_tgec_set_promiscuous(p_Tgec->p_MemMap, FALSE); ++ fman_tgec_enable(p_Tgec->p_MemMap, FALSE, FALSE); ++ fman_tgec_reset_stat(p_Tgec->p_MemMap); ++ fman_tgec_ack_event(p_Tgec->p_MemMap, 0xffffffff); ++#if defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0) ++ if (err) ++ XX_Print("FAILED!\n"); ++ else ++ XX_Print("done.\n"); ++#endif /* (DEBUG_ERRORS > 0) */ ++ ++ return err; ++} ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++/*****************************************************************************/ ++/* FM Init & Free API */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++static t_Error TgecInit(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ struct tgec_cfg *p_TgecDriverParam; ++ t_EnetAddr ethAddr; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE); ++ ++ FM_GetRevision(p_Tgec->fmMacControllerDriver.h_Fm, &p_Tgec->fmMacControllerDriver.fmRevInfo); ++ CHECK_INIT_PARAMETERS(p_Tgec, CheckInitParameters); ++ ++ p_TgecDriverParam = p_Tgec->p_TgecDriverParam; ++ ++ MAKE_ENET_ADDR_FROM_UINT64(p_Tgec->addr, ethAddr); ++ fman_tgec_set_mac_address(p_Tgec->p_MemMap, (uint8_t *)ethAddr); ++ ++ /* interrupts */ ++#ifdef FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005 ++ { ++ if (p_Tgec->fmMacControllerDriver.fmRevInfo.majorRev <=2) ++ p_Tgec->exceptions &= ~(TGEC_IMASK_REM_FAULT | TGEC_IMASK_LOC_FAULT); ++ } ++#endif /* FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005 */ ++ ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++ if (!p_Tgec->p_TgecDriverParam->skip_fman11_workaround && ++ ((err = TgecTxEccWorkaround(p_Tgec)) != E_OK)) ++ { ++ FreeInitResources(p_Tgec); ++ REPORT_ERROR(MINOR, err, ("TgecTxEccWorkaround FAILED")); ++ } ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++ err = fman_tgec_init(p_Tgec->p_MemMap, p_TgecDriverParam, p_Tgec->exceptions); ++ if (err) ++ { ++ FreeInitResources(p_Tgec); ++ RETURN_ERROR(MAJOR, err, ("This TGEC version does not support the required i/f mode")); ++ } ++ ++ /* Max Frame Length */ ++ err = FmSetMacMaxFrame(p_Tgec->fmMacControllerDriver.h_Fm, ++ e_FM_MAC_10G, ++ p_Tgec->fmMacControllerDriver.macId, ++ p_TgecDriverParam->max_frame_length); ++ if (err != E_OK) ++ { ++ FreeInitResources(p_Tgec); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++/* we consider having no IPC a non crasher... */ ++ ++#ifdef FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007 ++ if (p_Tgec->fmMacControllerDriver.fmRevInfo.majorRev == 2) ++ fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007(p_Tgec->p_MemMap); ++#endif /* FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007 */ ++ ++ p_Tgec->p_MulticastAddrHash = AllocHashTable(HASH_TABLE_SIZE); ++ if (!p_Tgec->p_MulticastAddrHash) ++ { ++ FreeInitResources(p_Tgec); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED")); ++ } ++ ++ p_Tgec->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE); ++ if (!p_Tgec->p_UnicastAddrHash) ++ { ++ FreeInitResources(p_Tgec); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED")); ++ } ++ ++ FmRegisterIntr(p_Tgec->fmMacControllerDriver.h_Fm, ++ e_FM_MOD_10G_MAC, ++ p_Tgec->macId, ++ e_FM_INTR_TYPE_ERR, ++ TgecErrException, ++ p_Tgec); ++ if (p_Tgec->mdioIrq != NO_IRQ) ++ { ++ XX_SetIntr(p_Tgec->mdioIrq, TgecException, p_Tgec); ++ XX_EnableIntr(p_Tgec->mdioIrq); ++ } ++ ++ XX_Free(p_TgecDriverParam); ++ p_Tgec->p_TgecDriverParam = NULL; ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static t_Error TgecFree(t_Handle h_Tgec) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ ++ if (p_Tgec->p_TgecDriverParam) ++ { ++ /* Called after config */ ++ XX_Free(p_Tgec->p_TgecDriverParam); ++ p_Tgec->p_TgecDriverParam = NULL; ++ } ++ else ++ /* Called after init */ ++ FreeInitResources(p_Tgec); ++ ++ XX_Free(p_Tgec); ++ ++ return E_OK; ++} ++ ++/* ......................................................................... */ ++ ++static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver) ++{ ++ p_FmMacControllerDriver->f_FM_MAC_Init = TgecInit; ++ p_FmMacControllerDriver->f_FM_MAC_Free = TgecFree; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetStatistics = NULL; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback = TgecConfigLoopback; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength = TgecConfigMaxFrameLength; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigWan = TgecConfigWan; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc = NULL; /* TGEC always works with pad+crc */ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex = NULL; /* half-duplex is not supported in xgec */ ++ p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck = TgecConfigLengthCheck; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigException = TgecConfigException; ++ p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit = NULL; ++ ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++ p_FmMacControllerDriver->f_FM_MAC_ConfigSkipFman11Workaround= TgecConfigSkipFman11Workaround; ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetException = TgecSetExcpetion; ++ ++ p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp = TgecEnable1588TimeStamp; ++ p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp = TgecDisable1588TimeStamp; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous = TgecSetPromiscuous; ++ p_FmMacControllerDriver->f_FM_MAC_AdjustLink = NULL; ++ p_FmMacControllerDriver->f_FM_MAC_SetWakeOnLan = NULL; ++ p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg = NULL; ++ ++ p_FmMacControllerDriver->f_FM_MAC_Enable = TgecEnable; ++ p_FmMacControllerDriver->f_FM_MAC_Disable = TgecDisable; ++ ++ p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames = TgecTxMacPause; ++ p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames = TgecSetTxPauseFrames; ++ p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames = TgecRxIgnoreMacPause; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ResetCounters = TgecResetCounters; ++ p_FmMacControllerDriver->f_FM_MAC_GetStatistics = TgecGetStatistics; ++ ++ p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr = TgecModifyMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr = TgecAddHashMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr = TgecDelHashMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr = TgecAddExactMatchMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr = TgecDelExactMatchMacAddress; ++ p_FmMacControllerDriver->f_FM_MAC_GetId = TgecGetId; ++ p_FmMacControllerDriver->f_FM_MAC_GetVersion = TgecGetVersion; ++ p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength = TgecGetMaxFrameLength; ++ ++ p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg = TGEC_MII_WritePhyReg; ++ p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg = TGEC_MII_ReadPhyReg; ++} ++ ++ ++/*****************************************************************************/ ++/* Tgec Config Main Entry */ ++/*****************************************************************************/ ++ ++/* ......................................................................... */ ++ ++t_Handle TGEC_Config(t_FmMacParams *p_FmMacParam) ++{ ++ t_Tgec *p_Tgec; ++ struct tgec_cfg *p_TgecDriverParam; ++ uintptr_t baseAddr; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL); ++ ++ baseAddr = p_FmMacParam->baseAddr; ++ /* allocate memory for the UCC GETH data structure. */ ++ p_Tgec = (t_Tgec *)XX_Malloc(sizeof(t_Tgec)); ++ if (!p_Tgec) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("10G MAC driver structure")); ++ return NULL; ++ } ++ memset(p_Tgec, 0, sizeof(t_Tgec)); ++ InitFmMacControllerDriver(&p_Tgec->fmMacControllerDriver); ++ ++ /* allocate memory for the 10G MAC driver parameters data structure. */ ++ p_TgecDriverParam = (struct tgec_cfg *) XX_Malloc(sizeof(struct tgec_cfg)); ++ if (!p_TgecDriverParam) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("10G MAC driver parameters")); ++ XX_Free(p_Tgec); ++ return NULL; ++ } ++ memset(p_TgecDriverParam, 0, sizeof(struct tgec_cfg)); ++ ++ /* Plant parameter structure pointer */ ++ p_Tgec->p_TgecDriverParam = p_TgecDriverParam; ++ ++ fman_tgec_defconfig(p_TgecDriverParam); ++ ++ p_Tgec->p_MemMap = (struct tgec_regs *)UINT_TO_PTR(baseAddr); ++ p_Tgec->p_MiiMemMap = (t_TgecMiiAccessMemMap *)UINT_TO_PTR(baseAddr + TGEC_TO_MII_OFFSET); ++ p_Tgec->addr = ENET_ADDR_TO_UINT64(p_FmMacParam->addr); ++ p_Tgec->enetMode = p_FmMacParam->enetMode; ++ p_Tgec->macId = p_FmMacParam->macId; ++ p_Tgec->exceptions = DEFAULT_exceptions; ++ p_Tgec->mdioIrq = p_FmMacParam->mdioIrq; ++ p_Tgec->f_Exception = p_FmMacParam->f_Exception; ++ p_Tgec->f_Event = p_FmMacParam->f_Event; ++ p_Tgec->h_App = p_FmMacParam->h_App; ++ ++ return p_Tgec; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/tgec.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/tgec.h +new file mode 100644 +index 0000000..2aa3923 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/tgec.h +@@ -0,0 +1,151 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File tgec.h ++ ++ @Description FM 10G MAC ... ++*//***************************************************************************/ ++#ifndef __TGEC_H ++#define __TGEC_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++#include "enet_ext.h" ++ ++#include "tgec_mii_acc.h" ++#include "fm_mac.h" ++ ++ ++#define DEFAULT_exceptions \ ++ ((uint32_t)(TGEC_IMASK_MDIO_SCAN_EVENT | \ ++ TGEC_IMASK_REM_FAULT | \ ++ TGEC_IMASK_LOC_FAULT | \ ++ TGEC_IMASK_TX_ECC_ER | \ ++ TGEC_IMASK_TX_FIFO_UNFL | \ ++ TGEC_IMASK_TX_FIFO_OVFL | \ ++ TGEC_IMASK_TX_ER | \ ++ TGEC_IMASK_RX_FIFO_OVFL | \ ++ TGEC_IMASK_RX_ECC_ER | \ ++ TGEC_IMASK_RX_JAB_FRM | \ ++ TGEC_IMASK_RX_OVRSZ_FRM | \ ++ TGEC_IMASK_RX_RUNT_FRM | \ ++ TGEC_IMASK_RX_FRAG_FRM | \ ++ TGEC_IMASK_RX_CRC_ER | \ ++ TGEC_IMASK_RX_ALIGN_ER)) ++ ++#define GET_EXCEPTION_FLAG(bitMask, exception) switch (exception){ \ ++ case e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO: \ ++ bitMask = TGEC_IMASK_MDIO_SCAN_EVENT ; break; \ ++ case e_FM_MAC_EX_10G_MDIO_CMD_CMPL: \ ++ bitMask = TGEC_IMASK_MDIO_CMD_CMPL ; break; \ ++ case e_FM_MAC_EX_10G_REM_FAULT: \ ++ bitMask = TGEC_IMASK_REM_FAULT ; break; \ ++ case e_FM_MAC_EX_10G_LOC_FAULT: \ ++ bitMask = TGEC_IMASK_LOC_FAULT ; break; \ ++ case e_FM_MAC_EX_10G_1TX_ECC_ER: \ ++ bitMask = TGEC_IMASK_TX_ECC_ER ; break; \ ++ case e_FM_MAC_EX_10G_TX_FIFO_UNFL: \ ++ bitMask = TGEC_IMASK_TX_FIFO_UNFL ; break; \ ++ case e_FM_MAC_EX_10G_TX_FIFO_OVFL: \ ++ bitMask = TGEC_IMASK_TX_FIFO_OVFL ; break; \ ++ case e_FM_MAC_EX_10G_TX_ER: \ ++ bitMask = TGEC_IMASK_TX_ER ; break; \ ++ case e_FM_MAC_EX_10G_RX_FIFO_OVFL: \ ++ bitMask = TGEC_IMASK_RX_FIFO_OVFL ; break; \ ++ case e_FM_MAC_EX_10G_RX_ECC_ER: \ ++ bitMask = TGEC_IMASK_RX_ECC_ER ; break; \ ++ case e_FM_MAC_EX_10G_RX_JAB_FRM: \ ++ bitMask = TGEC_IMASK_RX_JAB_FRM ; break; \ ++ case e_FM_MAC_EX_10G_RX_OVRSZ_FRM: \ ++ bitMask = TGEC_IMASK_RX_OVRSZ_FRM ; break; \ ++ case e_FM_MAC_EX_10G_RX_RUNT_FRM: \ ++ bitMask = TGEC_IMASK_RX_RUNT_FRM ; break; \ ++ case e_FM_MAC_EX_10G_RX_FRAG_FRM: \ ++ bitMask = TGEC_IMASK_RX_FRAG_FRM ; break; \ ++ case e_FM_MAC_EX_10G_RX_LEN_ER: \ ++ bitMask = TGEC_IMASK_RX_LEN_ER ; break; \ ++ case e_FM_MAC_EX_10G_RX_CRC_ER: \ ++ bitMask = TGEC_IMASK_RX_CRC_ER ; break; \ ++ case e_FM_MAC_EX_10G_RX_ALIGN_ER: \ ++ bitMask = TGEC_IMASK_RX_ALIGN_ER ; break; \ ++ default: bitMask = 0;break;} ++ ++#define MAX_PACKET_ALIGNMENT 31 ++#define MAX_INTER_PACKET_GAP 0x7f ++#define MAX_INTER_PALTERNATE_BEB 0x0f ++#define MAX_RETRANSMISSION 0x0f ++#define MAX_COLLISION_WINDOW 0x03ff ++ ++#define TGEC_NUM_OF_PADDRS 1 /* number of pattern match registers (entries) */ ++ ++#define GROUP_ADDRESS 0x0000010000000000LL /* Group address bit indication */ ++ ++#define HASH_TABLE_SIZE 512 /* Hash table size (= 32 bits * 8 regs) */ ++ ++#define TGEC_TO_MII_OFFSET 0x1030 /* Offset from the MEM map to the MDIO mem map */ ++ ++/* 10-gigabit Ethernet MAC Controller ID (10GEC_ID) */ ++#define TGEC_ID_ID 0xffff0000 ++#define TGEC_ID_MAC_VERSION 0x0000FF00 ++#define TGEC_ID_MAC_REV 0x000000ff ++ ++ ++typedef struct { ++ t_FmMacControllerDriver fmMacControllerDriver; /**< Upper Mac control block */ ++ t_Handle h_App; /**< Handle to the upper layer application */ ++ struct tgec_regs *p_MemMap; /**< pointer to 10G memory mapped registers. */ ++ t_TgecMiiAccessMemMap *p_MiiMemMap; /**< pointer to MII memory mapped registers. */ ++ uint64_t addr; /**< MAC address of device; */ ++ e_EnetMode enetMode; /**< Ethernet physical interface */ ++ t_FmMacExceptionCallback *f_Exception; ++ int mdioIrq; ++ t_FmMacExceptionCallback *f_Event; ++ bool indAddrRegUsed[TGEC_NUM_OF_PADDRS]; /**< Whether a particular individual address recognition register is being used */ ++ uint64_t paddr[TGEC_NUM_OF_PADDRS]; /**< MAC address for particular individual address recognition register */ ++ uint8_t numOfIndAddrInRegs; /**< Number of individual addresses in registers for this station. */ ++ t_EthHash *p_MulticastAddrHash; /**< pointer to driver's global address hash table */ ++ t_EthHash *p_UnicastAddrHash; /**< pointer to driver's individual address hash table */ ++ bool debugMode; ++ uint8_t macId; ++ uint32_t exceptions; ++ struct tgec_cfg *p_TgecDriverParam; ++} t_Tgec; ++ ++ ++t_Error TGEC_MII_WritePhyReg(t_Handle h_Tgec, uint8_t phyAddr, uint8_t reg, uint16_t data); ++t_Error TGEC_MII_ReadPhyReg(t_Handle h_Tgec, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data); ++ ++ ++#endif /* __TGEC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/tgec_mii_acc.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/tgec_mii_acc.c +new file mode 100644 +index 0000000..e0fafd1 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/tgec_mii_acc.c +@@ -0,0 +1,139 @@ ++/* ++ * Copyright 2008-2012 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 "error_ext.h" ++#include "std_ext.h" ++#include "fm_mac.h" ++#include "tgec.h" ++#include "xx_ext.h" ++ ++#include "fm_common.h" ++ ++ ++/*****************************************************************************/ ++t_Error TGEC_MII_WritePhyReg(t_Handle h_Tgec, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t data) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ t_TgecMiiAccessMemMap *p_MiiAccess; ++ uint32_t cfgStatusReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MiiMemMap, E_INVALID_HANDLE); ++ ++ p_MiiAccess = p_Tgec->p_MiiMemMap; ++ ++ /* Configure MII */ ++ cfgStatusReg = GET_UINT32(p_MiiAccess->mdio_cfg_status); ++ cfgStatusReg &= ~MIIMCOM_DIV_MASK; ++ /* (one half of fm clock => 2.5Mhz) */ ++ cfgStatusReg |=((((p_Tgec->fmMacControllerDriver.clkFreq*10)/2)/25) << MIIMCOM_DIV_SHIFT); ++ WRITE_UINT32(p_MiiAccess->mdio_cfg_status, cfgStatusReg); ++ ++ while ((GET_UINT32(p_MiiAccess->mdio_cfg_status)) & MIIMIND_BUSY) ++ XX_UDelay (1); ++ ++ WRITE_UINT32(p_MiiAccess->mdio_command, phyAddr); ++ ++ WRITE_UINT32(p_MiiAccess->mdio_regaddr, reg); ++ ++ CORE_MemoryBarrier(); ++ ++ while ((GET_UINT32(p_MiiAccess->mdio_cfg_status)) & MIIMIND_BUSY) ++ XX_UDelay (1); ++ ++ WRITE_UINT32(p_MiiAccess->mdio_data, data); ++ ++ CORE_MemoryBarrier(); ++ ++ while ((GET_UINT32(p_MiiAccess->mdio_data)) & MIIDATA_BUSY) ++ XX_UDelay (1); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error TGEC_MII_ReadPhyReg(t_Handle h_Tgec, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t *p_Data) ++{ ++ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec; ++ t_TgecMiiAccessMemMap *p_MiiAccess; ++ uint32_t cfgStatusReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MiiMemMap, E_INVALID_HANDLE); ++ ++ p_MiiAccess = p_Tgec->p_MiiMemMap; ++ ++ /* Configure MII */ ++ cfgStatusReg = GET_UINT32(p_MiiAccess->mdio_cfg_status); ++ cfgStatusReg &= ~MIIMCOM_DIV_MASK; ++ /* (one half of fm clock => 2.5Mhz) */ ++ cfgStatusReg |=((((p_Tgec->fmMacControllerDriver.clkFreq*10)/2)/25) << MIIMCOM_DIV_SHIFT); ++ WRITE_UINT32(p_MiiAccess->mdio_cfg_status, cfgStatusReg); ++ ++ while ((GET_UINT32(p_MiiAccess->mdio_cfg_status)) & MIIMIND_BUSY) ++ XX_UDelay (1); ++ ++ WRITE_UINT32(p_MiiAccess->mdio_command, phyAddr); ++ ++ WRITE_UINT32(p_MiiAccess->mdio_regaddr, reg); ++ ++ CORE_MemoryBarrier(); ++ ++ while ((GET_UINT32(p_MiiAccess->mdio_cfg_status)) & MIIMIND_BUSY) ++ XX_UDelay (1); ++ ++ WRITE_UINT32(p_MiiAccess->mdio_command, (uint32_t)(phyAddr | MIIMCOM_READ_CYCLE)); ++ ++ CORE_MemoryBarrier(); ++ ++ while ((GET_UINT32(p_MiiAccess->mdio_data)) & MIIDATA_BUSY) ++ XX_UDelay (1); ++ ++ *p_Data = (uint16_t)GET_UINT32(p_MiiAccess->mdio_data); ++ ++ cfgStatusReg = GET_UINT32(p_MiiAccess->mdio_cfg_status); ++ ++ if (cfgStatusReg & MIIMIND_READ_ERROR) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ++ ("Read Error: phyAddr 0x%x, dev 0x%x, reg 0x%x, cfgStatusReg 0x%x", ++ ((phyAddr & 0xe0)>>5), (phyAddr & 0x1f), reg, cfgStatusReg)); ++ ++ return E_OK; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/tgec_mii_acc.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/tgec_mii_acc.h +new file mode 100644 +index 0000000..645cdde +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/tgec_mii_acc.h +@@ -0,0 +1,80 @@ ++/* ++ * Copyright 2008-2012 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 __TGEC_MII_ACC_H ++#define __TGEC_MII_ACC_H ++ ++#include "std_ext.h" ++ ++ ++/* MII Management Command Register */ ++#define MIIMCOM_READ_POST_INCREMENT 0x00004000 ++#define MIIMCOM_READ_CYCLE 0x00008000 ++#define MIIMCOM_SCAN_CYCLE 0x00000800 ++#define MIIMCOM_PREAMBLE_DISABLE 0x00000400 ++ ++#define MIIMCOM_MDIO_HOLD_1_REG_CLK 0 ++#define MIIMCOM_MDIO_HOLD_2_REG_CLK 1 ++#define MIIMCOM_MDIO_HOLD_3_REG_CLK 2 ++#define MIIMCOM_MDIO_HOLD_4_REG_CLK 3 ++ ++#define MIIMCOM_DIV_MASK 0x0000ff00 ++#define MIIMCOM_DIV_SHIFT 8 ++ ++/* MII Management Indicator Register */ ++#define MIIMIND_BUSY 0x00000001 ++#define MIIMIND_READ_ERROR 0x00000002 ++ ++#define MIIDATA_BUSY 0x80000000 ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/*----------------------------------------------------*/ ++/* MII Configuration Control Memory Map Registers */ ++/*----------------------------------------------------*/ ++typedef _Packed struct t_TgecMiiAccessMemMap ++{ ++ volatile uint32_t mdio_cfg_status; /* 0x030 */ ++ volatile uint32_t mdio_command; /* 0x034 */ ++ volatile uint32_t mdio_data; /* 0x038 */ ++ volatile uint32_t mdio_regaddr; /* 0x03c */ ++} _PackedType t_TgecMiiAccessMemMap ; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++#endif /* __TGEC_MII_ACC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/Makefile b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/Makefile +new file mode 100644 +index 0000000..bfa02f5 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/Makefile +@@ -0,0 +1,15 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++ccflags-y += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk ++ ++NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc ++ ++ccflags-y += -I$(NCSW_FM_INC) ++ ++obj-y += fsl-ncsw-macsec.o ++ ++fsl-ncsw-macsec-objs := fm_macsec.o fm_macsec_guest.o fm_macsec_master.o fm_macsec_secy.o +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec.c +new file mode 100644 +index 0000000..0a1b31f +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec.c +@@ -0,0 +1,237 @@ ++/* ++ * Copyright 2008-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. ++ */ ++/****************************************************************************** ++ ++ @File fm_macsec.c ++ ++ @Description FM MACSEC driver routines implementation. ++*//***************************************************************************/ ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "xx_ext.h" ++#include "string_ext.h" ++#include "sprint_ext.h" ++#include "debug_ext.h" ++ ++#include "fm_macsec.h" ++ ++ ++/****************************************/ ++/* API Init unit functions */ ++/****************************************/ ++t_Handle FM_MACSEC_Config(t_FmMacsecParams *p_FmMacsecParam) ++{ ++ t_FmMacsecControllerDriver *p_FmMacsecControllerDriver; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmMacsecParam, E_INVALID_HANDLE, NULL); ++ ++ if (p_FmMacsecParam->guestMode) ++ p_FmMacsecControllerDriver = (t_FmMacsecControllerDriver *)FM_MACSEC_GUEST_Config(p_FmMacsecParam); ++ else ++ p_FmMacsecControllerDriver = (t_FmMacsecControllerDriver *)FM_MACSEC_MASTER_Config(p_FmMacsecParam); ++ ++ if (!p_FmMacsecControllerDriver) ++ return NULL; ++ ++ return (t_Handle)p_FmMacsecControllerDriver; ++} ++ ++t_Error FM_MACSEC_Init(t_Handle h_FmMacsec) ++{ ++ t_FmMacsecControllerDriver *p_FmMacsecControllerDriver = (t_FmMacsecControllerDriver *)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacsecControllerDriver->f_FM_MACSEC_Init) ++ return p_FmMacsecControllerDriver->f_FM_MACSEC_Init(h_FmMacsec); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_Free(t_Handle h_FmMacsec) ++{ ++ t_FmMacsecControllerDriver *p_FmMacsecControllerDriver = (t_FmMacsecControllerDriver *)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacsecControllerDriver->f_FM_MACSEC_Free) ++ return p_FmMacsecControllerDriver->f_FM_MACSEC_Free(h_FmMacsec); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_ConfigUnknownSciFrameTreatment(t_Handle h_FmMacsec, e_FmMacsecUnknownSciFrameTreatment treatMode) ++{ ++ t_FmMacsecControllerDriver *p_FmMacsecControllerDriver = (t_FmMacsecControllerDriver *)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigUnknownSciFrameTreatment) ++ return p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigUnknownSciFrameTreatment(h_FmMacsec, treatMode); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_ConfigInvalidTagsFrameTreatment(t_Handle h_FmMacsec, bool deliverUncontrolled) ++{ ++ t_FmMacsecControllerDriver *p_FmMacsecControllerDriver = (t_FmMacsecControllerDriver *)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigInvalidTagsFrameTreatment) ++ return p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigInvalidTagsFrameTreatment(h_FmMacsec, deliverUncontrolled); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_ConfigEncryptWithNoChangedTextFrameTreatment(t_Handle h_FmMacsec, bool discardUncontrolled) ++{ ++ t_FmMacsecControllerDriver *p_FmMacsecControllerDriver = (t_FmMacsecControllerDriver *)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigEncryptWithNoChangedTextFrameTreatment) ++ return p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigEncryptWithNoChangedTextFrameTreatment(h_FmMacsec, discardUncontrolled); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_ConfigUntagFrameTreatment(t_Handle h_FmMacsec, e_FmMacsecUntagFrameTreatment treatMode) ++{ ++ t_FmMacsecControllerDriver *p_FmMacsecControllerDriver = (t_FmMacsecControllerDriver *)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigUntagFrameTreatment) ++ return p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigUntagFrameTreatment(h_FmMacsec, treatMode); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_ConfigPnExhaustionThreshold(t_Handle h_FmMacsec, uint32_t pnExhThr) ++{ ++ t_FmMacsecControllerDriver *p_FmMacsecControllerDriver = (t_FmMacsecControllerDriver *)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigPnExhaustionThreshold) ++ return p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigPnExhaustionThreshold(h_FmMacsec, pnExhThr); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_ConfigKeysUnreadable(t_Handle h_FmMacsec) ++{ ++ t_FmMacsecControllerDriver *p_FmMacsecControllerDriver = (t_FmMacsecControllerDriver *)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigKeysUnreadable) ++ return p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigKeysUnreadable(h_FmMacsec); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_ConfigSectagWithoutSCI(t_Handle h_FmMacsec) ++{ ++ t_FmMacsecControllerDriver *p_FmMacsecControllerDriver = (t_FmMacsecControllerDriver *)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigSectagWithoutSCI) ++ return p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigSectagWithoutSCI(h_FmMacsec); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_ConfigException(t_Handle h_FmMacsec, e_FmMacsecExceptions exception, bool enable) ++{ ++ t_FmMacsecControllerDriver *p_FmMacsecControllerDriver = (t_FmMacsecControllerDriver *)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigException) ++ return p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigException(h_FmMacsec, exception, enable); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_GetRevision(t_Handle h_FmMacsec, uint32_t *p_MacsecRevision) ++{ ++ t_FmMacsecControllerDriver *p_FmMacsecControllerDriver = (t_FmMacsecControllerDriver *)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacsecControllerDriver->f_FM_MACSEC_GetRevision) ++ return p_FmMacsecControllerDriver->f_FM_MACSEC_GetRevision(h_FmMacsec, p_MacsecRevision); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++ ++t_Error FM_MACSEC_Enable(t_Handle h_FmMacsec) ++{ ++ t_FmMacsecControllerDriver *p_FmMacsecControllerDriver = (t_FmMacsecControllerDriver *)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacsecControllerDriver->f_FM_MACSEC_Enable) ++ return p_FmMacsecControllerDriver->f_FM_MACSEC_Enable(h_FmMacsec); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_Disable(t_Handle h_FmMacsec) ++{ ++ t_FmMacsecControllerDriver *p_FmMacsecControllerDriver = (t_FmMacsecControllerDriver *)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacsecControllerDriver->f_FM_MACSEC_Disable) ++ return p_FmMacsecControllerDriver->f_FM_MACSEC_Disable(h_FmMacsec); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_SetException(t_Handle h_FmMacsec, e_FmMacsecExceptions exception, bool enable) ++{ ++ t_FmMacsecControllerDriver *p_FmMacsecControllerDriver = (t_FmMacsecControllerDriver *)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecControllerDriver, E_INVALID_HANDLE); ++ ++ if (p_FmMacsecControllerDriver->f_FM_MACSEC_SetException) ++ return p_FmMacsecControllerDriver->f_FM_MACSEC_SetException(h_FmMacsec, exception, enable); ++ ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec.h +new file mode 100644 +index 0000000..fbe5187 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec.h +@@ -0,0 +1,203 @@ ++/* ++ * Copyright 2008-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. ++ */ ++ ++/****************************************************************************** ++ @File fm_macsec.h ++ ++ @Description FM MACSEC internal structures and definitions. ++*//***************************************************************************/ ++#ifndef __FM_MACSEC_H ++#define __FM_MACSEC_H ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "fm_macsec_ext.h" ++ ++#include "fm_common.h" ++ ++ ++#define __ERR_MODULE__ MODULE_FM_MACSEC ++ ++ ++typedef struct ++{ ++ t_Error (*f_FM_MACSEC_Init) (t_Handle h_FmMacsec); ++ t_Error (*f_FM_MACSEC_Free) (t_Handle h_FmMacsec); ++ ++ t_Error (*f_FM_MACSEC_ConfigUnknownSciFrameTreatment) (t_Handle h_FmMacsec, e_FmMacsecUnknownSciFrameTreatment treatMode); ++ t_Error (*f_FM_MACSEC_ConfigInvalidTagsFrameTreatment) (t_Handle h_FmMacsec, bool deliverUncontrolled); ++ t_Error (*f_FM_MACSEC_ConfigEncryptWithNoChangedTextFrameTreatment) (t_Handle h_FmMacsec, bool discardUncontrolled); ++ t_Error (*f_FM_MACSEC_ConfigChangedTextWithNoEncryptFrameTreatment) (t_Handle h_FmMacsec, bool deliverUncontrolled); ++ t_Error (*f_FM_MACSEC_ConfigUntagFrameTreatment) (t_Handle h_FmMacsec, e_FmMacsecUntagFrameTreatment treatMode); ++ t_Error (*f_FM_MACSEC_ConfigOnlyScbIsSetFrameTreatment) (t_Handle h_FmMacsec, bool deliverUncontrolled); ++ t_Error (*f_FM_MACSEC_ConfigPnExhaustionThreshold) (t_Handle h_FmMacsec, uint32_t pnExhThr); ++ t_Error (*f_FM_MACSEC_ConfigKeysUnreadable) (t_Handle h_FmMacsec); ++ t_Error (*f_FM_MACSEC_ConfigSectagWithoutSCI) (t_Handle h_FmMacsec); ++ t_Error (*f_FM_MACSEC_ConfigException) (t_Handle h_FmMacsec, e_FmMacsecExceptions exception, bool enable); ++ ++ t_Error (*f_FM_MACSEC_GetRevision) (t_Handle h_FmMacsec, uint32_t *p_MacsecRevision); ++ t_Error (*f_FM_MACSEC_Enable) (t_Handle h_FmMacsec); ++ t_Error (*f_FM_MACSEC_Disable) (t_Handle h_FmMacsec); ++ t_Error (*f_FM_MACSEC_SetException) (t_Handle h_FmMacsec, e_FmMacsecExceptions exception, bool enable); ++ ++} t_FmMacsecControllerDriver; ++ ++t_Handle FM_MACSEC_GUEST_Config(t_FmMacsecParams *p_FmMacsecParam); ++t_Handle FM_MACSEC_MASTER_Config(t_FmMacsecParams *p_FmMacsecParams); ++ ++/***********************************************************************/ ++/* MACSEC internal routines */ ++/***********************************************************************/ ++ ++/**************************************************************************//** ++ ++ @Group FM_MACSEC_InterModule_grp FM MACSEC Inter-Module Unit ++ ++ @Description FM MACSEC Inter Module functions - ++ These are not User API routines but routines that may be called ++ from other modules. This will be the case in a single core environment, ++ where instead of using the XX messaging mechanism, the routines may be ++ called from other modules. In a multicore environment, the other modules may ++ be run by other cores and therefore these routines may not be called directly. ++ ++ @{ ++*//***************************************************************************/ ++ ++#define MAX_NUM_OF_SA_PER_SC 4 ++ ++typedef enum ++{ ++ e_SC_RX = 0, ++ e_SC_TX ++} e_ScType; ++ ++typedef enum ++{ ++ e_SC_SA_A = 0, ++ e_SC_SA_B , ++ e_SC_SA_C , ++ e_SC_SA_D ++} e_ScSaId; ++ ++typedef struct ++{ ++ uint32_t scId; ++ macsecSCI_t sci; ++ bool replayProtect; ++ uint32_t replayWindow; ++ e_FmMacsecValidFrameBehavior validateFrames; ++ uint16_t confidentialityOffset; ++ e_FmMacsecSecYCipherSuite cipherSuite; ++} t_RxScParams; ++ ++typedef struct ++{ ++ uint32_t scId; ++ macsecSCI_t sci; ++ bool protectFrames; ++ e_FmMacsecSciInsertionMode sciInsertionMode; ++ bool confidentialityEnable; ++ uint16_t confidentialityOffset; ++ e_FmMacsecSecYCipherSuite cipherSuite; ++} t_TxScParams; ++ ++typedef enum e_FmMacsecGlobalExceptions { ++ e_FM_MACSEC_EX_TX_SC, /**< Tx Sc 0 frame discarded error. */ ++ e_FM_MACSEC_EX_ECC /**< MACSEC memory ECC multiple-bit error. */ ++} e_FmMacsecGlobalExceptions; ++ ++typedef enum e_FmMacsecGlobalEvents { ++ e_FM_MACSEC_EV_TX_SC_NEXT_PN /**< Tx Sc 0 Next Pn exhaustion threshold reached. */ ++} e_FmMacsecGlobalEvents; ++ ++/**************************************************************************//** ++ @Description Enum for inter-module interrupts registration ++*//***************************************************************************/ ++typedef enum e_FmMacsecEventModules{ ++ e_FM_MACSEC_MOD_SC_TX, ++ e_FM_MACSEC_MOD_DUMMY_LAST ++} e_FmMacsecEventModules; ++ ++typedef enum e_FmMacsecInterModuleEvent { ++ e_FM_MACSEC_EV_SC_TX, ++ e_FM_MACSEC_EV_ERR_SC_TX, ++ e_FM_MACSEC_EV_DUMMY_LAST ++} e_FmMacsecInterModuleEvent; ++ ++#define NUM_OF_INTER_MODULE_EVENTS (NUM_OF_TX_SC * 2) ++ ++#define GET_MACSEC_MODULE_EVENT(mod, id, intrType, event) \ ++ switch(mod){ \ ++ case e_FM_MACSEC_MOD_SC_TX: \ ++ event = (intrType == e_FM_INTR_TYPE_ERR) ? \ ++ e_FM_MACSEC_EV_ERR_SC_TX: \ ++ e_FM_MACSEC_EV_SC_TX; \ ++ event += (uint8_t)(2 * id);break; \ ++ break; \ ++ default:event = e_FM_MACSEC_EV_DUMMY_LAST; \ ++ break;} ++ ++void FmMacsecRegisterIntr(t_Handle h_FmMacsec, ++ e_FmMacsecEventModules module, ++ uint8_t modId, ++ e_FmIntrType intrType, ++ void (*f_Isr) (t_Handle h_Arg, uint32_t id), ++ t_Handle h_Arg); ++ ++void FmMacsecUnregisterIntr(t_Handle h_FmMacsec, ++ e_FmMacsecEventModules module, ++ uint8_t modId, ++ e_FmIntrType intrType); ++ ++t_Error FmMacsecAllocScs(t_Handle h_FmMacsec, e_ScType type, bool isPtp, uint32_t numOfScs, uint32_t *p_ScIds); ++t_Error FmMacsecFreeScs(t_Handle h_FmMacsec, e_ScType type, uint32_t numOfScs, uint32_t *p_ScIds); ++t_Error FmMacsecCreateRxSc(t_Handle h_FmMacsec, t_RxScParams *p_RxScParams); ++t_Error FmMacsecDeleteRxSc(t_Handle h_FmMacsec, uint32_t scId); ++t_Error FmMacsecCreateTxSc(t_Handle h_FmMacsec, t_TxScParams *p_RxScParams); ++t_Error FmMacsecDeleteTxSc(t_Handle h_FmMacsec, uint32_t scId); ++t_Error FmMacsecCreateRxSa(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId, macsecAN_t an, uint32_t lowestPn, macsecSAKey_t key); ++t_Error FmMacsecCreateTxSa(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId, macsecSAKey_t key); ++t_Error FmMacsecDeleteRxSa(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId); ++t_Error FmMacsecDeleteTxSa(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId); ++t_Error FmMacsecRxSaSetReceive(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId, bool enableReceive); ++t_Error FmMacsecRxSaUpdateNextPn(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId, uint32_t updtNextPN); ++t_Error FmMacsecRxSaUpdateLowestPn(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId, uint32_t updtLowestPN); ++t_Error FmMacsecTxSaSetActive(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId, macsecAN_t an); ++t_Error FmMacsecTxSaGetActive(t_Handle h_FmMacsec, uint32_t scId, macsecAN_t *p_An); ++t_Error FmMacsecSetPTP(t_Handle h_FmMacsec, bool enable); ++ ++t_Error FmMacsecSetException(t_Handle h_FmMacsec, e_FmMacsecGlobalExceptions exception, uint32_t scId, bool enable); ++t_Error FmMacsecSetEvent(t_Handle h_FmMacsec, e_FmMacsecGlobalEvents event, uint32_t scId, bool enable); ++ ++ ++ ++#endif /* __FM_MACSEC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_guest.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_guest.c +new file mode 100644 +index 0000000..31d789d +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_guest.c +@@ -0,0 +1,59 @@ ++/* ++ * Copyright 2008-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. ++ */ ++ ++/****************************************************************************** ++ @File fm_macsec.c ++ ++ @Description FM MACSEC driver routines implementation. ++*//***************************************************************************/ ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "xx_ext.h" ++#include "string_ext.h" ++#include "sprint_ext.h" ++#include "debug_ext.h" ++#include "fm_macsec.h" ++ ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++ ++/****************************************/ ++/* API Init unit functions */ ++/****************************************/ ++t_Handle FM_MACSEC_GUEST_Config(t_FmMacsecParams *p_FmMacsecParam) ++{ ++ UNUSED(p_FmMacsecParam); ++ return NULL; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_master.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_master.c +new file mode 100644 +index 0000000..79260c8 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_master.c +@@ -0,0 +1,1031 @@ ++/* ++ * Copyright 2008-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. ++ */ ++ ++/****************************************************************************** ++ @File fm_macsec.c ++ ++ @Description FM MACSEC driver routines implementation. ++*//***************************************************************************/ ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "xx_ext.h" ++#include "string_ext.h" ++#include "sprint_ext.h" ++#include "fm_mac_ext.h" ++ ++#include "fm_macsec_master.h" ++ ++ ++extern uint16_t FM_MAC_GetMaxFrameLength(t_Handle FmMac); ++ ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++static t_Error CheckFmMacsecParameters(t_FmMacsec *p_FmMacsec) ++{ ++ if (!p_FmMacsec->f_Exception) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceptions callback not provided")); ++ ++ return E_OK; ++} ++ ++static void UnimplementedIsr(t_Handle h_Arg, uint32_t id) ++{ ++ UNUSED(h_Arg); UNUSED(id); ++ ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unimplemented Isr!")); ++} ++ ++static void MacsecEventIsr(t_Handle h_FmMacsec) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ uint32_t events,event,i; ++ ++ SANITY_CHECK_RETURN(p_FmMacsec, E_INVALID_HANDLE); ++ ++ events = GET_UINT32(p_FmMacsec->p_FmMacsecRegs->evr); ++ events |= GET_UINT32(p_FmMacsec->p_FmMacsecRegs->ever); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->evr,events); ++ ++ for (i=0; iintrMng[event].f_Isr(p_FmMacsec->intrMng[event].h_SrcHandle, i); ++ } ++} ++ ++static void MacsecErrorIsr(t_Handle h_FmMacsec) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ uint32_t errors,error,i; ++ ++ SANITY_CHECK_RETURN(p_FmMacsec, E_INVALID_HANDLE); ++ ++ errors = GET_UINT32(p_FmMacsec->p_FmMacsecRegs->err); ++ errors |= GET_UINT32(p_FmMacsec->p_FmMacsecRegs->erer); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->err,errors); ++ ++ for (i=0; iintrMng[error].f_Isr(p_FmMacsec->intrMng[error].h_SrcHandle, i); ++ } ++ ++ if (errors & FM_MACSEC_EX_ECC) ++ { ++ uint8_t eccType; ++ uint32_t tmpReg; ++ ++ tmpReg = GET_UINT32(p_FmMacsec->p_FmMacsecRegs->meec); ++ ASSERT_COND(tmpReg & MECC_CAP); ++ eccType = (uint8_t)((tmpReg & MECC_CET) >> MECC_CET_SHIFT); ++ ++ if (!eccType && (p_FmMacsec->userExceptions & FM_MACSEC_USER_EX_SINGLE_BIT_ECC)) ++ p_FmMacsec->f_Exception(p_FmMacsec->h_App,e_FM_MACSEC_EX_SINGLE_BIT_ECC); ++ else if (eccType && (p_FmMacsec->userExceptions & FM_MACSEC_USER_EX_MULTI_BIT_ECC)) ++ p_FmMacsec->f_Exception(p_FmMacsec->h_App,e_FM_MACSEC_EX_MULTI_BIT_ECC); ++ else ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->meec,tmpReg); ++ } ++} ++ ++static t_Error MacsecInit(t_Handle h_FmMacsec) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ t_FmMacsecDriverParam *p_FmMacsecDriverParam = NULL; ++ uint32_t tmpReg,i,macId; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ CHECK_INIT_PARAMETERS(p_FmMacsec, CheckFmMacsecParameters); ++ ++ p_FmMacsecDriverParam = p_FmMacsec->p_FmMacsecDriverParam; ++ ++ for (i=0;iintrMng[i].f_Isr = UnimplementedIsr; ++ ++ tmpReg = 0; ++ tmpReg |= (p_FmMacsecDriverParam->changedTextWithNoEncryptDeliverUncontrolled << CFG_UECT_SHIFT)| ++ (p_FmMacsecDriverParam->onlyScbIsSetDeliverUncontrolled << CFG_ESCBT_SHIFT) | ++ (p_FmMacsecDriverParam->unknownSciTreatMode << CFG_USFT_SHIFT) | ++ (p_FmMacsecDriverParam->invalidTagsDeliverUncontrolled << CFG_ITT_SHIFT) | ++ (p_FmMacsecDriverParam->encryptWithNoChangedTextDiscardUncontrolled << CFG_KFT_SHIFT) | ++ (p_FmMacsecDriverParam->untagTreatMode << CFG_UFT_SHIFT) | ++ (p_FmMacsecDriverParam->keysUnreadable << CFG_KSS_SHIFT) | ++ (p_FmMacsecDriverParam->reservedSc0 << CFG_S0I_SHIFT) | ++ (p_FmMacsecDriverParam->byPassMode << CFG_BYPN_SHIFT); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->cfg, tmpReg); ++ ++ tmpReg = FM_MAC_GetMaxFrameLength(p_FmMacsec->h_FmMac); ++ /* At least Ethernet FCS (4 bytes) overhead must be subtracted from MFL. ++ * In addition, the SCI (8 bytes) overhead might be subtracted as well. */ ++ tmpReg -= p_FmMacsecDriverParam->mflSubtract; ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->mfl, tmpReg); ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->tpnet, p_FmMacsecDriverParam->pnExhThr); ++ ++ if (!p_FmMacsec->userExceptions) ++ p_FmMacsec->exceptions &= ~FM_MACSEC_EX_ECC; ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->erer, p_FmMacsec->exceptions); ++ ++ p_FmMacsec->numRxScAvailable = NUM_OF_RX_SC; ++ if (p_FmMacsecDriverParam->reservedSc0) ++ p_FmMacsec->numRxScAvailable --; ++ p_FmMacsec->numTxScAvailable = NUM_OF_TX_SC; ++ ++ XX_Free(p_FmMacsecDriverParam); ++ p_FmMacsec->p_FmMacsecDriverParam = NULL; ++ ++ FM_MAC_GetId(p_FmMacsec->h_FmMac, &macId); ++ FmRegisterIntr(p_FmMacsec->h_Fm, ++ e_FM_MOD_MACSEC, ++ (uint8_t)macId, ++ e_FM_INTR_TYPE_NORMAL, ++ MacsecEventIsr, ++ p_FmMacsec); ++ ++ FmRegisterIntr(p_FmMacsec->h_Fm, ++ e_FM_MOD_MACSEC, ++ 0, ++ e_FM_INTR_TYPE_ERR, ++ MacsecErrorIsr, ++ p_FmMacsec); ++ ++ return E_OK; ++} ++ ++static t_Error MacsecFree(t_Handle h_FmMacsec) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ uint32_t macId; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ FM_MAC_GetId(p_FmMacsec->h_FmMac, &macId); ++ FmUnregisterIntr(p_FmMacsec->h_Fm, ++ e_FM_MOD_MACSEC, ++ (uint8_t)macId, ++ e_FM_INTR_TYPE_NORMAL); ++ ++ FmUnregisterIntr(p_FmMacsec->h_Fm, ++ e_FM_MOD_MACSEC, ++ 0, ++ e_FM_INTR_TYPE_ERR); ++ ++ if (p_FmMacsec->rxScSpinLock) ++ XX_FreeSpinlock(p_FmMacsec->rxScSpinLock); ++ if (p_FmMacsec->txScSpinLock) ++ XX_FreeSpinlock(p_FmMacsec->txScSpinLock); ++ ++ XX_Free(p_FmMacsec); ++ ++ return E_OK; ++} ++ ++static t_Error MacsecConfigUnknownSciFrameTreatment(t_Handle h_FmMacsec, e_FmMacsecUnknownSciFrameTreatment treatMode) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ p_FmMacsec->p_FmMacsecDriverParam->unknownSciTreatMode = treatMode; ++ ++ return E_OK; ++} ++ ++static t_Error MacsecConfigInvalidTagsFrameTreatment(t_Handle h_FmMacsec, bool deliverUncontrolled) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ p_FmMacsec->p_FmMacsecDriverParam->invalidTagsDeliverUncontrolled = deliverUncontrolled; ++ ++ return E_OK; ++} ++ ++static t_Error MacsecConfigChangedTextWithNoEncryptFrameTreatment(t_Handle h_FmMacsec, bool deliverUncontrolled) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ p_FmMacsec->p_FmMacsecDriverParam->changedTextWithNoEncryptDeliverUncontrolled = deliverUncontrolled; ++ ++ return E_OK; ++} ++ ++static t_Error MacsecConfigOnlyScbIsSetFrameTreatment(t_Handle h_FmMacsec, bool deliverUncontrolled) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ p_FmMacsec->p_FmMacsecDriverParam->onlyScbIsSetDeliverUncontrolled = deliverUncontrolled; ++ ++ return E_OK; ++} ++ ++static t_Error MacsecConfigEncryptWithNoChangedTextFrameTreatment(t_Handle h_FmMacsec, bool discardUncontrolled) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ p_FmMacsec->p_FmMacsecDriverParam->encryptWithNoChangedTextDiscardUncontrolled = discardUncontrolled; ++ ++ return E_OK; ++} ++ ++static t_Error MacsecConfigUntagFrameTreatment(t_Handle h_FmMacsec, e_FmMacsecUntagFrameTreatment treatMode) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ p_FmMacsec->p_FmMacsecDriverParam->untagTreatMode = treatMode; ++ ++ return E_OK; ++} ++ ++static t_Error MacsecConfigPnExhaustionThreshold(t_Handle h_FmMacsec, uint32_t pnExhThr) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ p_FmMacsec->p_FmMacsecDriverParam->pnExhThr = pnExhThr; ++ ++ return E_OK; ++} ++ ++static t_Error MacsecConfigKeysUnreadable(t_Handle h_FmMacsec) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ p_FmMacsec->p_FmMacsecDriverParam->keysUnreadable = TRUE; ++ ++ return E_OK; ++} ++ ++static t_Error MacsecConfigSectagWithoutSCI(t_Handle h_FmMacsec) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ p_FmMacsec->p_FmMacsecDriverParam->sectagOverhead -= MACSEC_SCI_SIZE; ++ p_FmMacsec->p_FmMacsecDriverParam->mflSubtract += MACSEC_SCI_SIZE; ++ ++ return E_OK; ++} ++ ++static t_Error MacsecConfigException(t_Handle h_FmMacsec, e_FmMacsecExceptions exception, bool enable) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ GET_USER_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_FmMacsec->userExceptions |= bitMask; ++ else ++ p_FmMacsec->userExceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ return E_OK; ++} ++ ++static t_Error MacsecGetRevision(t_Handle h_FmMacsec, uint32_t *p_MacsecRevision) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ *p_MacsecRevision = GET_UINT32(p_FmMacsec->p_FmMacsecRegs->ip_rev1); ++ ++ return E_OK; ++} ++ ++static t_Error MacsecEnable(t_Handle h_FmMacsec) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ uint32_t tmpReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ tmpReg = GET_UINT32(p_FmMacsec->p_FmMacsecRegs->cfg); ++ tmpReg |= CFG_BYPN; ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->cfg,tmpReg); ++ ++ return E_OK; ++} ++ ++static t_Error MacsecDisable(t_Handle h_FmMacsec) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ uint32_t tmpReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ tmpReg = GET_UINT32(p_FmMacsec->p_FmMacsecRegs->cfg); ++ tmpReg &= ~CFG_BYPN; ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->cfg,tmpReg); ++ ++ return E_OK; ++} ++ ++static t_Error MacsecSetException(t_Handle h_FmMacsec, e_FmMacsecExceptions exception, bool enable) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ uint32_t bitMask; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ GET_USER_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_FmMacsec->userExceptions |= bitMask; ++ else ++ p_FmMacsec->userExceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ if (!p_FmMacsec->userExceptions) ++ p_FmMacsec->exceptions &= ~FM_MACSEC_EX_ECC; ++ else ++ p_FmMacsec->exceptions |= FM_MACSEC_EX_ECC; ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->erer, p_FmMacsec->exceptions); ++ ++ return E_OK; ++} ++ ++static void InitFmMacsecControllerDriver(t_FmMacsecControllerDriver *p_FmMacsecControllerDriver) ++{ ++ p_FmMacsecControllerDriver->f_FM_MACSEC_Init = MacsecInit; ++ p_FmMacsecControllerDriver->f_FM_MACSEC_Free = MacsecFree; ++ p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigUnknownSciFrameTreatment = MacsecConfigUnknownSciFrameTreatment; ++ p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigInvalidTagsFrameTreatment = MacsecConfigInvalidTagsFrameTreatment; ++ p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigEncryptWithNoChangedTextFrameTreatment = MacsecConfigEncryptWithNoChangedTextFrameTreatment; ++ p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigUntagFrameTreatment = MacsecConfigUntagFrameTreatment; ++ p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigChangedTextWithNoEncryptFrameTreatment = MacsecConfigChangedTextWithNoEncryptFrameTreatment; ++ p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigOnlyScbIsSetFrameTreatment = MacsecConfigOnlyScbIsSetFrameTreatment; ++ p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigPnExhaustionThreshold = MacsecConfigPnExhaustionThreshold; ++ p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigKeysUnreadable = MacsecConfigKeysUnreadable; ++ p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigSectagWithoutSCI = MacsecConfigSectagWithoutSCI; ++ p_FmMacsecControllerDriver->f_FM_MACSEC_ConfigException = MacsecConfigException; ++ p_FmMacsecControllerDriver->f_FM_MACSEC_GetRevision = MacsecGetRevision; ++ p_FmMacsecControllerDriver->f_FM_MACSEC_Enable = MacsecEnable; ++ p_FmMacsecControllerDriver->f_FM_MACSEC_Disable = MacsecDisable; ++ p_FmMacsecControllerDriver->f_FM_MACSEC_SetException = MacsecSetException; ++} ++ ++/****************************************/ ++/* Inter-Module functions */ ++/****************************************/ ++ ++void FmMacsecRegisterIntr(t_Handle h_FmMacsec, ++ e_FmMacsecEventModules module, ++ uint8_t modId, ++ e_FmIntrType intrType, ++ void (*f_Isr) (t_Handle h_Arg, uint32_t id), ++ t_Handle h_Arg) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ uint8_t event= 0; ++ ++ SANITY_CHECK_RETURN(p_FmMacsec, E_INVALID_HANDLE); ++ ++ GET_MACSEC_MODULE_EVENT(module, modId, intrType, event); ++ ++ ASSERT_COND(event != e_FM_MACSEC_EV_DUMMY_LAST); ++ p_FmMacsec->intrMng[event].f_Isr = f_Isr; ++ p_FmMacsec->intrMng[event].h_SrcHandle = h_Arg; ++} ++ ++void FmMacsecUnregisterIntr(t_Handle h_FmMacsec, ++ e_FmMacsecEventModules module, ++ uint8_t modId, ++ e_FmIntrType intrType) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ uint8_t event= 0; ++ ++ SANITY_CHECK_RETURN(p_FmMacsec, E_INVALID_HANDLE); ++ ++ GET_MACSEC_MODULE_EVENT(module, modId,intrType, event); ++ ++ ASSERT_COND(event != e_FM_MACSEC_EV_DUMMY_LAST); ++ p_FmMacsec->intrMng[event].f_Isr = NULL; ++ p_FmMacsec->intrMng[event].h_SrcHandle = NULL; ++} ++ ++t_Error FmMacsecAllocScs(t_Handle h_FmMacsec, e_ScType type, bool isPtp, uint32_t numOfScs, uint32_t *p_ScIds) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ t_Error err = E_OK; ++ bool *p_ScTable; ++ uint32_t *p_ScAvailable,i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_ScIds, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(numOfScs, E_INVALID_HANDLE); ++ ++ if (type == e_SC_RX) ++ { ++ p_ScTable = (bool *)p_FmMacsec->rxScTable; ++ p_ScAvailable = &p_FmMacsec->numRxScAvailable; ++ i = (NUM_OF_RX_SC - 1); ++ } ++ else ++ { ++ p_ScTable = (bool *)p_FmMacsec->txScTable; ++ p_ScAvailable = &p_FmMacsec->numTxScAvailable; ++ i = (NUM_OF_TX_SC - 1); ++ ++ } ++ if (*p_ScAvailable < numOfScs) ++ RETURN_ERROR(MINOR, E_NOT_AVAILABLE, ("Not enough SCs available")); ++ ++ if (isPtp) ++ { ++ i = 0; ++ if (p_ScTable[i]) ++ RETURN_ERROR(MINOR, E_NOT_AVAILABLE, ("Sc 0 Not available")); ++ } ++ ++ for (;numOfScs;i--) ++ { ++ if (p_ScTable[i]) ++ continue; ++ numOfScs --; ++ (*p_ScAvailable)--; ++ p_ScIds[numOfScs] = i; ++ p_ScTable[i] = TRUE; ++ } ++ ++ return err; ++} ++ ++t_Error FmMacsecFreeScs(t_Handle h_FmMacsec, e_ScType type, uint32_t numOfScs, uint32_t *p_ScIds) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ t_Error err = E_OK; ++ bool *p_ScTable; ++ uint32_t *p_ScAvailable,maxNumOfSc,i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_ScIds, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(numOfScs, E_INVALID_HANDLE); ++ ++ if (type == e_SC_RX) ++ { ++ p_ScTable = (bool *)p_FmMacsec->rxScTable; ++ p_ScAvailable = &p_FmMacsec->numRxScAvailable; ++ maxNumOfSc = NUM_OF_RX_SC; ++ } ++ else ++ { ++ p_ScTable = (bool *)p_FmMacsec->txScTable; ++ p_ScAvailable = &p_FmMacsec->numTxScAvailable; ++ maxNumOfSc = NUM_OF_TX_SC; ++ } ++ ++ if ((*p_ScAvailable + numOfScs) > maxNumOfSc) ++ RETURN_ERROR(MINOR, E_FULL, ("Too much SCs")); ++ ++ for (i=0;ip_FmMacsecRegs->cfg); ++ if (enable && (tmpReg & CFG_S0I)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("MACSEC already in point-to-point mode")); ++ ++ if (enable) ++ tmpReg |= CFG_S0I; ++ else ++ tmpReg &= ~CFG_S0I; ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->cfg, tmpReg); ++ ++ return E_OK; ++} ++ ++t_Error FmMacsecCreateRxSc(t_Handle h_FmMacsec, t_RxScParams *p_RxScParams) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ t_Error err = E_OK; ++ uint32_t tmpReg = 0, intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_RxScParams, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_RxScParams->scId < NUM_OF_RX_SC, E_INVALID_HANDLE); ++ ++ intFlags = XX_LockIntrSpinlock(p_FmMacsec->rxScSpinLock); ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->rxsca, p_RxScParams->scId); ++ tmpReg = GET_UINT32(p_FmMacsec->p_FmMacsecRegs->rxsccfg); ++ if (tmpReg & RX_SCCFG_SCI_EN_MASK) ++ { ++ XX_UnlockIntrSpinlock(p_FmMacsec->rxScSpinLock, intFlags); ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Rx Sc %d must be disable",p_RxScParams->scId)); ++ } ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->rxsci1h, GET_SCI_FIRST_HALF(p_RxScParams->sci)); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->rxsci2h, GET_SCI_SECOND_HALF(p_RxScParams->sci)); ++ tmpReg |= ((p_RxScParams->replayProtect << RX_SCCFG_RP_SHIFT) & RX_SCCFG_RP_MASK); ++ tmpReg |= ((p_RxScParams->validateFrames << RX_SCCFG_VF_SHIFT) & RX_SCCFG_VF_MASK); ++ tmpReg |= ((p_RxScParams->confidentialityOffset << RX_SCCFG_CO_SHIFT) & RX_SCCFG_CO_MASK); ++ tmpReg |= RX_SCCFG_SCI_EN_MASK; ++ tmpReg |= (p_RxScParams->cipherSuite << RX_SCCFG_CS_SHIFT); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->rxsccfg, tmpReg); ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->rpw, p_RxScParams->replayWindow); ++ ++ XX_UnlockIntrSpinlock(p_FmMacsec->rxScSpinLock, intFlags); ++ ++ return err; ++} ++ ++t_Error FmMacsecDeleteRxSc(t_Handle h_FmMacsec, uint32_t scId) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ t_Error err = E_OK; ++ uint32_t tmpReg = 0, intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(scId < NUM_OF_RX_SC, E_INVALID_HANDLE); ++ ++ intFlags = XX_LockIntrSpinlock(p_FmMacsec->rxScSpinLock); ++ ++ tmpReg &= ~RX_SCCFG_SCI_EN_MASK; ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->rxsca, scId); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->rxsccfg, tmpReg); ++ ++ XX_UnlockIntrSpinlock(p_FmMacsec->rxScSpinLock, intFlags); ++ ++ return err; ++} ++ ++t_Error FmMacsecCreateTxSc(t_Handle h_FmMacsec, t_TxScParams *p_TxScParams) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ t_Error err = E_OK; ++ uint32_t tmpReg = 0, intFlags; ++ bool alwaysIncludeSCI = FALSE, useES = FALSE, useSCB = FALSE; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_TxScParams, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_TxScParams->scId < NUM_OF_TX_SC, E_INVALID_HANDLE); ++ ++ intFlags = XX_LockIntrSpinlock(p_FmMacsec->txScSpinLock); ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->txsca, p_TxScParams->scId); ++ ++ tmpReg = GET_UINT32(p_FmMacsec->p_FmMacsecRegs->txsccfg); ++ if (tmpReg & TX_SCCFG_SCE_MASK) ++ { ++ XX_UnlockIntrSpinlock(p_FmMacsec->txScSpinLock, intFlags); ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Tx Sc %d must be disable",p_TxScParams->scId)); ++ } ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->txsci1h, GET_SCI_FIRST_HALF(p_TxScParams->sci)); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->txsci2h, GET_SCI_SECOND_HALF(p_TxScParams->sci)); ++ alwaysIncludeSCI = (p_TxScParams->sciInsertionMode == e_FM_MACSEC_SCI_INSERTION_MODE_EXPLICIT_SECTAG); ++ useES = (p_TxScParams->sciInsertionMode == e_FM_MACSEC_SCI_INSERTION_MODE_EXPLICIT_MAC_SA); ++ ++ tmpReg |= ((p_TxScParams->protectFrames << TX_SCCFG_PF_SHIFT) & TX_SCCFG_PF_MASK); ++ tmpReg |= ((alwaysIncludeSCI << TX_SCCFG_AIS_SHIFT) & TX_SCCFG_AIS_MASK); ++ tmpReg |= ((useES << TX_SCCFG_UES_SHIFT) & TX_SCCFG_UES_MASK); ++ tmpReg |= ((useSCB << TX_SCCFG_USCB_SHIFT) & TX_SCCFG_USCB_MASK); ++ tmpReg |= ((p_TxScParams->confidentialityEnable << TX_SCCFG_CE_SHIFT) & TX_SCCFG_CE_MASK); ++ tmpReg |= ((p_TxScParams->confidentialityOffset << TX_SCCFG_CO_SHIFT) & TX_SCCFG_CO_MASK); ++ tmpReg |= TX_SCCFG_SCE_MASK; ++ tmpReg |= (p_TxScParams->cipherSuite << TX_SCCFG_CS_SHIFT); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->txsccfg, tmpReg); ++ ++ XX_UnlockIntrSpinlock(p_FmMacsec->txScSpinLock, intFlags); ++ ++ return err; ++} ++ ++t_Error FmMacsecDeleteTxSc(t_Handle h_FmMacsec, uint32_t scId) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ t_Error err = E_OK; ++ uint32_t tmpReg = 0, intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(scId < NUM_OF_TX_SC, E_INVALID_HANDLE); ++ ++ intFlags = XX_LockIntrSpinlock(p_FmMacsec->txScSpinLock); ++ ++ tmpReg &= ~TX_SCCFG_SCE_MASK; ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->txsca, scId); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->txsccfg, tmpReg); ++ ++ XX_UnlockIntrSpinlock(p_FmMacsec->txScSpinLock, intFlags); ++ ++ return err; ++} ++ ++t_Error FmMacsecCreateRxSa(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId, macsecAN_t an, uint32_t lowestPn, macsecSAKey_t key) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ t_Error err = E_OK; ++ uint32_t tmpReg = 0, intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(scId < NUM_OF_RX_SC, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(saId < NUM_OF_SA_PER_RX_SC, E_INVALID_HANDLE); ++ ++ intFlags = XX_LockIntrSpinlock(p_FmMacsec->rxScSpinLock); ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->rxsca, scId); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecRxScSa[saId].rxsanpn, DEFAULT_initNextPn); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecRxScSa[saId].rxsalpn, lowestPn); ++ Mem2IOCpy32((void*)p_FmMacsec->p_FmMacsecRegs->fmMacsecRxScSa[saId].rxsak, key, sizeof(macsecSAKey_t)); ++ ++ tmpReg |= RX_SACFG_ACTIVE; ++ tmpReg |= ((an << RX_SACFG_AN_SHIFT) & RX_SACFG_AN_MASK); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecRxScSa[saId].rxsacs, tmpReg); ++ ++ XX_UnlockIntrSpinlock(p_FmMacsec->rxScSpinLock, intFlags); ++ ++ return err; ++} ++ ++t_Error FmMacsecCreateTxSa(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId, macsecSAKey_t key) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ t_Error err = E_OK; ++ uint32_t tmpReg = 0, intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(scId < NUM_OF_RX_SC, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(saId < NUM_OF_SA_PER_TX_SC, E_INVALID_HANDLE); ++ ++ intFlags = XX_LockIntrSpinlock(p_FmMacsec->txScSpinLock); ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->txsca, scId); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecTxScSa[saId].txsanpn, DEFAULT_initNextPn); ++ Mem2IOCpy32((void*)p_FmMacsec->p_FmMacsecRegs->fmMacsecTxScSa[saId].txsak, key, sizeof(macsecSAKey_t)); ++ ++ tmpReg |= TX_SACFG_ACTIVE; ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecTxScSa[saId].txsacs, tmpReg); ++ ++ XX_UnlockIntrSpinlock(p_FmMacsec->txScSpinLock, intFlags); ++ ++ return err; ++} ++ ++t_Error FmMacsecDeleteRxSa(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ t_Error err = E_OK; ++ uint32_t tmpReg = 0, i, intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(scId < NUM_OF_RX_SC, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(saId < NUM_OF_SA_PER_RX_SC, E_INVALID_HANDLE); ++ ++ intFlags = XX_LockIntrSpinlock(p_FmMacsec->rxScSpinLock); ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->rxsca, scId); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecRxScSa[saId].rxsanpn, 0x0); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecRxScSa[saId].rxsalpn, 0x0); ++ for (i=0; i<4; i++) ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecRxScSa[saId].rxsak[i], 0x0); ++ ++ tmpReg |= RX_SACFG_ACTIVE; ++ tmpReg &= ~RX_SACFG_EN_MASK; ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecRxScSa[saId].rxsacs, tmpReg); ++ ++ XX_UnlockIntrSpinlock(p_FmMacsec->rxScSpinLock, intFlags); ++ ++ return err; ++} ++ ++t_Error FmMacsecDeleteTxSa(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ t_Error err = E_OK; ++ uint32_t tmpReg = 0, i, intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(scId < NUM_OF_RX_SC, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(saId < NUM_OF_SA_PER_TX_SC, E_INVALID_HANDLE); ++ ++ intFlags = XX_LockIntrSpinlock(p_FmMacsec->txScSpinLock); ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->txsca, scId); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecTxScSa[saId].txsanpn, 0x0); ++ for (i=0; i<4; i++) ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecTxScSa[saId].txsak[i], 0x0); ++ ++ tmpReg |= TX_SACFG_ACTIVE; ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecTxScSa[saId].txsacs, tmpReg); ++ ++ XX_UnlockIntrSpinlock(p_FmMacsec->txScSpinLock, intFlags); ++ ++ return err; ++} ++ ++t_Error FmMacsecRxSaSetReceive(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId, bool enableReceive) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ t_Error err = E_OK; ++ uint32_t tmpReg = 0, intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(scId < NUM_OF_RX_SC, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(saId < NUM_OF_SA_PER_RX_SC, E_INVALID_HANDLE); ++ ++ intFlags = XX_LockIntrSpinlock(p_FmMacsec->rxScSpinLock); ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->rxsca, scId); ++ tmpReg = GET_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecRxScSa[saId].rxsacs); ++ if (enableReceive) ++ tmpReg |= RX_SACFG_EN_MASK; ++ else ++ tmpReg &= ~RX_SACFG_EN_MASK; ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecRxScSa[saId].rxsacs, tmpReg); ++ ++ XX_UnlockIntrSpinlock(p_FmMacsec->rxScSpinLock, intFlags); ++ ++ return err; ++} ++ ++t_Error FmMacsecRxSaUpdateNextPn(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId, uint32_t updtNextPN) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ t_Error err = E_OK; ++ uint32_t intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(scId < NUM_OF_RX_SC, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(saId < NUM_OF_SA_PER_RX_SC, E_INVALID_HANDLE); ++ ++ intFlags = XX_LockIntrSpinlock(p_FmMacsec->rxScSpinLock); ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->rxsca, scId); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecRxScSa[saId].rxsanpn, updtNextPN); ++ ++ XX_UnlockIntrSpinlock(p_FmMacsec->rxScSpinLock, intFlags); ++ ++ return err; ++} ++ ++t_Error FmMacsecRxSaUpdateLowestPn(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId, uint32_t updtLowestPN) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ t_Error err = E_OK; ++ uint32_t intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(scId < NUM_OF_RX_SC, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(saId < NUM_OF_SA_PER_RX_SC, E_INVALID_HANDLE); ++ ++ intFlags = XX_LockIntrSpinlock(p_FmMacsec->rxScSpinLock); ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->rxsca, scId); ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecRxScSa[saId].rxsalpn, updtLowestPN); ++ ++ XX_UnlockIntrSpinlock(p_FmMacsec->rxScSpinLock, intFlags); ++ ++ return err; ++} ++ ++t_Error FmMacsecTxSaSetActive(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId, macsecAN_t an) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ t_Error err = E_OK; ++ uint32_t tmpReg = 0, intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(scId < NUM_OF_RX_SC, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(saId < NUM_OF_SA_PER_TX_SC, E_INVALID_HANDLE); ++ ++ intFlags = XX_LockIntrSpinlock(p_FmMacsec->txScSpinLock); ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->txsca, scId); ++ ++ tmpReg = GET_UINT32(p_FmMacsec->p_FmMacsecRegs->txsccfg); ++ ++ tmpReg |= ((an << TX_SCCFG_AN_SHIFT) & TX_SCCFG_AN_MASK); ++ tmpReg |= ((saId << TX_SCCFG_ASA_SHIFT) & TX_SCCFG_ASA_MASK); ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->txsccfg, tmpReg); ++ ++ XX_UnlockIntrSpinlock(p_FmMacsec->txScSpinLock, intFlags); ++ ++ return err; ++} ++ ++t_Error FmMacsecTxSaGetActive(t_Handle h_FmMacsec, uint32_t scId, macsecAN_t *p_An) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ t_Error err = E_OK; ++ uint32_t tmpReg = 0, intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(scId < NUM_OF_RX_SC, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_An, E_INVALID_HANDLE); ++ ++ intFlags = XX_LockIntrSpinlock(p_FmMacsec->txScSpinLock); ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->txsca, scId); ++ ++ tmpReg = GET_UINT32(p_FmMacsec->p_FmMacsecRegs->txsccfg); ++ ++ XX_UnlockIntrSpinlock(p_FmMacsec->txScSpinLock, intFlags); ++ ++ *p_An = (macsecAN_t)((tmpReg & TX_SCCFG_AN_MASK) >> TX_SCCFG_AN_SHIFT); ++ ++ return err; ++} ++ ++t_Error FmMacsecSetException(t_Handle h_FmMacsec, e_FmMacsecGlobalExceptions exception, uint32_t scId, bool enable) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ uint32_t bitMask; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ GET_EXCEPTION_FLAG(bitMask, exception, scId); ++ if (bitMask) ++ { ++ if (enable) ++ p_FmMacsec->exceptions |= bitMask; ++ else ++ p_FmMacsec->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->erer, p_FmMacsec->exceptions); ++ ++ return E_OK; ++} ++ ++t_Error FmMacsecSetEvent(t_Handle h_FmMacsec, e_FmMacsecGlobalEvents event, uint32_t scId, bool enable) ++{ ++ t_FmMacsec *p_FmMacsec = (t_FmMacsec*)h_FmMacsec; ++ uint32_t bitMask; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsec->p_FmMacsecDriverParam, E_INVALID_HANDLE); ++ ++ GET_EVENT_FLAG(bitMask, event, scId); ++ if (bitMask) ++ { ++ if (enable) ++ p_FmMacsec->events |= bitMask; ++ else ++ p_FmMacsec->events &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined event")); ++ ++ WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->ever, p_FmMacsec->events); ++ ++ return E_OK; ++} ++ ++/****************************************/ ++/* API Init unit functions */ ++/****************************************/ ++t_Handle FM_MACSEC_MASTER_Config(t_FmMacsecParams *p_FmMacsecParam) ++{ ++ t_FmMacsec *p_FmMacsec; ++ uint32_t macId; ++ ++ /* Allocate FM MACSEC structure */ ++ p_FmMacsec = (t_FmMacsec *) XX_Malloc(sizeof(t_FmMacsec)); ++ if (!p_FmMacsec) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM MACSEC driver structure")); ++ return NULL; ++ } ++ memset(p_FmMacsec, 0, sizeof(t_FmMacsec)); ++ InitFmMacsecControllerDriver(&p_FmMacsec->fmMacsecControllerDriver); ++ ++ /* Allocate the FM MACSEC driver's parameters structure */ ++ p_FmMacsec->p_FmMacsecDriverParam = (t_FmMacsecDriverParam *)XX_Malloc(sizeof(t_FmMacsecDriverParam)); ++ if (!p_FmMacsec->p_FmMacsecDriverParam) ++ { ++ XX_Free(p_FmMacsec); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM MACSEC driver parameters")); ++ return NULL; ++ } ++ memset(p_FmMacsec->p_FmMacsecDriverParam, 0, sizeof(t_FmMacsecDriverParam)); ++ ++ /* Initialize FM MACSEC parameters which will be kept by the driver */ ++ p_FmMacsec->h_Fm = p_FmMacsecParam->h_Fm; ++ p_FmMacsec->h_FmMac = p_FmMacsecParam->nonGuestParams.h_FmMac; ++ p_FmMacsec->p_FmMacsecRegs = (t_FmMacsecRegs *)UINT_TO_PTR(p_FmMacsecParam->nonGuestParams.baseAddr); ++ p_FmMacsec->f_Exception = p_FmMacsecParam->nonGuestParams.f_Exception; ++ p_FmMacsec->h_App = p_FmMacsecParam->nonGuestParams.h_App; ++ p_FmMacsec->userExceptions = DEFAULT_userExceptions; ++ p_FmMacsec->exceptions = DEFAULT_exceptions; ++ p_FmMacsec->events = DEFAULT_events; ++ p_FmMacsec->rxScSpinLock = XX_InitSpinlock(); ++ p_FmMacsec->txScSpinLock = XX_InitSpinlock(); ++ ++ /* Initialize FM MACSEC driver parameters parameters (for initialization phase only) */ ++ p_FmMacsec->p_FmMacsecDriverParam->unknownSciTreatMode = DEFAULT_unknownSciFrameTreatment; ++ p_FmMacsec->p_FmMacsecDriverParam->invalidTagsDeliverUncontrolled = DEFAULT_invalidTagsFrameTreatment; ++ p_FmMacsec->p_FmMacsecDriverParam->encryptWithNoChangedTextDiscardUncontrolled = DEFAULT_encryptWithNoChangedTextFrameTreatment; ++ p_FmMacsec->p_FmMacsecDriverParam->untagTreatMode = DEFAULT_untagFrameTreatment; ++ p_FmMacsec->p_FmMacsecDriverParam->keysUnreadable = DEFAULT_keysUnreadable; ++ p_FmMacsec->p_FmMacsecDriverParam->reservedSc0 = DEFAULT_sc0ReservedForPTP; ++ p_FmMacsec->p_FmMacsecDriverParam->byPassMode = !DEFAULT_normalMode; ++ p_FmMacsec->p_FmMacsecDriverParam->pnExhThr = DEFAULT_pnExhThr; ++ p_FmMacsec->p_FmMacsecDriverParam->sectagOverhead = DEFAULT_sectagOverhead; ++ p_FmMacsec->p_FmMacsecDriverParam->mflSubtract = DEFAULT_mflSubtract; ++ /* build the FM MACSEC master IPC address */ ++ memset(p_FmMacsec->fmMacsecModuleName, 0, (sizeof(char))*MODULE_NAME_SIZE); ++ FM_MAC_GetId(p_FmMacsec->h_FmMac,&macId); ++ if (Sprint (p_FmMacsec->fmMacsecModuleName, "FM-%d-MAC-%d-MACSEC-Master", ++ FmGetId(p_FmMacsec->h_Fm),macId) != 24) ++ { ++ XX_Free(p_FmMacsec->p_FmMacsecDriverParam); ++ XX_Free(p_FmMacsec); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ return NULL; ++ } ++ return p_FmMacsec; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_master.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_master.h +new file mode 100644 +index 0000000..2296a0f +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_master.h +@@ -0,0 +1,479 @@ ++/* ++ * Copyright 2008-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. ++ */ ++ ++/****************************************************************************** ++ @File fm_macsec_master.h ++ ++ @Description FM MACSEC internal structures and definitions. ++*//***************************************************************************/ ++#ifndef __FM_MACSEC_MASTER_H ++#define __FM_MACSEC_MASTER_H ++ ++#include "error_ext.h" ++#include "std_ext.h" ++ ++#include "fm_macsec.h" ++ ++ ++#define MACSEC_ICV_SIZE 16 ++#define MACSEC_SECTAG_SIZE 16 ++#define MACSEC_SCI_SIZE 8 ++#define MACSEC_FCS_SIZE 4 ++ ++/**************************************************************************//** ++ @Description Exceptions ++*//***************************************************************************/ ++ ++#define FM_MACSEC_EX_TX_SC_0 0x80000000 ++#define FM_MACSEC_EX_TX_SC(sc) (FM_MACSEC_EX_TX_SC_0 >> (sc)) ++#define FM_MACSEC_EX_ECC 0x00000001 ++ ++#define GET_EXCEPTION_FLAG(bitMask, exception, id) switch (exception){ \ ++ case e_FM_MACSEC_EX_TX_SC: \ ++ bitMask = FM_MACSEC_EX_TX_SC(id); break; \ ++ case e_FM_MACSEC_EX_ECC: \ ++ bitMask = FM_MACSEC_EX_ECC; break; \ ++ default: bitMask = 0;break;} ++ ++#define FM_MACSEC_USER_EX_SINGLE_BIT_ECC 0x80000000 ++#define FM_MACSEC_USER_EX_MULTI_BIT_ECC 0x40000000 ++ ++#define GET_USER_EXCEPTION_FLAG(bitMask, exception) switch (exception){ \ ++ case e_FM_MACSEC_EX_SINGLE_BIT_ECC: \ ++ bitMask = FM_MACSEC_USER_EX_SINGLE_BIT_ECC; break; \ ++ case e_FM_MACSEC_EX_MULTI_BIT_ECC: \ ++ bitMask = FM_MACSEC_USER_EX_MULTI_BIT_ECC; break; \ ++ default: bitMask = 0;break;} ++ ++/**************************************************************************//** ++ @Description Events ++*//***************************************************************************/ ++ ++#define FM_MACSEC_EV_TX_SC_0_NEXT_PN 0x80000000 ++#define FM_MACSEC_EV_TX_SC_NEXT_PN(sc) (FM_MACSEC_EV_TX_SC_0_NEXT_PN >> (sc)) ++ ++#define GET_EVENT_FLAG(bitMask, event, id) switch (event){ \ ++ case e_FM_MACSEC_EV_TX_SC_NEXT_PN: \ ++ bitMask = FM_MACSEC_EV_TX_SC_NEXT_PN(id); break; \ ++ default: bitMask = 0;break;} ++ ++/**************************************************************************//** ++ @Description Defaults ++*//***************************************************************************/ ++#define DEFAULT_userExceptions (FM_MACSEC_USER_EX_SINGLE_BIT_ECC |\ ++ FM_MACSEC_USER_EX_MULTI_BIT_ECC) ++ ++#define DEFAULT_exceptions (FM_MACSEC_EX_TX_SC(0) |\ ++ FM_MACSEC_EX_TX_SC(1) |\ ++ FM_MACSEC_EX_TX_SC(2) |\ ++ FM_MACSEC_EX_TX_SC(3) |\ ++ FM_MACSEC_EX_TX_SC(4) |\ ++ FM_MACSEC_EX_TX_SC(5) |\ ++ FM_MACSEC_EX_TX_SC(6) |\ ++ FM_MACSEC_EX_TX_SC(7) |\ ++ FM_MACSEC_EX_TX_SC(8) |\ ++ FM_MACSEC_EX_TX_SC(9) |\ ++ FM_MACSEC_EX_TX_SC(10) |\ ++ FM_MACSEC_EX_TX_SC(11) |\ ++ FM_MACSEC_EX_TX_SC(12) |\ ++ FM_MACSEC_EX_TX_SC(13) |\ ++ FM_MACSEC_EX_TX_SC(14) |\ ++ FM_MACSEC_EX_TX_SC(15) |\ ++ FM_MACSEC_EX_ECC ) ++ ++#define DEFAULT_events (FM_MACSEC_EV_TX_SC_NEXT_PN(0) |\ ++ FM_MACSEC_EV_TX_SC_NEXT_PN(1) |\ ++ FM_MACSEC_EV_TX_SC_NEXT_PN(2) |\ ++ FM_MACSEC_EV_TX_SC_NEXT_PN(3) |\ ++ FM_MACSEC_EV_TX_SC_NEXT_PN(4) |\ ++ FM_MACSEC_EV_TX_SC_NEXT_PN(5) |\ ++ FM_MACSEC_EV_TX_SC_NEXT_PN(6) |\ ++ FM_MACSEC_EV_TX_SC_NEXT_PN(7) |\ ++ FM_MACSEC_EV_TX_SC_NEXT_PN(8) |\ ++ FM_MACSEC_EV_TX_SC_NEXT_PN(9) |\ ++ FM_MACSEC_EV_TX_SC_NEXT_PN(10) |\ ++ FM_MACSEC_EV_TX_SC_NEXT_PN(11) |\ ++ FM_MACSEC_EV_TX_SC_NEXT_PN(12) |\ ++ FM_MACSEC_EV_TX_SC_NEXT_PN(13) |\ ++ FM_MACSEC_EV_TX_SC_NEXT_PN(14) |\ ++ FM_MACSEC_EV_TX_SC_NEXT_PN(15) ) ++ ++#define DEFAULT_unknownSciFrameTreatment e_FM_MACSEC_UNKNOWN_SCI_FRAME_TREATMENT_DISCARD_BOTH ++#define DEFAULT_invalidTagsFrameTreatment FALSE ++#define DEFAULT_encryptWithNoChangedTextFrameTreatment FALSE ++#define DEFAULT_untagFrameTreatment e_FM_MACSEC_UNTAG_FRAME_TREATMENT_DELIVER_UNCONTROLLED_DISCARD_CONTROLLED ++#define DEFAULT_changedTextWithNoEncryptFrameTreatment FALSE ++#define DEFAULT_onlyScbIsSetFrameTreatment FALSE ++#define DEFAULT_keysUnreadable FALSE ++#define DEFAULT_normalMode TRUE ++#define DEFAULT_sc0ReservedForPTP FALSE ++#define DEFAULT_initNextPn 1 ++#define DEFAULT_pnExhThr 0xffffffff ++#define DEFAULT_sectagOverhead (MACSEC_ICV_SIZE + MACSEC_SECTAG_SIZE) ++#define DEFAULT_mflSubtract MACSEC_FCS_SIZE ++ ++ ++/**************************************************************************//** ++ @Description Memory Mapped Registers ++*//***************************************************************************/ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++typedef _Packed struct ++{ ++ /* MACsec configuration */ ++ volatile uint32_t cfg; /**< MACsec configuration */ ++ volatile uint32_t et; /**< MACsec EtherType */ ++ volatile uint8_t res1[56]; /**< reserved */ ++ volatile uint32_t mfl; /**< Maximum Frame Length */ ++ volatile uint32_t tpnet; /**< TX Packet Number exhaustion threshold */ ++ volatile uint8_t res2[56]; /**< reserved */ ++ volatile uint32_t rxsca; /**< RX SC access select */ ++ volatile uint8_t res3[60]; /**< reserved */ ++ volatile uint32_t txsca; /**< TX SC access select */ ++ volatile uint8_t res4[60]; /**< reserved */ ++ ++ /* RX configuration, status and statistic */ ++ volatile uint32_t rxsci1h; /**< RX Secure Channel Identifier first half */ ++ volatile uint32_t rxsci2h; /**< RX Secure Channel Identifier second half */ ++ volatile uint8_t res5[8]; /**< reserved */ ++ volatile uint32_t ifio1hs; /**< ifInOctets first half Statistic */ ++ volatile uint32_t ifio2hs; /**< ifInOctets second half Statistic */ ++ volatile uint32_t ifiups; /**< ifInUcastPkts Statistic */ ++ volatile uint8_t res6[4]; /**< reserved */ ++ volatile uint32_t ifimps; /**< ifInMulticastPkts Statistic */ ++ volatile uint32_t ifibps; /**< ifInBroadcastPkts Statistic */ ++ volatile uint32_t rxsccfg; /**< RX Secure Channel configuration */ ++ volatile uint32_t rpw; /**< replayWindow */ ++ volatile uint8_t res7[16]; /**< reserved */ ++ volatile uint32_t inov1hs; /**< InOctetsValidated first half Statistic */ ++ volatile uint32_t inov2hs; /**< InOctetsValidated second half Statistic */ ++ volatile uint32_t inod1hs; /**< InOctetsDecrypted first half Statistic */ ++ volatile uint32_t inod2hs; /**< InOctetsDecrypted second half Statistic */ ++ volatile uint32_t rxscipus; /**< RX Secure Channel InPktsUnchecked Statistic */ ++ volatile uint32_t rxscipds; /**< RX Secure Channel InPktsDelayed Statistic */ ++ volatile uint32_t rxscipls; /**< RX Secure Channel InPktsLate Statistic */ ++ volatile uint8_t res8[4]; /**< reserved */ ++ volatile uint32_t rxaninuss[MAX_NUM_OF_SA_PER_SC]; /**< RX AN 0-3 InNotUsingSA Statistic */ ++ volatile uint32_t rxanipuss[MAX_NUM_OF_SA_PER_SC]; /**< RX AN 0-3 InPktsUnusedSA Statistic */ ++ _Packed struct ++ { ++ volatile uint32_t rxsacs; /**< RX Security Association configuration and status */ ++ volatile uint32_t rxsanpn; /**< RX Security Association nextPN */ ++ volatile uint32_t rxsalpn; /**< RX Security Association lowestPN */ ++ volatile uint32_t rxsaipos; /**< RX Security Association InPktsOK Statistic */ ++ volatile uint32_t rxsak[4]; /**< RX Security Association key (128 bit) */ ++ volatile uint32_t rxsah[4]; /**< RX Security Association hash (128 bit) */ ++ volatile uint32_t rxsaipis; /**< RX Security Association InPktsInvalid Statistic */ ++ volatile uint32_t rxsaipnvs; /**< RX Security Association InPktsNotValid Statistic */ ++ volatile uint8_t res9[8]; /**< reserved */ ++ } _PackedType fmMacsecRxScSa[NUM_OF_SA_PER_RX_SC]; ++ ++ /* TX configuration, status and statistic */ ++ volatile uint32_t txsci1h; /**< TX Secure Channel Identifier first half */ ++ volatile uint32_t txsci2h; /**< TX Secure Channel Identifier second half */ ++ volatile uint8_t res10[8]; /**< reserved */ ++ volatile uint32_t ifoo1hs; /**< ifOutOctets first half Statistic */ ++ volatile uint32_t ifoo2hs; /**< ifOutOctets second half Statistic */ ++ volatile uint32_t ifoups; /**< ifOutUcastPkts Statistic */ ++ volatile uint32_t opus; /**< OutPktsUntagged Statistic */ ++ volatile uint32_t ifomps; /**< ifOutMulticastPkts Statistic */ ++ volatile uint32_t ifobps; /**< ifOutBroadcastPkts Statistic */ ++ volatile uint32_t txsccfg; /**< TX Secure Channel configuration */ ++ volatile uint32_t optls; /**< OutPktsTooLong Statistic */ ++ volatile uint8_t res11[16]; /**< reserved */ ++ volatile uint32_t oop1hs; /**< OutOctetsProtected first half Statistic */ ++ volatile uint32_t oop2hs; /**< OutOctetsProtected second half Statistic */ ++ volatile uint32_t ooe1hs; /**< OutOctetsEncrypted first half Statistic */ ++ volatile uint32_t ooe2hs; /**< OutOctetsEncrypted second half Statistic */ ++ volatile uint8_t res12[48]; /**< reserved */ ++ _Packed struct ++ { ++ volatile uint32_t txsacs; /**< TX Security Association configuration and status */ ++ volatile uint32_t txsanpn; /**< TX Security Association nextPN */ ++ volatile uint32_t txsaopps; /**< TX Security Association OutPktsProtected Statistic */ ++ volatile uint32_t txsaopes; /**< TX Security Association OutPktsEncrypted Statistic */ ++ volatile uint32_t txsak[4]; /**< TX Security Association key (128 bit) */ ++ volatile uint32_t txsah[4]; /**< TX Security Association hash (128 bit) */ ++ volatile uint8_t res13[16]; /**< reserved */ ++ } _PackedType fmMacsecTxScSa[NUM_OF_SA_PER_TX_SC]; ++ volatile uint8_t res14[248]; /**< reserved */ ++ ++ /* Global configuration and status */ ++ volatile uint32_t ip_rev1; /**< MACsec IP Block Revision 1 register */ ++ volatile uint32_t ip_rev2; /**< MACsec IP Block Revision 2 register */ ++ volatile uint32_t evr; /**< MACsec Event Register */ ++ volatile uint32_t ever; /**< MACsec Event Enable Register */ ++ volatile uint32_t evfr; /**< MACsec Event Force Register */ ++ volatile uint32_t err; /**< MACsec Error Register */ ++ volatile uint32_t erer; /**< MACsec Error Enable Register */ ++ volatile uint32_t erfr; /**< MACsec Error Force Register */ ++ volatile uint8_t res15[40]; /**< reserved */ ++ volatile uint32_t meec; /**< MACsec Memory ECC Error Capture Register */ ++ volatile uint32_t idle; /**< MACsec Idle status Register */ ++ volatile uint8_t res16[184]; /**< reserved */ ++ /* DEBUG */ ++ volatile uint32_t rxec; /**< MACsec RX error capture Register */ ++ volatile uint8_t res17[28]; /**< reserved */ ++ volatile uint32_t txec; /**< MACsec TX error capture Register */ ++ volatile uint8_t res18[220]; /**< reserved */ ++ ++ /* Macsec Rx global statistic */ ++ volatile uint32_t ifiocp1hs; /**< ifInOctetsCp first half Statistic */ ++ volatile uint32_t ifiocp2hs; /**< ifInOctetsCp second half Statistic */ ++ volatile uint32_t ifiupcps; /**< ifInUcastPktsCp Statistic */ ++ volatile uint8_t res19[4]; /**< reserved */ ++ volatile uint32_t ifioup1hs; /**< ifInOctetsUp first half Statistic */ ++ volatile uint32_t ifioup2hs; /**< ifInOctetsUp second half Statistic */ ++ volatile uint32_t ifiupups; /**< ifInUcastPktsUp Statistic */ ++ volatile uint8_t res20[4]; /**< reserved */ ++ volatile uint32_t ifimpcps; /**< ifInMulticastPktsCp Statistic */ ++ volatile uint32_t ifibpcps; /**< ifInBroadcastPktsCp Statistic */ ++ volatile uint32_t ifimpups; /**< ifInMulticastPktsUp Statistic */ ++ volatile uint32_t ifibpups; /**< ifInBroadcastPktsUp Statistic */ ++ volatile uint32_t ipwts; /**< InPktsWithoutTag Statistic */ ++ volatile uint32_t ipkays; /**< InPktsKaY Statistic */ ++ volatile uint32_t ipbts; /**< InPktsBadTag Statistic */ ++ volatile uint32_t ipsnfs; /**< InPktsSCINotFound Statistic */ ++ volatile uint32_t ipuecs; /**< InPktsUnsupportedEC Statistic */ ++ volatile uint32_t ipescbs; /**< InPktsEponSingleCopyBroadcast Statistic */ ++ volatile uint32_t iptls; /**< InPktsTooLong Statistic */ ++ volatile uint8_t res21[52]; /**< reserved */ ++ ++ /* Macsec Tx global statistic */ ++ volatile uint32_t opds; /**< OutPktsDiscarded Statistic */ ++#if (DPAA_VERSION >= 11) ++ volatile uint8_t res22[124]; /**< reserved */ ++ _Packed struct ++ { ++ volatile uint32_t rxsak[8]; /**< RX Security Association key (128/256 bit) */ ++ volatile uint8_t res23[32]; /**< reserved */ ++ } _PackedType rxScSaKey[NUM_OF_SA_PER_RX_SC]; ++ _Packed struct ++ { ++ volatile uint32_t txsak[8]; /**< TX Security Association key (128/256 bit) */ ++ volatile uint8_t res24[32]; /**< reserved */ ++ } _PackedType txScSaKey[NUM_OF_SA_PER_TX_SC]; ++#endif /* (DPAA_VERSION >= 11) */ ++} _PackedType t_FmMacsecRegs; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/**************************************************************************//** ++ @Description General defines ++*//***************************************************************************/ ++ ++#define SCI_HIGH_MASK 0xffffffff00000000LL ++#define SCI_LOW_MASK 0x00000000ffffffffLL ++ ++#define LONG_SHIFT 32 ++ ++#define GET_SCI_FIRST_HALF(sci) (uint32_t)((macsecSCI_t)((macsecSCI_t)(sci) & SCI_HIGH_MASK) >> LONG_SHIFT) ++#define GET_SCI_SECOND_HALF(sci) (uint32_t)((macsecSCI_t)(sci) & SCI_LOW_MASK) ++ ++/**************************************************************************//** ++ @Description Configuration defines ++*//***************************************************************************/ ++ ++/* masks */ ++#define CFG_UECT 0x00000800 ++#define CFG_ESCBT 0x00000400 ++#define CFG_USFT 0x00000300 ++#define CFG_ITT 0x00000080 ++#define CFG_KFT 0x00000040 ++#define CFG_UFT 0x00000030 ++#define CFG_KSS 0x00000004 ++#define CFG_BYPN 0x00000002 ++#define CFG_S0I 0x00000001 ++ ++#define ET_TYPE 0x0000ffff ++ ++#define MFL_MAX_LEN 0x0000ffff ++ ++#define RXSCA_SC_SEL 0x0000000f ++ ++#define TXSCA_SC_SEL 0x0000000f ++ ++#define IP_REV_1_IP_ID 0xffff0000 ++#define IP_REV_1_IP_MJ 0x0000ff00 ++#define IP_REV_1_IP_MM 0x000000ff ++ ++#define IP_REV_2_IP_INT 0x00ff0000 ++#define IP_REV_2_IP_ERR 0x0000ff00 ++#define IP_REV_2_IP_CFG 0x000000ff ++ ++#define MECC_CAP 0x80000000 ++#define MECC_CET 0x40000000 ++#define MECC_SERCNT 0x00ff0000 ++#define MECC_MEMADDR 0x000001ff ++ ++/* shifts */ ++#define CFG_UECT_SHIFT (31-20) ++#define CFG_ESCBT_SHIFT (31-21) ++#define CFG_USFT_SHIFT (31-23) ++#define CFG_ITT_SHIFT (31-24) ++#define CFG_KFT_SHIFT (31-25) ++#define CFG_UFT_SHIFT (31-27) ++#define CFG_KSS_SHIFT (31-29) ++#define CFG_BYPN_SHIFT (31-30) ++#define CFG_S0I_SHIFT (31-31) ++ ++#define IP_REV_1_IP_ID_SHIFT (31-15) ++#define IP_REV_1_IP_MJ_SHIFT (31-23) ++#define IP_REV_1_IP_MM_SHIFT (31-31) ++ ++#define IP_REV_2_IP_INT_SHIFT (31-15) ++#define IP_REV_2_IP_ERR_SHIFT (31-23) ++#define IP_REV_2_IP_CFG_SHIFT (31-31) ++ ++#define MECC_CAP_SHIFT (31-0) ++#define MECC_CET_SHIFT (31-1) ++#define MECC_SERCNT_SHIFT (31-15) ++#define MECC_MEMADDR_SHIFT (31-31) ++ ++/**************************************************************************//** ++ @Description RX SC defines ++*//***************************************************************************/ ++ ++/* masks */ ++#define RX_SCCFG_SCI_EN_MASK 0x00000800 ++#define RX_SCCFG_RP_MASK 0x00000400 ++#define RX_SCCFG_VF_MASK 0x00000300 ++#define RX_SCCFG_CO_MASK 0x0000003f ++ ++/* shifts */ ++#define RX_SCCFG_SCI_EN_SHIFT (31-20) ++#define RX_SCCFG_RP_SHIFT (31-21) ++#define RX_SCCFG_VF_SHIFT (31-23) ++#define RX_SCCFG_CO_SHIFT (31-31) ++#define RX_SCCFG_CS_SHIFT (31-7) ++ ++/**************************************************************************//** ++ @Description RX SA defines ++*//***************************************************************************/ ++ ++/* masks */ ++#define RX_SACFG_ACTIVE 0x80000000 ++#define RX_SACFG_AN_MASK 0x00000006 ++#define RX_SACFG_EN_MASK 0x00000001 ++ ++/* shifts */ ++#define RX_SACFG_AN_SHIFT (31-30) ++#define RX_SACFG_EN_SHIFT (31-31) ++ ++/**************************************************************************//** ++ @Description TX SC defines ++*//***************************************************************************/ ++ ++/* masks */ ++#define TX_SCCFG_AN_MASK 0x000c0000 ++#define TX_SCCFG_ASA_MASK 0x00020000 ++#define TX_SCCFG_SCE_MASK 0x00010000 ++#define TX_SCCFG_CO_MASK 0x00003f00 ++#define TX_SCCFG_CE_MASK 0x00000010 ++#define TX_SCCFG_PF_MASK 0x00000008 ++#define TX_SCCFG_AIS_MASK 0x00000004 ++#define TX_SCCFG_UES_MASK 0x00000002 ++#define TX_SCCFG_USCB_MASK 0x00000001 ++ ++/* shifts */ ++#define TX_SCCFG_AN_SHIFT (31-13) ++#define TX_SCCFG_ASA_SHIFT (31-14) ++#define TX_SCCFG_SCE_SHIFT (31-15) ++#define TX_SCCFG_CO_SHIFT (31-23) ++#define TX_SCCFG_CE_SHIFT (31-27) ++#define TX_SCCFG_PF_SHIFT (31-28) ++#define TX_SCCFG_AIS_SHIFT (31-29) ++#define TX_SCCFG_UES_SHIFT (31-30) ++#define TX_SCCFG_USCB_SHIFT (31-31) ++#define TX_SCCFG_CS_SHIFT (31-7) ++ ++/**************************************************************************//** ++ @Description TX SA defines ++*//***************************************************************************/ ++ ++/* masks */ ++#define TX_SACFG_ACTIVE 0x80000000 ++ ++ ++typedef struct ++{ ++ void (*f_Isr) (t_Handle h_Arg, uint32_t id); ++ t_Handle h_SrcHandle; ++} t_FmMacsecIntrSrc; ++ ++typedef struct ++{ ++ e_FmMacsecUnknownSciFrameTreatment unknownSciTreatMode; ++ bool invalidTagsDeliverUncontrolled; ++ bool changedTextWithNoEncryptDeliverUncontrolled; ++ bool onlyScbIsSetDeliverUncontrolled; ++ bool encryptWithNoChangedTextDiscardUncontrolled; ++ e_FmMacsecUntagFrameTreatment untagTreatMode; ++ uint32_t pnExhThr; ++ bool keysUnreadable; ++ bool byPassMode; ++ bool reservedSc0; ++ uint32_t sectagOverhead; ++ uint32_t mflSubtract; ++} t_FmMacsecDriverParam; ++ ++typedef struct ++{ ++ t_FmMacsecControllerDriver fmMacsecControllerDriver; ++ t_Handle h_Fm; ++ t_FmMacsecRegs *p_FmMacsecRegs; ++ t_Handle h_FmMac; /**< A handle to the FM MAC object related to */ ++ char fmMacsecModuleName[MODULE_NAME_SIZE]; ++ t_FmMacsecIntrSrc intrMng[NUM_OF_INTER_MODULE_EVENTS]; ++ uint32_t events; ++ uint32_t exceptions; ++ uint32_t userExceptions; ++ t_FmMacsecExceptionsCallback *f_Exception; /**< Exception Callback Routine */ ++ t_Handle h_App; /**< A handle to an application layer object; This handle will ++ be passed by the driver upon calling the above callbacks */ ++ bool rxScTable[NUM_OF_RX_SC]; ++ uint32_t numRxScAvailable; ++ bool txScTable[NUM_OF_TX_SC]; ++ uint32_t numTxScAvailable; ++ t_Handle rxScSpinLock; ++ t_Handle txScSpinLock; ++ t_FmMacsecDriverParam *p_FmMacsecDriverParam; ++} t_FmMacsec; ++ ++ ++#endif /* __FM_MACSEC_MASTER_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_secy.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_secy.c +new file mode 100644 +index 0000000..7c72dc9 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_secy.c +@@ -0,0 +1,883 @@ ++/* ++ * Copyright 2008-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. ++ */ ++ ++/****************************************************************************** ++ @File fm_macsec_secy.c ++ ++ @Description FM MACSEC SECY driver routines implementation. ++*//***************************************************************************/ ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "xx_ext.h" ++#include "string_ext.h" ++#include "sprint_ext.h" ++ ++#include "fm_macsec_secy.h" ++ ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++static void FmMacsecSecYExceptionsIsr(t_Handle h_FmMacsecSecY, uint32_t id) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ ++ UNUSED(id); ++ SANITY_CHECK_RETURN(p_FmMacsecSecY, E_INVALID_HANDLE); ++ ++ if (p_FmMacsecSecY->exceptions & FM_MACSEC_SECY_EX_FRAME_DISCARDED) ++ p_FmMacsecSecY->f_Exception(p_FmMacsecSecY->h_App, e_FM_MACSEC_SECY_EX_FRAME_DISCARDED); ++} ++ ++static void FmMacsecSecYEventsIsr(t_Handle h_FmMacsecSecY, uint32_t id) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ ++ UNUSED(id); ++ SANITY_CHECK_RETURN(p_FmMacsecSecY, E_INVALID_HANDLE); ++ ++ if (p_FmMacsecSecY->events & FM_MACSEC_SECY_EV_NEXT_PN) ++ p_FmMacsecSecY->f_Event(p_FmMacsecSecY->h_App, e_FM_MACSEC_SECY_EV_NEXT_PN); ++} ++ ++static t_Error CheckFmMacsecSecYParameters(t_FmMacsecSecY *p_FmMacsecSecY) ++{ ++ if (!p_FmMacsecSecY->f_Exception) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceptions callback not provided")); ++ ++ if (!p_FmMacsecSecY->f_Event) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Events callback not provided")); ++ ++ if (!p_FmMacsecSecY->numOfRxSc) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Num of Rx Scs must be greater than '0'")); ++ ++ ++ return E_OK; ++} ++ ++static t_Handle FmMacsecSecYCreateSc(t_FmMacsecSecY *p_FmMacsecSecY, ++ macsecSCI_t sci, ++ e_FmMacsecSecYCipherSuite cipherSuite, ++ e_ScType type) ++{ ++ t_SecYSc *p_ScTable; ++ void *p_Params; ++ uint32_t numOfSc,i; ++ t_Error err = E_OK; ++ t_RxScParams rxScParams; ++ t_TxScParams txScParams; ++ ++ ASSERT_COND(p_FmMacsecSecY); ++ ASSERT_COND(p_FmMacsecSecY->h_FmMacsec); ++ ++ if (type == e_SC_RX) ++ { ++ memset(&rxScParams, 0, sizeof(rxScParams)); ++ i = (NUM_OF_RX_SC - 1); ++ p_ScTable = p_FmMacsecSecY->p_RxSc; ++ numOfSc = p_FmMacsecSecY->numOfRxSc; ++ rxScParams.confidentialityOffset = p_FmMacsecSecY->confidentialityOffset; ++ rxScParams.replayProtect = p_FmMacsecSecY->replayProtect; ++ rxScParams.replayWindow = p_FmMacsecSecY->replayWindow; ++ rxScParams.validateFrames = p_FmMacsecSecY->validateFrames; ++ rxScParams.cipherSuite = cipherSuite; ++ p_Params = &rxScParams; ++ } ++ else ++ { ++ memset(&txScParams, 0, sizeof(txScParams)); ++ i = (NUM_OF_TX_SC - 1); ++ p_ScTable = p_FmMacsecSecY->p_TxSc; ++ numOfSc = p_FmMacsecSecY->numOfTxSc; ++ txScParams.sciInsertionMode = p_FmMacsecSecY->sciInsertionMode; ++ txScParams.protectFrames = p_FmMacsecSecY->protectFrames; ++ txScParams.confidentialityEnable = p_FmMacsecSecY->confidentialityEnable; ++ txScParams.confidentialityOffset = p_FmMacsecSecY->confidentialityOffset; ++ txScParams.cipherSuite = cipherSuite; ++ p_Params = &txScParams; ++ } ++ ++ for (i=0;iscId = p_ScTable[i].scId; ++ ((t_RxScParams *)p_Params)->sci = sci; ++ if ((err = FmMacsecCreateRxSc(p_FmMacsecSecY->h_FmMacsec, (t_RxScParams *)p_Params)) != E_OK) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM MACSEC SECY RX SC")); ++ return NULL; ++ } ++ } ++ else ++ { ++ ((t_TxScParams *)p_Params)->scId = p_ScTable[i].scId; ++ ((t_TxScParams *)p_Params)->sci = sci; ++ if ((err = FmMacsecCreateTxSc(p_FmMacsecSecY->h_FmMacsec, (t_TxScParams *)p_Params)) != E_OK) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM MACSEC SECY TX SC")); ++ return NULL; ++ } ++ } ++ ++ p_ScTable[i].inUse = TRUE; ++ return &p_ScTable[i]; ++} ++ ++static t_Error FmMacsecSecYDeleteSc(t_FmMacsecSecY *p_FmMacsecSecY, t_SecYSc *p_FmSecYSc, e_ScType type) ++{ ++ t_Error err = E_OK; ++ ++ ASSERT_COND(p_FmMacsecSecY); ++ ASSERT_COND(p_FmMacsecSecY->h_FmMacsec); ++ ASSERT_COND(p_FmSecYSc); ++ ++ if (type == e_SC_RX) ++ { ++ if ((err = FmMacsecDeleteRxSc(p_FmMacsecSecY->h_FmMacsec, p_FmSecYSc->scId)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ else ++ if ((err = FmMacsecDeleteTxSc(p_FmMacsecSecY->h_FmMacsec, p_FmSecYSc->scId)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ p_FmSecYSc->inUse = FALSE; ++ ++ return err; ++} ++ ++/****************************************/ ++/* API Init unit functions */ ++/****************************************/ ++t_Handle FM_MACSEC_SECY_Config(t_FmMacsecSecYParams *p_FmMacsecSecYParam) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY; ++ ++ /* Allocate FM MACSEC structure */ ++ p_FmMacsecSecY = (t_FmMacsecSecY *) XX_Malloc(sizeof(t_FmMacsecSecY)); ++ if (!p_FmMacsecSecY) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM MACSEC SECY driver structure")); ++ return NULL; ++ } ++ memset(p_FmMacsecSecY, 0, sizeof(t_FmMacsecSecY)); ++ ++ /* Allocate the FM MACSEC driver's parameters structure */ ++ p_FmMacsecSecY->p_FmMacsecSecYDriverParam = (t_FmMacsecSecYDriverParam *)XX_Malloc(sizeof(t_FmMacsecSecYDriverParam)); ++ if (!p_FmMacsecSecY->p_FmMacsecSecYDriverParam) ++ { ++ XX_Free(p_FmMacsecSecY); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM MACSEC SECY driver parameters")); ++ return NULL; ++ } ++ memset(p_FmMacsecSecY->p_FmMacsecSecYDriverParam, 0, sizeof(t_FmMacsecSecYDriverParam)); ++ ++ /* Initialize FM MACSEC SECY parameters which will be kept by the driver */ ++ p_FmMacsecSecY->h_FmMacsec = p_FmMacsecSecYParam->h_FmMacsec; ++ p_FmMacsecSecY->f_Event = p_FmMacsecSecYParam->f_Event; ++ p_FmMacsecSecY->f_Exception = p_FmMacsecSecYParam->f_Exception; ++ p_FmMacsecSecY->h_App = p_FmMacsecSecYParam->h_App; ++ p_FmMacsecSecY->confidentialityEnable = DEFAULT_confidentialityEnable; ++ p_FmMacsecSecY->confidentialityOffset = DEFAULT_confidentialityOffset; ++ p_FmMacsecSecY->validateFrames = DEFAULT_validateFrames; ++ p_FmMacsecSecY->replayProtect = DEFAULT_replayEnable; ++ p_FmMacsecSecY->replayWindow = DEFAULT_replayWindow; ++ p_FmMacsecSecY->protectFrames = DEFAULT_protectFrames; ++ p_FmMacsecSecY->sciInsertionMode = DEFAULT_sciInsertionMode; ++ p_FmMacsecSecY->isPointToPoint = DEFAULT_ptp; ++ p_FmMacsecSecY->numOfRxSc = p_FmMacsecSecYParam->numReceiveChannels; ++ p_FmMacsecSecY->numOfTxSc = DEFAULT_numOfTxSc; ++ p_FmMacsecSecY->exceptions = DEFAULT_exceptions; ++ p_FmMacsecSecY->events = DEFAULT_events; ++ ++ memcpy(&p_FmMacsecSecY->p_FmMacsecSecYDriverParam->txScParams, ++ &p_FmMacsecSecYParam->txScParams, ++ sizeof(t_FmMacsecSecYSCParams)); ++ return p_FmMacsecSecY; ++} ++ ++t_Error FM_MACSEC_SECY_Init(t_Handle h_FmMacsecSecY) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ t_FmMacsecSecYDriverParam *p_FmMacsecSecYDriverParam = NULL; ++ uint32_t rxScIds[NUM_OF_RX_SC], txScIds[NUM_OF_TX_SC], i, j; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_HANDLE); ++ ++ CHECK_INIT_PARAMETERS(p_FmMacsecSecY, CheckFmMacsecSecYParameters); ++ ++ p_FmMacsecSecYDriverParam = p_FmMacsecSecY->p_FmMacsecSecYDriverParam; ++ ++ if ((p_FmMacsecSecY->isPointToPoint) && ++ ((err = FmMacsecSetPTP(p_FmMacsecSecY->h_FmMacsec, TRUE)) != E_OK)) ++ RETURN_ERROR(MAJOR, err, ("Can't set Poin-to-Point")); ++ ++ /* Rx Sc Allocation */ ++ p_FmMacsecSecY->p_RxSc = (t_SecYSc *)XX_Malloc(sizeof(t_SecYSc) * p_FmMacsecSecY->numOfRxSc); ++ if (!p_FmMacsecSecY->p_RxSc) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM MACSEC SECY RX SC")); ++ memset(p_FmMacsecSecY->p_RxSc, 0, sizeof(t_SecYSc) * p_FmMacsecSecY->numOfRxSc); ++ if ((err = FmMacsecAllocScs(p_FmMacsecSecY->h_FmMacsec, e_SC_RX, p_FmMacsecSecY->isPointToPoint, p_FmMacsecSecY->numOfRxSc, rxScIds)) != E_OK) ++ { ++ if (p_FmMacsecSecY->p_TxSc) ++ XX_Free(p_FmMacsecSecY->p_TxSc); ++ if (p_FmMacsecSecY->p_RxSc) ++ XX_Free(p_FmMacsecSecY->p_RxSc); ++ return ERROR_CODE(err); ++ } ++ for (i=0; inumOfRxSc; i++) ++ { ++ p_FmMacsecSecY->p_RxSc[i].scId = rxScIds[i]; ++ p_FmMacsecSecY->p_RxSc[i].type = e_SC_RX; ++ for (j=0; jp_RxSc[i].sa[j].saId = (e_ScSaId)SECY_AN_FREE_VALUE; ++ } ++ ++ /* Tx Sc Allocation */ ++ p_FmMacsecSecY->p_TxSc = (t_SecYSc *)XX_Malloc(sizeof(t_SecYSc) * p_FmMacsecSecY->numOfTxSc); ++ if (!p_FmMacsecSecY->p_TxSc) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM MACSEC SECY TX SC")); ++ memset(p_FmMacsecSecY->p_TxSc, 0, sizeof(t_SecYSc) * p_FmMacsecSecY->numOfTxSc); ++ ++ if ((err = FmMacsecAllocScs(p_FmMacsecSecY->h_FmMacsec, e_SC_TX, p_FmMacsecSecY->isPointToPoint, p_FmMacsecSecY->numOfTxSc, txScIds)) != E_OK) ++ { ++ if (p_FmMacsecSecY->p_TxSc) ++ XX_Free(p_FmMacsecSecY->p_TxSc); ++ if (p_FmMacsecSecY->p_RxSc) ++ XX_Free(p_FmMacsecSecY->p_RxSc); ++ return ERROR_CODE(err); ++ } ++ for (i=0; inumOfTxSc; i++) ++ { ++ p_FmMacsecSecY->p_TxSc[i].scId = txScIds[i]; ++ p_FmMacsecSecY->p_TxSc[i].type = e_SC_TX; ++ for (j=0; jp_TxSc[i].sa[j].saId = (e_ScSaId)SECY_AN_FREE_VALUE; ++ FmMacsecRegisterIntr(p_FmMacsecSecY->h_FmMacsec, ++ e_FM_MACSEC_MOD_SC_TX, ++ (uint8_t)txScIds[i], ++ e_FM_INTR_TYPE_ERR, ++ FmMacsecSecYExceptionsIsr, ++ p_FmMacsecSecY); ++ FmMacsecRegisterIntr(p_FmMacsecSecY->h_FmMacsec, ++ e_FM_MACSEC_MOD_SC_TX, ++ (uint8_t)txScIds[i], ++ e_FM_INTR_TYPE_NORMAL, ++ FmMacsecSecYEventsIsr, ++ p_FmMacsecSecY); ++ ++ if (p_FmMacsecSecY->exceptions & FM_MACSEC_SECY_EX_FRAME_DISCARDED) ++ FmMacsecSetException(p_FmMacsecSecY->h_FmMacsec, e_FM_MACSEC_EX_TX_SC, txScIds[i], TRUE); ++ if (p_FmMacsecSecY->events & FM_MACSEC_SECY_EV_NEXT_PN) ++ FmMacsecSetEvent(p_FmMacsecSecY->h_FmMacsec, e_FM_MACSEC_EV_TX_SC_NEXT_PN, txScIds[i], TRUE); ++ } ++ ++ FmMacsecSecYCreateSc(p_FmMacsecSecY, ++ p_FmMacsecSecYDriverParam->txScParams.sci, ++ p_FmMacsecSecYDriverParam->txScParams.cipherSuite, ++ e_SC_TX); ++ XX_Free(p_FmMacsecSecYDriverParam); ++ p_FmMacsecSecY->p_FmMacsecSecYDriverParam = NULL; ++ ++ return E_OK; ++} ++ ++t_Error FM_MACSEC_SECY_Free(t_Handle h_FmMacsecSecY) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ t_Error err = E_OK; ++ uint32_t rxScIds[NUM_OF_RX_SC], txScIds[NUM_OF_TX_SC], i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ ++ if (p_FmMacsecSecY->isPointToPoint) ++ FmMacsecSetPTP(p_FmMacsecSecY->h_FmMacsec, FALSE); ++ if (p_FmMacsecSecY->p_RxSc) ++ { ++ for (i=0; inumOfRxSc; i++) ++ rxScIds[i] = p_FmMacsecSecY->p_RxSc[i].scId; ++ if ((err = FmMacsecFreeScs(p_FmMacsecSecY->h_FmMacsec, e_SC_RX, p_FmMacsecSecY->numOfRxSc, rxScIds)) != E_OK) ++ return ERROR_CODE(err); ++ XX_Free(p_FmMacsecSecY->p_RxSc); ++ } ++ if (p_FmMacsecSecY->p_TxSc) ++ { ++ FmMacsecSecYDeleteSc(p_FmMacsecSecY, &p_FmMacsecSecY->p_TxSc[0], e_SC_TX); ++ ++ for (i=0; inumOfTxSc; i++) { ++ txScIds[i] = p_FmMacsecSecY->p_TxSc[i].scId; ++ FmMacsecUnregisterIntr(p_FmMacsecSecY->h_FmMacsec, ++ e_FM_MACSEC_MOD_SC_TX, ++ (uint8_t)txScIds[i], ++ e_FM_INTR_TYPE_ERR); ++ FmMacsecUnregisterIntr(p_FmMacsecSecY->h_FmMacsec, ++ e_FM_MACSEC_MOD_SC_TX, ++ (uint8_t)txScIds[i], ++ e_FM_INTR_TYPE_NORMAL); ++ ++ if (p_FmMacsecSecY->exceptions & FM_MACSEC_SECY_EX_FRAME_DISCARDED) ++ FmMacsecSetException(p_FmMacsecSecY->h_FmMacsec, e_FM_MACSEC_EX_TX_SC, txScIds[i], FALSE); ++ if (p_FmMacsecSecY->events & FM_MACSEC_SECY_EV_NEXT_PN) ++ FmMacsecSetEvent(p_FmMacsecSecY->h_FmMacsec, e_FM_MACSEC_EV_TX_SC_NEXT_PN, txScIds[i], FALSE); ++ } ++ ++ if ((err = FmMacsecFreeScs(p_FmMacsecSecY->h_FmMacsec, e_SC_TX, p_FmMacsecSecY->numOfTxSc, txScIds)) != E_OK) ++ return ERROR_CODE(err); ++ XX_Free(p_FmMacsecSecY->p_TxSc); ++ } ++ ++ XX_Free(p_FmMacsecSecY); ++ ++ return err; ++} ++ ++t_Error FM_MACSEC_SECY_ConfigSciInsertionMode(t_Handle h_FmMacsecSecY, e_FmMacsecSciInsertionMode sciInsertionMode) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ ++ p_FmMacsecSecY->sciInsertionMode = sciInsertionMode; ++ ++ return E_OK; ++} ++ ++t_Error FM_MACSEC_SECY_ConfigProtectFrames(t_Handle h_FmMacsecSecY, bool protectFrames) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ ++ p_FmMacsecSecY->protectFrames = protectFrames; ++ ++ return E_OK; ++} ++ ++t_Error FM_MACSEC_SECY_ConfigReplayWindow(t_Handle h_FmMacsecSecY, bool replayProtect, uint32_t replayWindow) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ ++ p_FmMacsecSecY->replayProtect = replayProtect; ++ p_FmMacsecSecY->replayWindow = replayWindow; ++ ++ return E_OK; ++} ++ ++t_Error FM_MACSEC_SECY_ConfigValidationMode(t_Handle h_FmMacsecSecY, e_FmMacsecValidFrameBehavior validateFrames) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ ++ p_FmMacsecSecY->validateFrames = validateFrames; ++ ++ return E_OK; ++} ++ ++t_Error FM_MACSEC_SECY_ConfigConfidentiality(t_Handle h_FmMacsecSecY, bool confidentialityEnable, uint16_t confidentialityOffset) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ ++ p_FmMacsecSecY->confidentialityEnable = confidentialityEnable; ++ p_FmMacsecSecY->confidentialityOffset = confidentialityOffset; ++ ++ return E_OK; ++} ++ ++t_Error FM_MACSEC_SECY_ConfigPointToPoint(t_Handle h_FmMacsecSecY) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ ++ p_FmMacsecSecY->numOfRxSc = 1; ++ p_FmMacsecSecY->isPointToPoint = TRUE; ++ p_FmMacsecSecY->sciInsertionMode = e_FM_MACSEC_SCI_INSERTION_MODE_IMPLICT_PTP; ++ ++ return E_OK; ++} ++ ++t_Error FM_MACSEC_SECY_ConfigException(t_Handle h_FmMacsecSecY, e_FmMacsecSecYExceptions exception, bool enable) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_FmMacsecSecY->exceptions |= bitMask; ++ else ++ p_FmMacsecSecY->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ return E_OK; ++} ++ ++t_Error FM_MACSEC_SECY_ConfigEvent(t_Handle h_FmMacsecSecY, e_FmMacsecSecYEvents event, bool enable) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ ++ GET_EVENT_FLAG(bitMask, event); ++ if (bitMask) ++ { ++ if (enable) ++ p_FmMacsecSecY->events |= bitMask; ++ else ++ p_FmMacsecSecY->events &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined event")); ++ ++ return E_OK; ++} ++ ++t_Handle FM_MACSEC_SECY_CreateRxSc(t_Handle h_FmMacsecSecY, t_FmMacsecSecYSCParams *p_ScParams) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmMacsecSecY, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_FmMacsecSecY->h_FmMacsec, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_ScParams, E_NULL_POINTER, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE, NULL); ++ ++ return FmMacsecSecYCreateSc(p_FmMacsecSecY, p_ScParams->sci, p_ScParams->cipherSuite, e_SC_RX); ++} ++ ++t_Error FM_MACSEC_SECY_DeleteRxSc(t_Handle h_FmMacsecSecY, t_Handle h_Sc) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ t_SecYSc *p_FmSecYSc = (t_SecYSc *)h_Sc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->h_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmSecYSc, E_INVALID_HANDLE); ++ ++ return FmMacsecSecYDeleteSc(p_FmMacsecSecY, p_FmSecYSc, e_SC_RX); ++} ++ ++t_Error FM_MACSEC_SECY_CreateRxSa(t_Handle h_FmMacsecSecY, t_Handle h_Sc, macsecAN_t an, uint32_t lowestPn, macsecSAKey_t key) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ t_SecYSc *p_FmSecYSc = (t_SecYSc *)h_Sc; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->h_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmSecYSc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(an < MAX_NUM_OF_SA_PER_SC, E_INVALID_STATE); ++ ++ if (p_FmSecYSc->sa[an].saId != SECY_AN_FREE_VALUE) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("An %d is already assigned",an)); ++ ++ if ((err = FmMacsecCreateRxSa(p_FmMacsecSecY->h_FmMacsec, p_FmSecYSc->scId, (e_ScSaId)p_FmSecYSc->numOfSa, an, lowestPn, key)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ p_FmSecYSc->sa[an].saId = (e_ScSaId)p_FmSecYSc->numOfSa++; ++ return err; ++} ++ ++t_Error FM_MACSEC_SECY_DeleteRxSa(t_Handle h_FmMacsecSecY, t_Handle h_Sc, macsecAN_t an) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ t_SecYSc *p_FmSecYSc = (t_SecYSc *)h_Sc; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->h_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmSecYSc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(an < MAX_NUM_OF_SA_PER_SC, E_INVALID_STATE); ++ ++ if (p_FmSecYSc->sa[an].saId == SECY_AN_FREE_VALUE) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("An %d is already deleted",an)); ++ ++ if ((err = FmMacsecDeleteRxSa(p_FmMacsecSecY->h_FmMacsec, p_FmSecYSc->scId, p_FmSecYSc->sa[an].saId)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ p_FmSecYSc->numOfSa--; ++ p_FmSecYSc->sa[an].saId = (e_ScSaId)SECY_AN_FREE_VALUE; ++ /* TODO - check if statistics need to be read*/ ++ return err; ++} ++ ++t_Error FM_MACSEC_SECY_RxSaEnableReceive(t_Handle h_FmMacsecSecY, t_Handle h_Sc, macsecAN_t an) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ t_SecYSc *p_FmSecYSc = (t_SecYSc *)h_Sc; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->h_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmSecYSc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(an < MAX_NUM_OF_SA_PER_SC, E_INVALID_STATE); ++ ++ if (p_FmSecYSc->sa[an].saId == SECY_AN_FREE_VALUE) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("An %d is not configured",an)); ++ ++ if ((err = FmMacsecRxSaSetReceive(p_FmMacsecSecY->h_FmMacsec,p_FmSecYSc->scId, p_FmSecYSc->sa[an].saId, TRUE)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ p_FmSecYSc->sa[an].active = TRUE; ++ return err; ++} ++ ++t_Error FM_MACSEC_SECY_RxSaDisableReceive(t_Handle h_FmMacsecSecY, t_Handle h_Sc, macsecAN_t an) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ t_SecYSc *p_FmSecYSc = (t_SecYSc *)h_Sc; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->h_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmSecYSc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(an < MAX_NUM_OF_SA_PER_SC, E_INVALID_STATE); ++ ++ if (p_FmSecYSc->sa[an].saId == SECY_AN_FREE_VALUE) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("An %d is not configured",an)); ++ ++ if ((err = FmMacsecRxSaSetReceive(p_FmMacsecSecY->h_FmMacsec,p_FmSecYSc->scId, p_FmSecYSc->sa[an].saId, FALSE)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ p_FmSecYSc->sa[an].active = FALSE; ++ return err; ++} ++ ++t_Error FM_MACSEC_SECY_RxSaUpdateNextPn(t_Handle h_FmMacsecSecY, t_Handle h_Sc, macsecAN_t an, uint32_t updtNextPN) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ t_SecYSc *p_FmSecYSc = (t_SecYSc *)h_Sc; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->h_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmSecYSc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(an < MAX_NUM_OF_SA_PER_SC, E_INVALID_STATE); ++ ++ if (p_FmSecYSc->sa[an].saId == SECY_AN_FREE_VALUE) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("An %d is not configured",an)); ++ ++ if ((err = FmMacsecRxSaUpdateNextPn(p_FmMacsecSecY->h_FmMacsec,p_FmSecYSc->scId, p_FmSecYSc->sa[an].saId, updtNextPN)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return err; ++} ++ ++t_Error FM_MACSEC_SECY_RxSaUpdateLowestPn(t_Handle h_FmMacsecSecY, t_Handle h_Sc, macsecAN_t an, uint32_t updtLowestPN) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ t_SecYSc *p_FmSecYSc = (t_SecYSc *)h_Sc; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->h_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmSecYSc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(an < MAX_NUM_OF_SA_PER_SC, E_INVALID_STATE); ++ ++ if (p_FmSecYSc->sa[an].saId == SECY_AN_FREE_VALUE) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("An %d is not configured",an)); ++ ++ if ((err = FmMacsecRxSaUpdateLowestPn(p_FmMacsecSecY->h_FmMacsec,p_FmSecYSc->scId, p_FmSecYSc->sa[an].saId, updtLowestPN)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return err; ++} ++ ++t_Error FM_MACSEC_SECY_RxSaModifyKey(t_Handle h_FmMacsecSecY, t_Handle h_Sc, macsecAN_t an, macsecSAKey_t key) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ t_SecYSc *p_FmSecYSc = (t_SecYSc *)h_Sc; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->h_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmSecYSc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(an < MAX_NUM_OF_SA_PER_SC, E_INVALID_STATE); ++ ++ if (p_FmSecYSc->sa[an].saId == SECY_AN_FREE_VALUE) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("An %d is not configured",an)); ++ ++ if (p_FmSecYSc->sa[an].active) ++ if ((err = FmMacsecRxSaSetReceive(p_FmMacsecSecY->h_FmMacsec, p_FmSecYSc->scId, p_FmSecYSc->sa[an].saId, FALSE)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ /* TODO - statistics should be read */ ++ ++ if ((err = FmMacsecCreateRxSa(p_FmMacsecSecY->h_FmMacsec, p_FmSecYSc->scId, p_FmSecYSc->sa[an].saId, an, 1, key)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ if (p_FmSecYSc->sa[an].active) ++ if ((err = FmMacsecRxSaSetReceive(p_FmMacsecSecY->h_FmMacsec, p_FmSecYSc->scId, p_FmSecYSc->sa[an].saId, TRUE)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ return err; ++} ++ ++ ++t_Error FM_MACSEC_SECY_CreateTxSa(t_Handle h_FmMacsecSecY, macsecAN_t an, macsecSAKey_t key) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ t_SecYSc *p_FmSecYSc; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->h_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ p_FmSecYSc = &p_FmMacsecSecY->p_TxSc[0]; ++ SANITY_CHECK_RETURN_ERROR(p_FmSecYSc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(an < MAX_NUM_OF_SA_PER_SC, E_INVALID_STATE); ++ ++ if (p_FmSecYSc->sa[an].saId != SECY_AN_FREE_VALUE) ++ RETURN_ERROR(MINOR, err, ("An %d is already assigned",an)); ++ ++ if ((err = FmMacsecCreateTxSa(p_FmMacsecSecY->h_FmMacsec,p_FmSecYSc->scId, (e_ScSaId)p_FmSecYSc->numOfSa, key)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ p_FmSecYSc->sa[an].saId = (e_ScSaId)p_FmSecYSc->numOfSa++; ++ return err; ++} ++ ++t_Error FM_MACSEC_SECY_DeleteTxSa(t_Handle h_FmMacsecSecY, macsecAN_t an) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ t_SecYSc *p_FmSecYSc; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->h_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ p_FmSecYSc = &p_FmMacsecSecY->p_TxSc[0]; ++ SANITY_CHECK_RETURN_ERROR(p_FmSecYSc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(an < MAX_NUM_OF_SA_PER_SC, E_INVALID_STATE); ++ ++ if (p_FmSecYSc->sa[an].saId == SECY_AN_FREE_VALUE) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("An %d is already deleted",an)); ++ ++ if ((err = FmMacsecDeleteTxSa(p_FmMacsecSecY->h_FmMacsec, p_FmSecYSc->scId, p_FmSecYSc->sa[an].saId)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ p_FmSecYSc->numOfSa--; ++ p_FmSecYSc->sa[an].saId = (e_ScSaId)SECY_AN_FREE_VALUE; ++ /* TODO - check if statistics need to be read*/ ++ return err; ++} ++ ++t_Error FM_MACSEC_SECY_TxSaModifyKey(t_Handle h_FmMacsecSecY, macsecAN_t nextActiveAn, macsecSAKey_t key) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ t_SecYSc *p_FmSecYSc; ++ macsecAN_t currentAn; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->h_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ p_FmSecYSc = &p_FmMacsecSecY->p_TxSc[0]; ++ SANITY_CHECK_RETURN_ERROR(p_FmSecYSc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(nextActiveAn < MAX_NUM_OF_SA_PER_SC, E_INVALID_STATE); ++ ++ if ((err = FmMacsecTxSaGetActive(p_FmMacsecSecY->h_FmMacsec, ++ p_FmSecYSc->scId, ++ ¤tAn)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ if ((err = FmMacsecTxSaSetActive(p_FmMacsecSecY->h_FmMacsec, ++ p_FmSecYSc->scId, ++ p_FmSecYSc->sa[nextActiveAn].saId, ++ nextActiveAn)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ /* TODO - statistics should be read */ ++ ++ if ((err = FmMacsecCreateTxSa(p_FmMacsecSecY->h_FmMacsec, p_FmSecYSc->scId, p_FmSecYSc->sa[currentAn].saId, key)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return err; ++} ++ ++t_Error FM_MACSEC_SECY_TxSaSetActive(t_Handle h_FmMacsecSecY, macsecAN_t an) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ t_SecYSc *p_FmSecYSc; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->h_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ p_FmSecYSc = &p_FmMacsecSecY->p_TxSc[0]; ++ SANITY_CHECK_RETURN_ERROR(p_FmSecYSc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(an < MAX_NUM_OF_SA_PER_SC, E_INVALID_STATE); ++ ++ if (p_FmSecYSc->sa[an].saId == SECY_AN_FREE_VALUE) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("An %d is not configured",an)); ++ ++ if ((err = FmMacsecTxSaSetActive(p_FmMacsecSecY->h_FmMacsec, ++ p_FmSecYSc->scId, ++ p_FmSecYSc->sa[an].saId, ++ an)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return err; ++} ++ ++t_Error FM_MACSEC_SECY_TxSaGetActive(t_Handle h_FmMacsecSecY, macsecAN_t *p_An) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ t_SecYSc *p_FmSecYSc; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->h_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ p_FmSecYSc = &p_FmMacsecSecY->p_TxSc[0]; ++ SANITY_CHECK_RETURN_ERROR(p_FmSecYSc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_An, E_INVALID_HANDLE); ++ ++ if ((err = FmMacsecTxSaGetActive(p_FmMacsecSecY->h_FmMacsec, ++ p_FmSecYSc->scId, ++ p_An)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return err; ++} ++ ++t_Error FM_MACSEC_SECY_GetRxScPhysId(t_Handle h_FmMacsecSecY, t_Handle h_Sc, uint32_t *p_ScPhysId) ++{ ++ t_SecYSc *p_FmSecYSc = (t_SecYSc *)h_Sc; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(((t_FmMacsecSecY *)h_FmMacsecSecY)->h_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!((t_FmMacsecSecY *)h_FmMacsecSecY)->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmSecYSc, E_INVALID_HANDLE); ++#ifdef DISABLE_SANITY_CHECKS ++ UNUSED(h_FmMacsecSecY); ++#endif /* DISABLE_SANITY_CHECKS */ ++ ++ *p_ScPhysId = p_FmSecYSc->scId; ++ return err; ++} ++ ++t_Error FM_MACSEC_SECY_GetTxScPhysId(t_Handle h_FmMacsecSecY, uint32_t *p_ScPhysId) ++{ ++ t_FmMacsecSecY *p_FmMacsecSecY = (t_FmMacsecSecY *)h_FmMacsecSecY; ++ t_SecYSc *p_FmSecYSc; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMacsecSecY->h_FmMacsec, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmMacsecSecY->p_FmMacsecSecYDriverParam, E_INVALID_STATE); ++ p_FmSecYSc = &p_FmMacsecSecY->p_TxSc[0]; ++ SANITY_CHECK_RETURN_ERROR(p_FmSecYSc, E_INVALID_HANDLE); ++ ++ *p_ScPhysId = p_FmSecYSc->scId; ++ return err; ++} ++ ++t_Error FM_MACSEC_SECY_SetException(t_Handle h_FmMacsecSecY, e_FmMacsecExceptions exception, bool enable) ++{ ++ UNUSED(h_FmMacsecSecY);UNUSED(exception);UNUSED(enable); ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_SECY_SetEvent(t_Handle h_FmMacsecSecY, e_FmMacsecSecYEvents event, bool enable) ++{ ++ UNUSED(h_FmMacsecSecY);UNUSED(event);UNUSED(enable); ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_SECY_GetStatistics(t_Handle h_FmMacsecSecY, t_FmMacsecSecYStatistics *p_Statistics) ++{ ++ UNUSED(h_FmMacsecSecY);UNUSED(p_Statistics); ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_SECY_RxScGetStatistics(t_Handle h_FmMacsecSecY, t_Handle h_Sc, t_FmMacsecSecYRxScStatistics *p_Statistics) ++{ ++ UNUSED(h_FmMacsecSecY);UNUSED(h_Sc);UNUSED(p_Statistics); ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_SECY_RxSaGetStatistics(t_Handle h_FmMacsecSecY, t_Handle h_Sc, macsecAN_t an, t_FmMacsecSecYRxSaStatistics *p_Statistics) ++{ ++ UNUSED(h_FmMacsecSecY);UNUSED(h_Sc);UNUSED(an);UNUSED(p_Statistics); ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_SECY_TxScGetStatistics(t_Handle h_FmMacsecSecY, t_FmMacsecSecYTxScStatistics *p_Statistics) ++{ ++ UNUSED(h_FmMacsecSecY);UNUSED(p_Statistics); ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ ++t_Error FM_MACSEC_SECY_TxSaGetStatistics(t_Handle h_FmMacsecSecY, macsecAN_t an, t_FmMacsecSecYTxSaStatistics *p_Statistics) ++{ ++ UNUSED(h_FmMacsecSecY);UNUSED(an);UNUSED(p_Statistics); ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++} ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_secy.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_secy.h +new file mode 100644 +index 0000000..0cf624e +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_secy.h +@@ -0,0 +1,144 @@ ++/* ++ * Copyright 2008-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. ++ */ ++ ++/****************************************************************************** ++ @File fm_macsec_secy.h ++ ++ @Description FM MACSEC SecY internal structures and definitions. ++*//***************************************************************************/ ++#ifndef __FM_MACSEC_SECY_H ++#define __FM_MACSEC_SECY_H ++ ++#include "error_ext.h" ++#include "std_ext.h" ++ ++#include "fm_macsec.h" ++ ++ ++/**************************************************************************//** ++ @Description Exceptions ++*//***************************************************************************/ ++ ++#define FM_MACSEC_SECY_EX_FRAME_DISCARDED 0x80000000 ++ ++#define GET_EXCEPTION_FLAG(bitMask, exception) switch (exception){ \ ++ case e_FM_MACSEC_SECY_EX_FRAME_DISCARDED: \ ++ bitMask = FM_MACSEC_SECY_EX_FRAME_DISCARDED; break; \ ++ default: bitMask = 0;break;} ++ ++/**************************************************************************//** ++ @Description Events ++*//***************************************************************************/ ++ ++#define FM_MACSEC_SECY_EV_NEXT_PN 0x80000000 ++ ++#define GET_EVENT_FLAG(bitMask, event) switch (event){ \ ++ case e_FM_MACSEC_SECY_EV_NEXT_PN: \ ++ bitMask = FM_MACSEC_SECY_EV_NEXT_PN; break; \ ++ default: bitMask = 0;break;} ++ ++/**************************************************************************//** ++ @Description Defaults ++*//***************************************************************************/ ++ ++#define DEFAULT_exceptions (FM_MACSEC_SECY_EX_FRAME_DISCARDED) ++#define DEFAULT_events (FM_MACSEC_SECY_EV_NEXT_PN) ++#define DEFAULT_numOfTxSc 1 ++#define DEFAULT_confidentialityEnable FALSE ++#define DEFAULT_confidentialityOffset 0 ++#define DEFAULT_sciInsertionMode e_FM_MACSEC_SCI_INSERTION_MODE_EXPLICIT_SECTAG ++#define DEFAULT_validateFrames e_FM_MACSEC_VALID_FRAME_BEHAVIOR_STRICT ++#define DEFAULT_replayEnable FALSE ++#define DEFAULT_replayWindow 0 ++#define DEFAULT_protectFrames TRUE ++#define DEFAULT_ptp FALSE ++ ++/**************************************************************************//** ++ @Description General defines ++*//***************************************************************************/ ++ ++#define SECY_AN_FREE_VALUE MAX_NUM_OF_SA_PER_SC ++ ++ ++typedef struct { ++ e_ScSaId saId; ++ bool active; ++ union { ++ t_FmMacsecSecYRxSaStatistics rxSaStatistics; ++ t_FmMacsecSecYTxSaStatistics txSaStatistics; ++ }; ++} t_SecYSa; ++ ++typedef struct { ++ bool inUse; ++ uint32_t scId; ++ e_ScType type; ++ uint8_t numOfSa; ++ t_SecYSa sa[MAX_NUM_OF_SA_PER_SC]; ++ union { ++ t_FmMacsecSecYRxScStatistics rxScStatistics; ++ t_FmMacsecSecYTxScStatistics txScStatistics; ++ }; ++} t_SecYSc; ++ ++typedef struct { ++ t_FmMacsecSecYSCParams txScParams; /**< Tx SC Params */ ++} t_FmMacsecSecYDriverParam; ++ ++typedef struct { ++ t_Handle h_FmMacsec; ++ bool confidentialityEnable; /**< TRUE - confidentiality protection and integrity protection ++ FALSE - no confidentiality protection, only integrity protection*/ ++ uint16_t confidentialityOffset; /**< The number of initial octets of each MSDU without confidentiality protection ++ common values are 0, 30, and 50 */ ++ bool replayProtect; /**< replay protection function mode */ ++ uint32_t replayWindow; /**< the size of the replay window */ ++ e_FmMacsecValidFrameBehavior validateFrames; /**< validation function mode */ ++ e_FmMacsecSciInsertionMode sciInsertionMode; ++ bool protectFrames; ++ bool isPointToPoint; ++ e_FmMacsecSecYCipherSuite cipherSuite; /**< Cipher suite to be used for this SecY */ ++ uint32_t numOfRxSc; /**< Number of receive channels */ ++ uint32_t numOfTxSc; /**< Number of transmit channels */ ++ t_SecYSc *p_RxSc; ++ t_SecYSc *p_TxSc; ++ uint32_t events; ++ uint32_t exceptions; ++ t_FmMacsecSecYExceptionsCallback *f_Exception; /**< TODO */ ++ t_FmMacsecSecYEventsCallback *f_Event; /**< TODO */ ++ t_Handle h_App; ++ t_FmMacsecSecYStatistics statistics; ++ t_FmMacsecSecYDriverParam *p_FmMacsecSecYDriverParam; ++} t_FmMacsecSecY; ++ ++ ++#endif /* __FM_MACSEC_SECY_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Makefile b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Makefile +new file mode 100644 +index 0000000..619f660 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Makefile +@@ -0,0 +1,23 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++ccflags-y += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk ++NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc ++ ++ccflags-y += -I$(NCSW_FM_INC) ++ ++ ++obj-y += fsl-ncsw-PFM1.o ++ ++fsl-ncsw-PFM1-objs := fm.o fm_muram.o fman.o ++ ++obj-y += MAC/ ++obj-y += Pcd/ ++obj-y += SP/ ++obj-y += Port/ ++obj-y += HC/ ++obj-y += Rtc/ ++obj-y += MACSEC/ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/Makefile b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/Makefile +new file mode 100644 +index 0000000..880c0e1 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/Makefile +@@ -0,0 +1,23 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++ccflags-y += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk ++ ++NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc ++ ++ccflags-y += -I$(NCSW_FM_INC) ++ ++obj-y += fsl-ncsw-Pcd.o ++ ++fsl-ncsw-Pcd-objs := fman_kg.o fman_prs.o fm_cc.o fm_kg.o fm_pcd.o fm_plcr.o fm_prs.o fm_manip.o ++ ++ifeq ($(CONFIG_FMAN_V3H),y) ++fsl-ncsw-Pcd-objs += fm_replic.o ++endif ++ifeq ($(CONFIG_FMAN_V3L),y) ++fsl-ncsw-Pcd-objs += fm_replic.o ++endif ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/crc64.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/crc64.h +new file mode 100644 +index 0000000..335ee68 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/crc64.h +@@ -0,0 +1,360 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++ /**************************************************************************//** ++ @File crc64.h ++ ++ @Description brief This file contains the CRC64 Table, and __inline__ ++ functions used for calculating crc. ++*//***************************************************************************/ ++#ifndef __CRC64_H ++#define __CRC64_H ++ ++#include "std_ext.h" ++ ++ ++#define BITS_PER_BYTE 8 ++ ++#define CRC64_EXPON_ECMA_182 0xC96C5795D7870F42ULL ++#define CRC64_DEFAULT_INITVAL 0xFFFFFFFFFFFFFFFFULL ++ ++#define CRC64_BYTE_MASK 0xFF ++#define CRC64_TABLE_ENTRIES ( 1 << BITS_PER_BYTE ) ++#define CRC64_ODD_MASK 1 ++ ++ ++/** ++ \brief '64 bit crc' Table ++ */ ++struct crc64_t { ++ uint64_t initial; /**< Initial seed */ ++ uint64_t table[CRC64_TABLE_ENTRIES]; /**< CRC table entries */ ++}; ++ ++ ++static struct crc64_t CRC64_ECMA_182 = { ++ CRC64_DEFAULT_INITVAL, ++ { ++ 0x0000000000000000ULL, ++ 0xb32e4cbe03a75f6fULL, ++ 0xf4843657a840a05bULL, ++ 0x47aa7ae9abe7ff34ULL, ++ 0x7bd0c384ff8f5e33ULL, ++ 0xc8fe8f3afc28015cULL, ++ 0x8f54f5d357cffe68ULL, ++ 0x3c7ab96d5468a107ULL, ++ 0xf7a18709ff1ebc66ULL, ++ 0x448fcbb7fcb9e309ULL, ++ 0x0325b15e575e1c3dULL, ++ 0xb00bfde054f94352ULL, ++ 0x8c71448d0091e255ULL, ++ 0x3f5f08330336bd3aULL, ++ 0x78f572daa8d1420eULL, ++ 0xcbdb3e64ab761d61ULL, ++ 0x7d9ba13851336649ULL, ++ 0xceb5ed8652943926ULL, ++ 0x891f976ff973c612ULL, ++ 0x3a31dbd1fad4997dULL, ++ 0x064b62bcaebc387aULL, ++ 0xb5652e02ad1b6715ULL, ++ 0xf2cf54eb06fc9821ULL, ++ 0x41e11855055bc74eULL, ++ 0x8a3a2631ae2dda2fULL, ++ 0x39146a8fad8a8540ULL, ++ 0x7ebe1066066d7a74ULL, ++ 0xcd905cd805ca251bULL, ++ 0xf1eae5b551a2841cULL, ++ 0x42c4a90b5205db73ULL, ++ 0x056ed3e2f9e22447ULL, ++ 0xb6409f5cfa457b28ULL, ++ 0xfb374270a266cc92ULL, ++ 0x48190ecea1c193fdULL, ++ 0x0fb374270a266cc9ULL, ++ 0xbc9d3899098133a6ULL, ++ 0x80e781f45de992a1ULL, ++ 0x33c9cd4a5e4ecdceULL, ++ 0x7463b7a3f5a932faULL, ++ 0xc74dfb1df60e6d95ULL, ++ 0x0c96c5795d7870f4ULL, ++ 0xbfb889c75edf2f9bULL, ++ 0xf812f32ef538d0afULL, ++ 0x4b3cbf90f69f8fc0ULL, ++ 0x774606fda2f72ec7ULL, ++ 0xc4684a43a15071a8ULL, ++ 0x83c230aa0ab78e9cULL, ++ 0x30ec7c140910d1f3ULL, ++ 0x86ace348f355aadbULL, ++ 0x3582aff6f0f2f5b4ULL, ++ 0x7228d51f5b150a80ULL, ++ 0xc10699a158b255efULL, ++ 0xfd7c20cc0cdaf4e8ULL, ++ 0x4e526c720f7dab87ULL, ++ 0x09f8169ba49a54b3ULL, ++ 0xbad65a25a73d0bdcULL, ++ 0x710d64410c4b16bdULL, ++ 0xc22328ff0fec49d2ULL, ++ 0x85895216a40bb6e6ULL, ++ 0x36a71ea8a7ace989ULL, ++ 0x0adda7c5f3c4488eULL, ++ 0xb9f3eb7bf06317e1ULL, ++ 0xfe5991925b84e8d5ULL, ++ 0x4d77dd2c5823b7baULL, ++ 0x64b62bcaebc387a1ULL, ++ 0xd7986774e864d8ceULL, ++ 0x90321d9d438327faULL, ++ 0x231c512340247895ULL, ++ 0x1f66e84e144cd992ULL, ++ 0xac48a4f017eb86fdULL, ++ 0xebe2de19bc0c79c9ULL, ++ 0x58cc92a7bfab26a6ULL, ++ 0x9317acc314dd3bc7ULL, ++ 0x2039e07d177a64a8ULL, ++ 0x67939a94bc9d9b9cULL, ++ 0xd4bdd62abf3ac4f3ULL, ++ 0xe8c76f47eb5265f4ULL, ++ 0x5be923f9e8f53a9bULL, ++ 0x1c4359104312c5afULL, ++ 0xaf6d15ae40b59ac0ULL, ++ 0x192d8af2baf0e1e8ULL, ++ 0xaa03c64cb957be87ULL, ++ 0xeda9bca512b041b3ULL, ++ 0x5e87f01b11171edcULL, ++ 0x62fd4976457fbfdbULL, ++ 0xd1d305c846d8e0b4ULL, ++ 0x96797f21ed3f1f80ULL, ++ 0x2557339fee9840efULL, ++ 0xee8c0dfb45ee5d8eULL, ++ 0x5da24145464902e1ULL, ++ 0x1a083bacedaefdd5ULL, ++ 0xa9267712ee09a2baULL, ++ 0x955cce7fba6103bdULL, ++ 0x267282c1b9c65cd2ULL, ++ 0x61d8f8281221a3e6ULL, ++ 0xd2f6b4961186fc89ULL, ++ 0x9f8169ba49a54b33ULL, ++ 0x2caf25044a02145cULL, ++ 0x6b055fede1e5eb68ULL, ++ 0xd82b1353e242b407ULL, ++ 0xe451aa3eb62a1500ULL, ++ 0x577fe680b58d4a6fULL, ++ 0x10d59c691e6ab55bULL, ++ 0xa3fbd0d71dcdea34ULL, ++ 0x6820eeb3b6bbf755ULL, ++ 0xdb0ea20db51ca83aULL, ++ 0x9ca4d8e41efb570eULL, ++ 0x2f8a945a1d5c0861ULL, ++ 0x13f02d374934a966ULL, ++ 0xa0de61894a93f609ULL, ++ 0xe7741b60e174093dULL, ++ 0x545a57dee2d35652ULL, ++ 0xe21ac88218962d7aULL, ++ 0x5134843c1b317215ULL, ++ 0x169efed5b0d68d21ULL, ++ 0xa5b0b26bb371d24eULL, ++ 0x99ca0b06e7197349ULL, ++ 0x2ae447b8e4be2c26ULL, ++ 0x6d4e3d514f59d312ULL, ++ 0xde6071ef4cfe8c7dULL, ++ 0x15bb4f8be788911cULL, ++ 0xa6950335e42fce73ULL, ++ 0xe13f79dc4fc83147ULL, ++ 0x521135624c6f6e28ULL, ++ 0x6e6b8c0f1807cf2fULL, ++ 0xdd45c0b11ba09040ULL, ++ 0x9aefba58b0476f74ULL, ++ 0x29c1f6e6b3e0301bULL, ++ 0xc96c5795d7870f42ULL, ++ 0x7a421b2bd420502dULL, ++ 0x3de861c27fc7af19ULL, ++ 0x8ec62d7c7c60f076ULL, ++ 0xb2bc941128085171ULL, ++ 0x0192d8af2baf0e1eULL, ++ 0x4638a2468048f12aULL, ++ 0xf516eef883efae45ULL, ++ 0x3ecdd09c2899b324ULL, ++ 0x8de39c222b3eec4bULL, ++ 0xca49e6cb80d9137fULL, ++ 0x7967aa75837e4c10ULL, ++ 0x451d1318d716ed17ULL, ++ 0xf6335fa6d4b1b278ULL, ++ 0xb199254f7f564d4cULL, ++ 0x02b769f17cf11223ULL, ++ 0xb4f7f6ad86b4690bULL, ++ 0x07d9ba1385133664ULL, ++ 0x4073c0fa2ef4c950ULL, ++ 0xf35d8c442d53963fULL, ++ 0xcf273529793b3738ULL, ++ 0x7c0979977a9c6857ULL, ++ 0x3ba3037ed17b9763ULL, ++ 0x888d4fc0d2dcc80cULL, ++ 0x435671a479aad56dULL, ++ 0xf0783d1a7a0d8a02ULL, ++ 0xb7d247f3d1ea7536ULL, ++ 0x04fc0b4dd24d2a59ULL, ++ 0x3886b22086258b5eULL, ++ 0x8ba8fe9e8582d431ULL, ++ 0xcc0284772e652b05ULL, ++ 0x7f2cc8c92dc2746aULL, ++ 0x325b15e575e1c3d0ULL, ++ 0x8175595b76469cbfULL, ++ 0xc6df23b2dda1638bULL, ++ 0x75f16f0cde063ce4ULL, ++ 0x498bd6618a6e9de3ULL, ++ 0xfaa59adf89c9c28cULL, ++ 0xbd0fe036222e3db8ULL, ++ 0x0e21ac88218962d7ULL, ++ 0xc5fa92ec8aff7fb6ULL, ++ 0x76d4de52895820d9ULL, ++ 0x317ea4bb22bfdfedULL, ++ 0x8250e80521188082ULL, ++ 0xbe2a516875702185ULL, ++ 0x0d041dd676d77eeaULL, ++ 0x4aae673fdd3081deULL, ++ 0xf9802b81de97deb1ULL, ++ 0x4fc0b4dd24d2a599ULL, ++ 0xfceef8632775faf6ULL, ++ 0xbb44828a8c9205c2ULL, ++ 0x086ace348f355aadULL, ++ 0x34107759db5dfbaaULL, ++ 0x873e3be7d8faa4c5ULL, ++ 0xc094410e731d5bf1ULL, ++ 0x73ba0db070ba049eULL, ++ 0xb86133d4dbcc19ffULL, ++ 0x0b4f7f6ad86b4690ULL, ++ 0x4ce50583738cb9a4ULL, ++ 0xffcb493d702be6cbULL, ++ 0xc3b1f050244347ccULL, ++ 0x709fbcee27e418a3ULL, ++ 0x3735c6078c03e797ULL, ++ 0x841b8ab98fa4b8f8ULL, ++ 0xadda7c5f3c4488e3ULL, ++ 0x1ef430e13fe3d78cULL, ++ 0x595e4a08940428b8ULL, ++ 0xea7006b697a377d7ULL, ++ 0xd60abfdbc3cbd6d0ULL, ++ 0x6524f365c06c89bfULL, ++ 0x228e898c6b8b768bULL, ++ 0x91a0c532682c29e4ULL, ++ 0x5a7bfb56c35a3485ULL, ++ 0xe955b7e8c0fd6beaULL, ++ 0xaeffcd016b1a94deULL, ++ 0x1dd181bf68bdcbb1ULL, ++ 0x21ab38d23cd56ab6ULL, ++ 0x9285746c3f7235d9ULL, ++ 0xd52f0e859495caedULL, ++ 0x6601423b97329582ULL, ++ 0xd041dd676d77eeaaULL, ++ 0x636f91d96ed0b1c5ULL, ++ 0x24c5eb30c5374ef1ULL, ++ 0x97eba78ec690119eULL, ++ 0xab911ee392f8b099ULL, ++ 0x18bf525d915feff6ULL, ++ 0x5f1528b43ab810c2ULL, ++ 0xec3b640a391f4fadULL, ++ 0x27e05a6e926952ccULL, ++ 0x94ce16d091ce0da3ULL, ++ 0xd3646c393a29f297ULL, ++ 0x604a2087398eadf8ULL, ++ 0x5c3099ea6de60cffULL, ++ 0xef1ed5546e415390ULL, ++ 0xa8b4afbdc5a6aca4ULL, ++ 0x1b9ae303c601f3cbULL, ++ 0x56ed3e2f9e224471ULL, ++ 0xe5c372919d851b1eULL, ++ 0xa26908783662e42aULL, ++ 0x114744c635c5bb45ULL, ++ 0x2d3dfdab61ad1a42ULL, ++ 0x9e13b115620a452dULL, ++ 0xd9b9cbfcc9edba19ULL, ++ 0x6a978742ca4ae576ULL, ++ 0xa14cb926613cf817ULL, ++ 0x1262f598629ba778ULL, ++ 0x55c88f71c97c584cULL, ++ 0xe6e6c3cfcadb0723ULL, ++ 0xda9c7aa29eb3a624ULL, ++ 0x69b2361c9d14f94bULL, ++ 0x2e184cf536f3067fULL, ++ 0x9d36004b35545910ULL, ++ 0x2b769f17cf112238ULL, ++ 0x9858d3a9ccb67d57ULL, ++ 0xdff2a94067518263ULL, ++ 0x6cdce5fe64f6dd0cULL, ++ 0x50a65c93309e7c0bULL, ++ 0xe388102d33392364ULL, ++ 0xa4226ac498dedc50ULL, ++ 0x170c267a9b79833fULL, ++ 0xdcd7181e300f9e5eULL, ++ 0x6ff954a033a8c131ULL, ++ 0x28532e49984f3e05ULL, ++ 0x9b7d62f79be8616aULL, ++ 0xa707db9acf80c06dULL, ++ 0x14299724cc279f02ULL, ++ 0x5383edcd67c06036ULL, ++ 0xe0ada17364673f59ULL ++ } ++}; ++ ++ ++/** ++ \brief Initializes the crc seed ++ */ ++static __inline__ uint64_t crc64_init(void) ++{ ++ return CRC64_ECMA_182.initial; ++} ++ ++/** ++ \brief Computes 64 bit the crc ++ \param[in] data Pointer to the Data in the frame ++ \param[in] len Length of the Data ++ \param[in] crc seed ++ \return calculated crc ++ */ ++static __inline__ uint64_t crc64_compute(void const *data, ++ uint32_t len, ++ uint64_t seed) ++{ ++ uint32_t i; ++ uint64_t crc = seed; ++ uint8_t *bdata = (uint8_t *) data; ++ ++ for (i = 0; i < len; i++) ++ crc = ++ CRC64_ECMA_182. ++ table[(crc ^ *bdata++) & CRC64_BYTE_MASK] ^ (crc >> 8); ++ ++ return crc; ++} ++ ++ ++#endif /* __CRC64_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_cc.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_cc.c +new file mode 100644 +index 0000000..51df898 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_cc.c +@@ -0,0 +1,7533 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_cc.c ++ ++ @Description FM Coarse Classifier implementation ++ *//***************************************************************************/ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "debug_ext.h" ++#include "fm_pcd_ext.h" ++#include "fm_muram_ext.h" ++ ++#include "fm_common.h" ++#include "fm_pcd.h" ++#include "fm_hc.h" ++#include "fm_cc.h" ++#include "crc64.h" ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++ ++ ++static t_Error CcRootTryLock(t_Handle h_FmPcdCcTree) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree; ++ ++ ASSERT_COND(h_FmPcdCcTree); ++ ++ if (FmPcdLockTryLock(p_FmPcdCcTree->p_Lock)) ++ return E_OK; ++ ++ return ERROR_CODE(E_BUSY); ++} ++ ++static void CcRootReleaseLock(t_Handle h_FmPcdCcTree) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree; ++ ++ ASSERT_COND(h_FmPcdCcTree); ++ ++ FmPcdLockUnlock(p_FmPcdCcTree->p_Lock); ++} ++ ++static void UpdateNodeOwner(t_FmPcdCcNode *p_CcNode, bool add) ++{ ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_CcNode); ++ ++ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock); ++ ++ if (add) ++ p_CcNode->owners++; ++ else ++ { ++ ASSERT_COND(p_CcNode->owners); ++ p_CcNode->owners--; ++ } ++ ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++} ++ ++static __inline__ t_FmPcdStatsObj* DequeueStatsObj(t_List *p_List) ++{ ++ t_FmPcdStatsObj *p_StatsObj = NULL; ++ t_List *p_Next; ++ ++ if (!LIST_IsEmpty(p_List)) ++ { ++ p_Next = LIST_FIRST(p_List); ++ p_StatsObj = LIST_OBJECT(p_Next, t_FmPcdStatsObj, node); ++ ASSERT_COND(p_StatsObj); ++ LIST_DelAndInit(p_Next); ++ } ++ ++ return p_StatsObj; ++} ++ ++static __inline__ void EnqueueStatsObj(t_List *p_List, ++ t_FmPcdStatsObj *p_StatsObj) ++{ ++ LIST_AddToTail(&p_StatsObj->node, p_List); ++} ++ ++static void FreeStatObjects(t_List *p_List, t_Handle h_FmMuram) ++{ ++ t_FmPcdStatsObj *p_StatsObj; ++ ++ while (!LIST_IsEmpty(p_List)) ++ { ++ p_StatsObj = DequeueStatsObj(p_List); ++ ASSERT_COND(p_StatsObj); ++ ++ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsAd); ++ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsCounters); ++ ++ XX_Free(p_StatsObj); ++ } ++} ++ ++static t_FmPcdStatsObj* GetStatsObj(t_FmPcdCcNode *p_CcNode) ++{ ++ t_FmPcdStatsObj* p_StatsObj; ++ t_Handle h_FmMuram; ++ ++ ASSERT_COND(p_CcNode); ++ ++ /* If 'maxNumOfKeys' was passed, all statistics object were preallocated ++ upon node initialization */ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ p_StatsObj = DequeueStatsObj(&p_CcNode->availableStatsLst); ++ } ++ else ++ { ++ h_FmMuram = ((t_FmPcd *)(p_CcNode->h_FmPcd))->h_FmMuram; ++ ASSERT_COND(h_FmMuram); ++ ++ p_StatsObj = XX_Malloc(sizeof(t_FmPcdStatsObj)); ++ if (!p_StatsObj) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("statistics object")); ++ return NULL; ++ } ++ ++ p_StatsObj->h_StatsAd = (t_Handle)FM_MURAM_AllocMem( ++ h_FmMuram, FM_PCD_CC_AD_ENTRY_SIZE, FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_StatsObj->h_StatsAd) ++ { ++ XX_Free(p_StatsObj); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics ADs")); ++ return NULL; ++ } ++ IOMemSet32(p_StatsObj->h_StatsAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ p_StatsObj->h_StatsCounters = (t_Handle)FM_MURAM_AllocMem( ++ h_FmMuram, p_CcNode->countersArraySize, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_StatsObj->h_StatsCounters) ++ { ++ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsAd); ++ XX_Free(p_StatsObj); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics counters")); ++ return NULL; ++ } ++ IOMemSet32(p_StatsObj->h_StatsCounters, 0, p_CcNode->countersArraySize); ++ } ++ ++ return p_StatsObj; ++} ++ ++static void PutStatsObj(t_FmPcdCcNode *p_CcNode, t_FmPcdStatsObj *p_StatsObj) ++{ ++ t_Handle h_FmMuram; ++ ++ ASSERT_COND(p_CcNode); ++ ASSERT_COND(p_StatsObj); ++ ++ /* If 'maxNumOfKeys' was passed, all statistics object were preallocated ++ upon node initialization and now will be enqueued back to the list */ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ /* Nullify counters */ ++ IOMemSet32(p_StatsObj->h_StatsCounters, 0, p_CcNode->countersArraySize); ++ ++ EnqueueStatsObj(&p_CcNode->availableStatsLst, p_StatsObj); ++ } ++ else ++ { ++ h_FmMuram = ((t_FmPcd *)(p_CcNode->h_FmPcd))->h_FmMuram; ++ ASSERT_COND(h_FmMuram); ++ ++ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsAd); ++ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsCounters); ++ ++ XX_Free(p_StatsObj); ++ } ++} ++ ++static void SetStatsCounters(t_AdOfTypeStats *p_StatsAd, ++ uint32_t statsCountersAddr) ++{ ++ uint32_t tmp = (statsCountersAddr & FM_PCD_AD_STATS_COUNTERS_ADDR_MASK); ++ ++ WRITE_UINT32(p_StatsAd->statsTableAddr, tmp); ++} ++ ++ ++static void UpdateStatsAd(t_FmPcdCcStatsParams *p_FmPcdCcStatsParams, ++ t_Handle h_Ad, uint64_t physicalMuramBase) ++{ ++ t_AdOfTypeStats *p_StatsAd; ++ uint32_t statsCountersAddr, nextActionAddr, tmp; ++#if (DPAA_VERSION >= 11) ++ uint32_t frameLengthRangesAddr; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ p_StatsAd = (t_AdOfTypeStats *)p_FmPcdCcStatsParams->h_StatsAd; ++ ++ tmp = FM_PCD_AD_STATS_TYPE; ++ ++#if (DPAA_VERSION >= 11) ++ if (p_FmPcdCcStatsParams->h_StatsFLRs) ++ { ++ frameLengthRangesAddr = (uint32_t)((XX_VirtToPhys( ++ p_FmPcdCcStatsParams->h_StatsFLRs) - physicalMuramBase)); ++ tmp |= (frameLengthRangesAddr & FM_PCD_AD_STATS_FLR_ADDR_MASK); ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ WRITE_UINT32(p_StatsAd->profileTableAddr, tmp); ++ ++ nextActionAddr = (uint32_t)((XX_VirtToPhys(h_Ad) - physicalMuramBase)); ++ tmp = 0; ++ tmp |= (uint32_t)((nextActionAddr << FM_PCD_AD_STATS_NEXT_ACTION_SHIFT) ++ & FM_PCD_AD_STATS_NEXT_ACTION_MASK); ++ tmp |= (FM_PCD_AD_STATS_NAD_EN | FM_PCD_AD_STATS_OP_CODE); ++ ++#if (DPAA_VERSION >= 11) ++ if (p_FmPcdCcStatsParams->h_StatsFLRs) ++ tmp |= FM_PCD_AD_STATS_FLR_EN; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ WRITE_UINT32(p_StatsAd->nextActionIndx, tmp); ++ ++ statsCountersAddr = (uint32_t)((XX_VirtToPhys( ++ p_FmPcdCcStatsParams->h_StatsCounters) - physicalMuramBase)); ++ SetStatsCounters(p_StatsAd, statsCountersAddr); ++} ++ ++static void FillAdOfTypeContLookup(t_Handle h_Ad, ++ t_FmPcdCcStatsParams *p_FmPcdCcStatsParams, ++ t_Handle h_FmPcd, t_Handle p_CcNode, ++ t_Handle h_Manip, t_Handle h_FrmReplic) ++{ ++ t_FmPcdCcNode *p_Node = (t_FmPcdCcNode *)p_CcNode; ++ t_AdOfTypeContLookup *p_AdContLookup = (t_AdOfTypeContLookup *)h_Ad; ++ t_Handle h_TmpAd; ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t tmpReg32; ++ t_Handle p_AdNewPtr = NULL; ++ ++ UNUSED(h_Manip); ++ UNUSED(h_FrmReplic); ++ ++ /* there are 3 cases handled in this routine of building a "Continue lookup" type AD. ++ * Case 1: No Manip. The action descriptor is built within the match table. ++ * p_AdResult = p_AdNewPtr; ++ * Case 2: Manip exists. A new AD is created - p_AdNewPtr. It is initialized ++ * either in the FmPcdManipUpdateAdResultForCc routine or it was already ++ * initialized and returned here. ++ * p_AdResult (within the match table) will be initialized after ++ * this routine returns and point to the existing AD. ++ * Case 3: Manip exists. The action descriptor is built within the match table. ++ * FmPcdManipUpdateAdContLookupForCc returns a NULL p_AdNewPtr. ++ */ ++ ++ /* As default, the "new" ptr is the current one. i.e. the content of the result ++ * AD will be written into the match table itself (case (1))*/ ++ p_AdNewPtr = p_AdContLookup; ++ ++ /* Initialize an action descriptor, if current statistics mode requires an Ad */ ++ if (p_FmPcdCcStatsParams) ++ { ++ ASSERT_COND(p_FmPcdCcStatsParams->h_StatsAd); ++ ASSERT_COND(p_FmPcdCcStatsParams->h_StatsCounters); ++ ++ /* Swapping addresses between statistics Ad and the current lookup AD */ ++ h_TmpAd = p_FmPcdCcStatsParams->h_StatsAd; ++ p_FmPcdCcStatsParams->h_StatsAd = h_Ad; ++ h_Ad = h_TmpAd; ++ ++ p_AdNewPtr = h_Ad; ++ p_AdContLookup = h_Ad; ++ ++ /* Init statistics Ad and connect current lookup AD as 'next action' from statistics Ad */ ++ UpdateStatsAd(p_FmPcdCcStatsParams, h_Ad, p_FmPcd->physicalMuramBase); ++ } ++ ++#if DPAA_VERSION >= 11 ++ if (h_Manip && h_FrmReplic) ++ FmPcdManipUpdateAdContLookupForCc( ++ h_Manip, ++ h_Ad, ++ &p_AdNewPtr, ++ (uint32_t)((XX_VirtToPhys( ++ FrmReplicGroupGetSourceTableDescriptor(h_FrmReplic)) ++ - p_FmPcd->physicalMuramBase))); ++ else ++ if (h_FrmReplic) ++ FrmReplicGroupUpdateAd(h_FrmReplic, h_Ad, &p_AdNewPtr); ++ else ++#endif /* (DPAA_VERSION >= 11) */ ++ if (h_Manip) ++ FmPcdManipUpdateAdContLookupForCc( ++ h_Manip, ++ h_Ad, ++ &p_AdNewPtr, ++ ++#ifdef FM_CAPWAP_SUPPORT ++ /*no check for opcode of manip - this step can be reached only with capwap_applic_specific*/ ++ (uint32_t)((XX_VirtToPhys(p_Node->h_AdTable) - p_FmPcd->physicalMuramBase)) ++#else /* not FM_CAPWAP_SUPPORT */ ++ (uint32_t)((XX_VirtToPhys(p_Node->h_Ad) ++ - p_FmPcd->physicalMuramBase)) ++#endif /* not FM_CAPWAP_SUPPORT */ ++ ); ++ ++ /* if (p_AdNewPtr = NULL) --> Done. (case (3)) */ ++ if (p_AdNewPtr) ++ { ++ /* cases (1) & (2) */ ++ tmpReg32 = 0; ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ tmpReg32 |= ++ p_Node->sizeOfExtraction ? ((p_Node->sizeOfExtraction - 1) << 24) : ++ 0; ++ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Node->h_AdTable) ++ - p_FmPcd->physicalMuramBase); ++ WRITE_UINT32(p_AdContLookup->ccAdBase, tmpReg32); ++ ++ tmpReg32 = 0; ++ tmpReg32 |= p_Node->numOfKeys << 24; ++ tmpReg32 |= (p_Node->lclMask ? FM_PCD_AD_CONT_LOOKUP_LCL_MASK : 0); ++ tmpReg32 |= ++ p_Node->h_KeysMatchTable ? (uint32_t)(XX_VirtToPhys( ++ p_Node->h_KeysMatchTable) - p_FmPcd->physicalMuramBase) : ++ 0; ++ WRITE_UINT32(p_AdContLookup->matchTblPtr, tmpReg32); ++ ++ tmpReg32 = 0; ++ tmpReg32 |= p_Node->prsArrayOffset << 24; ++ tmpReg32 |= p_Node->offset << 16; ++ tmpReg32 |= p_Node->parseCode; ++ WRITE_UINT32(p_AdContLookup->pcAndOffsets, tmpReg32); ++ ++ Mem2IOCpy32((void*)&p_AdContLookup->gmask, p_Node->p_GlblMask, ++ CC_GLBL_MASK_SIZE); ++ } ++} ++ ++static t_Error AllocAndFillAdForContLookupManip(t_Handle h_CcNode) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_CcNode); ++ ++ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock); ++ ++ if (!p_CcNode->h_Ad) ++ { ++ if (p_CcNode->maxNumOfKeys) ++ p_CcNode->h_Ad = p_CcNode->h_TmpAd; ++ else ++ p_CcNode->h_Ad = (t_Handle)FM_MURAM_AllocMem( ++ ((t_FmPcd *)(p_CcNode->h_FmPcd))->h_FmMuram, ++ FM_PCD_CC_AD_ENTRY_SIZE, FM_PCD_CC_AD_TABLE_ALIGN); ++ ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ ++ if (!p_CcNode->h_Ad) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("MURAM allocation for CC action descriptor")); ++ ++ IOMemSet32(p_CcNode->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ FillAdOfTypeContLookup(p_CcNode->h_Ad, NULL, p_CcNode->h_FmPcd, ++ p_CcNode, NULL, NULL); ++ } ++ else ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ ++ return E_OK; ++} ++ ++static t_Error SetRequiredAction1( ++ t_Handle h_FmPcd, uint32_t requiredAction, ++ t_FmPcdCcKeyAndNextEngineParams *p_CcKeyAndNextEngineParamsTmp, ++ t_Handle h_AdTmp, uint16_t numOfEntries, t_Handle h_Tree) ++{ ++ t_AdOfTypeResult *p_AdTmp = (t_AdOfTypeResult *)h_AdTmp; ++ uint32_t tmpReg32; ++ t_Error err; ++ t_FmPcdCcNode *p_CcNode; ++ int i = 0; ++ uint16_t tmp = 0; ++ uint16_t profileId; ++ uint8_t relativeSchemeId, physicalSchemeId; ++ t_CcNodeInformation ccNodeInfo; ++ ++ for (i = 0; i < numOfEntries; i++) ++ { ++ if (i == 0) ++ h_AdTmp = PTR_MOVE(h_AdTmp, i*FM_PCD_CC_AD_ENTRY_SIZE); ++ else ++ h_AdTmp = PTR_MOVE(h_AdTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ switch (p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.nextEngine) ++ { ++ case (e_FM_PCD_CC): ++ if (requiredAction) ++ { ++ p_CcNode = ++ p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.ccParams.h_CcNode; ++ ASSERT_COND(p_CcNode); ++ if (p_CcNode->shadowAction == requiredAction) ++ break; ++ if ((requiredAction & UPDATE_CC_WITH_TREE) ++ && !(p_CcNode->shadowAction & UPDATE_CC_WITH_TREE)) ++ { ++ ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = h_Tree; ++ EnqueueNodeInfoToRelevantLst(&p_CcNode->ccTreesLst, ++ &ccNodeInfo, NULL); ++ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= ++ UPDATE_CC_WITH_TREE; ++ } ++ if ((requiredAction & UPDATE_CC_SHADOW_CLEAR) ++ && !(p_CcNode->shadowAction & UPDATE_CC_SHADOW_CLEAR)) ++ { ++ ++ p_CcNode->shadowAction = 0; ++ } ++ ++ if ((requiredAction & UPDATE_CC_WITH_DELETE_TREE) ++ && !(p_CcNode->shadowAction ++ & UPDATE_CC_WITH_DELETE_TREE)) ++ { ++ DequeueNodeInfoFromRelevantLst(&p_CcNode->ccTreesLst, ++ h_Tree, NULL); ++ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= ++ UPDATE_CC_WITH_DELETE_TREE; ++ } ++ if (p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine ++ != e_FM_PCD_INVALID) ++ tmp = (uint8_t)(p_CcNode->numOfKeys + 1); ++ else ++ tmp = p_CcNode->numOfKeys; ++ err = SetRequiredAction1(h_FmPcd, requiredAction, ++ p_CcNode->keyAndNextEngineParams, ++ p_CcNode->h_AdTable, tmp, h_Tree); ++ if (err != E_OK) ++ return err; ++ if (requiredAction != UPDATE_CC_SHADOW_CLEAR) ++ p_CcNode->shadowAction |= requiredAction; ++ } ++ break; ++ ++ case (e_FM_PCD_KG): ++ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) ++ && !(p_CcKeyAndNextEngineParamsTmp[i].shadowAction ++ & UPDATE_NIA_ENQ_WITHOUT_DMA)) ++ { ++ physicalSchemeId = ++ FmPcdKgGetSchemeId( ++ p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.kgParams.h_DirectScheme); ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId( ++ h_FmPcd, physicalSchemeId); ++ if (relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ if (!FmPcdKgIsSchemeValidSw( ++ p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.kgParams.h_DirectScheme)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("Invalid direct scheme.")); ++ if (!KgIsSchemeAlwaysDirect(h_FmPcd, relativeSchemeId)) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_STATE, ++ ("For this action scheme has to be direct.")); ++ err = ++ FmPcdKgCcGetSetParams( ++ h_FmPcd, ++ p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.kgParams.h_DirectScheme, ++ requiredAction, 0); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= ++ requiredAction; ++ } ++ break; ++ ++ case (e_FM_PCD_PLCR): ++ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) ++ && !(p_CcKeyAndNextEngineParamsTmp[i].shadowAction ++ & UPDATE_NIA_ENQ_WITHOUT_DMA)) ++ { ++ if (!p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.plcrParams.overrideParams) ++ RETURN_ERROR( ++ MAJOR, ++ E_NOT_SUPPORTED, ++ ("In this initialization only overrideFqid can be initialized")); ++ if (!p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.plcrParams.sharedProfile) ++ RETURN_ERROR( ++ MAJOR, ++ E_NOT_SUPPORTED, ++ ("In this initialization only overrideFqid can be initialized")); ++ err = ++ FmPcdPlcrGetAbsoluteIdByProfileParams( ++ h_FmPcd, ++ e_FM_PCD_PLCR_SHARED, ++ NULL, ++ p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.plcrParams.newRelativeProfileId, ++ &profileId); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ err = FmPcdPlcrCcGetSetParams(h_FmPcd, profileId, ++ requiredAction); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= ++ requiredAction; ++ } ++ break; ++ ++ case (e_FM_PCD_DONE): ++ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) ++ && !(p_CcKeyAndNextEngineParamsTmp[i].shadowAction ++ & UPDATE_NIA_ENQ_WITHOUT_DMA)) ++ { ++ tmpReg32 = GET_UINT32(p_AdTmp->nia); ++ if ((tmpReg32 & GET_NIA_BMI_AC_ENQ_FRAME(h_FmPcd)) ++ != GET_NIA_BMI_AC_ENQ_FRAME(h_FmPcd)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("Next engine was previously assigned not as PCD_DONE")); ++ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; ++ WRITE_UINT32(p_AdTmp->nia, tmpReg32); ++ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= ++ requiredAction; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ return E_OK; ++} ++ ++static t_Error SetRequiredAction( ++ t_Handle h_FmPcd, uint32_t requiredAction, ++ t_FmPcdCcKeyAndNextEngineParams *p_CcKeyAndNextEngineParamsTmp, ++ t_Handle h_AdTmp, uint16_t numOfEntries, t_Handle h_Tree) ++{ ++ t_Error err = SetRequiredAction1(h_FmPcd, requiredAction, ++ p_CcKeyAndNextEngineParamsTmp, h_AdTmp, ++ numOfEntries, h_Tree); ++ if (err != E_OK) ++ return err; ++ return SetRequiredAction1(h_FmPcd, UPDATE_CC_SHADOW_CLEAR, ++ p_CcKeyAndNextEngineParamsTmp, h_AdTmp, ++ numOfEntries, h_Tree); ++} ++ ++static t_Error ReleaseModifiedDataStructure( ++ t_Handle h_FmPcd, t_List *h_FmPcdOldPointersLst, ++ t_List *h_FmPcdNewPointersLst, ++ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalParams, ++ bool useShadowStructs) ++{ ++ t_List *p_Pos; ++ t_Error err = E_OK; ++ t_CcNodeInformation ccNodeInfo, *p_CcNodeInformation; ++ t_Handle h_Muram; ++ t_FmPcdCcNode *p_FmPcdCcNextNode, *p_FmPcdCcWorkingOnNode; ++ t_List *p_UpdateLst; ++ uint32_t intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_AdditionalParams->h_CurrentNode, ++ E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPcdOldPointersLst, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPcdNewPointersLst, E_INVALID_HANDLE); ++ ++ /* We don't update subtree of the new node with new tree because it was done in the previous stage */ ++ if (p_AdditionalParams->h_NodeForAdd) ++ { ++ p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_AdditionalParams->h_NodeForAdd; ++ ++ if (!p_AdditionalParams->tree) ++ p_UpdateLst = &p_FmPcdCcNextNode->ccPrevNodesLst; ++ else ++ p_UpdateLst = &p_FmPcdCcNextNode->ccTreeIdLst; ++ ++ p_CcNodeInformation = FindNodeInfoInReleventLst( ++ p_UpdateLst, p_AdditionalParams->h_CurrentNode, ++ p_FmPcdCcNextNode->h_Spinlock); ++ ++ if (p_CcNodeInformation) ++ p_CcNodeInformation->index++; ++ else ++ { ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = (t_Handle)p_AdditionalParams->h_CurrentNode; ++ ccNodeInfo.index = 1; ++ EnqueueNodeInfoToRelevantLst(p_UpdateLst, &ccNodeInfo, ++ p_FmPcdCcNextNode->h_Spinlock); ++ } ++ if (p_AdditionalParams->h_ManipForAdd) ++ { ++ p_CcNodeInformation = FindNodeInfoInReleventLst( ++ FmPcdManipGetNodeLstPointedOnThisManip( ++ p_AdditionalParams->h_ManipForAdd), ++ p_AdditionalParams->h_CurrentNode, ++ FmPcdManipGetSpinlock(p_AdditionalParams->h_ManipForAdd)); ++ ++ if (p_CcNodeInformation) ++ p_CcNodeInformation->index++; ++ else ++ { ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = ++ (t_Handle)p_AdditionalParams->h_CurrentNode; ++ ccNodeInfo.index = 1; ++ EnqueueNodeInfoToRelevantLst( ++ FmPcdManipGetNodeLstPointedOnThisManip( ++ p_AdditionalParams->h_ManipForAdd), ++ &ccNodeInfo, ++ FmPcdManipGetSpinlock( ++ p_AdditionalParams->h_ManipForAdd)); ++ } ++ } ++ } ++ ++ if (p_AdditionalParams->h_NodeForRmv) ++ { ++ p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_AdditionalParams->h_NodeForRmv; ++ ++ if (!p_AdditionalParams->tree) ++ { ++ p_UpdateLst = &p_FmPcdCcNextNode->ccPrevNodesLst; ++ p_FmPcdCcWorkingOnNode = ++ (t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode); ++ ++ for (p_Pos = LIST_FIRST(&p_FmPcdCcWorkingOnNode->ccTreesLst); ++ p_Pos != (&p_FmPcdCcWorkingOnNode->ccTreesLst); p_Pos = ++ LIST_NEXT(p_Pos)) ++ { ++ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos); ++ ++ ASSERT_COND(p_CcNodeInformation->h_CcNode); ++ ++ err = ++ SetRequiredAction( ++ h_FmPcd, ++ UPDATE_CC_WITH_DELETE_TREE, ++ &((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams[p_AdditionalParams->savedKeyIndex], ++ PTR_MOVE(((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_AdTable, p_AdditionalParams->savedKeyIndex*FM_PCD_CC_AD_ENTRY_SIZE), ++ 1, p_CcNodeInformation->h_CcNode); ++ } ++ } ++ else ++ { ++ p_UpdateLst = &p_FmPcdCcNextNode->ccTreeIdLst; ++ ++ err = ++ SetRequiredAction( ++ h_FmPcd, ++ UPDATE_CC_WITH_DELETE_TREE, ++ &((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams[p_AdditionalParams->savedKeyIndex], ++ UINT_TO_PTR(((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->ccTreeBaseAddr + p_AdditionalParams->savedKeyIndex*FM_PCD_CC_AD_ENTRY_SIZE), ++ 1, p_AdditionalParams->h_CurrentNode); ++ } ++ if (err) ++ return err; ++ ++ /* We remove from the subtree of the removed node tree because it wasn't done in the previous stage ++ Update ccPrevNodesLst or ccTreeIdLst of the removed node ++ Update of the node owner */ ++ p_CcNodeInformation = FindNodeInfoInReleventLst( ++ p_UpdateLst, p_AdditionalParams->h_CurrentNode, ++ p_FmPcdCcNextNode->h_Spinlock); ++ ++ ASSERT_COND(p_CcNodeInformation); ++ ASSERT_COND(p_CcNodeInformation->index); ++ ++ p_CcNodeInformation->index--; ++ ++ if (p_CcNodeInformation->index == 0) ++ DequeueNodeInfoFromRelevantLst(p_UpdateLst, ++ p_AdditionalParams->h_CurrentNode, ++ p_FmPcdCcNextNode->h_Spinlock); ++ ++ UpdateNodeOwner(p_FmPcdCcNextNode, FALSE); ++ ++ if (p_AdditionalParams->h_ManipForRmv) ++ { ++ p_CcNodeInformation = FindNodeInfoInReleventLst( ++ FmPcdManipGetNodeLstPointedOnThisManip( ++ p_AdditionalParams->h_ManipForRmv), ++ p_AdditionalParams->h_CurrentNode, ++ FmPcdManipGetSpinlock(p_AdditionalParams->h_ManipForRmv)); ++ ++ ASSERT_COND(p_CcNodeInformation); ++ ASSERT_COND(p_CcNodeInformation->index); ++ ++ p_CcNodeInformation->index--; ++ ++ if (p_CcNodeInformation->index == 0) ++ DequeueNodeInfoFromRelevantLst( ++ FmPcdManipGetNodeLstPointedOnThisManip( ++ p_AdditionalParams->h_ManipForRmv), ++ p_AdditionalParams->h_CurrentNode, ++ FmPcdManipGetSpinlock( ++ p_AdditionalParams->h_ManipForRmv)); ++ } ++ } ++ ++ if (p_AdditionalParams->h_ManipForRmv) ++ FmPcdManipUpdateOwner(p_AdditionalParams->h_ManipForRmv, FALSE); ++ ++ if (p_AdditionalParams->p_StatsObjForRmv) ++ PutStatsObj((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode), ++ p_AdditionalParams->p_StatsObjForRmv); ++ ++#if (DPAA_VERSION >= 11) ++ if (p_AdditionalParams->h_FrmReplicForRmv) ++ FrmReplicGroupUpdateOwner(p_AdditionalParams->h_FrmReplicForRmv, ++ FALSE/* remove */); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (!useShadowStructs) ++ { ++ h_Muram = FmPcdGetMuramHandle(h_FmPcd); ++ ASSERT_COND(h_Muram); ++ ++ if ((p_AdditionalParams->tree && !((t_FmPcd *)h_FmPcd)->p_CcShadow) ++ || (!p_AdditionalParams->tree ++ && !((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->maxNumOfKeys)) ++ { ++ /* We release new AD which was allocated and updated for copy from to actual AD */ ++ for (p_Pos = LIST_FIRST(h_FmPcdNewPointersLst); ++ p_Pos != (h_FmPcdNewPointersLst); p_Pos = LIST_NEXT(p_Pos)) ++ { ++ ++ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos); ++ ASSERT_COND(p_CcNodeInformation->h_CcNode); ++ FM_MURAM_FreeMem(h_Muram, p_CcNodeInformation->h_CcNode); ++ } ++ } ++ ++ /* Free Old data structure if it has to be freed - new data structure was allocated*/ ++ if (p_AdditionalParams->p_AdTableOld) ++ FM_MURAM_FreeMem(h_Muram, p_AdditionalParams->p_AdTableOld); ++ ++ if (p_AdditionalParams->p_KeysMatchTableOld) ++ FM_MURAM_FreeMem(h_Muram, p_AdditionalParams->p_KeysMatchTableOld); ++ } ++ ++ /* Update current modified node with changed fields if it's required*/ ++ if (!p_AdditionalParams->tree) ++ { ++ if (p_AdditionalParams->p_AdTableNew) ++ ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_AdTable = ++ p_AdditionalParams->p_AdTableNew; ++ ++ if (p_AdditionalParams->p_KeysMatchTableNew) ++ ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_KeysMatchTable = ++ p_AdditionalParams->p_KeysMatchTableNew; ++ ++ /* Locking node's spinlock before updating 'keys and next engine' structure, ++ as it maybe used to retrieve keys statistics */ ++ intFlags = ++ XX_LockIntrSpinlock( ++ ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_Spinlock); ++ ++ ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->numOfKeys = ++ p_AdditionalParams->numOfKeys; ++ ++ memcpy(((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams, ++ &p_AdditionalParams->keyAndNextEngineParams, ++ sizeof(t_FmPcdCcKeyAndNextEngineParams) * (CC_MAX_NUM_OF_KEYS)); ++ ++ XX_UnlockIntrSpinlock( ++ ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_Spinlock, ++ intFlags); ++ } ++ else ++ { ++ uint8_t numEntries = ++ ((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->numOfEntries; ++ ASSERT_COND(numEntries < FM_PCD_MAX_NUM_OF_CC_GROUPS); ++ memcpy(&((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams, ++ &p_AdditionalParams->keyAndNextEngineParams, ++ sizeof(t_FmPcdCcKeyAndNextEngineParams) * numEntries); ++ } ++ ++ ReleaseLst(h_FmPcdOldPointersLst); ++ ReleaseLst(h_FmPcdNewPointersLst); ++ ++ XX_Free(p_AdditionalParams); ++ ++ return E_OK; ++} ++ ++static t_Handle BuildNewAd( ++ t_Handle h_Ad, ++ t_FmPcdModifyCcKeyAdditionalParams *p_FmPcdModifyCcKeyAdditionalParams, ++ t_FmPcdCcNode *p_CcNode, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcdCcNode *p_FmPcdCcNodeTmp; ++ t_Handle h_OrigAd = NULL; ++ ++ p_FmPcdCcNodeTmp = (t_FmPcdCcNode*)XX_Malloc(sizeof(t_FmPcdCcNode)); ++ if (!p_FmPcdCcNodeTmp) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_FmPcdCcNodeTmp")); ++ return NULL; ++ } ++ memset(p_FmPcdCcNodeTmp, 0, sizeof(t_FmPcdCcNode)); ++ ++ p_FmPcdCcNodeTmp->numOfKeys = p_FmPcdModifyCcKeyAdditionalParams->numOfKeys; ++ p_FmPcdCcNodeTmp->h_KeysMatchTable = ++ p_FmPcdModifyCcKeyAdditionalParams->p_KeysMatchTableNew; ++ p_FmPcdCcNodeTmp->h_AdTable = ++ p_FmPcdModifyCcKeyAdditionalParams->p_AdTableNew; ++ ++ p_FmPcdCcNodeTmp->lclMask = p_CcNode->lclMask; ++ p_FmPcdCcNodeTmp->parseCode = p_CcNode->parseCode; ++ p_FmPcdCcNodeTmp->offset = p_CcNode->offset; ++ p_FmPcdCcNodeTmp->prsArrayOffset = p_CcNode->prsArrayOffset; ++ p_FmPcdCcNodeTmp->ctrlFlow = p_CcNode->ctrlFlow; ++ p_FmPcdCcNodeTmp->ccKeySizeAccExtraction = p_CcNode->ccKeySizeAccExtraction; ++ p_FmPcdCcNodeTmp->sizeOfExtraction = p_CcNode->sizeOfExtraction; ++ p_FmPcdCcNodeTmp->glblMaskSize = p_CcNode->glblMaskSize; ++ p_FmPcdCcNodeTmp->p_GlblMask = p_CcNode->p_GlblMask; ++ ++ if (p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_CC) ++ { ++ if (p_FmPcdCcNextEngineParams->h_Manip) ++ { ++ h_OrigAd = p_CcNode->h_Ad; ++ if (AllocAndFillAdForContLookupManip( ++ p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode) ++ != E_OK) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ XX_Free(p_FmPcdCcNodeTmp); ++ return NULL; ++ } ++ } ++ FillAdOfTypeContLookup(h_Ad, NULL, p_CcNode->h_FmPcd, p_FmPcdCcNodeTmp, ++ h_OrigAd ? NULL : p_FmPcdCcNextEngineParams->h_Manip, NULL); ++ } ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_FR) ++ && (p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic)) ++ { ++ FillAdOfTypeContLookup( ++ h_Ad, NULL, p_CcNode->h_FmPcd, p_FmPcdCcNodeTmp, ++ p_FmPcdCcNextEngineParams->h_Manip, ++ p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic); ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ XX_Free(p_FmPcdCcNodeTmp); ++ ++ return E_OK; ++} ++ ++static t_Error DynamicChangeHc( ++ t_Handle h_FmPcd, t_List *h_OldPointersLst, t_List *h_NewPointersLst, ++ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalParams, ++ bool useShadowStructs) ++{ ++ t_List *p_PosOld, *p_PosNew; ++ uint32_t oldAdAddrOffset, newAdAddrOffset; ++ uint16_t i = 0; ++ t_Error err = E_OK; ++ uint8_t numOfModifiedPtr; ++ ++ ASSERT_COND(h_FmPcd); ++ ASSERT_COND(h_OldPointersLst); ++ ASSERT_COND(h_NewPointersLst); ++ ++ numOfModifiedPtr = (uint8_t)LIST_NumOfObjs(h_OldPointersLst); ++ ++ if (numOfModifiedPtr) ++ { ++ p_PosNew = LIST_FIRST(h_NewPointersLst); ++ p_PosOld = LIST_FIRST(h_OldPointersLst); ++ ++ /* Retrieve address of new AD */ ++ newAdAddrOffset = FmPcdCcGetNodeAddrOffsetFromNodeInfo(h_FmPcd, ++ p_PosNew); ++ if (newAdAddrOffset == (uint32_t)ILLEGAL_BASE) ++ { ++ ReleaseModifiedDataStructure(h_FmPcd, h_OldPointersLst, ++ h_NewPointersLst, ++ p_AdditionalParams, useShadowStructs); ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("New AD address")); ++ } ++ ++ for (i = 0; i < numOfModifiedPtr; i++) ++ { ++ /* Retrieve address of current AD */ ++ oldAdAddrOffset = FmPcdCcGetNodeAddrOffsetFromNodeInfo(h_FmPcd, ++ p_PosOld); ++ if (oldAdAddrOffset == (uint32_t)ILLEGAL_BASE) ++ { ++ ReleaseModifiedDataStructure(h_FmPcd, h_OldPointersLst, ++ h_NewPointersLst, ++ p_AdditionalParams, ++ useShadowStructs); ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Old AD address")); ++ } ++ ++ /* Invoke host command to copy from new AD to old AD */ ++ err = FmHcPcdCcDoDynamicChange(((t_FmPcd *)h_FmPcd)->h_Hc, ++ oldAdAddrOffset, newAdAddrOffset); ++ if (err) ++ { ++ ReleaseModifiedDataStructure(h_FmPcd, h_OldPointersLst, ++ h_NewPointersLst, ++ p_AdditionalParams, ++ useShadowStructs); ++ RETURN_ERROR( ++ MAJOR, ++ err, ++ ("For part of nodes changes are done - situation is danger")); ++ } ++ ++ p_PosOld = LIST_NEXT(p_PosOld); ++ } ++ } ++ return E_OK; ++} ++ ++static t_Error DoDynamicChange( ++ t_Handle h_FmPcd, t_List *h_OldPointersLst, t_List *h_NewPointersLst, ++ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalParams, ++ bool useShadowStructs) ++{ ++ t_FmPcdCcNode *p_CcNode = ++ (t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode); ++ t_List *p_PosNew; ++ t_CcNodeInformation *p_CcNodeInfo; ++ t_FmPcdCcNextEngineParams nextEngineParams; ++ t_Handle h_Ad; ++ uint32_t keySize; ++ t_Error err = E_OK; ++ uint8_t numOfModifiedPtr; ++ ++ ASSERT_COND(h_FmPcd); ++ ++ memset(&nextEngineParams, 0, sizeof(t_FmPcdCcNextEngineParams)); ++ ++ numOfModifiedPtr = (uint8_t)LIST_NumOfObjs(h_OldPointersLst); ++ ++ if (numOfModifiedPtr) ++ { ++ ++ p_PosNew = LIST_FIRST(h_NewPointersLst); ++ ++ /* Invoke host-command to copy from the new Ad to existing Ads */ ++ err = DynamicChangeHc(h_FmPcd, h_OldPointersLst, h_NewPointersLst, ++ p_AdditionalParams, useShadowStructs); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (useShadowStructs) ++ { ++ /* When the host-command above has ended, the old structures are 'free'and we can update ++ them by copying from the new shadow structures. */ ++ if (p_CcNode->lclMask) ++ keySize = (uint32_t)(2 * p_CcNode->ccKeySizeAccExtraction); ++ else ++ keySize = p_CcNode->ccKeySizeAccExtraction; ++ ++ IO2IOCpy32(p_AdditionalParams->p_KeysMatchTableOld, ++ p_AdditionalParams->p_KeysMatchTableNew, ++ p_CcNode->maxNumOfKeys * keySize * sizeof(uint8_t)); ++ ++ IO2IOCpy32( ++ p_AdditionalParams->p_AdTableOld, ++ p_AdditionalParams->p_AdTableNew, ++ (uint32_t)((p_CcNode->maxNumOfKeys + 1) ++ * FM_PCD_CC_AD_ENTRY_SIZE)); ++ ++ /* Retrieve the address of the allocated Ad */ ++ p_CcNodeInfo = CC_NODE_F_OBJECT(p_PosNew); ++ h_Ad = p_CcNodeInfo->h_CcNode; ++ ++ /* Build a new Ad that holds the old (now updated) structures */ ++ p_AdditionalParams->p_KeysMatchTableNew = ++ p_AdditionalParams->p_KeysMatchTableOld; ++ p_AdditionalParams->p_AdTableNew = p_AdditionalParams->p_AdTableOld; ++ ++ nextEngineParams.nextEngine = e_FM_PCD_CC; ++ nextEngineParams.params.ccParams.h_CcNode = (t_Handle)p_CcNode; ++ ++ BuildNewAd(h_Ad, p_AdditionalParams, p_CcNode, &nextEngineParams); ++ ++ /* HC to copy from the new Ad (old updated structures) to current Ad (uses shadow structures) */ ++ err = DynamicChangeHc(h_FmPcd, h_OldPointersLst, h_NewPointersLst, ++ p_AdditionalParams, useShadowStructs); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ ++ err = ReleaseModifiedDataStructure(h_FmPcd, h_OldPointersLst, ++ h_NewPointersLst, ++ p_AdditionalParams, useShadowStructs); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++#ifdef FM_CAPWAP_SUPPORT ++static bool IsCapwapApplSpecific(t_Handle h_Node) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_Node; ++ bool isManipForCapwapApplSpecificBuild = FALSE; ++ int i = 0; ++ ++ ASSERT_COND(h_Node); ++ /* assumption that this function called only for INDEXED_FLOW_ID - so no miss*/ ++ for (i = 0; i < p_CcNode->numOfKeys; i++) ++ { ++ if ( p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip && ++ FmPcdManipIsCapwapApplSpecific(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip)) ++ { ++ isManipForCapwapApplSpecificBuild = TRUE; ++ break; ++ } ++ } ++ return isManipForCapwapApplSpecificBuild; ++ ++} ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++static t_Error CcUpdateParam( ++ t_Handle h_FmPcd, t_Handle h_PcdParams, t_Handle h_FmPort, ++ t_FmPcdCcKeyAndNextEngineParams *p_CcKeyAndNextEngineParams, ++ uint16_t numOfEntries, t_Handle h_Ad, bool validate, uint16_t level, ++ t_Handle h_FmTree, bool modify) ++{ ++ t_FmPcdCcNode *p_CcNode; ++ t_Error err; ++ uint16_t tmp = 0; ++ int i = 0; ++ t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_FmTree; ++ ++ level++; ++ ++ if (p_CcTree->h_IpReassemblyManip) ++ { ++ err = FmPcdManipUpdate(h_FmPcd, h_PcdParams, h_FmPort, ++ p_CcTree->h_IpReassemblyManip, NULL, validate, ++ level, h_FmTree, modify); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ if (p_CcTree->h_CapwapReassemblyManip) ++ { ++ err = FmPcdManipUpdate(h_FmPcd, h_PcdParams, h_FmPort, ++ p_CcTree->h_CapwapReassemblyManip, NULL, validate, ++ level, h_FmTree, modify); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ if (numOfEntries) ++ { ++ for (i = 0; i < numOfEntries; i++) ++ { ++ if (i == 0) ++ h_Ad = PTR_MOVE(h_Ad, i*FM_PCD_CC_AD_ENTRY_SIZE); ++ else ++ h_Ad = PTR_MOVE(h_Ad, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ if (p_CcKeyAndNextEngineParams[i].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ { ++ p_CcNode = ++ p_CcKeyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode; ++ ASSERT_COND(p_CcNode); ++ ++ if (p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip) ++ { ++ err = ++ FmPcdManipUpdate( ++ h_FmPcd, ++ NULL, ++ h_FmPort, ++ p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip, ++ h_Ad, validate, level, h_FmTree, modify); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ if (p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine ++ != e_FM_PCD_INVALID) ++ tmp = (uint8_t)(p_CcNode->numOfKeys + 1); ++ else ++ tmp = p_CcNode->numOfKeys; ++ ++ err = CcUpdateParam(h_FmPcd, h_PcdParams, h_FmPort, ++ p_CcNode->keyAndNextEngineParams, tmp, ++ p_CcNode->h_AdTable, validate, level, ++ h_FmTree, modify); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ else ++ { ++ if (p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip) ++ { ++ err = ++ FmPcdManipUpdate( ++ h_FmPcd, ++ NULL, ++ h_FmPort, ++ p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip, ++ h_Ad, validate, level, h_FmTree, modify); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ } ++ } ++ ++ return E_OK; ++} ++ ++static ccPrivateInfo_t IcDefineCode(t_FmPcdCcNodeParams *p_CcNodeParam) ++{ ++ switch (p_CcNodeParam->extractCcParams.extractNonHdr.action) ++ { ++ case (e_FM_PCD_ACTION_EXACT_MATCH): ++ switch (p_CcNodeParam->extractCcParams.extractNonHdr.src) ++ { ++ case (e_FM_PCD_EXTRACT_FROM_KEY): ++ return CC_PRIVATE_INFO_IC_KEY_EXACT_MATCH; ++ case (e_FM_PCD_EXTRACT_FROM_HASH): ++ return CC_PRIVATE_INFO_IC_HASH_EXACT_MATCH; ++ default: ++ return CC_PRIVATE_INFO_NONE; ++ } ++ ++ case (e_FM_PCD_ACTION_INDEXED_LOOKUP): ++ switch (p_CcNodeParam->extractCcParams.extractNonHdr.src) ++ { ++ case (e_FM_PCD_EXTRACT_FROM_HASH): ++ return CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP; ++ case (e_FM_PCD_EXTRACT_FROM_FLOW_ID): ++ return CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP; ++ default: ++ return CC_PRIVATE_INFO_NONE; ++ } ++ ++ default: ++ break; ++ } ++ ++ return CC_PRIVATE_INFO_NONE; ++} ++ ++static t_CcNodeInformation * DequeueAdditionalInfoFromRelevantLst( ++ t_List *p_List) ++{ ++ t_CcNodeInformation *p_CcNodeInfo = NULL; ++ ++ if (!LIST_IsEmpty(p_List)) ++ { ++ p_CcNodeInfo = CC_NODE_F_OBJECT(p_List->p_Next); ++ LIST_DelAndInit(&p_CcNodeInfo->node); ++ } ++ ++ return p_CcNodeInfo; ++} ++ ++void ReleaseLst(t_List *p_List) ++{ ++ t_CcNodeInformation *p_CcNodeInfo = NULL; ++ ++ if (!LIST_IsEmpty(p_List)) ++ { ++ p_CcNodeInfo = DequeueAdditionalInfoFromRelevantLst(p_List); ++ while (p_CcNodeInfo) ++ { ++ XX_Free(p_CcNodeInfo); ++ p_CcNodeInfo = DequeueAdditionalInfoFromRelevantLst(p_List); ++ } ++ } ++ ++ LIST_Del(p_List); ++} ++ ++static void DeleteNode(t_FmPcdCcNode *p_CcNode) ++{ ++ uint32_t i; ++ ++ if (!p_CcNode) ++ return; ++ ++ if (p_CcNode->p_GlblMask) ++ { ++ XX_Free(p_CcNode->p_GlblMask); ++ p_CcNode->p_GlblMask = NULL; ++ } ++ ++ if (p_CcNode->h_KeysMatchTable) ++ { ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), ++ p_CcNode->h_KeysMatchTable); ++ p_CcNode->h_KeysMatchTable = NULL; ++ } ++ ++ if (p_CcNode->h_AdTable) ++ { ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), ++ p_CcNode->h_AdTable); ++ p_CcNode->h_AdTable = NULL; ++ } ++ ++ if (p_CcNode->h_Ad) ++ { ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), ++ p_CcNode->h_Ad); ++ p_CcNode->h_Ad = NULL; ++ p_CcNode->h_TmpAd = NULL; ++ } ++ ++ if (p_CcNode->h_StatsFLRs) ++ { ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), ++ p_CcNode->h_StatsFLRs); ++ p_CcNode->h_StatsFLRs = NULL; ++ } ++ ++ if (p_CcNode->h_Spinlock) ++ { ++ XX_FreeSpinlock(p_CcNode->h_Spinlock); ++ p_CcNode->h_Spinlock = NULL; ++ } ++ ++ /* Restore the original counters pointer instead of the mutual pointer (mutual to all hash buckets) */ ++ if (p_CcNode->isHashBucket ++ && (p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_NONE)) ++ p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].p_StatsObj->h_StatsCounters = ++ p_CcNode->h_PrivMissStatsCounters; ++ ++ /* Releasing all currently used statistics objects, including 'miss' entry */ ++ for (i = 0; i < p_CcNode->numOfKeys + 1; i++) ++ if (p_CcNode->keyAndNextEngineParams[i].p_StatsObj) ++ PutStatsObj(p_CcNode, ++ p_CcNode->keyAndNextEngineParams[i].p_StatsObj); ++ ++ if (!LIST_IsEmpty(&p_CcNode->availableStatsLst)) ++ { ++ t_Handle h_FmMuram = FmPcdGetMuramHandle(p_CcNode->h_FmPcd); ++ ASSERT_COND(h_FmMuram); ++ ++ FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram); ++ } ++ ++ LIST_Del(&p_CcNode->availableStatsLst); ++ ++ ReleaseLst(&p_CcNode->ccPrevNodesLst); ++ ReleaseLst(&p_CcNode->ccTreeIdLst); ++ ReleaseLst(&p_CcNode->ccTreesLst); ++ ++ XX_Free(p_CcNode); ++} ++ ++static void DeleteTree(t_FmPcdCcTree *p_FmPcdTree, t_FmPcd *p_FmPcd) ++{ ++ if (p_FmPcdTree) ++ { ++ if (p_FmPcdTree->ccTreeBaseAddr) ++ { ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_FmPcd), ++ UINT_TO_PTR(p_FmPcdTree->ccTreeBaseAddr)); ++ p_FmPcdTree->ccTreeBaseAddr = 0; ++ } ++ ++ ReleaseLst(&p_FmPcdTree->fmPortsLst); ++ ++ XX_Free(p_FmPcdTree); ++ } ++} ++ ++static void GetCcExtractKeySize(uint8_t parseCodeRealSize, ++ uint8_t *parseCodeCcSize) ++{ ++ if ((parseCodeRealSize > 0) && (parseCodeRealSize < 2)) ++ *parseCodeCcSize = 1; ++ else ++ if (parseCodeRealSize == 2) ++ *parseCodeCcSize = 2; ++ else ++ if ((parseCodeRealSize > 2) && (parseCodeRealSize <= 4)) ++ *parseCodeCcSize = 4; ++ else ++ if ((parseCodeRealSize > 4) && (parseCodeRealSize <= 8)) ++ *parseCodeCcSize = 8; ++ else ++ if ((parseCodeRealSize > 8) && (parseCodeRealSize <= 16)) ++ *parseCodeCcSize = 16; ++ else ++ if ((parseCodeRealSize > 16) ++ && (parseCodeRealSize <= 24)) ++ *parseCodeCcSize = 24; ++ else ++ if ((parseCodeRealSize > 24) ++ && (parseCodeRealSize <= 32)) ++ *parseCodeCcSize = 32; ++ else ++ if ((parseCodeRealSize > 32) ++ && (parseCodeRealSize <= 40)) ++ *parseCodeCcSize = 40; ++ else ++ if ((parseCodeRealSize > 40) ++ && (parseCodeRealSize <= 48)) ++ *parseCodeCcSize = 48; ++ else ++ if ((parseCodeRealSize > 48) ++ && (parseCodeRealSize <= 56)) ++ *parseCodeCcSize = 56; ++ else ++ *parseCodeCcSize = 0; ++} ++ ++static void GetSizeHeaderField(e_NetHeaderType hdr, t_FmPcdFields field, ++ uint8_t *parseCodeRealSize) ++{ ++ switch (hdr) ++ { ++ case (HEADER_TYPE_ETH): ++ switch (field.eth) ++ { ++ case (NET_HEADER_FIELD_ETH_DA): ++ *parseCodeRealSize = 6; ++ break; ++ ++ case (NET_HEADER_FIELD_ETH_SA): ++ *parseCodeRealSize = 6; ++ break; ++ ++ case (NET_HEADER_FIELD_ETH_TYPE): ++ *parseCodeRealSize = 2; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported1")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_PPPoE): ++ switch (field.pppoe) ++ { ++ case (NET_HEADER_FIELD_PPPoE_PID): ++ *parseCodeRealSize = 2; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported1")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_VLAN): ++ switch (field.vlan) ++ { ++ case (NET_HEADER_FIELD_VLAN_TCI): ++ *parseCodeRealSize = 2; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported2")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_MPLS): ++ switch (field.mpls) ++ { ++ case (NET_HEADER_FIELD_MPLS_LABEL_STACK): ++ *parseCodeRealSize = 4; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported3")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_IPv4): ++ switch (field.ipv4) ++ { ++ case (NET_HEADER_FIELD_IPv4_DST_IP): ++ case (NET_HEADER_FIELD_IPv4_SRC_IP): ++ *parseCodeRealSize = 4; ++ break; ++ ++ case (NET_HEADER_FIELD_IPv4_TOS): ++ case (NET_HEADER_FIELD_IPv4_PROTO): ++ *parseCodeRealSize = 1; ++ break; ++ ++ case (NET_HEADER_FIELD_IPv4_DST_IP ++ | NET_HEADER_FIELD_IPv4_SRC_IP): ++ *parseCodeRealSize = 8; ++ break; ++ ++ case (NET_HEADER_FIELD_IPv4_TTL): ++ *parseCodeRealSize = 1; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported4")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_IPv6): ++ switch (field.ipv6) ++ { ++ case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL ++ | NET_HEADER_FIELD_IPv6_TC): ++ *parseCodeRealSize = 4; ++ break; ++ ++ case (NET_HEADER_FIELD_IPv6_NEXT_HDR): ++ case (NET_HEADER_FIELD_IPv6_HOP_LIMIT): ++ *parseCodeRealSize = 1; ++ break; ++ ++ case (NET_HEADER_FIELD_IPv6_DST_IP): ++ case (NET_HEADER_FIELD_IPv6_SRC_IP): ++ *parseCodeRealSize = 16; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported5")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_IP): ++ switch (field.ip) ++ { ++ case (NET_HEADER_FIELD_IP_DSCP): ++ case (NET_HEADER_FIELD_IP_PROTO): ++ *parseCodeRealSize = 1; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported5")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_GRE): ++ switch (field.gre) ++ { ++ case (NET_HEADER_FIELD_GRE_TYPE): ++ *parseCodeRealSize = 2; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported6")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_MINENCAP): ++ switch (field.minencap) ++ { ++ case (NET_HEADER_FIELD_MINENCAP_TYPE): ++ *parseCodeRealSize = 1; ++ break; ++ ++ case (NET_HEADER_FIELD_MINENCAP_DST_IP): ++ case (NET_HEADER_FIELD_MINENCAP_SRC_IP): ++ *parseCodeRealSize = 4; ++ break; ++ ++ case (NET_HEADER_FIELD_MINENCAP_SRC_IP ++ | NET_HEADER_FIELD_MINENCAP_DST_IP): ++ *parseCodeRealSize = 8; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported7")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_TCP): ++ switch (field.tcp) ++ { ++ case (NET_HEADER_FIELD_TCP_PORT_SRC): ++ case (NET_HEADER_FIELD_TCP_PORT_DST): ++ *parseCodeRealSize = 2; ++ break; ++ ++ case (NET_HEADER_FIELD_TCP_PORT_SRC ++ | NET_HEADER_FIELD_TCP_PORT_DST): ++ *parseCodeRealSize = 4; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported8")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ case (HEADER_TYPE_UDP): ++ switch (field.udp) ++ { ++ case (NET_HEADER_FIELD_UDP_PORT_SRC): ++ case (NET_HEADER_FIELD_UDP_PORT_DST): ++ *parseCodeRealSize = 2; ++ break; ++ ++ case (NET_HEADER_FIELD_UDP_PORT_SRC ++ | NET_HEADER_FIELD_UDP_PORT_DST): ++ *parseCodeRealSize = 4; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported9")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported10")); ++ *parseCodeRealSize = CC_SIZE_ILLEGAL; ++ break; ++ } ++} ++ ++t_Error ValidateNextEngineParams( ++ t_Handle h_FmPcd, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams, ++ e_FmPcdCcStatsMode statsMode) ++{ ++ uint16_t absoluteProfileId; ++ t_Error err = E_OK; ++ uint8_t relativeSchemeId; ++ ++ if ((statsMode == e_FM_PCD_CC_STATS_MODE_NONE) ++ && (p_FmPcdCcNextEngineParams->statisticsEn)) ++ RETURN_ERROR( ++ MAJOR, ++ E_CONFLICT, ++ ("Statistics are requested for a key, but statistics mode was set" ++ "to 'NONE' upon initialization")); ++ ++ switch (p_FmPcdCcNextEngineParams->nextEngine) ++ { ++ case (e_FM_PCD_INVALID): ++ err = E_NOT_SUPPORTED; ++ break; ++ ++ case (e_FM_PCD_DONE): ++ if ((p_FmPcdCcNextEngineParams->params.enqueueParams.action ++ == e_FM_PCD_ENQ_FRAME) ++ && p_FmPcdCcNextEngineParams->params.enqueueParams.overrideFqid) ++ { ++ if (!p_FmPcdCcNextEngineParams->params.enqueueParams.newFqid) ++ RETURN_ERROR( ++ MAJOR, ++ E_CONFLICT, ++ ("When overrideFqid is set, newFqid must not be zero")); ++ if (p_FmPcdCcNextEngineParams->params.enqueueParams.newFqid ++ & ~0x00FFFFFF) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("fqidForCtrlFlow must be between 1 and 2^24-1")); ++ } ++ break; ++ ++ case (e_FM_PCD_KG): ++ relativeSchemeId = ++ FmPcdKgGetRelativeSchemeId( ++ h_FmPcd, ++ FmPcdKgGetSchemeId( ++ p_FmPcdCcNextEngineParams->params.kgParams.h_DirectScheme)); ++ if (relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ if (!FmPcdKgIsSchemeValidSw( ++ p_FmPcdCcNextEngineParams->params.kgParams.h_DirectScheme)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("not valid schemeIndex in KG next engine param")); ++ if (!KgIsSchemeAlwaysDirect(h_FmPcd, relativeSchemeId)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("CC Node may point only to a scheme that is always direct.")); ++ break; ++ ++ case (e_FM_PCD_PLCR): ++ if (p_FmPcdCcNextEngineParams->params.plcrParams.overrideParams) ++ { ++ /* if private policer profile, it may be uninitialized yet, therefore no checks are done at this stage */ ++ if (p_FmPcdCcNextEngineParams->params.plcrParams.sharedProfile) ++ { ++ err = ++ FmPcdPlcrGetAbsoluteIdByProfileParams( ++ h_FmPcd, ++ e_FM_PCD_PLCR_SHARED, ++ NULL, ++ p_FmPcdCcNextEngineParams->params.plcrParams.newRelativeProfileId, ++ &absoluteProfileId); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ++ ("Shared profile offset is out of range")); ++ if (!FmPcdPlcrIsProfileValid(h_FmPcd, absoluteProfileId)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("Invalid profile")); ++ } ++ } ++ break; ++ ++ case (e_FM_PCD_HASH): ++ p_FmPcdCcNextEngineParams->nextEngine = e_FM_PCD_CC; ++ case (e_FM_PCD_CC): ++ if (!p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode) ++ RETURN_ERROR(MAJOR, E_NULL_POINTER, ++ ("handler to next Node is NULL")); ++ break; ++ ++#if (DPAA_VERSION >= 11) ++ case (e_FM_PCD_FR): ++ if (!p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic) ++ err = E_NOT_SUPPORTED; ++ break; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("Next engine is not correct")); ++ } ++ ++ ++ return err; ++} ++ ++static uint8_t GetGenParseCode(e_FmPcdExtractFrom src, ++ uint32_t offset, bool glblMask, ++ uint8_t *parseArrayOffset, bool fromIc, ++ ccPrivateInfo_t icCode) ++{ ++ if (!fromIc) ++ { ++ switch (src) ++ { ++ case (e_FM_PCD_EXTRACT_FROM_FRAME_START): ++ if (glblMask) ++ return CC_PC_GENERIC_WITH_MASK; ++ else ++ return CC_PC_GENERIC_WITHOUT_MASK; ++ ++ case (e_FM_PCD_EXTRACT_FROM_CURR_END_OF_PARSE): ++ *parseArrayOffset = CC_PC_PR_NEXT_HEADER_OFFSET; ++ if (offset) ++ return CC_PR_OFFSET; ++ else ++ return CC_PR_WITHOUT_OFFSET; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 'extract from' src")); ++ return CC_PC_ILLEGAL; ++ } ++ } ++ else ++ { ++ switch (icCode) ++ { ++ case (CC_PRIVATE_INFO_IC_KEY_EXACT_MATCH): ++ *parseArrayOffset = 0x50; ++ return CC_PC_GENERIC_IC_GMASK; ++ ++ case (CC_PRIVATE_INFO_IC_HASH_EXACT_MATCH): ++ *parseArrayOffset = 0x48; ++ return CC_PC_GENERIC_IC_GMASK; ++ ++ case (CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP): ++ *parseArrayOffset = 0x48; ++ return CC_PC_GENERIC_IC_HASH_INDEXED; ++ ++ case (CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP): ++ *parseArrayOffset = 0x16; ++ return CC_PC_GENERIC_IC_HASH_INDEXED; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 'extract from' src")); ++ break; ++ } ++ } ++ ++ return CC_PC_ILLEGAL; ++} ++ ++static uint8_t GetFullFieldParseCode(e_NetHeaderType hdr, e_FmPcdHdrIndex index, ++ t_FmPcdFields field) ++{ ++ switch (hdr) ++ { ++ case (HEADER_TYPE_NONE): ++ ASSERT_COND(FALSE); ++ return CC_PC_ILLEGAL; ++ ++ case (HEADER_TYPE_ETH): ++ switch (field.eth) ++ { ++ case (NET_HEADER_FIELD_ETH_DA): ++ return CC_PC_FF_MACDST; ++ case (NET_HEADER_FIELD_ETH_SA): ++ return CC_PC_FF_MACSRC; ++ case (NET_HEADER_FIELD_ETH_TYPE): ++ return CC_PC_FF_ETYPE; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_VLAN): ++ switch (field.vlan) ++ { ++ case (NET_HEADER_FIELD_VLAN_TCI): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) ++ || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_TCI1; ++ if (index == e_FM_PCD_HDR_INDEX_LAST) ++ return CC_PC_FF_TCI2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_MPLS): ++ switch (field.mpls) ++ { ++ case (NET_HEADER_FIELD_MPLS_LABEL_STACK): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) ++ || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_MPLS1; ++ if (index == e_FM_PCD_HDR_INDEX_LAST) ++ return CC_PC_FF_MPLS_LAST; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS index")); ++ return CC_PC_ILLEGAL; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_IPv4): ++ switch (field.ipv4) ++ { ++ case (NET_HEADER_FIELD_IPv4_DST_IP): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) ++ || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPV4DST1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPV4DST2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index")); ++ return CC_PC_ILLEGAL; ++ case (NET_HEADER_FIELD_IPv4_TOS): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) ++ || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPV4IPTOS_TC1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPV4IPTOS_TC2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index")); ++ return CC_PC_ILLEGAL; ++ case (NET_HEADER_FIELD_IPv4_PROTO): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) ++ || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPV4PTYPE1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPV4PTYPE2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index")); ++ return CC_PC_ILLEGAL; ++ case (NET_HEADER_FIELD_IPv4_SRC_IP): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) ++ || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPV4SRC1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPV4SRC2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index")); ++ return CC_PC_ILLEGAL; ++ case (NET_HEADER_FIELD_IPv4_SRC_IP ++ | NET_HEADER_FIELD_IPv4_DST_IP): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) ++ || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPV4SRC1_IPV4DST1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPV4SRC2_IPV4DST2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index")); ++ return CC_PC_ILLEGAL; ++ case (NET_HEADER_FIELD_IPv4_TTL): ++ return CC_PC_FF_IPV4TTL; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_IPv6): ++ switch (field.ipv6) ++ { ++ case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL ++ | NET_HEADER_FIELD_IPv6_TC): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) ++ || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index")); ++ return CC_PC_ILLEGAL; ++ ++ case (NET_HEADER_FIELD_IPv6_NEXT_HDR): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) ++ || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPV6PTYPE1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPV6PTYPE2; ++ if (index == e_FM_PCD_HDR_INDEX_LAST) ++ return CC_PC_FF_IPPID; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index")); ++ return CC_PC_ILLEGAL; ++ ++ case (NET_HEADER_FIELD_IPv6_DST_IP): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) ++ || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPV6DST1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPV6DST2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index")); ++ return CC_PC_ILLEGAL; ++ ++ case (NET_HEADER_FIELD_IPv6_SRC_IP): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) ++ || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPV6SRC1; ++ if (index == e_FM_PCD_HDR_INDEX_2) ++ return CC_PC_FF_IPV6SRC2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index")); ++ return CC_PC_ILLEGAL; ++ ++ case (NET_HEADER_FIELD_IPv6_HOP_LIMIT): ++ return CC_PC_FF_IPV6HOP_LIMIT; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_IP): ++ switch (field.ip) ++ { ++ case (NET_HEADER_FIELD_IP_DSCP): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) ++ || (index == e_FM_PCD_HDR_INDEX_1)) ++ return CC_PC_FF_IPDSCP; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP index")); ++ return CC_PC_ILLEGAL; ++ ++ case (NET_HEADER_FIELD_IP_PROTO): ++ if (index == e_FM_PCD_HDR_INDEX_LAST) ++ return CC_PC_FF_IPPID; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP index")); ++ return CC_PC_ILLEGAL; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_GRE): ++ switch (field.gre) ++ { ++ case (NET_HEADER_FIELD_GRE_TYPE): ++ return CC_PC_FF_GREPTYPE; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_MINENCAP): ++ switch (field.minencap) ++ { ++ case (NET_HEADER_FIELD_MINENCAP_TYPE): ++ return CC_PC_FF_MINENCAP_PTYPE; ++ ++ case (NET_HEADER_FIELD_MINENCAP_DST_IP): ++ return CC_PC_FF_MINENCAP_IPDST; ++ ++ case (NET_HEADER_FIELD_MINENCAP_SRC_IP): ++ return CC_PC_FF_MINENCAP_IPSRC; ++ ++ case (NET_HEADER_FIELD_MINENCAP_SRC_IP ++ | NET_HEADER_FIELD_MINENCAP_DST_IP): ++ return CC_PC_FF_MINENCAP_IPSRC_IPDST; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_TCP): ++ switch (field.tcp) ++ { ++ case (NET_HEADER_FIELD_TCP_PORT_SRC): ++ return CC_PC_FF_L4PSRC; ++ ++ case (NET_HEADER_FIELD_TCP_PORT_DST): ++ return CC_PC_FF_L4PDST; ++ ++ case (NET_HEADER_FIELD_TCP_PORT_DST ++ | NET_HEADER_FIELD_TCP_PORT_SRC): ++ return CC_PC_FF_L4PSRC_L4PDST; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_PPPoE): ++ switch (field.pppoe) ++ { ++ case (NET_HEADER_FIELD_PPPoE_PID): ++ return CC_PC_FF_PPPPID; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ case (HEADER_TYPE_UDP): ++ switch (field.udp) ++ { ++ case (NET_HEADER_FIELD_UDP_PORT_SRC): ++ return CC_PC_FF_L4PSRC; ++ ++ case (NET_HEADER_FIELD_UDP_PORT_DST): ++ return CC_PC_FF_L4PDST; ++ ++ case (NET_HEADER_FIELD_UDP_PORT_DST ++ | NET_HEADER_FIELD_UDP_PORT_SRC): ++ return CC_PC_FF_L4PSRC_L4PDST; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++} ++ ++static uint8_t GetPrParseCode(e_NetHeaderType hdr, e_FmPcdHdrIndex hdrIndex, ++ uint32_t offset, bool glblMask, ++ uint8_t *parseArrayOffset) ++{ ++ bool offsetRelevant = FALSE; ++ ++ if (offset) ++ offsetRelevant = TRUE; ++ ++ switch (hdr) ++ { ++ case (HEADER_TYPE_NONE): ++ ASSERT_COND(FALSE); ++ return CC_PC_ILLEGAL; ++ ++ case (HEADER_TYPE_ETH): ++ *parseArrayOffset = (uint8_t)CC_PC_PR_ETH_OFFSET; ++ break; ++ ++ case (HEADER_TYPE_USER_DEFINED_SHIM1): ++ if (offset || glblMask) ++ *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM1_OFFSET; ++ else ++ return CC_PC_PR_SHIM1; ++ break; ++ ++ case (HEADER_TYPE_USER_DEFINED_SHIM2): ++ if (offset || glblMask) ++ *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM2_OFFSET; ++ else ++ return CC_PC_PR_SHIM2; ++ break; ++ ++ case (HEADER_TYPE_LLC_SNAP): ++ *parseArrayOffset = CC_PC_PR_USER_LLC_SNAP_OFFSET; ++ break; ++ ++ case (HEADER_TYPE_PPPoE): ++ *parseArrayOffset = CC_PC_PR_PPPOE_OFFSET; ++ break; ++ ++ case (HEADER_TYPE_MPLS): ++ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) ++ || (hdrIndex == e_FM_PCD_HDR_INDEX_1)) ++ *parseArrayOffset = CC_PC_PR_MPLS1_OFFSET; ++ else ++ if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST) ++ *parseArrayOffset = CC_PC_PR_MPLS_LAST_OFFSET; ++ else ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS header index")); ++ return CC_PC_ILLEGAL; ++ } ++ break; ++ ++ case (HEADER_TYPE_IPv4): ++ case (HEADER_TYPE_IPv6): ++ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) ++ || (hdrIndex == e_FM_PCD_HDR_INDEX_1)) ++ *parseArrayOffset = CC_PC_PR_IP1_OFFSET; ++ else ++ if (hdrIndex == e_FM_PCD_HDR_INDEX_2) ++ *parseArrayOffset = CC_PC_PR_IP_LAST_OFFSET; ++ else ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP header index")); ++ return CC_PC_ILLEGAL; ++ } ++ break; ++ ++ case (HEADER_TYPE_MINENCAP): ++ *parseArrayOffset = CC_PC_PR_MINENC_OFFSET; ++ break; ++ ++ case (HEADER_TYPE_GRE): ++ *parseArrayOffset = CC_PC_PR_GRE_OFFSET; ++ break; ++ ++ case (HEADER_TYPE_TCP): ++ case (HEADER_TYPE_UDP): ++ case (HEADER_TYPE_IPSEC_AH): ++ case (HEADER_TYPE_IPSEC_ESP): ++ case (HEADER_TYPE_DCCP): ++ case (HEADER_TYPE_SCTP): ++ *parseArrayOffset = CC_PC_PR_L4_OFFSET; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP header for this type of operation")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ if (offsetRelevant) ++ return CC_PR_OFFSET; ++ else ++ return CC_PR_WITHOUT_OFFSET; ++} ++ ++static uint8_t GetFieldParseCode(e_NetHeaderType hdr, t_FmPcdFields field, ++ uint32_t offset, uint8_t *parseArrayOffset, ++ e_FmPcdHdrIndex hdrIndex) ++{ ++ bool offsetRelevant = FALSE; ++ ++ if (offset) ++ offsetRelevant = TRUE; ++ ++ switch (hdr) ++ { ++ case (HEADER_TYPE_NONE): ++ ASSERT_COND(FALSE); ++ break; ++ case (HEADER_TYPE_ETH): ++ switch (field.eth) ++ { ++ case (NET_HEADER_FIELD_ETH_TYPE): ++ *parseArrayOffset = CC_PC_PR_ETYPE_LAST_OFFSET; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ break; ++ ++ case (HEADER_TYPE_VLAN): ++ switch (field.vlan) ++ { ++ case (NET_HEADER_FIELD_VLAN_TCI): ++ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) ++ || (hdrIndex == e_FM_PCD_HDR_INDEX_1)) ++ *parseArrayOffset = CC_PC_PR_VLAN1_OFFSET; ++ else ++ if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST) ++ *parseArrayOffset = CC_PC_PR_VLAN2_OFFSET; ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return CC_PC_ILLEGAL; ++ } ++ break; ++ ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal header ")); ++ return CC_PC_ILLEGAL; ++ } ++ ++ if (offsetRelevant) ++ return CC_PR_OFFSET; ++ else ++ return CC_PR_WITHOUT_OFFSET; ++} ++ ++static void FillAdOfTypeResult(t_Handle h_Ad, ++ t_FmPcdCcStatsParams *p_FmPcdCcStatsParams, ++ t_FmPcd *p_FmPcd, ++ t_FmPcdCcNextEngineParams *p_CcNextEngineParams) ++{ ++ t_AdOfTypeResult *p_AdResult = (t_AdOfTypeResult *)h_Ad; ++ t_Handle h_TmpAd; ++ uint32_t tmp = 0, tmpNia = 0; ++ uint16_t profileId; ++ t_Handle p_AdNewPtr = NULL; ++ ++ /* There are 3 cases handled in this routine of building a "result" type AD. ++ * Case 1: No Manip. The action descriptor is built within the match table. ++ * Case 2: Manip exists. A new AD is created - p_AdNewPtr. It is initialized ++ * either in the FmPcdManipUpdateAdResultForCc routine or it was already ++ * initialized and returned here. ++ * p_AdResult (within the match table) will be initialized after ++ * this routine returns and point to the existing AD. ++ * Case 3: Manip exists. The action descriptor is built within the match table. ++ * FmPcdManipUpdateAdResultForCc returns a NULL p_AdNewPtr. ++ * ++ * If statistics were enabled and the statistics mode of this node requires ++ * a statistics Ad, it will be placed after the result Ad and before the ++ * manip Ad, if manip Ad exists here. ++ */ ++ ++ /* As default, the "new" ptr is the current one. i.e. the content of the result ++ * AD will be written into the match table itself (case (1))*/ ++ p_AdNewPtr = p_AdResult; ++ ++ /* Initialize an action descriptor, if current statistics mode requires an Ad */ ++ if (p_FmPcdCcStatsParams) ++ { ++ ASSERT_COND(p_FmPcdCcStatsParams->h_StatsAd); ++ ASSERT_COND(p_FmPcdCcStatsParams->h_StatsCounters); ++ ++ /* Swapping addresses between statistics Ad and the current lookup AD addresses */ ++ h_TmpAd = p_FmPcdCcStatsParams->h_StatsAd; ++ p_FmPcdCcStatsParams->h_StatsAd = h_Ad; ++ h_Ad = h_TmpAd; ++ ++ p_AdNewPtr = h_Ad; ++ p_AdResult = h_Ad; ++ ++ /* Init statistics Ad and connect current lookup AD as 'next action' from statistics Ad */ ++ UpdateStatsAd(p_FmPcdCcStatsParams, h_Ad, p_FmPcd->physicalMuramBase); ++ } ++ ++ /* Create manip and return p_AdNewPtr to either a new descriptor or NULL */ ++ if (p_CcNextEngineParams->h_Manip) ++ FmPcdManipUpdateAdResultForCc(p_CcNextEngineParams->h_Manip, ++ p_CcNextEngineParams, h_Ad, &p_AdNewPtr); ++ ++ /* if (p_AdNewPtr = NULL) --> Done. (case (3)) */ ++ if (p_AdNewPtr) ++ { ++ /* case (1) and (2) */ ++ switch (p_CcNextEngineParams->nextEngine) ++ { ++ case (e_FM_PCD_DONE): ++ if (p_CcNextEngineParams->params.enqueueParams.action ++ == e_FM_PCD_ENQ_FRAME) ++ { ++ if (p_CcNextEngineParams->params.enqueueParams.overrideFqid) ++ { ++ tmp = FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE; ++ tmp |= ++ p_CcNextEngineParams->params.enqueueParams.newFqid; ++#if (DPAA_VERSION >= 11) ++ tmp |= ++ (p_CcNextEngineParams->params.enqueueParams.newRelativeStorageProfileId ++ & FM_PCD_AD_RESULT_VSP_MASK) ++ << FM_PCD_AD_RESULT_VSP_SHIFT; ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ else ++ { ++ tmp = FM_PCD_AD_RESULT_DATA_FLOW_TYPE; ++ tmp |= FM_PCD_AD_RESULT_PLCR_DIS; ++ } ++ } ++ ++ if (p_CcNextEngineParams->params.enqueueParams.action ++ == e_FM_PCD_DROP_FRAME) ++ tmpNia |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd); ++ else ++ tmpNia |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd); ++ break; ++ ++ case (e_FM_PCD_KG): ++ if (p_CcNextEngineParams->params.kgParams.overrideFqid) ++ { ++ tmp = FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE; ++ tmp |= p_CcNextEngineParams->params.kgParams.newFqid; ++#if (DPAA_VERSION >= 11) ++ tmp |= ++ (p_CcNextEngineParams->params.kgParams.newRelativeStorageProfileId ++ & FM_PCD_AD_RESULT_VSP_MASK) ++ << FM_PCD_AD_RESULT_VSP_SHIFT; ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ else ++ { ++ tmp = FM_PCD_AD_RESULT_DATA_FLOW_TYPE; ++ tmp |= FM_PCD_AD_RESULT_PLCR_DIS; ++ } ++ tmpNia = NIA_KG_DIRECT; ++ tmpNia |= NIA_ENG_KG; ++ tmpNia |= NIA_KG_CC_EN; ++ tmpNia |= FmPcdKgGetSchemeId( ++ p_CcNextEngineParams->params.kgParams.h_DirectScheme); ++ break; ++ ++ case (e_FM_PCD_PLCR): ++ if (p_CcNextEngineParams->params.plcrParams.overrideParams) ++ { ++ tmp = FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE; ++ ++ /* if private policer profile, it may be uninitialized yet, therefore no checks are done at this stage */ ++ if (p_CcNextEngineParams->params.plcrParams.sharedProfile) ++ { ++ tmpNia |= NIA_PLCR_ABSOLUTE; ++ FmPcdPlcrGetAbsoluteIdByProfileParams( ++ (t_Handle)p_FmPcd, ++ e_FM_PCD_PLCR_SHARED, ++ NULL, ++ p_CcNextEngineParams->params.plcrParams.newRelativeProfileId, ++ &profileId); ++ } ++ else ++ profileId = ++ p_CcNextEngineParams->params.plcrParams.newRelativeProfileId; ++ ++ tmp |= p_CcNextEngineParams->params.plcrParams.newFqid; ++#if (DPAA_VERSION >= 11) ++ tmp |= ++ (p_CcNextEngineParams->params.plcrParams.newRelativeStorageProfileId ++ & FM_PCD_AD_RESULT_VSP_MASK) ++ << FM_PCD_AD_RESULT_VSP_SHIFT; ++#endif /* (DPAA_VERSION >= 11) */ ++ WRITE_UINT32( ++ p_AdResult->plcrProfile, ++ (uint32_t)((uint32_t)profileId << FM_PCD_AD_PROFILEID_FOR_CNTRL_SHIFT)); ++ } ++ else ++ tmp = FM_PCD_AD_RESULT_DATA_FLOW_TYPE; ++ ++ tmpNia |= ++ NIA_ENG_PLCR ++ | p_CcNextEngineParams->params.plcrParams.newRelativeProfileId; ++ break; ++ ++ default: ++ return; ++ }WRITE_UINT32(p_AdResult->fqid, tmp); ++ ++ if (p_CcNextEngineParams->h_Manip) ++ { ++ tmp = GET_UINT32(p_AdResult->plcrProfile); ++ tmp |= (uint32_t)(XX_VirtToPhys(p_AdNewPtr) ++ - (p_FmPcd->physicalMuramBase)) >> 4; ++ WRITE_UINT32(p_AdResult->plcrProfile, tmp); ++ ++ tmpNia |= FM_PCD_AD_RESULT_EXTENDED_MODE; ++ tmpNia |= FM_PCD_AD_RESULT_NADEN; ++ } ++ ++#if (DPAA_VERSION >= 11) ++ tmpNia |= FM_PCD_AD_RESULT_NO_OM_VSPE; ++#endif /* (DPAA_VERSION >= 11) */ ++ WRITE_UINT32(p_AdResult->nia, tmpNia); ++ } ++} ++ ++static t_Error CcUpdateParams(t_Handle h_FmPcd, t_Handle h_PcdParams, ++ t_Handle h_FmPort, t_Handle h_FmTree, ++ bool validate) ++{ ++ t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_FmTree; ++ ++ return CcUpdateParam(h_FmPcd, h_PcdParams, h_FmPort, ++ p_CcTree->keyAndNextEngineParams, ++ p_CcTree->numOfEntries, ++ UINT_TO_PTR(p_CcTree->ccTreeBaseAddr), validate, 0, ++ h_FmTree, FALSE); ++} ++ ++ ++static void ReleaseNewNodeCommonPart( ++ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo) ++{ ++ if (p_AdditionalInfo->p_AdTableNew) ++ FM_MURAM_FreeMem( ++ FmPcdGetMuramHandle( ++ ((t_FmPcdCcNode *)(p_AdditionalInfo->h_CurrentNode))->h_FmPcd), ++ p_AdditionalInfo->p_AdTableNew); ++ ++ if (p_AdditionalInfo->p_KeysMatchTableNew) ++ FM_MURAM_FreeMem( ++ FmPcdGetMuramHandle( ++ ((t_FmPcdCcNode *)(p_AdditionalInfo->h_CurrentNode))->h_FmPcd), ++ p_AdditionalInfo->p_KeysMatchTableNew); ++} ++ ++static t_Error UpdateGblMask(t_FmPcdCcNode *p_CcNode, uint8_t keySize, ++ uint8_t *p_Mask) ++{ ++ uint8_t prvGlblMaskSize = p_CcNode->glblMaskSize; ++ ++ if (p_Mask && !p_CcNode->glblMaskUpdated && (keySize <= 4) ++ && !p_CcNode->lclMask) ++ { ++ if (p_CcNode->parseCode && (p_CcNode->parseCode != CC_PC_FF_TCI1) ++ && (p_CcNode->parseCode != CC_PC_FF_TCI2) ++ && (p_CcNode->parseCode != CC_PC_FF_MPLS1) ++ && (p_CcNode->parseCode != CC_PC_FF_MPLS_LAST) ++ && (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC1) ++ && (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC2) ++ && (p_CcNode->parseCode != CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1) ++ && (p_CcNode->parseCode != CC_PC_FF_IPDSCP) ++ && (p_CcNode->parseCode != CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2)) ++ { ++ p_CcNode->glblMaskSize = 0; ++ p_CcNode->lclMask = TRUE; ++ } ++ else ++ { ++ memcpy(p_CcNode->p_GlblMask, p_Mask, (sizeof(uint8_t)) * keySize); ++ p_CcNode->glblMaskUpdated = TRUE; ++ p_CcNode->glblMaskSize = 4; ++ } ++ } ++ else ++ if (p_Mask && (keySize <= 4) && !p_CcNode->lclMask) ++ { ++ if (memcmp(p_CcNode->p_GlblMask, p_Mask, keySize) != 0) ++ { ++ p_CcNode->lclMask = TRUE; ++ p_CcNode->glblMaskSize = 0; ++ } ++ } ++ else ++ if (!p_Mask && p_CcNode->glblMaskUpdated && (keySize <= 4)) ++ { ++ uint32_t tmpMask = 0xffffffff; ++ if (memcmp(p_CcNode->p_GlblMask, &tmpMask, 4) != 0) ++ { ++ p_CcNode->lclMask = TRUE; ++ p_CcNode->glblMaskSize = 0; ++ } ++ } ++ else ++ if (p_Mask) ++ { ++ p_CcNode->lclMask = TRUE; ++ p_CcNode->glblMaskSize = 0; ++ } ++ ++ /* In static mode (maxNumOfKeys > 0), local mask is supported ++ only is mask support was enabled at initialization */ ++ if (p_CcNode->maxNumOfKeys && (!p_CcNode->maskSupport) && p_CcNode->lclMask) ++ { ++ p_CcNode->lclMask = FALSE; ++ p_CcNode->glblMaskSize = prvGlblMaskSize; ++ return ERROR_CODE(E_NOT_SUPPORTED); ++ } ++ ++ return E_OK; ++} ++ ++static __inline__ t_Handle GetNewAd(t_Handle h_FmPcdCcNodeOrTree, bool isTree) ++{ ++ t_FmPcd *p_FmPcd; ++ t_Handle h_Ad; ++ ++ if (isTree) ++ p_FmPcd = (t_FmPcd *)(((t_FmPcdCcTree *)h_FmPcdCcNodeOrTree)->h_FmPcd); ++ else ++ p_FmPcd = (t_FmPcd *)(((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->h_FmPcd); ++ ++ if ((isTree && p_FmPcd->p_CcShadow) ++ || (!isTree && ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->maxNumOfKeys)) ++ { ++ /* The allocated shadow is divided as follows: ++ 0 . . . 16 . . . ++ --------------------------------------------------- ++ | Shadow | Shadow Keys | Shadow Next | ++ | Ad | Match Table | Engine Table | ++ | (16 bytes) | (maximal size) | (maximal size) | ++ --------------------------------------------------- ++ */ ++ if (!p_FmPcd->p_CcShadow) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("CC Shadow not allocated")); ++ return NULL; ++ } ++ ++ h_Ad = p_FmPcd->p_CcShadow; ++ } ++ else ++ { ++ h_Ad = (t_Handle)FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd), ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!h_Ad) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptor")); ++ return NULL; ++ } ++ } ++ ++ return h_Ad; ++} ++ ++static t_Error BuildNewNodeCommonPart( ++ t_FmPcdCcNode *p_CcNode, int *size, ++ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ ++ if (p_CcNode->lclMask) ++ *size = 2 * p_CcNode->ccKeySizeAccExtraction; ++ else ++ *size = p_CcNode->ccKeySizeAccExtraction; ++ ++ if (p_CcNode->maxNumOfKeys == 0) ++ { ++ p_AdditionalInfo->p_AdTableNew = (t_Handle)FM_MURAM_AllocMem( ++ FmPcdGetMuramHandle(p_FmPcd), ++ (uint32_t)((p_AdditionalInfo->numOfKeys + 1) ++ * FM_PCD_CC_AD_ENTRY_SIZE), ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_AdditionalInfo->p_AdTableNew) ++ RETURN_ERROR( ++ MAJOR, E_NO_MEMORY, ++ ("MURAM allocation for CC node action descriptors table")); ++ ++ p_AdditionalInfo->p_KeysMatchTableNew = (t_Handle)FM_MURAM_AllocMem( ++ FmPcdGetMuramHandle(p_FmPcd), ++ (uint32_t)(*size * sizeof(uint8_t) ++ * (p_AdditionalInfo->numOfKeys + 1)), ++ FM_PCD_CC_KEYS_MATCH_TABLE_ALIGN); ++ if (!p_AdditionalInfo->p_KeysMatchTableNew) ++ { ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), ++ p_AdditionalInfo->p_AdTableNew); ++ p_AdditionalInfo->p_AdTableNew = NULL; ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("MURAM allocation for CC node key match table")); ++ } ++ ++ IOMemSet32( ++ (uint8_t*)p_AdditionalInfo->p_AdTableNew, ++ 0, ++ (uint32_t)((p_AdditionalInfo->numOfKeys + 1) ++ * FM_PCD_CC_AD_ENTRY_SIZE)); ++ IOMemSet32((uint8_t*)p_AdditionalInfo->p_KeysMatchTableNew, 0, ++ *size * sizeof(uint8_t) * (p_AdditionalInfo->numOfKeys + 1)); ++ } ++ else ++ { ++ /* The allocated shadow is divided as follows: ++ 0 . . . 16 . . . ++ --------------------------------------------------- ++ | Shadow | Shadow Keys | Shadow Next | ++ | Ad | Match Table | Engine Table | ++ | (16 bytes) | (maximal size) | (maximal size) | ++ --------------------------------------------------- ++ */ ++ ++ if (!p_FmPcd->p_CcShadow) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("CC Shadow not allocated")); ++ ++ p_AdditionalInfo->p_KeysMatchTableNew = ++ PTR_MOVE(p_FmPcd->p_CcShadow, FM_PCD_CC_AD_ENTRY_SIZE); ++ p_AdditionalInfo->p_AdTableNew = ++ PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, p_CcNode->keysMatchTableMaxSize); ++ ++ IOMemSet32( ++ (uint8_t*)p_AdditionalInfo->p_AdTableNew, ++ 0, ++ (uint32_t)((p_CcNode->maxNumOfKeys + 1) ++ * FM_PCD_CC_AD_ENTRY_SIZE)); ++ IOMemSet32((uint8_t*)p_AdditionalInfo->p_KeysMatchTableNew, 0, ++ (*size) * sizeof(uint8_t) * (p_CcNode->maxNumOfKeys)); ++ } ++ ++ p_AdditionalInfo->p_AdTableOld = p_CcNode->h_AdTable; ++ p_AdditionalInfo->p_KeysMatchTableOld = p_CcNode->h_KeysMatchTable; ++ ++ return E_OK; ++} ++ ++static t_Error BuildNewNodeAddOrMdfyKeyAndNextEngine( ++ t_Handle h_FmPcd, t_FmPcdCcNode *p_CcNode, uint16_t keyIndex, ++ t_FmPcdCcKeyParams *p_KeyParams, ++ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo, bool add) ++{ ++ t_Error err = E_OK; ++ t_Handle p_AdTableNewTmp, p_KeysMatchTableNewTmp; ++ t_Handle p_KeysMatchTableOldTmp, p_AdTableOldTmp; ++ int size; ++ int i = 0, j = 0; ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t requiredAction = 0; ++ bool prvLclMask; ++ t_CcNodeInformation *p_CcNodeInformation; ++ t_FmPcdCcStatsParams statsParams = { 0 }; ++ t_List *p_Pos; ++ t_FmPcdStatsObj *p_StatsObj; ++ ++ /* Check that new NIA is legal */ ++ err = ValidateNextEngineParams(h_FmPcd, &p_KeyParams->ccNextEngineParams, ++ p_CcNode->statisticsMode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ prvLclMask = p_CcNode->lclMask; ++ ++ /* Check that new key is not require update of localMask */ ++ err = UpdateGblMask(p_CcNode, p_CcNode->ccKeySizeAccExtraction, ++ p_KeyParams->p_Mask); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ ++ /* Update internal data structure with new next engine for the given index */ ++ memcpy(&p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams, ++ &p_KeyParams->ccNextEngineParams, sizeof(t_FmPcdCcNextEngineParams)); ++ ++ memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].key, ++ p_KeyParams->p_Key, p_CcNode->userSizeOfExtraction); ++ ++ if ((p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ && p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip) ++ { ++ err = ++ AllocAndFillAdForContLookupManip( ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ if (p_KeyParams->p_Mask) ++ memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask, ++ p_KeyParams->p_Mask, p_CcNode->userSizeOfExtraction); ++ else ++ memset(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask, 0xFF, ++ p_CcNode->userSizeOfExtraction); ++ ++ /* Update numOfKeys */ ++ if (add) ++ p_AdditionalInfo->numOfKeys = (uint8_t)(p_CcNode->numOfKeys + 1); ++ else ++ p_AdditionalInfo->numOfKeys = (uint8_t)p_CcNode->numOfKeys; ++ ++ /* Allocate new tables in MURAM: keys match table and action descriptors table */ ++ err = BuildNewNodeCommonPart(p_CcNode, &size, p_AdditionalInfo); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ /* Check that manip is legal and what requiredAction is necessary for this manip */ ++ if (p_KeyParams->ccNextEngineParams.h_Manip) ++ { ++ err = FmPcdManipCheckParamsForCcNextEngine( ++ &p_KeyParams->ccNextEngineParams, &requiredAction); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction = ++ requiredAction; ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction |= ++ UPDATE_CC_WITH_TREE; ++ ++ /* Update new Ad and new Key Table according to new requirement */ ++ i = 0; ++ for (j = 0; j < p_AdditionalInfo->numOfKeys; j++) ++ { ++ p_AdTableNewTmp = ++ PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j*FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ if (j == keyIndex) ++ { ++ if (p_KeyParams->ccNextEngineParams.statisticsEn) ++ { ++ /* Allocate a statistics object that holds statistics AD and counters. ++ - For added key - New statistics AD and counters pointer need to be allocated ++ new statistics object. If statistics were enabled, we need to replace the ++ existing descriptor with a new descriptor with nullified counters. ++ */ ++ p_StatsObj = GetStatsObj(p_CcNode); ++ ASSERT_COND(p_StatsObj); ++ ++ /* Store allocated statistics object */ ++ ASSERT_COND(keyIndex < CC_MAX_NUM_OF_KEYS); ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = ++ p_StatsObj; ++ ++ statsParams.h_StatsAd = p_StatsObj->h_StatsAd; ++ statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters; ++#if (DPAA_VERSION >= 11) ++ statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs; ++ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ /* Building action descriptor for the received new key */ ++ NextStepAd(p_AdTableNewTmp, &statsParams, ++ &p_KeyParams->ccNextEngineParams, p_FmPcd); ++ } ++ else ++ { ++ /* Building action descriptor for the received new key */ ++ NextStepAd(p_AdTableNewTmp, NULL, ++ &p_KeyParams->ccNextEngineParams, p_FmPcd); ++ } ++ ++ /* Copy the received new key into keys match table */ ++ p_KeysMatchTableNewTmp = ++ PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j*size*sizeof(uint8_t)); ++ ++ Mem2IOCpy32((void*)p_KeysMatchTableNewTmp, p_KeyParams->p_Key, ++ p_CcNode->userSizeOfExtraction); ++ ++ /* Update mask for the received new key */ ++ if (p_CcNode->lclMask) ++ { ++ if (p_KeyParams->p_Mask) ++ { ++ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ p_KeyParams->p_Mask, ++ p_CcNode->userSizeOfExtraction); ++ } ++ else ++ if (p_CcNode->ccKeySizeAccExtraction > 4) ++ { ++ IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ 0xff, p_CcNode->userSizeOfExtraction); ++ } ++ else ++ { ++ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ p_CcNode->p_GlblMask, ++ p_CcNode->userSizeOfExtraction); ++ } ++ } ++ ++ /* If key modification requested, the old entry is omitted and replaced by the new parameters */ ++ if (!add) ++ i++; ++ } ++ else ++ { ++ /* Copy existing action descriptors to the newly allocated Ad table */ ++ p_AdTableOldTmp = ++ PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i*FM_PCD_CC_AD_ENTRY_SIZE); ++ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, ++ FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* Copy existing keys and their masks to the newly allocated keys match table */ ++ p_KeysMatchTableNewTmp = ++ PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j * size * sizeof(uint8_t)); ++ p_KeysMatchTableOldTmp = ++ PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableOld, i * size * sizeof(uint8_t)); ++ ++ if (p_CcNode->lclMask) ++ { ++ if (prvLclMask) ++ { ++ IO2IOCpy32( ++ PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction), ++ PTR_MOVE(p_KeysMatchTableOldTmp, p_CcNode->ccKeySizeAccExtraction), ++ p_CcNode->ccKeySizeAccExtraction); ++ } ++ else ++ { ++ p_KeysMatchTableOldTmp = ++ PTR_MOVE(p_CcNode->h_KeysMatchTable, ++ i * (int)p_CcNode->ccKeySizeAccExtraction * sizeof(uint8_t)); ++ ++ if (p_CcNode->ccKeySizeAccExtraction > 4) ++ { ++ IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ 0xff, p_CcNode->userSizeOfExtraction); ++ } ++ else ++ { ++ IO2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ p_CcNode->p_GlblMask, ++ p_CcNode->userSizeOfExtraction); ++ } ++ } ++ } ++ ++ IO2IOCpy32(p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp, ++ p_CcNode->ccKeySizeAccExtraction); ++ ++ i++; ++ } ++ } ++ ++ /* Miss action descriptor */ ++ p_AdTableNewTmp = ++ PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j * FM_PCD_CC_AD_ENTRY_SIZE); ++ p_AdTableOldTmp = ++ PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i * FM_PCD_CC_AD_ENTRY_SIZE); ++ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ if (!LIST_IsEmpty(&p_CcNode->ccTreesLst)) ++ { ++ LIST_FOR_EACH(p_Pos, &p_CcNode->ccTreesLst) ++ { ++ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos); ++ ASSERT_COND(p_CcNodeInformation->h_CcNode); ++ /* Update the manipulation which has to be updated from parameters of the port */ ++ /* It's has to be updated with restrictions defined in the function */ ++ err = ++ SetRequiredAction( ++ p_CcNode->h_FmPcd, ++ p_CcNode->shadowAction ++ | p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction, ++ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex], ++ PTR_MOVE(p_AdditionalInfo->p_AdTableNew, keyIndex*FM_PCD_CC_AD_ENTRY_SIZE), ++ 1, p_CcNodeInformation->h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ ++ err = ++ CcUpdateParam( ++ p_CcNode->h_FmPcd, ++ NULL, ++ NULL, ++ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex], ++ 1, ++ PTR_MOVE(p_AdditionalInfo->p_AdTableNew, keyIndex*FM_PCD_CC_AD_ENTRY_SIZE), ++ TRUE, p_CcNodeInformation->index, ++ p_CcNodeInformation->h_CcNode, TRUE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ } ++ ++ if (p_CcNode->lclMask) ++ memset(p_CcNode->p_GlblMask, 0xff, CC_GLBL_MASK_SIZE * sizeof(uint8_t)); ++ ++ if (p_KeyParams->ccNextEngineParams.nextEngine == e_FM_PCD_CC) ++ p_AdditionalInfo->h_NodeForAdd = ++ p_KeyParams->ccNextEngineParams.params.ccParams.h_CcNode; ++ if (p_KeyParams->ccNextEngineParams.h_Manip) ++ p_AdditionalInfo->h_ManipForAdd = ++ p_KeyParams->ccNextEngineParams.h_Manip; ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_KeyParams->ccNextEngineParams.nextEngine == e_FM_PCD_FR) ++ && (p_KeyParams->ccNextEngineParams.params.frParams.h_FrmReplic)) ++ p_AdditionalInfo->h_FrmReplicForAdd = ++ p_KeyParams->ccNextEngineParams.params.frParams.h_FrmReplic; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (!add) ++ { ++ if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ p_AdditionalInfo->h_NodeForRmv = ++ p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode; ++ ++ if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip) ++ p_AdditionalInfo->h_ManipForRmv = ++ p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip; ++ ++ /* If statistics were previously enabled, store the old statistics object to be released */ ++ if (p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj) ++ { ++ p_AdditionalInfo->p_StatsObjForRmv = ++ p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj; ++ } ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine ++ == e_FM_PCD_FR) ++ && (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic)) ++ p_AdditionalInfo->h_FrmReplicForRmv = ++ p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic; ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ return E_OK; ++} ++ ++static t_Error BuildNewNodeRemoveKey( ++ t_FmPcdCcNode *p_CcNode, uint16_t keyIndex, ++ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo) ++{ ++ int i = 0, j = 0; ++ t_Handle p_AdTableNewTmp, p_KeysMatchTableNewTmp; ++ t_Handle p_KeysMatchTableOldTmp, p_AdTableOldTmp; ++ int size; ++ t_Error err = E_OK; ++ ++ /*save new numOfKeys*/ ++ p_AdditionalInfo->numOfKeys = (uint16_t)(p_CcNode->numOfKeys - 1); ++ ++ /*function which allocates in the memory new KeyTbl, AdTbl*/ ++ err = BuildNewNodeCommonPart(p_CcNode, &size, p_AdditionalInfo); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ /*update new Ad and new Key Table according to new requirement*/ ++ for (i = 0, j = 0; j < p_CcNode->numOfKeys; i++, j++) ++ { ++ if (j == keyIndex) ++ j++; ++ ++ if (j == p_CcNode->numOfKeys) ++ break; ++ p_AdTableNewTmp = ++ PTR_MOVE(p_AdditionalInfo->p_AdTableNew, i * FM_PCD_CC_AD_ENTRY_SIZE); ++ p_AdTableOldTmp = ++ PTR_MOVE(p_AdditionalInfo->p_AdTableOld, j * FM_PCD_CC_AD_ENTRY_SIZE); ++ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ p_KeysMatchTableOldTmp = ++ PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableOld, j * size * sizeof(uint8_t)); ++ p_KeysMatchTableNewTmp = ++ PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, i * size * sizeof(uint8_t)); ++ IO2IOCpy32(p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp, ++ size * sizeof(uint8_t)); ++ } ++ ++ p_AdTableNewTmp = ++ PTR_MOVE(p_AdditionalInfo->p_AdTableNew, i * FM_PCD_CC_AD_ENTRY_SIZE); ++ p_AdTableOldTmp = ++ PTR_MOVE(p_AdditionalInfo->p_AdTableOld, j * FM_PCD_CC_AD_ENTRY_SIZE); ++ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ p_AdditionalInfo->h_NodeForRmv = ++ p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode; ++ ++ if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip) ++ p_AdditionalInfo->h_ManipForRmv = ++ p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip; ++ ++ /* If statistics were previously enabled, store the old statistics object to be released */ ++ if (p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj) ++ { ++ p_AdditionalInfo->p_StatsObjForRmv = ++ p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj; ++ } ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine ++ == e_FM_PCD_FR) ++ && (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic)) ++ p_AdditionalInfo->h_FrmReplicForRmv = ++ p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ return E_OK; ++} ++ ++static t_Error BuildNewNodeModifyKey( ++ t_FmPcdCcNode *p_CcNode, uint16_t keyIndex, uint8_t *p_Key, ++ uint8_t *p_Mask, t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ t_Error err = E_OK; ++ t_Handle p_AdTableNewTmp, p_KeysMatchTableNewTmp; ++ t_Handle p_KeysMatchTableOldTmp, p_AdTableOldTmp; ++ int size; ++ int i = 0, j = 0; ++ bool prvLclMask; ++ t_FmPcdStatsObj *p_StatsObj, tmpStatsObj; ++ p_AdditionalInfo->numOfKeys = p_CcNode->numOfKeys; ++ ++ prvLclMask = p_CcNode->lclMask; ++ ++ /* Check that new key is not require update of localMask */ ++ err = UpdateGblMask(p_CcNode, p_CcNode->ccKeySizeAccExtraction, p_Mask); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ ++ /* Update internal data structure with new next engine for the given index */ ++ memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].key, p_Key, ++ p_CcNode->userSizeOfExtraction); ++ ++ if (p_Mask) ++ memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask, p_Mask, ++ p_CcNode->userSizeOfExtraction); ++ else ++ memset(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask, 0xFF, ++ p_CcNode->userSizeOfExtraction); ++ ++ /*function which build in the memory new KeyTbl, AdTbl*/ ++ err = BuildNewNodeCommonPart(p_CcNode, &size, p_AdditionalInfo); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ /*fill the New AdTable and New KeyTable*/ ++ for (j = 0, i = 0; j < p_AdditionalInfo->numOfKeys; j++, i++) ++ { ++ p_AdTableNewTmp = ++ PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j*FM_PCD_CC_AD_ENTRY_SIZE); ++ p_AdTableOldTmp = ++ PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i*FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ if (j == keyIndex) ++ { ++ ASSERT_COND(keyIndex < CC_MAX_NUM_OF_KEYS); ++ if (p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj) ++ { ++ /* As statistics were enabled, we need to update the existing ++ statistics descriptor with a new nullified counters. */ ++ p_StatsObj = GetStatsObj(p_CcNode); ++ ASSERT_COND(p_StatsObj); ++ ++ SetStatsCounters( ++ p_AdTableNewTmp, ++ (uint32_t)((XX_VirtToPhys(p_StatsObj->h_StatsCounters) ++ - p_FmPcd->physicalMuramBase))); ++ ++ tmpStatsObj.h_StatsAd = p_StatsObj->h_StatsAd; ++ tmpStatsObj.h_StatsCounters = p_StatsObj->h_StatsCounters; ++ ++ /* As we need to replace only the counters, we build a new statistics ++ object that holds the old AD and the new counters - this will be the ++ currently used statistics object. ++ The newly allocated AD is not required and may be released back to ++ the available objects with the previous counters pointer. */ ++ p_StatsObj->h_StatsAd = ++ p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsAd; ++ ++ p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsAd = ++ tmpStatsObj.h_StatsAd; ++ ++ /* Store allocated statistics object */ ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = ++ p_StatsObj; ++ ++ /* As statistics were previously enabled, store the old statistics object to be released */ ++ p_AdditionalInfo->p_StatsObjForRmv = ++ p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj; ++ } ++ ++ p_KeysMatchTableNewTmp = ++ PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j * size * sizeof(uint8_t)); ++ ++ Mem2IOCpy32(p_KeysMatchTableNewTmp, p_Key, ++ p_CcNode->userSizeOfExtraction); ++ ++ if (p_CcNode->lclMask) ++ { ++ if (p_Mask) ++ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ p_Mask, p_CcNode->userSizeOfExtraction); ++ else ++ if (p_CcNode->ccKeySizeAccExtraction > 4) ++ IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ 0xff, p_CcNode->userSizeOfExtraction); ++ else ++ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ p_CcNode->p_GlblMask, ++ p_CcNode->userSizeOfExtraction); ++ } ++ } ++ else ++ { ++ p_KeysMatchTableNewTmp = ++ PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j * size * sizeof(uint8_t)); ++ p_KeysMatchTableOldTmp = ++ PTR_MOVE(p_CcNode->h_KeysMatchTable, i * size * sizeof(uint8_t)); ++ ++ if (p_CcNode->lclMask) ++ { ++ if (prvLclMask) ++ IO2IOCpy32( ++ PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction), ++ PTR_MOVE(p_KeysMatchTableOldTmp, p_CcNode->ccKeySizeAccExtraction), ++ p_CcNode->userSizeOfExtraction); ++ else ++ { ++ p_KeysMatchTableOldTmp = ++ PTR_MOVE(p_CcNode->h_KeysMatchTable, ++ i * (int)p_CcNode->ccKeySizeAccExtraction * sizeof(uint8_t)); ++ ++ if (p_CcNode->ccKeySizeAccExtraction > 4) ++ IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ p_CcNode->ccKeySizeAccExtraction), ++ 0xff, p_CcNode->userSizeOfExtraction); ++ else ++ IO2IOCpy32( ++ PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction), ++ p_CcNode->p_GlblMask, ++ p_CcNode->userSizeOfExtraction); ++ } ++ } ++ IO2IOCpy32((void*)p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp, ++ p_CcNode->ccKeySizeAccExtraction); ++ } ++ } ++ ++ p_AdTableNewTmp = ++ PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j * FM_PCD_CC_AD_ENTRY_SIZE); ++ p_AdTableOldTmp = PTR_MOVE(p_CcNode->h_AdTable, i * FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ return E_OK; ++} ++ ++static t_Error BuildNewNodeModifyNextEngine( ++ t_Handle h_FmPcd, t_Handle h_FmPcdCcNodeOrTree, uint16_t keyIndex, ++ t_FmPcdCcNextEngineParams *p_CcNextEngineParams, t_List *h_OldLst, ++ t_List *h_NewLst, t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo) ++{ ++ t_Error err = E_OK; ++ uint32_t requiredAction = 0; ++ t_List *p_Pos; ++ t_CcNodeInformation *p_CcNodeInformation, ccNodeInfo; ++ t_Handle p_Ad; ++ t_FmPcdCcNode *p_FmPcdCcNode1 = NULL; ++ t_FmPcdCcTree *p_FmPcdCcTree = NULL; ++ t_FmPcdStatsObj *p_StatsObj; ++ t_FmPcdCcStatsParams statsParams = { 0 }; ++ ++ ASSERT_COND(p_CcNextEngineParams); ++ ++ /* check that new NIA is legal */ ++ if (!p_AdditionalInfo->tree) ++ err = ValidateNextEngineParams( ++ h_FmPcd, p_CcNextEngineParams, ++ ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->statisticsMode); ++ else ++ /* Statistics are not supported for CC root */ ++ err = ValidateNextEngineParams(h_FmPcd, p_CcNextEngineParams, ++ e_FM_PCD_CC_STATS_MODE_NONE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ /* Update internal data structure for next engine per index (index - key) */ ++ memcpy(&p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams, ++ p_CcNextEngineParams, sizeof(t_FmPcdCcNextEngineParams)); ++ ++ /* Check that manip is legal and what requiredAction is necessary for this manip */ ++ if (p_CcNextEngineParams->h_Manip) ++ { ++ err = FmPcdManipCheckParamsForCcNextEngine(p_CcNextEngineParams, ++ &requiredAction); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ if (!p_AdditionalInfo->tree) ++ { ++ p_FmPcdCcNode1 = (t_FmPcdCcNode *)h_FmPcdCcNodeOrTree; ++ p_AdditionalInfo->numOfKeys = p_FmPcdCcNode1->numOfKeys; ++ p_Ad = p_FmPcdCcNode1->h_AdTable; ++ ++ if (p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ p_AdditionalInfo->h_NodeForRmv = ++ p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode; ++ ++ if (p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip) ++ p_AdditionalInfo->h_ManipForRmv = ++ p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip; ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine ++ == e_FM_PCD_FR) ++ && (p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic)) ++ p_AdditionalInfo->h_FrmReplicForRmv = ++ p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic; ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ else ++ { ++ p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcNodeOrTree; ++ p_Ad = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); ++ ++ if (p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ p_AdditionalInfo->h_NodeForRmv = ++ p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode; ++ ++ if (p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip) ++ p_AdditionalInfo->h_ManipForRmv = ++ p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip; ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine ++ == e_FM_PCD_FR) ++ && (p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic)) ++ p_AdditionalInfo->h_FrmReplicForRmv = ++ p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic; ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ if ((p_CcNextEngineParams->nextEngine == e_FM_PCD_CC) ++ && p_CcNextEngineParams->h_Manip) ++ { ++ err = AllocAndFillAdForContLookupManip( ++ p_CcNextEngineParams->params.ccParams.h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ ASSERT_COND(p_Ad); ++ ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = PTR_MOVE(p_Ad, keyIndex * FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* If statistics were enabled, this Ad is the statistics Ad. Need to follow its ++ nextAction to retrieve the actual Nia-Ad. If statistics should remain enabled, ++ only the actual Nia-Ad should be modified. */ ++ if ((!p_AdditionalInfo->tree) ++ && (((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj) ++ && (p_CcNextEngineParams->statisticsEn)) ++ ccNodeInfo.h_CcNode = ++ ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsAd; ++ ++ EnqueueNodeInfoToRelevantLst(h_OldLst, &ccNodeInfo, NULL); ++ ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ p_Ad = GetNewAd(h_FmPcdCcNodeOrTree, p_AdditionalInfo->tree); ++ if (!p_Ad) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("MURAM allocation for CC node action descriptor")); ++ IOMemSet32((uint8_t *)p_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* If statistics were not enabled before, but requested now - Allocate a statistics ++ object that holds statistics AD and counters. */ ++ if ((!p_AdditionalInfo->tree) ++ && (!((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj) ++ && (p_CcNextEngineParams->statisticsEn)) ++ { ++ p_StatsObj = GetStatsObj((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree); ++ ASSERT_COND(p_StatsObj); ++ ++ /* Store allocated statistics object */ ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = ++ p_StatsObj; ++ ++ statsParams.h_StatsAd = p_StatsObj->h_StatsAd; ++ statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters; ++ ++#if (DPAA_VERSION >= 11) ++ statsParams.h_StatsFLRs = ++ ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->h_StatsFLRs; ++ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ NextStepAd(p_Ad, &statsParams, p_CcNextEngineParams, h_FmPcd); ++ } ++ else ++ NextStepAd(p_Ad, NULL, p_CcNextEngineParams, h_FmPcd); ++ ++ ccNodeInfo.h_CcNode = p_Ad; ++ EnqueueNodeInfoToRelevantLst(h_NewLst, &ccNodeInfo, NULL); ++ ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction = ++ requiredAction; ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction |= ++ UPDATE_CC_WITH_TREE; ++ ++ if (!p_AdditionalInfo->tree) ++ { ++ ASSERT_COND(p_FmPcdCcNode1); ++ if (!LIST_IsEmpty(&p_FmPcdCcNode1->ccTreesLst)) ++ { ++ LIST_FOR_EACH(p_Pos, &p_FmPcdCcNode1->ccTreesLst) ++ { ++ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos); ++ ++ ASSERT_COND(p_CcNodeInformation->h_CcNode); ++ /* Update the manipulation which has to be updated from parameters of the port ++ it's has to be updated with restrictions defined in the function */ ++ ++ err = ++ SetRequiredAction( ++ p_FmPcdCcNode1->h_FmPcd, ++ p_FmPcdCcNode1->shadowAction ++ | p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction, ++ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex], ++ p_Ad, 1, p_CcNodeInformation->h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ ++ err = CcUpdateParam( ++ p_FmPcdCcNode1->h_FmPcd, NULL, NULL, ++ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex], 1, ++ p_Ad, TRUE, p_CcNodeInformation->index, ++ p_CcNodeInformation->h_CcNode, TRUE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ } ++ } ++ else ++ { ++ ASSERT_COND(p_FmPcdCcTree); ++ ++ err = ++ SetRequiredAction( ++ h_FmPcd, ++ p_FmPcdCcTree->requiredAction ++ | p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction, ++ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex], ++ p_Ad, 1, (t_Handle)p_FmPcdCcTree); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ ++ err = CcUpdateParam(h_FmPcd, NULL, NULL, ++ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex], ++ 1, p_Ad, TRUE, 0, (t_Handle)p_FmPcdCcTree, TRUE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ if (p_CcNextEngineParams->nextEngine == e_FM_PCD_CC) ++ p_AdditionalInfo->h_NodeForAdd = ++ p_CcNextEngineParams->params.ccParams.h_CcNode; ++ if (p_CcNextEngineParams->h_Manip) ++ p_AdditionalInfo->h_ManipForAdd = p_CcNextEngineParams->h_Manip; ++ ++ /* If statistics were previously enabled, but now are disabled, ++ store the old statistics object to be released */ ++ if ((!p_AdditionalInfo->tree) ++ && (((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj) ++ && (!p_CcNextEngineParams->statisticsEn)) ++ { ++ p_AdditionalInfo->p_StatsObjForRmv = ++ ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj; ++ ++ ++ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = NULL; ++ } ++#if (DPAA_VERSION >= 11) ++ if ((p_CcNextEngineParams->nextEngine == e_FM_PCD_FR) ++ && (p_CcNextEngineParams->params.frParams.h_FrmReplic)) ++ p_AdditionalInfo->h_FrmReplicForAdd = ++ p_CcNextEngineParams->params.frParams.h_FrmReplic; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ return E_OK; ++} ++ ++static void UpdateAdPtrOfNodesWhichPointsOnCrntMdfNode( ++ t_FmPcdCcNode *p_CrntMdfNode, t_List *h_OldLst, ++ t_FmPcdCcNextEngineParams **p_NextEngineParams) ++{ ++ t_CcNodeInformation *p_CcNodeInformation; ++ t_FmPcdCcNode *p_NodePtrOnCurrentMdfNode = NULL; ++ t_List *p_Pos; ++ int i = 0; ++ t_Handle p_AdTablePtOnCrntCurrentMdfNode/*, p_AdTableNewModified*/; ++ t_CcNodeInformation ccNodeInfo; ++ ++ LIST_FOR_EACH(p_Pos, &p_CrntMdfNode->ccPrevNodesLst) ++ { ++ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos); ++ p_NodePtrOnCurrentMdfNode = ++ (t_FmPcdCcNode *)p_CcNodeInformation->h_CcNode; ++ ++ ASSERT_COND(p_NodePtrOnCurrentMdfNode); ++ ++ /* Search in the previous node which exact index points on this current modified node for getting AD */ ++ for (i = 0; i < p_NodePtrOnCurrentMdfNode->numOfKeys + 1; i++) ++ { ++ if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ { ++ if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode ++ == (t_Handle)p_CrntMdfNode) ++ { ++ if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip) ++ p_AdTablePtOnCrntCurrentMdfNode = p_CrntMdfNode->h_Ad; ++ else ++ if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].p_StatsObj) ++ p_AdTablePtOnCrntCurrentMdfNode = ++ p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].p_StatsObj->h_StatsAd; ++ else ++ p_AdTablePtOnCrntCurrentMdfNode = ++ PTR_MOVE(p_NodePtrOnCurrentMdfNode->h_AdTable, i*FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = p_AdTablePtOnCrntCurrentMdfNode; ++ EnqueueNodeInfoToRelevantLst(h_OldLst, &ccNodeInfo, NULL); ++ ++ if (!(*p_NextEngineParams)) ++ *p_NextEngineParams = ++ &p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams; ++ } ++ } ++ } ++ ++ ASSERT_COND(i != p_NodePtrOnCurrentMdfNode->numOfKeys); ++ } ++} ++ ++static void UpdateAdPtrOfTreesWhichPointsOnCrntMdfNode( ++ t_FmPcdCcNode *p_CrntMdfNode, t_List *h_OldLst, ++ t_FmPcdCcNextEngineParams **p_NextEngineParams) ++{ ++ t_CcNodeInformation *p_CcNodeInformation; ++ t_FmPcdCcTree *p_TreePtrOnCurrentMdfNode = NULL; ++ t_List *p_Pos; ++ int i = 0; ++ t_Handle p_AdTableTmp; ++ t_CcNodeInformation ccNodeInfo; ++ ++ LIST_FOR_EACH(p_Pos, &p_CrntMdfNode->ccTreeIdLst) ++ { ++ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos); ++ p_TreePtrOnCurrentMdfNode = ++ (t_FmPcdCcTree *)p_CcNodeInformation->h_CcNode; ++ ++ ASSERT_COND(p_TreePtrOnCurrentMdfNode); ++ ++ /*search in the trees which exact index points on this current modified node for getting AD */ ++ for (i = 0; i < p_TreePtrOnCurrentMdfNode->numOfEntries; i++) ++ { ++ if (p_TreePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ { ++ if (p_TreePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode ++ == (t_Handle)p_CrntMdfNode) ++ { ++ p_AdTableTmp = ++ UINT_TO_PTR(p_TreePtrOnCurrentMdfNode->ccTreeBaseAddr + i*FM_PCD_CC_AD_ENTRY_SIZE); ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = p_AdTableTmp; ++ EnqueueNodeInfoToRelevantLst(h_OldLst, &ccNodeInfo, NULL); ++ ++ if (!(*p_NextEngineParams)) ++ *p_NextEngineParams = ++ &p_TreePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams; ++ } ++ } ++ } ++ ++ ASSERT_COND(i == p_TreePtrOnCurrentMdfNode->numOfEntries); ++ } ++} ++ ++static t_FmPcdModifyCcKeyAdditionalParams * ModifyNodeCommonPart( ++ t_Handle h_FmPcdCcNodeOrTree, uint16_t keyIndex, ++ e_ModifyState modifyState, bool ttlCheck, bool hashCheck, bool tree) ++{ ++ t_FmPcdModifyCcKeyAdditionalParams *p_FmPcdModifyCcKeyAdditionalParams; ++ int i = 0, j = 0; ++ bool wasUpdate = FALSE; ++ t_FmPcdCcNode *p_CcNode = NULL; ++ t_FmPcdCcTree *p_FmPcdCcTree; ++ uint16_t numOfKeys; ++ t_FmPcdCcKeyAndNextEngineParams *p_KeyAndNextEngineParams; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcdCcNodeOrTree, E_INVALID_HANDLE, NULL); ++ ++ if (!tree) ++ { ++ p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNodeOrTree; ++ numOfKeys = p_CcNode->numOfKeys; ++ ++ /* node has to be pointed by another node or tree */ ++ ++ p_KeyAndNextEngineParams = (t_FmPcdCcKeyAndNextEngineParams *)XX_Malloc( ++ sizeof(t_FmPcdCcKeyAndNextEngineParams) * (numOfKeys + 1)); ++ if (!p_KeyAndNextEngineParams) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Next engine and required action structure")); ++ return NULL; ++ } ++ memcpy(p_KeyAndNextEngineParams, p_CcNode->keyAndNextEngineParams, ++ (numOfKeys + 1) * sizeof(t_FmPcdCcKeyAndNextEngineParams)); ++ ++ if (ttlCheck) ++ { ++ if ((p_CcNode->parseCode == CC_PC_FF_IPV4TTL) ++ || (p_CcNode->parseCode == CC_PC_FF_IPV6HOP_LIMIT)) ++ { ++ XX_Free(p_KeyAndNextEngineParams); ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("nodeId of CC_PC_FF_IPV4TTL or CC_PC_FF_IPV6HOP_LIMIT can not be used for this operation")); ++ return NULL; ++ } ++ } ++ ++ if (hashCheck) ++ { ++ if (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED) ++ { ++ XX_Free(p_KeyAndNextEngineParams); ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("nodeId of CC_PC_GENERIC_IC_HASH_INDEXED can not be used for this operation")); ++ return NULL; ++ } ++ } ++ } ++ else ++ { ++ p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcNodeOrTree; ++ numOfKeys = p_FmPcdCcTree->numOfEntries; ++ ++ p_KeyAndNextEngineParams = (t_FmPcdCcKeyAndNextEngineParams *)XX_Malloc( ++ sizeof(t_FmPcdCcKeyAndNextEngineParams) ++ * FM_PCD_MAX_NUM_OF_CC_GROUPS); ++ if (!p_KeyAndNextEngineParams) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Next engine and required action structure")); ++ return NULL; ++ } ++ memcpy(p_KeyAndNextEngineParams, ++ p_FmPcdCcTree->keyAndNextEngineParams, ++ FM_PCD_MAX_NUM_OF_CC_GROUPS ++ * sizeof(t_FmPcdCcKeyAndNextEngineParams)); ++ } ++ ++ p_FmPcdModifyCcKeyAdditionalParams = ++ (t_FmPcdModifyCcKeyAdditionalParams *)XX_Malloc( ++ sizeof(t_FmPcdModifyCcKeyAdditionalParams)); ++ if (!p_FmPcdModifyCcKeyAdditionalParams) ++ { ++ XX_Free(p_KeyAndNextEngineParams); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of internal data structure FAILED")); ++ return NULL; ++ } ++ memset(p_FmPcdModifyCcKeyAdditionalParams, 0, ++ sizeof(t_FmPcdModifyCcKeyAdditionalParams)); ++ ++ p_FmPcdModifyCcKeyAdditionalParams->h_CurrentNode = h_FmPcdCcNodeOrTree; ++ p_FmPcdModifyCcKeyAdditionalParams->savedKeyIndex = keyIndex; ++ ++ while (i < numOfKeys) ++ { ++ if ((j == keyIndex) && !wasUpdate) ++ { ++ if (modifyState == e_MODIFY_STATE_ADD) ++ j++; ++ else ++ if (modifyState == e_MODIFY_STATE_REMOVE) ++ i++; ++ wasUpdate = TRUE; ++ } ++ else ++ { ++ memcpy(&p_FmPcdModifyCcKeyAdditionalParams->keyAndNextEngineParams[j], ++ p_KeyAndNextEngineParams + i, ++ sizeof(t_FmPcdCcKeyAndNextEngineParams)); ++ i++; ++ j++; ++ } ++ } ++ ++ if (keyIndex == numOfKeys) ++ { ++ if (modifyState == e_MODIFY_STATE_ADD) ++ j++; ++ } ++ ++ memcpy(&p_FmPcdModifyCcKeyAdditionalParams->keyAndNextEngineParams[j], ++ p_KeyAndNextEngineParams + numOfKeys, ++ sizeof(t_FmPcdCcKeyAndNextEngineParams)); ++ ++ XX_Free(p_KeyAndNextEngineParams); ++ ++ return p_FmPcdModifyCcKeyAdditionalParams; ++} ++ ++static t_Error UpdatePtrWhichPointOnCrntMdfNode( ++ t_FmPcdCcNode *p_CcNode, ++ t_FmPcdModifyCcKeyAdditionalParams *p_FmPcdModifyCcKeyAdditionalParams, ++ t_List *h_OldLst, t_List *h_NewLst) ++{ ++ t_FmPcdCcNextEngineParams *p_NextEngineParams = NULL; ++ t_CcNodeInformation ccNodeInfo = { 0 }; ++ t_Handle h_NewAd; ++ t_Handle h_OrigAd = NULL; ++ ++ /* Building a list of all action descriptors that point to the previous node */ ++ if (!LIST_IsEmpty(&p_CcNode->ccPrevNodesLst)) ++ UpdateAdPtrOfNodesWhichPointsOnCrntMdfNode(p_CcNode, h_OldLst, ++ &p_NextEngineParams); ++ ++ if (!LIST_IsEmpty(&p_CcNode->ccTreeIdLst)) ++ UpdateAdPtrOfTreesWhichPointsOnCrntMdfNode(p_CcNode, h_OldLst, ++ &p_NextEngineParams); ++ ++ /* This node must be found as next engine of one of its previous nodes or trees*/ ++ if (p_NextEngineParams) ++ { ++ /* Building a new action descriptor that points to the modified node */ ++ h_NewAd = GetNewAd(p_CcNode, FALSE); ++ if (!h_NewAd) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ IOMemSet32(h_NewAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ h_OrigAd = p_CcNode->h_Ad; ++ BuildNewAd(h_NewAd, p_FmPcdModifyCcKeyAdditionalParams, p_CcNode, ++ p_NextEngineParams); ++ ++ ccNodeInfo.h_CcNode = h_NewAd; ++ EnqueueNodeInfoToRelevantLst(h_NewLst, &ccNodeInfo, NULL); ++ ++ if (p_NextEngineParams->h_Manip && !h_OrigAd) ++ FmPcdManipUpdateOwner(p_NextEngineParams->h_Manip, FALSE); ++ } ++ return E_OK; ++} ++ ++static void UpdateCcRootOwner(t_FmPcdCcTree *p_FmPcdCcTree, bool add) ++{ ++ ASSERT_COND(p_FmPcdCcTree); ++ ++ /* this routine must be protected by the calling routine! */ ++ ++ if (add) ++ p_FmPcdCcTree->owners++; ++ else ++ { ++ ASSERT_COND(p_FmPcdCcTree->owners); ++ p_FmPcdCcTree->owners--; ++ } ++} ++ ++static t_Error CheckAndSetManipParamsWithCcNodeParams(t_FmPcdCcNode *p_CcNode) ++{ ++ t_Error err = E_OK; ++ int i = 0; ++ ++ for (i = 0; i < p_CcNode->numOfKeys; i++) ++ { ++ if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip) ++ { ++ err = ++ FmPcdManipCheckParamsWithCcNodeParams( ++ p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip, ++ (t_Handle)p_CcNode); ++ if (err) ++ return err; ++ } ++ } ++ ++ return err; ++} ++static t_Error ValidateAndCalcStatsParams(t_FmPcdCcNode *p_CcNode, ++ t_FmPcdCcNodeParams *p_CcNodeParam, ++ uint32_t *p_NumOfRanges, ++ uint32_t *p_CountersArraySize) ++{ ++ e_FmPcdCcStatsMode statisticsMode = p_CcNode->statisticsMode; ++ uint32_t i; ++ ++ UNUSED(p_CcNodeParam); ++ ++ switch (statisticsMode) ++ { ++ case e_FM_PCD_CC_STATS_MODE_NONE: ++ for (i = 0; i < p_CcNode->numOfKeys; i++) ++ if (p_CcNodeParam->keysParams.keyParams[i].ccNextEngineParams.statisticsEn) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("Statistics cannot be enabled for key %d when statistics mode was set to 'NONE'", i)); ++ return E_OK; ++ ++ case e_FM_PCD_CC_STATS_MODE_FRAME: ++ case e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME: ++ *p_NumOfRanges = 1; ++ *p_CountersArraySize = 2 * FM_PCD_CC_STATS_COUNTER_SIZE; ++ return E_OK; ++ ++#if (DPAA_VERSION >= 11) ++ case e_FM_PCD_CC_STATS_MODE_RMON: ++ { ++ uint16_t *p_FrameLengthRanges = ++ p_CcNodeParam->keysParams.frameLengthRanges; ++ uint32_t i; ++ ++ if (p_FrameLengthRanges[0] <= 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Statistics mode")); ++ ++ if (p_FrameLengthRanges[0] == 0xFFFF) ++ { ++ *p_NumOfRanges = 1; ++ *p_CountersArraySize = 2 * FM_PCD_CC_STATS_COUNTER_SIZE; ++ return E_OK; ++ } ++ ++ for (i = 1; i < FM_PCD_CC_STATS_MAX_NUM_OF_FLR; i++) ++ { ++ if (p_FrameLengthRanges[i - 1] >= p_FrameLengthRanges[i]) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("Frame length range must be larger at least by 1 from preceding range")); ++ ++ /* Stop when last range is reached */ ++ if (p_FrameLengthRanges[i] == 0xFFFF) ++ break; ++ } ++ ++ if ((i >= FM_PCD_CC_STATS_MAX_NUM_OF_FLR) ++ || (p_FrameLengthRanges[i] != 0xFFFF)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("Last Frame length range must be 0xFFFF")); ++ ++ *p_NumOfRanges = i + 1; ++ ++ /* Allocate an extra counter for byte count, as counters ++ array always begins with byte count */ ++ *p_CountersArraySize = (*p_NumOfRanges + 1) ++ * FM_PCD_CC_STATS_COUNTER_SIZE; ++ ++ } ++ return E_OK; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Statistics mode")); ++ } ++} ++ ++static t_Error CheckParams(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodeParam, ++ t_FmPcdCcNode *p_CcNode, bool *isKeyTblAlloc) ++{ ++ int tmp = 0; ++ t_FmPcdCcKeyParams *p_KeyParams; ++ t_Error err; ++ uint32_t requiredAction = 0; ++ ++ /* Validate statistics parameters */ ++ err = ValidateAndCalcStatsParams(p_CcNode, p_CcNodeParam, ++ &(p_CcNode->numOfStatsFLRs), ++ &(p_CcNode->countersArraySize)); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("Invalid statistics parameters")); ++ ++ /* Validate next engine parameters on Miss */ ++ err = ValidateNextEngineParams( ++ h_FmPcd, &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, ++ p_CcNode->statisticsMode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ++ ("For this node MissNextEngineParams are not valid")); ++ ++ if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.h_Manip) ++ { ++ err = FmPcdManipCheckParamsForCcNextEngine( ++ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, ++ &requiredAction); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ memcpy(&p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams, ++ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].requiredAction = ++ requiredAction; ++ ++ if ((p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ && p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.h_Manip) ++ { ++ err = ++ AllocAndFillAdForContLookupManip( ++ p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.params.ccParams.h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++) ++ { ++ p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp]; ++ ++ if (!p_KeyParams->p_Key) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_Key is not initialized")); ++ ++ err = ValidateNextEngineParams(h_FmPcd, ++ &p_KeyParams->ccNextEngineParams, ++ p_CcNode->statisticsMode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ ++ err = UpdateGblMask(p_CcNode, p_CcNodeParam->keysParams.keySize, ++ p_KeyParams->p_Mask); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ ++ if (p_KeyParams->ccNextEngineParams.h_Manip) ++ { ++ err = FmPcdManipCheckParamsForCcNextEngine( ++ &p_KeyParams->ccNextEngineParams, &requiredAction); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ /* Store 'key' parameters - key, mask (if passed by the user) */ ++ memcpy(p_CcNode->keyAndNextEngineParams[tmp].key, p_KeyParams->p_Key, ++ p_CcNodeParam->keysParams.keySize); ++ ++ if (p_KeyParams->p_Mask) ++ memcpy(p_CcNode->keyAndNextEngineParams[tmp].mask, ++ p_KeyParams->p_Mask, p_CcNodeParam->keysParams.keySize); ++ else ++ memset((void *)(p_CcNode->keyAndNextEngineParams[tmp].mask), 0xFF, ++ p_CcNodeParam->keysParams.keySize); ++ ++ /* Store next engine parameters */ ++ memcpy(&p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams, ++ &p_KeyParams->ccNextEngineParams, ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ p_CcNode->keyAndNextEngineParams[tmp].requiredAction = requiredAction; ++ ++ if ((p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ && p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip) ++ { ++ err = ++ AllocAndFillAdForContLookupManip( ++ p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ } ++ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ if (p_CcNode->maxNumOfKeys < p_CcNode->numOfKeys) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("Number of keys exceed the provided maximal number of keys")); ++ } ++ ++ *isKeyTblAlloc = TRUE; ++ ++ return E_OK; ++} ++ ++static t_Error Ipv4TtlOrIpv6HopLimitCheckParams( ++ t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodeParam, ++ t_FmPcdCcNode *p_CcNode, bool *isKeyTblAlloc) ++{ ++ int tmp = 0; ++ t_FmPcdCcKeyParams *p_KeyParams; ++ t_Error err; ++ uint8_t key = 0x01; ++ uint32_t requiredAction = 0; ++ ++ if (p_CcNode->numOfKeys != 1) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT the maximal supported 'numOfKeys' is 1")); ++ ++ if ((p_CcNodeParam->keysParams.maxNumOfKeys) ++ && (p_CcNodeParam->keysParams.maxNumOfKeys != 1)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT the maximal supported 'maxNumOfKeys' is 1")); ++ ++ /* Validate statistics parameters */ ++ err = ValidateAndCalcStatsParams(p_CcNode, p_CcNodeParam, ++ &(p_CcNode->numOfStatsFLRs), ++ &(p_CcNode->countersArraySize)); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("Invalid statistics parameters")); ++ ++ err = ValidateNextEngineParams( ++ h_FmPcd, &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, ++ p_CcNodeParam->keysParams.statisticsMode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ++ ("For this node MissNextEngineParams are not valid")); ++ ++ if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.h_Manip) ++ { ++ err = FmPcdManipCheckParamsForCcNextEngine( ++ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, ++ &requiredAction); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ memcpy(&p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams, ++ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].requiredAction = ++ requiredAction; ++ ++ if ((p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ && p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.h_Manip) ++ { ++ err = ++ AllocAndFillAdForContLookupManip( ++ p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.params.ccParams.h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++) ++ { ++ p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp]; ++ ++ if (p_KeyParams->p_Mask) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT p_Mask can not be initialized")); ++ ++ if (memcmp(p_KeyParams->p_Key, &key, 1) != 0) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT p_Key has to be 1")); ++ ++ err = ValidateNextEngineParams(h_FmPcd, ++ &p_KeyParams->ccNextEngineParams, ++ p_CcNode->statisticsMode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ ++ if (p_KeyParams->ccNextEngineParams.h_Manip) ++ { ++ err = FmPcdManipCheckParamsForCcNextEngine( ++ &p_KeyParams->ccNextEngineParams, &requiredAction); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ ++ /* Store 'key' parameters - key (fixed to 0x01), key size of 1 byte and full mask */ ++ p_CcNode->keyAndNextEngineParams[tmp].key[0] = key; ++ p_CcNode->keyAndNextEngineParams[tmp].mask[0] = 0xFF; ++ ++ /* Store NextEngine parameters */ ++ memcpy(&p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams, ++ &p_KeyParams->ccNextEngineParams, ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ if ((p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ && p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip) ++ { ++ err = ++ AllocAndFillAdForContLookupManip( ++ p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ p_CcNode->keyAndNextEngineParams[tmp].requiredAction = requiredAction; ++ } ++ ++ *isKeyTblAlloc = FALSE; ++ ++ return E_OK; ++} ++ ++static t_Error IcHashIndexedCheckParams(t_Handle h_FmPcd, ++ t_FmPcdCcNodeParams *p_CcNodeParam, ++ t_FmPcdCcNode *p_CcNode, ++ bool *isKeyTblAlloc) ++{ ++ int tmp = 0, countOnes = 0; ++ t_FmPcdCcKeyParams *p_KeyParams; ++ t_Error err; ++ uint16_t glblMask = p_CcNodeParam->extractCcParams.extractNonHdr.icIndxMask; ++ uint16_t countMask = (uint16_t)(glblMask >> 4); ++ uint32_t requiredAction = 0; ++ ++ if (glblMask & 0x000f) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("icIndxMask has to be with last nibble 0")); ++ ++ while (countMask) ++ { ++ countOnes++; ++ countMask = (uint16_t)(countMask >> 1); ++ } ++ ++ if (!POWER_OF_2(p_CcNode->numOfKeys)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("For Node of the type INDEXED numOfKeys has to be powerOfTwo")); ++ ++ if (p_CcNode->numOfKeys != ((uint32_t)1 << countOnes)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("For Node of the type IC_HASH_INDEXED numOfKeys has to be powerOfTwo")); ++ ++ if (p_CcNodeParam->keysParams.maxNumOfKeys ++ && (p_CcNodeParam->keysParams.maxNumOfKeys != p_CcNode->numOfKeys)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("For Node of the type INDEXED 'maxNumOfKeys' should be 0 or equal 'numOfKeys'")); ++ ++ /* Validate statistics parameters */ ++ err = ValidateAndCalcStatsParams(p_CcNode, p_CcNodeParam, ++ &(p_CcNode->numOfStatsFLRs), ++ &(p_CcNode->countersArraySize)); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("Invalid statistics parameters")); ++ ++ err = ValidateNextEngineParams( ++ h_FmPcd, &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, ++ p_CcNode->statisticsMode); ++ if (GET_ERROR_TYPE(err) != E_NOT_SUPPORTED) ++ RETURN_ERROR( ++ MAJOR, ++ err, ++ ("MissNextEngineParams for the node of the type IC_INDEX_HASH has to be UnInitialized")); ++ ++ for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++) ++ { ++ p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp]; ++ ++ if (p_KeyParams->p_Mask || p_KeyParams->p_Key) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("For Node of the type IC_HASH_INDEXED p_Key or p_Mask has to be NULL")); ++ ++ if ((glblMask & (tmp * 16)) == (tmp * 16)) ++ { ++ err = ValidateNextEngineParams(h_FmPcd, ++ &p_KeyParams->ccNextEngineParams, ++ p_CcNode->statisticsMode); ++ if (err) ++ RETURN_ERROR( ++ MAJOR, ++ err, ++ ("This index has to be initialized for the node of the type IC_INDEX_HASH according to settings of GlobalMask ")); ++ ++ if (p_KeyParams->ccNextEngineParams.h_Manip) ++ { ++ err = FmPcdManipCheckParamsForCcNextEngine( ++ &p_KeyParams->ccNextEngineParams, &requiredAction); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ p_CcNode->keyAndNextEngineParams[tmp].requiredAction = ++ requiredAction; ++ } ++ ++ memcpy(&p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams, ++ &p_KeyParams->ccNextEngineParams, ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ if ((p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ && p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip) ++ { ++ err = ++ AllocAndFillAdForContLookupManip( ++ p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode); ++ if (err) ++ RETURN_ERROR(MAJOR, err, (NO_MSG)); ++ } ++ } ++ else ++ { ++ err = ValidateNextEngineParams(h_FmPcd, ++ &p_KeyParams->ccNextEngineParams, ++ p_CcNode->statisticsMode); ++ if (GET_ERROR_TYPE(err) != E_NOT_SUPPORTED) ++ RETURN_ERROR( ++ MAJOR, ++ err, ++ ("This index has to be UnInitialized for the node of the type IC_INDEX_HASH according to settings of GlobalMask")); ++ } ++ } ++ ++ *isKeyTblAlloc = FALSE; ++ memcpy(PTR_MOVE(p_CcNode->p_GlblMask, 2), &glblMask, 2); ++ ++ return E_OK; ++} ++ ++static t_Error ModifyNextEngineParamNode( ++ t_Handle h_FmPcd, t_Handle h_FmPcdCcNode, uint16_t keyIndex, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode; ++ t_FmPcd *p_FmPcd; ++ t_List h_OldPointersLst, h_NewPointersLst; ++ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_VALUE); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ ++ if (keyIndex >= p_CcNode->numOfKeys) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("keyIndex > previously cleared last index + 1")); ++ ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ ++ INIT_LIST(&h_OldPointersLst); ++ INIT_LIST(&h_NewPointersLst); ++ ++ p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex, ++ e_MODIFY_STATE_CHANGE, FALSE, ++ FALSE, FALSE); ++ if (!p_ModifyKeyParams) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ if (p_CcNode->maxNumOfKeys ++ && !TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ { ++ XX_Free(p_ModifyKeyParams); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = BuildNewNodeModifyNextEngine(h_FmPcd, p_CcNode, keyIndex, ++ p_FmPcdCcNextEngineParams, ++ &h_OldPointersLst, &h_NewPointersLst, ++ p_ModifyKeyParams); ++ if (err) ++ { ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst, ++ p_ModifyKeyParams, FALSE); ++ ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ ++ return err; ++} ++ ++static t_Error FindKeyIndex(t_Handle h_CcNode, uint8_t keySize, uint8_t *p_Key, ++ uint8_t *p_Mask, uint16_t *p_KeyIndex) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint8_t tmpMask[FM_PCD_MAX_SIZE_OF_KEY]; ++ uint16_t i; ++ ++ ASSERT_COND(p_Key); ++ ASSERT_COND(p_KeyIndex); ++ ASSERT_COND(keySize < FM_PCD_MAX_SIZE_OF_KEY); ++ ++ if (keySize != p_CcNode->userSizeOfExtraction) ++ RETURN_ERROR( ++ MINOR, E_INVALID_VALUE, ++ ("Key size doesn't match the extraction size of the node")); ++ ++ /* If user didn't pass a mask for this key, we'll look for full extraction mask */ ++ if (!p_Mask) ++ memset(tmpMask, 0xFF, keySize); ++ ++ for (i = 0; i < p_CcNode->numOfKeys; i++) ++ { ++ /* Comparing received key */ ++ if (memcmp(p_Key, p_CcNode->keyAndNextEngineParams[i].key, keySize) ++ == 0) ++ { ++ if (p_Mask) ++ { ++ /* If a user passed a mask for this key, it must match to the existing key's mask for a correct match */ ++ if (memcmp(p_Mask, p_CcNode->keyAndNextEngineParams[i].mask, ++ keySize) == 0) ++ { ++ *p_KeyIndex = i; ++ return E_OK; ++ } ++ } ++ else ++ { ++ /* If user didn't pass a mask for this key, check if the existing key mask is full extraction */ ++ if (memcmp(tmpMask, p_CcNode->keyAndNextEngineParams[i].mask, ++ keySize) == 0) ++ { ++ *p_KeyIndex = i; ++ return E_OK; ++ } ++ } ++ } ++ } ++ ++ return ERROR_CODE(E_NOT_FOUND); ++} ++ ++static t_Error CalcAndUpdateCcShadow(t_FmPcdCcNode *p_CcNode, ++ bool isKeyTblAlloc, ++ uint32_t *p_MatchTableSize, ++ uint32_t *p_AdTableSize) ++{ ++ uint32_t shadowSize; ++ t_Error err; ++ ++ /* Calculate keys table maximal size - each entry consists of a key and a mask, ++ (if local mask support is requested) */ ++ *p_MatchTableSize = p_CcNode->ccKeySizeAccExtraction * sizeof(uint8_t) ++ * p_CcNode->maxNumOfKeys; ++ ++ if (p_CcNode->maskSupport) ++ *p_MatchTableSize *= 2; ++ ++ /* Calculate next action descriptors table, including one more entry for miss */ ++ *p_AdTableSize = (uint32_t)((p_CcNode->maxNumOfKeys + 1) ++ * FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* Calculate maximal shadow size of this node. ++ All shadow structures will be used for runtime modifications host command. If ++ keys table was allocated for this node, the keys table and next engines table may ++ be modified in run time (entries added or removed), so shadow tables are requires. ++ Otherwise, the only supported runtime modification is a specific next engine update ++ and this requires shadow memory of a single AD */ ++ ++ /* Shadow size should be enough to hold the following 3 structures: ++ * 1 - an action descriptor */ ++ shadowSize = FM_PCD_CC_AD_ENTRY_SIZE; ++ ++ /* 2 - keys match table, if was allocated for the current node */ ++ if (isKeyTblAlloc) ++ shadowSize += *p_MatchTableSize; ++ ++ /* 3 - next action descriptors table */ ++ shadowSize += *p_AdTableSize; ++ ++ /* Update shadow to the calculated size */ ++ err = FmPcdUpdateCcShadow(p_CcNode->h_FmPcd, (uint32_t)shadowSize, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (err != E_OK) ++ { ++ DeleteNode(p_CcNode); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node shadow")); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error AllocStatsObjs(t_FmPcdCcNode *p_CcNode) ++{ ++ t_FmPcdStatsObj *p_StatsObj; ++ t_Handle h_FmMuram, h_StatsAd, h_StatsCounters; ++ uint32_t i; ++ ++ h_FmMuram = FmPcdGetMuramHandle(p_CcNode->h_FmPcd); ++ if (!h_FmMuram) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM MURAM")); ++ ++ /* Allocate statistics ADs and statistics counter. An extra pair (AD + counters) ++ will be allocated to support runtime modifications */ ++ for (i = 0; i < p_CcNode->maxNumOfKeys + 2; i++) ++ { ++ /* Allocate list object structure */ ++ p_StatsObj = XX_Malloc(sizeof(t_FmPcdStatsObj)); ++ if (!p_StatsObj) ++ { ++ FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Statistics object")); ++ } ++ memset(p_StatsObj, 0, sizeof(t_FmPcdStatsObj)); ++ ++ /* Allocate statistics AD from MURAM */ ++ h_StatsAd = (t_Handle)FM_MURAM_AllocMem(h_FmMuram, ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!h_StatsAd) ++ { ++ FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram); ++ XX_Free(p_StatsObj); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("MURAM allocation for statistics ADs")); ++ } ++ IOMemSet32(h_StatsAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* Allocate statistics counters from MURAM */ ++ h_StatsCounters = (t_Handle)FM_MURAM_AllocMem( ++ h_FmMuram, p_CcNode->countersArraySize, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!h_StatsCounters) ++ { ++ FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram); ++ FM_MURAM_FreeMem(h_FmMuram, h_StatsAd); ++ XX_Free(p_StatsObj); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("MURAM allocation for statistics counters")); ++ } ++ IOMemSet32(h_StatsCounters, 0, p_CcNode->countersArraySize); ++ ++ p_StatsObj->h_StatsAd = h_StatsAd; ++ p_StatsObj->h_StatsCounters = h_StatsCounters; ++ ++ EnqueueStatsObj(&p_CcNode->availableStatsLst, p_StatsObj); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error MatchTableGetKeyStatistics( ++ t_FmPcdCcNode *p_CcNode, uint16_t keyIndex, ++ t_FmPcdCcKeyStatistics *p_KeyStatistics) ++{ ++ uint32_t *p_StatsCounters, i; ++ ++ if (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("Statistics were not enabled for this match table")); ++ ++ if (!p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("Statistics were not enabled for this key")); ++ ++ memset(p_KeyStatistics, 0, sizeof(t_FmPcdCcKeyStatistics)); ++ ++ p_StatsCounters = ++ p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsCounters; ++ ASSERT_COND(p_StatsCounters); ++ ++ p_KeyStatistics->byteCount = GET_UINT32(*p_StatsCounters); ++ ++ for (i = 1; i <= p_CcNode->numOfStatsFLRs; i++) ++ { ++ p_StatsCounters = ++ PTR_MOVE(p_StatsCounters, FM_PCD_CC_STATS_COUNTER_SIZE); ++ ++ p_KeyStatistics->frameCount += GET_UINT32(*p_StatsCounters); ++ ++#if (DPAA_VERSION >= 11) ++ p_KeyStatistics->frameLengthRangeCount[i - 1] = ++ GET_UINT32(*p_StatsCounters); ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ return E_OK; ++} ++ ++static t_Error MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNode *p_CcNode, ++ t_FmPcdCcNodeParams *p_CcNodeParam) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_FmPcdCcNode *p_FmPcdCcNextNode; ++ t_Error err = E_OK; ++ uint32_t tmp, keySize; ++ bool glblMask = FALSE; ++ t_FmPcdCcKeyParams *p_KeyParams; ++ t_Handle h_FmMuram, p_KeysMatchTblTmp, p_AdTableTmp; ++#if (DPAA_VERSION >= 11) ++ t_Handle h_StatsFLRs; ++#endif /* (DPAA_VERSION >= 11) */ ++ bool fullField = FALSE; ++ ccPrivateInfo_t icCode = CC_PRIVATE_INFO_NONE; ++ bool isKeyTblAlloc, fromIc = FALSE; ++ uint32_t matchTableSize, adTableSize; ++ t_CcNodeInformation ccNodeInfo, *p_CcInformation; ++ t_FmPcdStatsObj *p_StatsObj; ++ t_FmPcdCcStatsParams statsParams = { 0 }; ++ t_Handle h_Manip; ++ ++ ASSERT_COND(h_FmPcd); ++ ASSERT_COND(p_CcNode); ++ ASSERT_COND(p_CcNodeParam); ++ ++ p_CcNode->p_GlblMask = (t_Handle)XX_Malloc( ++ CC_GLBL_MASK_SIZE * sizeof(uint8_t)); ++ memset(p_CcNode->p_GlblMask, 0, CC_GLBL_MASK_SIZE * sizeof(uint8_t)); ++ ++ p_CcNode->h_FmPcd = h_FmPcd; ++ p_CcNode->numOfKeys = p_CcNodeParam->keysParams.numOfKeys; ++ p_CcNode->maxNumOfKeys = p_CcNodeParam->keysParams.maxNumOfKeys; ++ p_CcNode->maskSupport = p_CcNodeParam->keysParams.maskSupport; ++ p_CcNode->statisticsMode = p_CcNodeParam->keysParams.statisticsMode; ++ ++ /* For backward compatibility - even if statistics mode is nullified, ++ we'll fix it to frame mode so we can support per-key request for ++ statistics using 'statisticsEn' in next engine parameters */ ++ if (!p_CcNode->maxNumOfKeys ++ && (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE)) ++ p_CcNode->statisticsMode = e_FM_PCD_CC_STATS_MODE_FRAME; ++ ++ h_FmMuram = FmPcdGetMuramHandle(h_FmPcd); ++ if (!h_FmMuram) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM MURAM")); ++ ++ INIT_LIST(&p_CcNode->ccPrevNodesLst); ++ INIT_LIST(&p_CcNode->ccTreeIdLst); ++ INIT_LIST(&p_CcNode->ccTreesLst); ++ INIT_LIST(&p_CcNode->availableStatsLst); ++ ++ p_CcNode->h_Spinlock = XX_InitSpinlock(); ++ if (!p_CcNode->h_Spinlock) ++ { ++ DeleteNode(p_CcNode); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("CC node spinlock")); ++ } ++ ++ if ((p_CcNodeParam->extractCcParams.type == e_FM_PCD_EXTRACT_BY_HDR) ++ && ((p_CcNodeParam->extractCcParams.extractByHdr.hdr ++ == HEADER_TYPE_IPv4) ++ || (p_CcNodeParam->extractCcParams.extractByHdr.hdr ++ == HEADER_TYPE_IPv6)) ++ && (p_CcNodeParam->extractCcParams.extractByHdr.type ++ == e_FM_PCD_EXTRACT_FULL_FIELD) ++ && ((p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField.ipv6 ++ == NET_HEADER_FIELD_IPv6_HOP_LIMIT) ++ || (p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField.ipv4 ++ == NET_HEADER_FIELD_IPv4_TTL))) ++ { ++ err = Ipv4TtlOrIpv6HopLimitCheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, ++ &isKeyTblAlloc); ++ glblMask = FALSE; ++ } ++ else ++ if ((p_CcNodeParam->extractCcParams.type == e_FM_PCD_EXTRACT_NON_HDR) ++ && ((p_CcNodeParam->extractCcParams.extractNonHdr.src ++ == e_FM_PCD_EXTRACT_FROM_KEY) ++ || (p_CcNodeParam->extractCcParams.extractNonHdr.src ++ == e_FM_PCD_EXTRACT_FROM_HASH) ++ || (p_CcNodeParam->extractCcParams.extractNonHdr.src ++ == e_FM_PCD_EXTRACT_FROM_FLOW_ID))) ++ { ++ if ((p_CcNodeParam->extractCcParams.extractNonHdr.src ++ == e_FM_PCD_EXTRACT_FROM_FLOW_ID) ++ && (p_CcNodeParam->extractCcParams.extractNonHdr.offset != 0)) ++ { ++ DeleteNode(p_CcNode); ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("In the case of the extraction from e_FM_PCD_EXTRACT_FROM_FLOW_ID offset has to be 0")); ++ } ++ ++ icCode = IcDefineCode(p_CcNodeParam); ++ fromIc = TRUE; ++ if (icCode == CC_PRIVATE_INFO_NONE) ++ { ++ DeleteNode(p_CcNode); ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("user asked extraction from IC and field in internal context or action wasn't initialized in the right way")); ++ } ++ ++ if ((icCode == CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP) ++ || (icCode == CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP)) ++ { ++ err = IcHashIndexedCheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, ++ &isKeyTblAlloc); ++ glblMask = TRUE; ++ } ++ else ++ { ++ err = CheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, ++ &isKeyTblAlloc); ++ if (p_CcNode->glblMaskSize) ++ glblMask = TRUE; ++ } ++ } ++ else ++ { ++ err = CheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc); ++ if (p_CcNode->glblMaskSize) ++ glblMask = TRUE; ++ } ++ ++ if (err) ++ { ++ DeleteNode(p_CcNode); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ switch (p_CcNodeParam->extractCcParams.type) ++ { ++ case (e_FM_PCD_EXTRACT_BY_HDR): ++ switch (p_CcNodeParam->extractCcParams.extractByHdr.type) ++ { ++ case (e_FM_PCD_EXTRACT_FULL_FIELD): ++ p_CcNode->parseCode = ++ GetFullFieldParseCode( ++ p_CcNodeParam->extractCcParams.extractByHdr.hdr, ++ p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex, ++ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField); ++ GetSizeHeaderField( ++ p_CcNodeParam->extractCcParams.extractByHdr.hdr, ++ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField, ++ &p_CcNode->sizeOfExtraction); ++ fullField = TRUE; ++ if ((p_CcNode->parseCode != CC_PC_FF_TCI1) ++ && (p_CcNode->parseCode != CC_PC_FF_TCI2) ++ && (p_CcNode->parseCode != CC_PC_FF_MPLS1) ++ && (p_CcNode->parseCode != CC_PC_FF_MPLS_LAST) ++ && (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC1) ++ && (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC2) ++ && (p_CcNode->parseCode ++ != CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1) ++ && (p_CcNode->parseCode != CC_PC_FF_IPDSCP) ++ && (p_CcNode->parseCode ++ != CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2) ++ && glblMask) ++ { ++ glblMask = FALSE; ++ p_CcNode->glblMaskSize = 4; ++ p_CcNode->lclMask = TRUE; ++ } ++ break; ++ ++ case (e_FM_PCD_EXTRACT_FROM_HDR): ++ p_CcNode->sizeOfExtraction = ++ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.size; ++ p_CcNode->offset = ++ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.offset; ++ p_CcNode->userOffset = ++ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.offset; ++ p_CcNode->parseCode = ++ GetPrParseCode( ++ p_CcNodeParam->extractCcParams.extractByHdr.hdr, ++ p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex, ++ p_CcNode->offset, glblMask, ++ &p_CcNode->prsArrayOffset); ++ break; ++ ++ case (e_FM_PCD_EXTRACT_FROM_FIELD): ++ p_CcNode->offset = ++ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.offset; ++ p_CcNode->userOffset = ++ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.offset; ++ p_CcNode->sizeOfExtraction = ++ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.size; ++ p_CcNode->parseCode = ++ GetFieldParseCode( ++ p_CcNodeParam->extractCcParams.extractByHdr.hdr, ++ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.field, ++ p_CcNode->offset, ++ &p_CcNode->prsArrayOffset, ++ p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex); ++ break; ++ ++ default: ++ DeleteNode(p_CcNode); ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ break; ++ ++ case (e_FM_PCD_EXTRACT_NON_HDR): ++ /* get the field code for the generic extract */ ++ p_CcNode->sizeOfExtraction = ++ p_CcNodeParam->extractCcParams.extractNonHdr.size; ++ p_CcNode->offset = ++ p_CcNodeParam->extractCcParams.extractNonHdr.offset; ++ p_CcNode->userOffset = ++ p_CcNodeParam->extractCcParams.extractNonHdr.offset; ++ p_CcNode->parseCode = GetGenParseCode( ++ p_CcNodeParam->extractCcParams.extractNonHdr.src, ++ p_CcNode->offset, glblMask, &p_CcNode->prsArrayOffset, ++ fromIc, icCode); ++ ++ if (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED) ++ { ++ if ((p_CcNode->offset + p_CcNode->sizeOfExtraction) > 8) ++ { ++ DeleteNode(p_CcNode); ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_SELECTION, ++ ("when node of the type CC_PC_GENERIC_IC_HASH_INDEXED offset + size can not be bigger then size of HASH 64 bits (8 bytes)")); ++ } ++ } ++ if ((p_CcNode->parseCode == CC_PC_GENERIC_IC_GMASK) ++ || (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED)) ++ { ++ p_CcNode->offset += p_CcNode->prsArrayOffset; ++ p_CcNode->prsArrayOffset = 0; ++ } ++ break; ++ ++ default: ++ DeleteNode(p_CcNode); ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ if (p_CcNode->parseCode == CC_PC_ILLEGAL) ++ { ++ DeleteNode(p_CcNode); ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("illegal extraction type")); ++ } ++ ++ if ((p_CcNode->sizeOfExtraction > FM_PCD_MAX_SIZE_OF_KEY) ++ || !p_CcNode->sizeOfExtraction) ++ { ++ DeleteNode(p_CcNode); ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("sizeOfExatrction can not be greater than 56 and not 0")); ++ } ++ ++ if (p_CcNodeParam->keysParams.keySize != p_CcNode->sizeOfExtraction) ++ { ++ DeleteNode(p_CcNode); ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("keySize has to be equal to sizeOfExtraction")); ++ } ++ ++ p_CcNode->userSizeOfExtraction = p_CcNode->sizeOfExtraction; ++ ++ if (!glblMask) ++ memset(p_CcNode->p_GlblMask, 0xff, CC_GLBL_MASK_SIZE * sizeof(uint8_t)); ++ ++ err = CheckAndSetManipParamsWithCcNodeParams(p_CcNode); ++ if (err != E_OK) ++ { ++ DeleteNode(p_CcNode); ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("keySize has to be equal to sizeOfExtraction")); ++ } ++ ++ /* Calculating matching table entry size by rounding up the user-defined size of extraction to valid entry size */ ++ GetCcExtractKeySize(p_CcNode->sizeOfExtraction, ++ &p_CcNode->ccKeySizeAccExtraction); ++ ++ /* If local mask is used, it is stored next to each key in the keys match table */ ++ if (p_CcNode->lclMask) ++ keySize = (uint32_t)(2 * p_CcNode->ccKeySizeAccExtraction); ++ else ++ keySize = p_CcNode->ccKeySizeAccExtraction; ++ ++ /* Update CC shadow with maximal size required by this node */ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ err = CalcAndUpdateCcShadow(p_CcNode, isKeyTblAlloc, &matchTableSize, ++ &adTableSize); ++ if (err != E_OK) ++ { ++ DeleteNode(p_CcNode); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ p_CcNode->keysMatchTableMaxSize = matchTableSize; ++ ++ if (p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_NONE) ++ { ++ err = AllocStatsObjs(p_CcNode); ++ if (err != E_OK) ++ { ++ DeleteNode(p_CcNode); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ ++ /* If manipulation will be initialized before this node, it will use the table ++ descriptor in the AD table of previous node and this node will need an extra ++ AD as his table descriptor. */ ++ p_CcNode->h_TmpAd = (t_Handle)FM_MURAM_AllocMem( ++ h_FmMuram, FM_PCD_CC_AD_ENTRY_SIZE, FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_CcNode->h_TmpAd) ++ { ++ DeleteNode(p_CcNode); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("MURAM allocation for CC action descriptor")); ++ } ++ } ++ else ++ { ++ matchTableSize = (uint32_t)(keySize * sizeof(uint8_t) ++ * (p_CcNode->numOfKeys + 1)); ++ adTableSize = (uint32_t)(FM_PCD_CC_AD_ENTRY_SIZE ++ * (p_CcNode->numOfKeys + 1)); ++ } ++ ++#if (DPAA_VERSION >= 11) ++ switch (p_CcNode->statisticsMode) ++ { ++ ++ case e_FM_PCD_CC_STATS_MODE_RMON: ++ /* If RMON statistics or RMON conditional statistics modes are requested, ++ allocate frame length ranges array */ ++ p_CcNode->h_StatsFLRs = FM_MURAM_AllocMem( ++ h_FmMuram, ++ (uint32_t)(p_CcNode->numOfStatsFLRs) ++ * FM_PCD_CC_STATS_FLR_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ ++ if (!p_CcNode->h_StatsFLRs) ++ { ++ DeleteNode(p_CcNode); ++ RETURN_ERROR( ++ MAJOR, E_NO_MEMORY, ++ ("MURAM allocation for CC frame length ranges array")); ++ } ++ ++ /* Initialize using value received from the user */ ++ for (tmp = 0; tmp < p_CcNode->numOfStatsFLRs; tmp++) ++ { ++ h_StatsFLRs = ++ PTR_MOVE(p_CcNode->h_StatsFLRs, tmp * FM_PCD_CC_STATS_FLR_SIZE); ++ ++ Mem2IOCpy32(h_StatsFLRs, ++ &(p_CcNodeParam->keysParams.frameLengthRanges[tmp]), ++ FM_PCD_CC_STATS_FLR_SIZE); ++ } ++ break; ++ ++ default: ++ break; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ /* Allocate keys match table. Not required for some CC nodes, for example for IPv4 TTL ++ identification, IPv6 hop count identification, etc. */ ++ if (isKeyTblAlloc) ++ { ++ p_CcNode->h_KeysMatchTable = (t_Handle)FM_MURAM_AllocMem( ++ h_FmMuram, matchTableSize, FM_PCD_CC_KEYS_MATCH_TABLE_ALIGN); ++ if (!p_CcNode->h_KeysMatchTable) ++ { ++ DeleteNode(p_CcNode); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("MURAM allocation for CC node key match table")); ++ } ++ IOMemSet32((uint8_t *)p_CcNode->h_KeysMatchTable, 0, matchTableSize); ++ } ++ ++ /* Allocate action descriptors table */ ++ p_CcNode->h_AdTable = (t_Handle)FM_MURAM_AllocMem(h_FmMuram, adTableSize, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_CcNode->h_AdTable) ++ { ++ DeleteNode(p_CcNode); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("MURAM allocation for CC node action descriptors table")); ++ } ++ IOMemSet32((uint8_t *)p_CcNode->h_AdTable, 0, adTableSize); ++ ++ p_KeysMatchTblTmp = p_CcNode->h_KeysMatchTable; ++ p_AdTableTmp = p_CcNode->h_AdTable; ++ ++ /* For each key, create the key and the next step AD */ ++ for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++) ++ { ++ p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp]; ++ ++ if (p_KeysMatchTblTmp) ++ { ++ /* Copy the key */ ++ Mem2IOCpy32((void*)p_KeysMatchTblTmp, p_KeyParams->p_Key, ++ p_CcNode->sizeOfExtraction); ++ ++ /* Copy the key mask or initialize it to 0xFF..F */ ++ if (p_CcNode->lclMask && p_KeyParams->p_Mask) ++ { ++ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTblTmp, ++ p_CcNode->ccKeySizeAccExtraction), /* User's size of extraction rounded up to a valid matching table entry size */ ++ p_KeyParams->p_Mask, p_CcNode->sizeOfExtraction); /* Exact size of extraction as received from the user */ ++ } ++ else ++ if (p_CcNode->lclMask) ++ { ++ IOMemSet32(PTR_MOVE(p_KeysMatchTblTmp, ++ p_CcNode->ccKeySizeAccExtraction), /* User's size of extraction rounded up to a valid matching table entry size */ ++ 0xff, p_CcNode->sizeOfExtraction); /* Exact size of extraction as received from the user */ ++ } ++ ++ p_KeysMatchTblTmp = ++ PTR_MOVE(p_KeysMatchTblTmp, keySize * sizeof(uint8_t)); ++ } ++ ++ /* Create the next action descriptor in the match table */ ++ if (p_KeyParams->ccNextEngineParams.statisticsEn) ++ { ++ p_StatsObj = GetStatsObj(p_CcNode); ++ ASSERT_COND(p_StatsObj); ++ ++ statsParams.h_StatsAd = p_StatsObj->h_StatsAd; ++ statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters; ++#if (DPAA_VERSION >= 11) ++ statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs; ++ ++#endif /* (DPAA_VERSION >= 11) */ ++ NextStepAd(p_AdTableTmp, &statsParams, ++ &p_KeyParams->ccNextEngineParams, p_FmPcd); ++ ++ p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = p_StatsObj; ++ } ++ else ++ { ++ NextStepAd(p_AdTableTmp, NULL, &p_KeyParams->ccNextEngineParams, ++ p_FmPcd); ++ ++ p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = NULL; ++ } ++ ++ p_AdTableTmp = PTR_MOVE(p_AdTableTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ } ++ ++ /* Update next engine for the 'miss' entry */ ++ if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.statisticsEn) ++ { ++ p_StatsObj = GetStatsObj(p_CcNode); ++ ASSERT_COND(p_StatsObj); ++ ++ /* All 'bucket' nodes of a hash table should share the same statistics counters, ++ allocated by the hash table. So, if this node is a bucket of a hash table, ++ we'll replace the locally allocated counters with the shared counters. */ ++ if (p_CcNode->isHashBucket) ++ { ++ ASSERT_COND(p_CcNode->h_MissStatsCounters); ++ ++ /* Store original counters pointer and replace it with mutual preallocated pointer */ ++ p_CcNode->h_PrivMissStatsCounters = p_StatsObj->h_StatsCounters; ++ p_StatsObj->h_StatsCounters = p_CcNode->h_MissStatsCounters; ++ } ++ ++ statsParams.h_StatsAd = p_StatsObj->h_StatsAd; ++ statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters; ++#if (DPAA_VERSION >= 11) ++ statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs; ++ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ NextStepAd(p_AdTableTmp, &statsParams, ++ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, ++ p_FmPcd); ++ ++ p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = p_StatsObj; ++ } ++ else ++ { ++ NextStepAd(p_AdTableTmp, NULL, ++ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, ++ p_FmPcd); ++ ++ p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = NULL; ++ } ++ ++ /* This parameter will be used to initialize the "key length" field in the action descriptor ++ that points to this node and it should be 0 for full field extraction */ ++ if (fullField == TRUE) ++ p_CcNode->sizeOfExtraction = 0; ++ ++ for (tmp = 0; tmp < MIN(p_CcNode->numOfKeys + 1, CC_MAX_NUM_OF_KEYS); tmp++) ++ { ++ if (p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ { ++ p_FmPcdCcNextNode = ++ (t_FmPcdCcNode*)p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode; ++ p_CcInformation = FindNodeInfoInReleventLst( ++ &p_FmPcdCcNextNode->ccPrevNodesLst, (t_Handle)p_CcNode, ++ p_FmPcdCcNextNode->h_Spinlock); ++ if (!p_CcInformation) ++ { ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = (t_Handle)p_CcNode; ++ ccNodeInfo.index = 1; ++ EnqueueNodeInfoToRelevantLst(&p_FmPcdCcNextNode->ccPrevNodesLst, ++ &ccNodeInfo, ++ p_FmPcdCcNextNode->h_Spinlock); ++ } ++ else ++ p_CcInformation->index++; ++ ++ if (p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip) ++ { ++ h_Manip = ++ p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip; ++ p_CcInformation = FindNodeInfoInReleventLst( ++ FmPcdManipGetNodeLstPointedOnThisManip(h_Manip), ++ (t_Handle)p_CcNode, FmPcdManipGetSpinlock(h_Manip)); ++ if (!p_CcInformation) ++ { ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = (t_Handle)p_CcNode; ++ ccNodeInfo.index = 1; ++ EnqueueNodeInfoToRelevantLst( ++ FmPcdManipGetNodeLstPointedOnThisManip(h_Manip), ++ &ccNodeInfo, FmPcdManipGetSpinlock(h_Manip)); ++ } ++ else ++ p_CcInformation->index++; ++ } ++ } ++ } ++ ++ p_AdTableTmp = p_CcNode->h_AdTable; ++ ++ if (!FmPcdLockTryLockAll(h_FmPcd)) ++ { ++ FM_PCD_MatchTableDelete((t_Handle)p_CcNode); ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ /* Required action for each next engine */ ++ for (tmp = 0; tmp < MIN(p_CcNode->numOfKeys + 1, CC_MAX_NUM_OF_KEYS); tmp++) ++ { ++ if (p_CcNode->keyAndNextEngineParams[tmp].requiredAction) ++ { ++ err = SetRequiredAction( ++ h_FmPcd, ++ p_CcNode->keyAndNextEngineParams[tmp].requiredAction, ++ &p_CcNode->keyAndNextEngineParams[tmp], p_AdTableTmp, 1, ++ NULL); ++ if (err) ++ { ++ FmPcdLockUnlockAll(h_FmPcd); ++ FM_PCD_MatchTableDelete((t_Handle)p_CcNode); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ p_AdTableTmp = PTR_MOVE(p_AdTableTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ } ++ } ++ ++ FmPcdLockUnlockAll(h_FmPcd); ++ ++ return E_OK; ++} ++/************************** End of static functions **************************/ ++ ++/*****************************************************************************/ ++/* Inter-module API routines */ ++/*****************************************************************************/ ++ ++t_CcNodeInformation* FindNodeInfoInReleventLst(t_List *p_List, t_Handle h_Info, ++ t_Handle h_Spinlock) ++{ ++ t_CcNodeInformation *p_CcInformation; ++ t_List *p_Pos; ++ uint32_t intFlags; ++ ++ intFlags = XX_LockIntrSpinlock(h_Spinlock); ++ ++ for (p_Pos = LIST_FIRST(p_List); p_Pos != (p_List); ++ p_Pos = LIST_NEXT(p_Pos)) ++ { ++ p_CcInformation = CC_NODE_F_OBJECT(p_Pos); ++ ++ ASSERT_COND(p_CcInformation->h_CcNode); ++ ++ if (p_CcInformation->h_CcNode == h_Info) ++ { ++ XX_UnlockIntrSpinlock(h_Spinlock, intFlags); ++ return p_CcInformation; ++ } ++ } ++ ++ XX_UnlockIntrSpinlock(h_Spinlock, intFlags); ++ ++ return NULL; ++} ++ ++void EnqueueNodeInfoToRelevantLst(t_List *p_List, t_CcNodeInformation *p_CcInfo, ++ t_Handle h_Spinlock) ++{ ++ t_CcNodeInformation *p_CcInformation; ++ uint32_t intFlags = 0; ++ ++ p_CcInformation = (t_CcNodeInformation *)XX_Malloc( ++ sizeof(t_CcNodeInformation)); ++ ++ if (p_CcInformation) ++ { ++ memset(p_CcInformation, 0, sizeof(t_CcNodeInformation)); ++ memcpy(p_CcInformation, p_CcInfo, sizeof(t_CcNodeInformation)); ++ INIT_LIST(&p_CcInformation->node); ++ ++ if (h_Spinlock) ++ intFlags = XX_LockIntrSpinlock(h_Spinlock); ++ ++ LIST_AddToTail(&p_CcInformation->node, p_List); ++ ++ if (h_Spinlock) ++ XX_UnlockIntrSpinlock(h_Spinlock, intFlags); ++ } ++ else ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("CC Node Information")); ++} ++ ++void DequeueNodeInfoFromRelevantLst(t_List *p_List, t_Handle h_Info, ++ t_Handle h_Spinlock) ++{ ++ t_CcNodeInformation *p_CcInformation = NULL; ++ uint32_t intFlags = 0; ++ t_List *p_Pos; ++ ++ if (h_Spinlock) ++ intFlags = XX_LockIntrSpinlock(h_Spinlock); ++ ++ if (LIST_IsEmpty(p_List)) ++ { ++ XX_RestoreAllIntr(intFlags); ++ return; ++ } ++ ++ for (p_Pos = LIST_FIRST(p_List); p_Pos != (p_List); ++ p_Pos = LIST_NEXT(p_Pos)) ++ { ++ p_CcInformation = CC_NODE_F_OBJECT(p_Pos); ++ ASSERT_COND(p_CcInformation); ++ ASSERT_COND(p_CcInformation->h_CcNode); ++ if (p_CcInformation->h_CcNode == h_Info) ++ break; ++ } ++ ++ if (p_CcInformation) ++ { ++ LIST_DelAndInit(&p_CcInformation->node); ++ XX_Free(p_CcInformation); ++ } ++ ++ if (h_Spinlock) ++ XX_UnlockIntrSpinlock(h_Spinlock, intFlags); ++} ++ ++void NextStepAd(t_Handle h_Ad, t_FmPcdCcStatsParams *p_FmPcdCcStatsParams, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams, ++ t_FmPcd *p_FmPcd) ++{ ++ switch (p_FmPcdCcNextEngineParams->nextEngine) ++ { ++ case (e_FM_PCD_KG): ++ case (e_FM_PCD_PLCR): ++ case (e_FM_PCD_DONE): ++ /* if NIA is not CC, create a "result" type AD */ ++ FillAdOfTypeResult(h_Ad, p_FmPcdCcStatsParams, p_FmPcd, ++ p_FmPcdCcNextEngineParams); ++ break; ++#if (DPAA_VERSION >= 11) ++ case (e_FM_PCD_FR): ++ if (p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic) ++ { ++ FillAdOfTypeContLookup( ++ h_Ad, p_FmPcdCcStatsParams, p_FmPcd, ++ p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode, ++ p_FmPcdCcNextEngineParams->h_Manip, ++ p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic); ++ FrmReplicGroupUpdateOwner( ++ p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic, ++ TRUE/* add */); ++ } ++ break; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ case (e_FM_PCD_CC): ++ /* if NIA is not CC, create a TD to continue the CC lookup */ ++ FillAdOfTypeContLookup( ++ h_Ad, p_FmPcdCcStatsParams, p_FmPcd, ++ p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode, ++ p_FmPcdCcNextEngineParams->h_Manip, NULL); ++ ++ UpdateNodeOwner(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode, ++ TRUE); ++ break; ++ ++ default: ++ return; ++ } ++} ++ ++t_Error FmPcdCcTreeAddIPR(t_Handle h_FmPcd, t_Handle h_FmTree, ++ t_Handle h_NetEnv, t_Handle h_IpReassemblyManip, ++ bool createSchemes) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree; ++ t_FmPcdCcNextEngineParams nextEngineParams; ++ t_NetEnvParams netEnvParams; ++ t_Handle h_Ad; ++ bool isIpv6Present; ++ uint8_t ipv4GroupId, ipv6GroupId; ++ t_Error err; ++ ++ ASSERT_COND(p_FmPcdCcTree); ++ ++ /* this routine must be protected by the calling routine! */ ++ ++ memset(&nextEngineParams, 0, sizeof(t_FmPcdCcNextEngineParams)); ++ memset(&netEnvParams, 0, sizeof(t_NetEnvParams)); ++ ++ h_Ad = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); ++ ++ isIpv6Present = FmPcdManipIpReassmIsIpv6Hdr(h_IpReassemblyManip); ++ ++ if (isIpv6Present ++ && (p_FmPcdCcTree->numOfEntries > (FM_PCD_MAX_NUM_OF_CC_GROUPS - 2))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("need two free entries for IPR")); ++ ++ if (p_FmPcdCcTree->numOfEntries > (FM_PCD_MAX_NUM_OF_CC_GROUPS - 1)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("need two free entries for IPR")); ++ ++ nextEngineParams.nextEngine = e_FM_PCD_DONE; ++ nextEngineParams.h_Manip = h_IpReassemblyManip; ++ ++ /* Lock tree */ ++ err = CcRootTryLock(p_FmPcdCcTree); ++ if (err) ++ return ERROR_CODE(E_BUSY); ++ ++ if (p_FmPcdCcTree->h_IpReassemblyManip == h_IpReassemblyManip) ++ { ++ CcRootReleaseLock(p_FmPcdCcTree); ++ return E_OK; ++ } ++ ++ if ((p_FmPcdCcTree->h_IpReassemblyManip) ++ && (p_FmPcdCcTree->h_IpReassemblyManip != h_IpReassemblyManip)) ++ { ++ CcRootReleaseLock(p_FmPcdCcTree); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("This tree was previously updated with different IPR")); ++ } ++ ++ /* Initialize IPR for the first time for this tree */ ++ if (isIpv6Present) ++ { ++ ipv6GroupId = p_FmPcdCcTree->numOfGrps++; ++ p_FmPcdCcTree->fmPcdGroupParam[ipv6GroupId].baseGroupEntry = ++ (FM_PCD_MAX_NUM_OF_CC_GROUPS - 2); ++ ++ if (createSchemes) ++ { ++ err = FmPcdManipBuildIpReassmScheme(h_FmPcd, h_NetEnv, ++ p_FmPcdCcTree, ++ h_IpReassemblyManip, FALSE, ++ ipv6GroupId); ++ if (err) ++ { ++ p_FmPcdCcTree->numOfGrps--; ++ CcRootReleaseLock(p_FmPcdCcTree); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ ++ NextStepAd( ++ PTR_MOVE(h_Ad, (FM_PCD_MAX_NUM_OF_CC_GROUPS-2) * FM_PCD_CC_AD_ENTRY_SIZE), ++ NULL, &nextEngineParams, h_FmPcd); ++ } ++ ++ ipv4GroupId = p_FmPcdCcTree->numOfGrps++; ++ p_FmPcdCcTree->fmPcdGroupParam[ipv4GroupId].totalBitsMask = 0; ++ p_FmPcdCcTree->fmPcdGroupParam[ipv4GroupId].baseGroupEntry = ++ (FM_PCD_MAX_NUM_OF_CC_GROUPS - 1); ++ ++ if (createSchemes) ++ { ++ err = FmPcdManipBuildIpReassmScheme(h_FmPcd, h_NetEnv, p_FmPcdCcTree, ++ h_IpReassemblyManip, TRUE, ++ ipv4GroupId); ++ if (err) ++ { ++ p_FmPcdCcTree->numOfGrps--; ++ if (isIpv6Present) ++ { ++ p_FmPcdCcTree->numOfGrps--; ++ FmPcdManipDeleteIpReassmSchemes(h_IpReassemblyManip); ++ } ++ CcRootReleaseLock(p_FmPcdCcTree); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ ++ NextStepAd( ++ PTR_MOVE(h_Ad, (FM_PCD_MAX_NUM_OF_CC_GROUPS-1) * FM_PCD_CC_AD_ENTRY_SIZE), ++ NULL, &nextEngineParams, h_FmPcd); ++ ++ p_FmPcdCcTree->h_IpReassemblyManip = h_IpReassemblyManip; ++ ++ CcRootReleaseLock(p_FmPcdCcTree); ++ ++ return E_OK; ++} ++ ++t_Error FmPcdCcTreeAddCPR(t_Handle h_FmPcd, t_Handle h_FmTree, ++ t_Handle h_NetEnv, t_Handle h_ReassemblyManip, ++ bool createSchemes) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree; ++ t_FmPcdCcNextEngineParams nextEngineParams; ++ t_NetEnvParams netEnvParams; ++ t_Handle h_Ad; ++ uint8_t groupId; ++ t_Error err; ++ ++ ASSERT_COND(p_FmPcdCcTree); ++ ++ /* this routine must be protected by the calling routine! */ ++ memset(&nextEngineParams, 0, sizeof(t_FmPcdCcNextEngineParams)); ++ memset(&netEnvParams, 0, sizeof(t_NetEnvParams)); ++ ++ h_Ad = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); ++ ++ if (p_FmPcdCcTree->numOfEntries > (FM_PCD_MAX_NUM_OF_CC_GROUPS - 1)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("need one free entries for CPR")); ++ ++ nextEngineParams.nextEngine = e_FM_PCD_DONE; ++ nextEngineParams.h_Manip = h_ReassemblyManip; ++ ++ /* Lock tree */ ++ err = CcRootTryLock(p_FmPcdCcTree); ++ if (err) ++ return ERROR_CODE(E_BUSY); ++ ++ if (p_FmPcdCcTree->h_CapwapReassemblyManip == h_ReassemblyManip) ++ { ++ CcRootReleaseLock(p_FmPcdCcTree); ++ return E_OK; ++ } ++ ++ if ((p_FmPcdCcTree->h_CapwapReassemblyManip) ++ && (p_FmPcdCcTree->h_CapwapReassemblyManip != h_ReassemblyManip)) ++ { ++ CcRootReleaseLock(p_FmPcdCcTree); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("This tree was previously updated with different CPR")); ++ } ++ ++ groupId = p_FmPcdCcTree->numOfGrps++; ++ p_FmPcdCcTree->fmPcdGroupParam[groupId].baseGroupEntry = ++ (FM_PCD_MAX_NUM_OF_CC_GROUPS - 1); ++ ++ if (createSchemes) ++ { ++ err = FmPcdManipBuildCapwapReassmScheme(h_FmPcd, h_NetEnv, ++ p_FmPcdCcTree, ++ h_ReassemblyManip, groupId); ++ if (err) ++ { ++ p_FmPcdCcTree->numOfGrps--; ++ CcRootReleaseLock(p_FmPcdCcTree); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ ++ NextStepAd( ++ PTR_MOVE(h_Ad, (FM_PCD_MAX_NUM_OF_CC_GROUPS-1) * FM_PCD_CC_AD_ENTRY_SIZE), ++ NULL, &nextEngineParams, h_FmPcd); ++ ++ p_FmPcdCcTree->h_CapwapReassemblyManip = h_ReassemblyManip; ++ ++ CcRootReleaseLock(p_FmPcdCcTree); ++ ++ return E_OK; ++} ++ ++t_Handle FmPcdCcTreeGetSavedManipParams(t_Handle h_FmTree) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree; ++ ++ ASSERT_COND(p_FmPcdCcTree); ++ ++ return p_FmPcdCcTree->h_FmPcdCcSavedManipParams; ++} ++ ++void FmPcdCcTreeSetSavedManipParams(t_Handle h_FmTree, ++ t_Handle h_SavedManipParams) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree; ++ ++ ASSERT_COND(p_FmPcdCcTree); ++ ++ p_FmPcdCcTree->h_FmPcdCcSavedManipParams = h_SavedManipParams; ++} ++ ++uint8_t FmPcdCcGetParseCode(t_Handle h_CcNode) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ ++ ASSERT_COND(p_CcNode); ++ ++ return p_CcNode->parseCode; ++} ++ ++uint8_t FmPcdCcGetOffset(t_Handle h_CcNode) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ ++ ASSERT_COND(p_CcNode); ++ ++ return p_CcNode->offset; ++} ++ ++uint16_t FmPcdCcGetNumOfKeys(t_Handle h_CcNode) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ ++ ASSERT_COND(p_CcNode); ++ ++ return p_CcNode->numOfKeys; ++} ++ ++t_Error FmPcdCcModifyNextEngineParamTree( ++ t_Handle h_FmPcd, t_Handle h_FmPcdCcTree, uint8_t grpId, uint8_t index, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree; ++ t_FmPcd *p_FmPcd; ++ t_List h_OldPointersLst, h_NewPointersLst; ++ uint16_t keyIndex; ++ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((grpId <= 7), E_INVALID_VALUE); ++ ++ if (grpId >= p_FmPcdCcTree->numOfGrps) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ++ ("grpId you asked > numOfGroup of relevant tree")); ++ ++ if (index >= p_FmPcdCcTree->fmPcdGroupParam[grpId].numOfEntriesInGroup) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("index > numOfEntriesInGroup")); ++ ++ p_FmPcd = (t_FmPcd *)h_FmPcd; ++ ++ INIT_LIST(&h_OldPointersLst); ++ INIT_LIST(&h_NewPointersLst); ++ ++ keyIndex = (uint16_t)(p_FmPcdCcTree->fmPcdGroupParam[grpId].baseGroupEntry ++ + index); ++ ++ p_ModifyKeyParams = ModifyNodeCommonPart(p_FmPcdCcTree, keyIndex, ++ e_MODIFY_STATE_CHANGE, FALSE, ++ FALSE, TRUE); ++ if (!p_ModifyKeyParams) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ p_ModifyKeyParams->tree = TRUE; ++ ++ if (p_FmPcd->p_CcShadow ++ && !TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ { ++ XX_Free(p_ModifyKeyParams); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = BuildNewNodeModifyNextEngine(p_FmPcd, p_FmPcdCcTree, keyIndex, ++ p_FmPcdCcNextEngineParams, ++ &h_OldPointersLst, &h_NewPointersLst, ++ p_ModifyKeyParams); ++ if (err) ++ { ++ XX_Free(p_ModifyKeyParams); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst, ++ p_ModifyKeyParams, FALSE); ++ ++ if (p_FmPcd->p_CcShadow) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ ++ return err; ++ ++} ++ ++t_Error FmPcdCcRemoveKey(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode, ++ uint16_t keyIndex) ++{ ++ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode; ++ t_FmPcd *p_FmPcd; ++ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams; ++ t_List h_OldPointersLst, h_NewPointersLst; ++ bool useShadowStructs = FALSE; ++ t_Error err = E_OK; ++ ++ if (keyIndex >= p_CcNode->numOfKeys) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("impossible to remove key when numOfKeys <= keyIndex")); ++ ++ if (p_CcNode->h_FmPcd != h_FmPcd) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("handler to FmPcd is different from the handle provided at node initialization time")); ++ ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ ++ INIT_LIST(&h_OldPointersLst); ++ INIT_LIST(&h_NewPointersLst); ++ ++ p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex, ++ e_MODIFY_STATE_REMOVE, TRUE, TRUE, ++ FALSE); ++ if (!p_ModifyKeyParams) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ { ++ XX_Free(p_ModifyKeyParams); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ useShadowStructs = TRUE; ++ } ++ ++ err = BuildNewNodeRemoveKey(p_CcNode, keyIndex, p_ModifyKeyParams); ++ if (err) ++ { ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode, p_ModifyKeyParams, ++ &h_OldPointersLst, ++ &h_NewPointersLst); ++ if (err) ++ { ++ ReleaseNewNodeCommonPart(p_ModifyKeyParams); ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst, ++ p_ModifyKeyParams, useShadowStructs); ++ ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ ++ return err; ++} ++ ++t_Error FmPcdCcModifyKey(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode, ++ uint16_t keyIndex, uint8_t keySize, uint8_t *p_Key, ++ uint8_t *p_Mask) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode; ++ t_FmPcd *p_FmPcd; ++ t_List h_OldPointersLst, h_NewPointersLst; ++ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams; ++ uint16_t tmpKeyIndex; ++ bool useShadowStructs = FALSE; ++ t_Error err = E_OK; ++ ++ if (keyIndex >= p_CcNode->numOfKeys) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("keyIndex > previously cleared last index + 1")); ++ ++ if (keySize != p_CcNode->userSizeOfExtraction) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("size for ModifyKey has to be the same as defined in SetNode")); ++ ++ if (p_CcNode->h_FmPcd != h_FmPcd) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("handler to FmPcd is different from the handle provided at node initialization time")); ++ ++ err = FindKeyIndex(h_FmPcdCcNode, keySize, p_Key, p_Mask, &tmpKeyIndex); ++ if (GET_ERROR_TYPE(err) != E_NOT_FOUND) ++ RETURN_ERROR( ++ MINOR, ++ E_ALREADY_EXISTS, ++ ("The received key and mask pair was already found in the match table of the provided node")); ++ ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ ++ INIT_LIST(&h_OldPointersLst); ++ INIT_LIST(&h_NewPointersLst); ++ ++ p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex, ++ e_MODIFY_STATE_CHANGE, TRUE, TRUE, ++ FALSE); ++ if (!p_ModifyKeyParams) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ { ++ XX_Free(p_ModifyKeyParams); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ useShadowStructs = TRUE; ++ } ++ ++ err = BuildNewNodeModifyKey(p_CcNode, keyIndex, p_Key, p_Mask, ++ p_ModifyKeyParams); ++ if (err) ++ { ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode, p_ModifyKeyParams, ++ &h_OldPointersLst, ++ &h_NewPointersLst); ++ if (err) ++ { ++ ReleaseNewNodeCommonPart(p_ModifyKeyParams); ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst, ++ p_ModifyKeyParams, useShadowStructs); ++ ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ ++ return err; ++} ++ ++t_Error FmPcdCcModifyMissNextEngineParamNode( ++ t_Handle h_FmPcd, t_Handle h_FmPcdCcNode, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode; ++ t_FmPcd *p_FmPcd; ++ t_List h_OldPointersLst, h_NewPointersLst; ++ uint16_t keyIndex; ++ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_VALUE); ++ ++ keyIndex = p_CcNode->numOfKeys; ++ ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ ++ INIT_LIST(&h_OldPointersLst); ++ INIT_LIST(&h_NewPointersLst); ++ ++ p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex, ++ e_MODIFY_STATE_CHANGE, FALSE, TRUE, ++ FALSE); ++ if (!p_ModifyKeyParams) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ if (p_CcNode->maxNumOfKeys ++ && !TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ { ++ XX_Free(p_ModifyKeyParams); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = BuildNewNodeModifyNextEngine(h_FmPcd, p_CcNode, keyIndex, ++ p_FmPcdCcNextEngineParams, ++ &h_OldPointersLst, &h_NewPointersLst, ++ p_ModifyKeyParams); ++ if (err) ++ { ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst, ++ p_ModifyKeyParams, FALSE); ++ ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ ++ return err; ++} ++ ++t_Error FmPcdCcAddKey(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode, ++ uint16_t keyIndex, uint8_t keySize, ++ t_FmPcdCcKeyParams *p_FmPcdCcKeyParams) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode; ++ t_FmPcd *p_FmPcd; ++ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams; ++ t_List h_OldPointersLst, h_NewPointersLst; ++ bool useShadowStructs = FALSE; ++ uint16_t tmpKeyIndex; ++ t_Error err = E_OK; ++ ++ if (keyIndex > p_CcNode->numOfKeys) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ++ ("keyIndex > previously cleared last index + 1")); ++ ++ if (keySize != p_CcNode->userSizeOfExtraction) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("keySize has to be defined as it was defined in initialization step")); ++ ++ if (p_CcNode->h_FmPcd != h_FmPcd) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("handler to FmPcd is different from the handle provided at node initialization time")); ++ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ if (p_CcNode->numOfKeys == p_CcNode->maxNumOfKeys) ++ RETURN_ERROR( ++ MAJOR, ++ E_FULL, ++ ("number of keys exceeds the maximal number of keys provided at node initialization time")); ++ } ++ else ++ if (p_CcNode->numOfKeys == FM_PCD_MAX_NUM_OF_KEYS) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("number of keys can not be larger than %d", FM_PCD_MAX_NUM_OF_KEYS)); ++ ++ err = FindKeyIndex(h_FmPcdCcNode, keySize, p_FmPcdCcKeyParams->p_Key, ++ p_FmPcdCcKeyParams->p_Mask, &tmpKeyIndex); ++ if (GET_ERROR_TYPE(err) != E_NOT_FOUND) ++ RETURN_ERROR( ++ MAJOR, ++ E_ALREADY_EXISTS, ++ ("The received key and mask pair was already found in the match table of the provided node")); ++ ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ ++ INIT_LIST(&h_OldPointersLst); ++ INIT_LIST(&h_NewPointersLst); ++ ++ p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex, ++ e_MODIFY_STATE_ADD, TRUE, TRUE, ++ FALSE); ++ if (!p_ModifyKeyParams) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ { ++ XX_Free(p_ModifyKeyParams); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ useShadowStructs = TRUE; ++ } ++ ++ err = BuildNewNodeAddOrMdfyKeyAndNextEngine(h_FmPcd, p_CcNode, keyIndex, ++ p_FmPcdCcKeyParams, ++ p_ModifyKeyParams, TRUE); ++ if (err) ++ { ++ ReleaseNewNodeCommonPart(p_ModifyKeyParams); ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode, p_ModifyKeyParams, ++ &h_OldPointersLst, ++ &h_NewPointersLst); ++ if (err) ++ { ++ ReleaseNewNodeCommonPart(p_ModifyKeyParams); ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst, ++ p_ModifyKeyParams, useShadowStructs); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ ++ return err; ++} ++ ++t_Error FmPcdCcModifyKeyAndNextEngine(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode, ++ uint16_t keyIndex, uint8_t keySize, ++ t_FmPcdCcKeyParams *p_FmPcdCcKeyParams) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode; ++ t_FmPcd *p_FmPcd; ++ t_List h_OldPointersLst, h_NewPointersLst; ++ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams; ++ uint16_t tmpKeyIndex; ++ bool useShadowStructs = FALSE; ++ t_Error err = E_OK; ++ ++ if (keyIndex > p_CcNode->numOfKeys) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("keyIndex > previously cleared last index + 1")); ++ ++ if (keySize != p_CcNode->userSizeOfExtraction) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("keySize has to be defined as it was defined in initialization step")); ++ ++ if (p_CcNode->h_FmPcd != h_FmPcd) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("handler to FmPcd is different from the handle provided at node initialization time")); ++ ++ err = FindKeyIndex(h_FmPcdCcNode, keySize, p_FmPcdCcKeyParams->p_Key, ++ p_FmPcdCcKeyParams->p_Mask, &tmpKeyIndex); ++ if (GET_ERROR_TYPE(err) != E_NOT_FOUND) ++ RETURN_ERROR( ++ MINOR, ++ E_ALREADY_EXISTS, ++ ("The received key and mask pair was already found in the match table of the provided node")); ++ ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ ++ INIT_LIST(&h_OldPointersLst); ++ INIT_LIST(&h_NewPointersLst); ++ ++ p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex, ++ e_MODIFY_STATE_CHANGE, TRUE, TRUE, ++ FALSE); ++ if (!p_ModifyKeyParams) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ if (p_CcNode->maxNumOfKeys) ++ { ++ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ { ++ XX_Free(p_ModifyKeyParams); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ useShadowStructs = TRUE; ++ } ++ ++ err = BuildNewNodeAddOrMdfyKeyAndNextEngine(h_FmPcd, p_CcNode, keyIndex, ++ p_FmPcdCcKeyParams, ++ p_ModifyKeyParams, FALSE); ++ if (err) ++ { ++ ReleaseNewNodeCommonPart(p_ModifyKeyParams); ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode, p_ModifyKeyParams, ++ &h_OldPointersLst, ++ &h_NewPointersLst); ++ if (err) ++ { ++ ReleaseNewNodeCommonPart(p_ModifyKeyParams); ++ XX_Free(p_ModifyKeyParams); ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst, ++ p_ModifyKeyParams, useShadowStructs); ++ ++ if (p_CcNode->maxNumOfKeys) ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ ++ return err; ++} ++ ++uint32_t FmPcdCcGetNodeAddrOffsetFromNodeInfo(t_Handle h_FmPcd, ++ t_Handle h_Pointer) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_CcNodeInformation *p_CcNodeInfo; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, ++ (uint32_t)ILLEGAL_BASE); ++ ++ p_CcNodeInfo = CC_NODE_F_OBJECT(h_Pointer); ++ ++ return (uint32_t)(XX_VirtToPhys(p_CcNodeInfo->h_CcNode) ++ - p_FmPcd->physicalMuramBase); ++} ++ ++t_Error FmPcdCcGetGrpParams(t_Handle h_FmPcdCcTree, uint8_t grpId, ++ uint32_t *p_GrpBits, uint8_t *p_GrpBase) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree, E_INVALID_HANDLE); ++ ++ if (grpId >= p_FmPcdCcTree->numOfGrps) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ++ ("grpId you asked > numOfGroup of relevant tree")); ++ ++ *p_GrpBits = p_FmPcdCcTree->fmPcdGroupParam[grpId].totalBitsMask; ++ *p_GrpBase = p_FmPcdCcTree->fmPcdGroupParam[grpId].baseGroupEntry; ++ ++ return E_OK; ++} ++ ++t_Error FmPcdCcBindTree(t_Handle h_FmPcd, t_Handle h_PcdParams, ++ t_Handle h_FmPcdCcTree, uint32_t *p_Offset, ++ t_Handle h_FmPort) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree, E_INVALID_HANDLE); ++ ++ /* this routine must be protected by the calling routine by locking all PCD modules! */ ++ ++ err = CcUpdateParams(h_FmPcd, h_PcdParams, h_FmPort, h_FmPcdCcTree, TRUE); ++ ++ if (err == E_OK) ++ UpdateCcRootOwner(p_FmPcdCcTree, TRUE); ++ ++ *p_Offset = (uint32_t)(XX_VirtToPhys( ++ UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr)) ++ - p_FmPcd->physicalMuramBase); ++ ++ return err; ++} ++ ++t_Error FmPcdCcUnbindTree(t_Handle h_FmPcd, t_Handle h_FmPcdCcTree) ++{ ++ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree; ++ ++ /* this routine must be protected by the calling routine by locking all PCD modules! */ ++ ++ UNUSED(h_FmPcd); ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree, E_INVALID_HANDLE); ++ ++ UpdateCcRootOwner(p_FmPcdCcTree, FALSE); ++ ++ return E_OK; ++} ++ ++t_Error FmPcdCcNodeTreeTryLock(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode, ++ t_List *p_List) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode; ++ t_List *p_Pos, *p_Tmp; ++ t_CcNodeInformation *p_CcNodeInfo, nodeInfo; ++ uint32_t intFlags; ++ t_Error err = E_OK; ++ ++ intFlags = FmPcdLock(h_FmPcd); ++ ++ LIST_FOR_EACH(p_Pos, &p_CcNode->ccTreesLst) ++ { ++ p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos); ++ ASSERT_COND(p_CcNodeInfo->h_CcNode); ++ ++ err = CcRootTryLock(p_CcNodeInfo->h_CcNode); ++ ++ if (err) ++ { ++ LIST_FOR_EACH(p_Tmp, &p_CcNode->ccTreesLst) ++ { ++ if (p_Tmp == p_Pos) ++ break; ++ ++ CcRootReleaseLock(p_CcNodeInfo->h_CcNode); ++ } ++ break; ++ } ++ ++ memset(&nodeInfo, 0, sizeof(t_CcNodeInformation)); ++ nodeInfo.h_CcNode = p_CcNodeInfo->h_CcNode; ++ EnqueueNodeInfoToRelevantLst(p_List, &nodeInfo, NULL); ++ } ++ ++ FmPcdUnlock(h_FmPcd, intFlags); ++ CORE_MemoryBarrier(); ++ ++ return err; ++} ++ ++void FmPcdCcNodeTreeReleaseLock(t_Handle h_FmPcd, t_List *p_List) ++{ ++ t_List *p_Pos; ++ t_CcNodeInformation *p_CcNodeInfo; ++ t_Handle h_FmPcdCcTree; ++ uint32_t intFlags; ++ ++ intFlags = FmPcdLock(h_FmPcd); ++ ++ LIST_FOR_EACH(p_Pos, p_List) ++ { ++ p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos); ++ h_FmPcdCcTree = p_CcNodeInfo->h_CcNode; ++ CcRootReleaseLock(h_FmPcdCcTree); ++ } ++ ++ ReleaseLst(p_List); ++ ++ FmPcdUnlock(h_FmPcd, intFlags); ++ CORE_MemoryBarrier(); ++} ++ ++t_Error FmPcdUpdateCcShadow(t_FmPcd *p_FmPcd, uint32_t size, uint32_t align) ++{ ++ uint32_t intFlags; ++ uint32_t newSize = 0, newAlign = 0; ++ bool allocFail = FALSE; ++ ++ ASSERT_COND(p_FmPcd); ++ ++ if (!size) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("size must be larger then 0")); ++ ++ if (!POWER_OF_2(align)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("alignment must be power of 2")); ++ ++ newSize = p_FmPcd->ccShadowSize; ++ newAlign = p_FmPcd->ccShadowAlign; ++ ++ /* Check if current shadow is large enough to hold the requested size */ ++ if (size > p_FmPcd->ccShadowSize) ++ newSize = size; ++ ++ /* Check if current shadow matches the requested alignment */ ++ if (align > p_FmPcd->ccShadowAlign) ++ newAlign = align; ++ ++ /* If a bigger shadow size or bigger shadow alignment are required, ++ a new shadow will be allocated */ ++ if ((newSize != p_FmPcd->ccShadowSize) ++ || (newAlign != p_FmPcd->ccShadowAlign)) ++ { ++ intFlags = FmPcdLock(p_FmPcd); ++ ++ if (p_FmPcd->p_CcShadow) ++ { ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_FmPcd), p_FmPcd->p_CcShadow); ++ p_FmPcd->ccShadowSize = 0; ++ p_FmPcd->ccShadowAlign = 0; ++ } ++ ++ p_FmPcd->p_CcShadow = FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd), ++ newSize, newAlign); ++ if (!p_FmPcd->p_CcShadow) ++ { ++ allocFail = TRUE; ++ ++ /* If new shadow size allocation failed, ++ re-allocate with previous parameters */ ++ p_FmPcd->p_CcShadow = FM_MURAM_AllocMem( ++ FmPcdGetMuramHandle(p_FmPcd), p_FmPcd->ccShadowSize, ++ p_FmPcd->ccShadowAlign); ++ } ++ ++ FmPcdUnlock(p_FmPcd, intFlags); ++ ++ if (allocFail) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("MURAM allocation for CC Shadow memory")); ++ ++ p_FmPcd->ccShadowSize = newSize; ++ p_FmPcd->ccShadowAlign = newAlign; ++ } ++ ++ return E_OK; ++} ++ ++#if (DPAA_VERSION >= 11) ++void FmPcdCcGetAdTablesThatPointOnReplicGroup(t_Handle h_Node, ++ t_Handle h_ReplicGroup, ++ t_List *p_AdTables, ++ uint32_t *p_NumOfAdTables) ++{ ++ t_FmPcdCcNode *p_CurrentNode = (t_FmPcdCcNode *)h_Node; ++ int i = 0; ++ void * p_AdTable; ++ t_CcNodeInformation ccNodeInfo; ++ ++ ASSERT_COND(h_Node); ++ *p_NumOfAdTables = 0; ++ ++ /* search in the current node which exact index points on this current replicator group for getting AD */ ++ for (i = 0; i < p_CurrentNode->numOfKeys + 1; i++) ++ { ++ if ((p_CurrentNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine ++ == e_FM_PCD_FR) ++ && ((p_CurrentNode->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic ++ == (t_Handle)h_ReplicGroup))) ++ { ++ /* save the current ad table in the list */ ++ /* this entry uses the input replicator group */ ++ p_AdTable = ++ PTR_MOVE(p_CurrentNode->h_AdTable, i*FM_PCD_CC_AD_ENTRY_SIZE); ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = p_AdTable; ++ EnqueueNodeInfoToRelevantLst(p_AdTables, &ccNodeInfo, NULL); ++ (*p_NumOfAdTables)++; ++ } ++ } ++ ++ ASSERT_COND(i != p_CurrentNode->numOfKeys); ++} ++#endif /* (DPAA_VERSION >= 11) */ ++/*********************** End of inter-module routines ************************/ ++ ++/****************************************/ ++/* API Init unit functions */ ++/****************************************/ ++ ++t_Handle FM_PCD_CcRootBuild(t_Handle h_FmPcd, ++ t_FmPcdCcTreeParams *p_PcdGroupsParam) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_Error err = E_OK; ++ int i = 0, j = 0, k = 0; ++ t_FmPcdCcTree *p_FmPcdCcTree; ++ uint8_t numOfEntries; ++ t_Handle p_CcTreeTmp; ++ t_FmPcdCcGrpParams *p_FmPcdCcGroupParams; ++ t_FmPcdCcKeyAndNextEngineParams *p_Params, *p_KeyAndNextEngineParams; ++ t_NetEnvParams netEnvParams; ++ uint8_t lastOne = 0; ++ uint32_t requiredAction = 0; ++ t_FmPcdCcNode *p_FmPcdCcNextNode; ++ t_CcNodeInformation ccNodeInfo, *p_CcInformation; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_PcdGroupsParam, E_INVALID_HANDLE, NULL); ++ ++ if (p_PcdGroupsParam->numOfGrps > FM_PCD_MAX_NUM_OF_CC_GROUPS) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfGrps should not exceed %d", FM_PCD_MAX_NUM_OF_CC_GROUPS)); ++ return NULL; ++ } ++ ++ p_FmPcdCcTree = (t_FmPcdCcTree*)XX_Malloc(sizeof(t_FmPcdCcTree)); ++ if (!p_FmPcdCcTree) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("PCD tree structure")); ++ return NULL; ++ } ++ memset(p_FmPcdCcTree, 0, sizeof(t_FmPcdCcTree)); ++ p_FmPcdCcTree->h_FmPcd = h_FmPcd; ++ ++ p_Params = (t_FmPcdCcKeyAndNextEngineParams*)XX_Malloc( ++ FM_PCD_MAX_NUM_OF_CC_GROUPS ++ * sizeof(t_FmPcdCcKeyAndNextEngineParams)); ++ memset(p_Params, ++ 0, ++ FM_PCD_MAX_NUM_OF_CC_GROUPS ++ * sizeof(t_FmPcdCcKeyAndNextEngineParams)); ++ ++ INIT_LIST(&p_FmPcdCcTree->fmPortsLst); ++ ++#ifdef FM_CAPWAP_SUPPORT ++ if ((p_PcdGroupsParam->numOfGrps == 1) && ++ (p_PcdGroupsParam->ccGrpParams[0].numOfDistinctionUnits == 0) && ++ (p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].nextEngine == e_FM_PCD_CC) && ++ p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode && ++ IsCapwapApplSpecific(p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode)) ++ { ++ p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip = FmPcdManipApplSpecificBuild(); ++ if (!p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip) ++ { ++ DeleteTree(p_FmPcdCcTree,p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ return NULL; ++ } ++ } ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++ numOfEntries = 0; ++ p_FmPcdCcTree->netEnvId = FmPcdGetNetEnvId(p_PcdGroupsParam->h_NetEnv); ++ ++ for (i = 0; i < p_PcdGroupsParam->numOfGrps; i++) ++ { ++ p_FmPcdCcGroupParams = &p_PcdGroupsParam->ccGrpParams[i]; ++ ++ if (p_FmPcdCcGroupParams->numOfDistinctionUnits ++ > FM_PCD_MAX_NUM_OF_CC_UNITS) ++ { ++ DeleteTree(p_FmPcdCcTree, p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("numOfDistinctionUnits (group %d) should not exceed %d", i, FM_PCD_MAX_NUM_OF_CC_UNITS)); ++ return NULL; ++ } ++ ++ p_FmPcdCcTree->fmPcdGroupParam[i].baseGroupEntry = numOfEntries; ++ p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup = (uint8_t)(0x01 ++ << p_FmPcdCcGroupParams->numOfDistinctionUnits); ++ numOfEntries += p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; ++ if (numOfEntries > FM_PCD_MAX_NUM_OF_CC_GROUPS) ++ { ++ DeleteTree(p_FmPcdCcTree, p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfEntries can not be larger than %d", FM_PCD_MAX_NUM_OF_CC_GROUPS)); ++ return NULL; ++ } ++ ++ if (lastOne) ++ { ++ if (p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup > lastOne) ++ { ++ DeleteTree(p_FmPcdCcTree, p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_CONFLICT, ("numOfEntries per group must be set in descending order")); ++ return NULL; ++ } ++ } ++ ++ lastOne = p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; ++ ++ netEnvParams.netEnvId = p_FmPcdCcTree->netEnvId; ++ netEnvParams.numOfDistinctionUnits = ++ p_FmPcdCcGroupParams->numOfDistinctionUnits; ++ ++ memcpy(netEnvParams.unitIds, &p_FmPcdCcGroupParams->unitIds, ++ (sizeof(uint8_t)) * p_FmPcdCcGroupParams->numOfDistinctionUnits); ++ ++ err = PcdGetUnitsVector(p_FmPcd, &netEnvParams); ++ if (err) ++ { ++ DeleteTree(p_FmPcdCcTree, p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return NULL; ++ } ++ ++ p_FmPcdCcTree->fmPcdGroupParam[i].totalBitsMask = netEnvParams.vector; ++ for (j = 0; j < p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; ++ j++) ++ { ++ err = ValidateNextEngineParams( ++ h_FmPcd, ++ &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], ++ e_FM_PCD_CC_STATS_MODE_NONE); ++ if (err) ++ { ++ DeleteTree(p_FmPcdCcTree, p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, err, (NO_MSG)); ++ return NULL; ++ } ++ ++ if (p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j].h_Manip) ++ { ++ err = FmPcdManipCheckParamsForCcNextEngine( ++ &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], ++ &requiredAction); ++ if (err) ++ { ++ DeleteTree(p_FmPcdCcTree, p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ return NULL; ++ } ++ } ++ p_KeyAndNextEngineParams = p_Params + k; ++ ++ memcpy(&p_KeyAndNextEngineParams->nextEngineParams, ++ &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ if ((p_KeyAndNextEngineParams->nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ && p_KeyAndNextEngineParams->nextEngineParams.h_Manip) ++ { ++ err = ++ AllocAndFillAdForContLookupManip( ++ p_KeyAndNextEngineParams->nextEngineParams.params.ccParams.h_CcNode); ++ if (err) ++ { ++ DeleteTree(p_FmPcdCcTree, p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree")); ++ return NULL; ++ } ++ } ++ ++ requiredAction |= UPDATE_CC_WITH_TREE; ++ p_KeyAndNextEngineParams->requiredAction = requiredAction; ++ ++ k++; ++ } ++ } ++ ++ p_FmPcdCcTree->numOfEntries = (uint8_t)k; ++ p_FmPcdCcTree->numOfGrps = p_PcdGroupsParam->numOfGrps; ++ ++ p_FmPcdCcTree->ccTreeBaseAddr = ++ PTR_TO_UINT(FM_MURAM_AllocMem(FmPcdGetMuramHandle(h_FmPcd), ++ (uint32_t)( FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE), ++ FM_PCD_CC_TREE_ADDR_ALIGN)); ++ if (!p_FmPcdCcTree->ccTreeBaseAddr) ++ { ++ DeleteTree(p_FmPcdCcTree, p_FmPcd); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree")); ++ return NULL; ++ } ++ IOMemSet32( ++ UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr), 0, ++ (uint32_t)(FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE)); ++ ++ p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); ++ ++ for (i = 0; i < numOfEntries; i++) ++ { ++ p_KeyAndNextEngineParams = p_Params + i; ++ ++ NextStepAd(p_CcTreeTmp, NULL, ++ &p_KeyAndNextEngineParams->nextEngineParams, p_FmPcd); ++ ++ p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ memcpy(&p_FmPcdCcTree->keyAndNextEngineParams[i], ++ p_KeyAndNextEngineParams, ++ sizeof(t_FmPcdCcKeyAndNextEngineParams)); ++ ++ if (p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ { ++ p_FmPcdCcNextNode = ++ (t_FmPcdCcNode*)p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode; ++ p_CcInformation = FindNodeInfoInReleventLst( ++ &p_FmPcdCcNextNode->ccTreeIdLst, (t_Handle)p_FmPcdCcTree, ++ p_FmPcdCcNextNode->h_Spinlock); ++ ++ if (!p_CcInformation) ++ { ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = (t_Handle)p_FmPcdCcTree; ++ ccNodeInfo.index = 1; ++ EnqueueNodeInfoToRelevantLst(&p_FmPcdCcNextNode->ccTreeIdLst, ++ &ccNodeInfo, ++ p_FmPcdCcNextNode->h_Spinlock); ++ } ++ else ++ p_CcInformation->index++; ++ } ++ } ++ ++ FmPcdIncNetEnvOwners(h_FmPcd, p_FmPcdCcTree->netEnvId); ++ p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ FM_PCD_CcRootDelete(p_FmPcdCcTree); ++ XX_Free(p_Params); ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return NULL; ++ } ++ ++ for (i = 0; i < numOfEntries; i++) ++ { ++ if (p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction) ++ { ++ err = SetRequiredAction( ++ h_FmPcd, ++ p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction, ++ &p_FmPcdCcTree->keyAndNextEngineParams[i], p_CcTreeTmp, 1, ++ p_FmPcdCcTree); ++ if (err) ++ { ++ FmPcdLockUnlockAll(p_FmPcd); ++ FM_PCD_CcRootDelete(p_FmPcdCcTree); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); ++ return NULL; ++ } ++ p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ } ++ } ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ p_FmPcdCcTree->p_Lock = FmPcdAcquireLock(p_FmPcd); ++ if (!p_FmPcdCcTree->p_Lock) ++ { ++ FM_PCD_CcRootDelete(p_FmPcdCcTree); ++ XX_Free(p_Params); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM CC lock")); ++ return NULL; ++ } ++ ++ XX_Free(p_Params); ++ ++ return p_FmPcdCcTree; ++} ++ ++t_Error FM_PCD_CcRootDelete(t_Handle h_CcTree) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree; ++ int i = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_CcTree, E_INVALID_STATE); ++ p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ FmPcdDecNetEnvOwners(p_FmPcd, p_CcTree->netEnvId); ++ ++ if (p_CcTree->owners) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_SELECTION, ++ ("the tree with this ID can not be removed because this tree is occupied, first - unbind this tree")); ++ ++ /* Delete ip-reassembly schemes if exist */ ++ if (p_CcTree->h_IpReassemblyManip) ++ { ++ FmPcdManipDeleteIpReassmSchemes(p_CcTree->h_IpReassemblyManip); ++ FmPcdManipUpdateOwner(p_CcTree->h_IpReassemblyManip, FALSE); ++ } ++ ++ /* Delete capwap-reassembly schemes if exist */ ++ if (p_CcTree->h_CapwapReassemblyManip) ++ { ++ FmPcdManipDeleteCapwapReassmSchemes(p_CcTree->h_CapwapReassemblyManip); ++ FmPcdManipUpdateOwner(p_CcTree->h_CapwapReassemblyManip, FALSE); ++ } ++ ++ for (i = 0; i < p_CcTree->numOfEntries; i++) ++ { ++ if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ UpdateNodeOwner( ++ p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode, ++ FALSE); ++ ++ if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip) ++ FmPcdManipUpdateOwner( ++ p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip, ++ FALSE); ++ ++#ifdef FM_CAPWAP_SUPPORT ++ if ((p_CcTree->numOfGrps == 1) && ++ (p_CcTree->fmPcdGroupParam[0].numOfEntriesInGroup == 1) && ++ (p_CcTree->keyAndNextEngineParams[0].nextEngineParams.nextEngine == e_FM_PCD_CC) && ++ p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode && ++ IsCapwapApplSpecific(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode)) ++ { ++ if (FM_PCD_ManipNodeDelete(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.h_Manip) != E_OK) ++ return E_INVALID_STATE; ++ } ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine ++ == e_FM_PCD_FR) ++ && (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic)) ++ FrmReplicGroupUpdateOwner( ++ p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic, ++ FALSE); ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ if (p_CcTree->p_Lock) ++ FmPcdReleaseLock(p_CcTree->h_FmPcd, p_CcTree->p_Lock); ++ ++ DeleteTree(p_CcTree, p_FmPcd); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_CcRootModifyNextEngine( ++ t_Handle h_CcTree, uint8_t grpId, uint8_t index, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcTree, E_INVALID_STATE); ++ p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdCcModifyNextEngineParamTree(p_FmPcd, p_CcTree, grpId, index, ++ p_FmPcdCcNextEngineParams); ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ if (err) ++ { ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ return E_OK; ++} ++ ++t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, ++ t_FmPcdCcNodeParams *p_CcNodeParam) ++{ ++ t_FmPcdCcNode *p_CcNode; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_CcNodeParam, E_NULL_POINTER, NULL); ++ ++ p_CcNode = (t_FmPcdCcNode*)XX_Malloc(sizeof(t_FmPcdCcNode)); ++ if (!p_CcNode) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); ++ return NULL; ++ } ++ memset(p_CcNode, 0, sizeof(t_FmPcdCcNode)); ++ ++ err = MatchTableSet(h_FmPcd, p_CcNode, p_CcNodeParam); ++ ++ switch(GET_ERROR_TYPE(err) ++) { ++ case E_OK: ++ break; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return NULL; ++ ++ default: ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return NULL; ++ } ++ ++ return p_CcNode; ++} ++ ++t_Error FM_PCD_MatchTableDelete(t_Handle h_CcNode) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ int i = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode->h_FmPcd, E_INVALID_HANDLE); ++ ++ if (p_CcNode->owners) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("This node cannot be removed because it is occupied; first unbind this node")); ++ ++ for (i = 0; i < p_CcNode->numOfKeys; i++) ++ if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ UpdateNodeOwner( ++ p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode, ++ FALSE); ++ ++ if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ UpdateNodeOwner( ++ p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode, ++ FALSE); ++ ++ /* Handle also Miss entry */ ++ for (i = 0; i < p_CcNode->numOfKeys + 1; i++) ++ { ++ if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip) ++ FmPcdManipUpdateOwner( ++ p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip, ++ FALSE); ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_CcNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine ++ == e_FM_PCD_FR) ++ && (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic)) ++ { ++ FrmReplicGroupUpdateOwner( ++ p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic, ++ FALSE); ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ DeleteNode(p_CcNode); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_MatchTableAddKey(t_Handle h_CcNode, uint16_t keyIndex, ++ uint8_t keySize, ++ t_FmPcdCcKeyParams *p_KeyParams) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (keyIndex == FM_PCD_LAST_KEY_INDEX) ++ keyIndex = p_CcNode->numOfKeys; ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdCcAddKey(p_FmPcd, p_CcNode, keyIndex, keySize, p_KeyParams); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch(GET_ERROR_TYPE(err) ++) { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++t_Error FM_PCD_MatchTableRemoveKey(t_Handle h_CcNode, uint16_t keyIndex) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdCcRemoveKey(p_FmPcd, p_CcNode, keyIndex); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch(GET_ERROR_TYPE(err) ++) { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_MatchTableModifyKey(t_Handle h_CcNode, uint16_t keyIndex, ++ uint8_t keySize, uint8_t *p_Key, ++ uint8_t *p_Mask) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdCcModifyKey(p_FmPcd, p_CcNode, keyIndex, keySize, p_Key, p_Mask); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch(GET_ERROR_TYPE(err) ++) { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++t_Error FM_PCD_MatchTableModifyNextEngine( ++ t_Handle h_CcNode, uint16_t keyIndex, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = ModifyNextEngineParamNode(p_FmPcd, p_CcNode, keyIndex, ++ p_FmPcdCcNextEngineParams); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch(GET_ERROR_TYPE(err) ++) { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++t_Error FM_PCD_MatchTableModifyMissNextEngine( ++ t_Handle h_CcNode, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdCcModifyMissNextEngineParamNode(p_FmPcd, p_CcNode, ++ p_FmPcdCcNextEngineParams); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch(GET_ERROR_TYPE(err) ++) { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++t_Error FM_PCD_MatchTableModifyKeyAndNextEngine(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ uint8_t keySize, ++ t_FmPcdCcKeyParams *p_KeyParams) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdCcModifyKeyAndNextEngine(p_FmPcd, p_CcNode, keyIndex, keySize, ++ p_KeyParams); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch(GET_ERROR_TYPE(err) ++) { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++t_Error FM_PCD_MatchTableFindNRemoveKey(t_Handle h_CcNode, uint8_t keySize, ++ uint8_t *p_Key, uint8_t *p_Mask) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint16_t keyIndex; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex); ++ if (GET_ERROR_TYPE(err) != E_OK) ++ { ++ FmPcdLockUnlockAll(p_FmPcd); ++ RETURN_ERROR( ++ MAJOR, ++ err, ++ ("The received key and mask pair was not found in the match table of the provided node")); ++ } ++ ++ err = FmPcdCcRemoveKey(p_FmPcd, p_CcNode, keyIndex); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch(GET_ERROR_TYPE(err) ++) { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++t_Error FM_PCD_MatchTableFindNModifyNextEngine( ++ t_Handle h_CcNode, uint8_t keySize, uint8_t *p_Key, uint8_t *p_Mask, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint16_t keyIndex; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex); ++ if (GET_ERROR_TYPE(err) != E_OK) ++ { ++ FmPcdLockUnlockAll(p_FmPcd); ++ RETURN_ERROR( ++ MAJOR, ++ err, ++ ("The received key and mask pair was not found in the match table of the provided node")); ++ } ++ ++ err = ModifyNextEngineParamNode(p_FmPcd, p_CcNode, keyIndex, ++ p_FmPcdCcNextEngineParams); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch(GET_ERROR_TYPE(err) ++) { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++t_Error FM_PCD_MatchTableFindNModifyKeyAndNextEngine( ++ t_Handle h_CcNode, uint8_t keySize, uint8_t *p_Key, uint8_t *p_Mask, ++ t_FmPcdCcKeyParams *p_KeyParams) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint16_t keyIndex; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex); ++ if (GET_ERROR_TYPE(err) != E_OK) ++ { ++ FmPcdLockUnlockAll(p_FmPcd); ++ RETURN_ERROR( ++ MAJOR, ++ err, ++ ("The received key and mask pair was not found in the match table of the provided node")); ++ } ++ ++ err = FmPcdCcModifyKeyAndNextEngine(p_FmPcd, h_CcNode, keyIndex, keySize, ++ p_KeyParams); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ switch(GET_ERROR_TYPE(err) ++) { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++t_Error FM_PCD_MatchTableFindNModifyKey(t_Handle h_CcNode, uint8_t keySize, ++ uint8_t *p_Key, uint8_t *p_Mask, ++ uint8_t *p_NewKey, uint8_t *p_NewMask) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ t_List h_List; ++ uint16_t keyIndex; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_NewKey, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ INIT_LIST(&h_List); ++ ++ err = FmPcdCcNodeTreeTryLock(p_FmPcd, p_CcNode, &h_List); ++ if (err) ++ { ++ DBG(TRACE, ("Node's trees lock failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex); ++ if (GET_ERROR_TYPE(err) != E_OK) ++ { ++ FmPcdCcNodeTreeReleaseLock(p_FmPcd, &h_List); ++ RETURN_ERROR(MAJOR, err, ++ ("The received key and mask pair was not found in the " ++ "match table of the provided node")); ++ } ++ ++ err = FmPcdCcModifyKey(p_FmPcd, p_CcNode, keyIndex, keySize, p_NewKey, ++ p_NewMask); ++ ++ FmPcdCcNodeTreeReleaseLock(p_FmPcd, &h_List); ++ ++ switch(GET_ERROR_TYPE(err) ++) { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++t_Error FM_PCD_MatchTableGetNextEngine( ++ t_Handle h_CcNode, uint16_t keyIndex, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ ++ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); ++ ++ if (keyIndex >= p_CcNode->numOfKeys) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("keyIndex exceeds current number of keys")); ++ ++ if (keyIndex > (FM_PCD_MAX_NUM_OF_KEYS - 1)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("keyIndex can not be larger than %d", (FM_PCD_MAX_NUM_OF_KEYS - 1))); ++ ++ memcpy(p_FmPcdCcNextEngineParams, ++ &p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams, ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ return E_OK; ++} ++ ++ ++uint32_t FM_PCD_MatchTableGetKeyCounter(t_Handle h_CcNode, uint16_t keyIndex) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint32_t *p_StatsCounters, frameCount; ++ uint32_t intFlags; ++ ++ SANITY_CHECK_RETURN_VALUE(p_CcNode, E_INVALID_HANDLE, 0); ++ ++ if (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this match table")); ++ return 0; ++ } ++ ++ if ((p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_FRAME) ++ && (p_CcNode->statisticsMode ++ != e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME)) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Frame count is not supported in the statistics mode of this match table")); ++ return 0; ++ } ++ ++ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock); ++ ++ if (keyIndex >= p_CcNode->numOfKeys) ++ { ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("The provided keyIndex exceeds the number of keys in this match table")); ++ return 0; ++ } ++ ++ if (!p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj) ++ { ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this key")); ++ return 0; ++ } ++ ++ p_StatsCounters = ++ p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsCounters; ++ ASSERT_COND(p_StatsCounters); ++ ++ /* The first counter is byte counter, so we need to advance to the next counter */ ++ frameCount = GET_UINT32(*(uint32_t *)(PTR_MOVE(p_StatsCounters, ++ FM_PCD_CC_STATS_COUNTER_SIZE))); ++ ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ ++ return frameCount; ++} ++ ++t_Error FM_PCD_MatchTableGetKeyStatistics( ++ t_Handle h_CcNode, uint16_t keyIndex, ++ t_FmPcdCcKeyStatistics *p_KeyStatistics) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint32_t intFlags; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(h_CcNode, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_KeyStatistics, E_NULL_POINTER); ++ ++ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock); ++ ++ if (keyIndex >= p_CcNode->numOfKeys) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("The provided keyIndex exceeds the number of keys in this match table")); ++ ++ err = MatchTableGetKeyStatistics(p_CcNode, keyIndex, p_KeyStatistics); ++ ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_MatchTableGetMissStatistics( ++ t_Handle h_CcNode, t_FmPcdCcKeyStatistics *p_MissStatistics) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint32_t intFlags; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(h_CcNode, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_MissStatistics, E_NULL_POINTER); ++ ++ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock); ++ ++ err = MatchTableGetKeyStatistics(p_CcNode, p_CcNode->numOfKeys, ++ p_MissStatistics); ++ ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_MatchTableFindNGetKeyStatistics( ++ t_Handle h_CcNode, uint8_t keySize, uint8_t *p_Key, uint8_t *p_Mask, ++ t_FmPcdCcKeyStatistics *p_KeyStatistics) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint16_t keyIndex; ++ uint32_t intFlags; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_KeyStatistics, E_NULL_POINTER); ++ ++ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock); ++ ++ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex); ++ if (GET_ERROR_TYPE(err) != E_OK) ++ { ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, err, ++ ("The received key and mask pair was not found in the " ++ "match table of the provided node")); ++ } ++ ++ ASSERT_COND(keyIndex < p_CcNode->numOfKeys); ++ ++ err = MatchTableGetKeyStatistics(p_CcNode, keyIndex, p_KeyStatistics); ++ ++ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_MatchTableGetIndexedHashBucket(t_Handle h_CcNode, ++ uint8_t keySize, uint8_t *p_Key, ++ uint8_t hashShift, ++ t_Handle *p_CcNodeBucketHandle, ++ uint8_t *p_BucketIndex, ++ uint16_t *p_LastIndex) ++{ ++ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode; ++ uint16_t glblMask; ++ uint64_t crc64 = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(h_CcNode, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR( ++ p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED, ++ E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_CcNodeBucketHandle, E_NULL_POINTER); ++ ++ memcpy(&glblMask, PTR_MOVE(p_CcNode->p_GlblMask, 2), 2); ++ ++ crc64 = crc64_init(); ++ crc64 = crc64_compute(p_Key, keySize, crc64); ++ crc64 >>= hashShift; ++ ++ *p_BucketIndex = (uint8_t)(((crc64 >> (8 * (6 - p_CcNode->userOffset))) ++ & glblMask) >> 4); ++ if (*p_BucketIndex >= p_CcNode->numOfKeys) ++ RETURN_ERROR(MINOR, E_NOT_IN_RANGE, ("bucket index!")); ++ ++ *p_CcNodeBucketHandle = ++ p_CcNode->keyAndNextEngineParams[*p_BucketIndex].nextEngineParams.params.ccParams.h_CcNode; ++ if (!*p_CcNodeBucketHandle) ++ RETURN_ERROR(MINOR, E_NOT_FOUND, ("bucket!")); ++ ++ *p_LastIndex = ((t_FmPcdCcNode *)*p_CcNodeBucketHandle)->numOfKeys; ++ ++ return E_OK; ++} ++ ++t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param) ++{ ++ t_FmPcdCcNode *p_CcNodeHashTbl; ++ t_FmPcdCcNodeParams *p_IndxHashCcNodeParam, *p_ExactMatchCcNodeParam; ++ t_FmPcdCcNode *p_CcNode; ++ t_Handle h_MissStatsCounters = NULL; ++ t_FmPcdCcKeyParams *p_HashKeyParams; ++ int i; ++ uint16_t numOfSets, numOfWays, countMask, onesCount = 0; ++ bool statsEnForMiss = FALSE; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_Param, E_NULL_POINTER, NULL); ++ ++ if (p_Param->maxNumOfKeys == 0) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_VALUE, ("Max number of keys must be higher then 0")); ++ return NULL; ++ } ++ ++ if (p_Param->hashResMask == 0) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_VALUE, ("Hash result mask must differ from 0")); ++ return NULL; ++ } ++ ++#if (DPAA_VERSION >= 11) ++ if (p_Param->statisticsMode == e_FM_PCD_CC_STATS_MODE_RMON) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("RMON statistics mode is not supported for hash table")); ++ return NULL; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ p_ExactMatchCcNodeParam = (t_FmPcdCcNodeParams*)XX_Malloc( ++ sizeof(t_FmPcdCcNodeParams)); ++ if (!p_ExactMatchCcNodeParam) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_ExactMatchCcNodeParam")); ++ return NULL; ++ } ++ memset(p_ExactMatchCcNodeParam, 0, sizeof(t_FmPcdCcNodeParams)); ++ ++ p_IndxHashCcNodeParam = (t_FmPcdCcNodeParams*)XX_Malloc( ++ sizeof(t_FmPcdCcNodeParams)); ++ if (!p_IndxHashCcNodeParam) ++ { ++ XX_Free(p_ExactMatchCcNodeParam); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_IndxHashCcNodeParam")); ++ return NULL; ++ } ++ memset(p_IndxHashCcNodeParam, 0, sizeof(t_FmPcdCcNodeParams)); ++ ++ /* Calculate number of sets and number of ways of the hash table */ ++ countMask = (uint16_t)(p_Param->hashResMask >> 4); ++ while (countMask) ++ { ++ onesCount++; ++ countMask = (uint16_t)(countMask >> 1); ++ } ++ ++ numOfSets = (uint16_t)(1 << onesCount); ++ numOfWays = (uint16_t)DIV_CEIL(p_Param->maxNumOfKeys, numOfSets); ++ ++ if (p_Param->maxNumOfKeys % numOfSets) ++ DBG(INFO, ("'maxNumOfKeys' is not a multiple of hash number of ways, so number of ways will be rounded up")); ++ ++ if ((p_Param->statisticsMode == e_FM_PCD_CC_STATS_MODE_FRAME) ++ || (p_Param->statisticsMode == e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME)) ++ { ++ /* Allocating a statistics counters table that will be used by all ++ 'miss' entries of the hash table */ ++ h_MissStatsCounters = (t_Handle)FM_MURAM_AllocMem( ++ FmPcdGetMuramHandle(h_FmPcd), 2 * FM_PCD_CC_STATS_COUNTER_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!h_MissStatsCounters) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics table for hash miss")); ++ XX_Free(p_IndxHashCcNodeParam); ++ XX_Free(p_ExactMatchCcNodeParam); ++ return NULL; ++ } ++ memset(h_MissStatsCounters, 0, (2 * FM_PCD_CC_STATS_COUNTER_SIZE)); ++ ++ /* Always enable statistics for 'miss', so that a statistics AD will be ++ initialized from the start. We'll store the requested 'statistics enable' ++ value and it will be used when statistics are read by the user. */ ++ statsEnForMiss = p_Param->ccNextEngineParamsForMiss.statisticsEn; ++ p_Param->ccNextEngineParamsForMiss.statisticsEn = TRUE; ++ } ++ ++ /* Building exact-match node params, will be used to create the hash buckets */ ++ p_ExactMatchCcNodeParam->extractCcParams.type = e_FM_PCD_EXTRACT_NON_HDR; ++ ++ p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.src = ++ e_FM_PCD_EXTRACT_FROM_KEY; ++ p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.action = ++ e_FM_PCD_ACTION_EXACT_MATCH; ++ p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.offset = 0; ++ p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.size = ++ p_Param->matchKeySize; ++ ++ p_ExactMatchCcNodeParam->keysParams.maxNumOfKeys = numOfWays; ++ p_ExactMatchCcNodeParam->keysParams.maskSupport = FALSE; ++ p_ExactMatchCcNodeParam->keysParams.statisticsMode = ++ p_Param->statisticsMode; ++ p_ExactMatchCcNodeParam->keysParams.numOfKeys = 0; ++ p_ExactMatchCcNodeParam->keysParams.keySize = p_Param->matchKeySize; ++ p_ExactMatchCcNodeParam->keysParams.ccNextEngineParamsForMiss = ++ p_Param->ccNextEngineParamsForMiss; ++ ++ p_HashKeyParams = p_IndxHashCcNodeParam->keysParams.keyParams; ++ ++ for (i = 0; i < numOfSets; i++) ++ { ++ /* Each exact-match node will be marked as a 'bucket' and provided with ++ a pointer to statistics counters, to be used for 'miss' entry ++ statistics */ ++ p_CcNode = (t_FmPcdCcNode *)XX_Malloc(sizeof(t_FmPcdCcNode)); ++ if (!p_CcNode) ++ break; ++ memset(p_CcNode, 0, sizeof(t_FmPcdCcNode)); ++ ++ p_CcNode->isHashBucket = TRUE; ++ p_CcNode->h_MissStatsCounters = h_MissStatsCounters; ++ ++ err = MatchTableSet(h_FmPcd, p_CcNode, p_ExactMatchCcNodeParam); ++ if (err) ++ break; ++ ++ p_HashKeyParams[i].ccNextEngineParams.nextEngine = e_FM_PCD_CC; ++ p_HashKeyParams[i].ccNextEngineParams.statisticsEn = FALSE; ++ p_HashKeyParams[i].ccNextEngineParams.params.ccParams.h_CcNode = ++ p_CcNode; ++ } ++ ++ if (i < numOfSets) ++ { ++ for (i = i - 1; i >= 0; i--) ++ FM_PCD_MatchTableDelete( ++ p_HashKeyParams[i].ccNextEngineParams.params.ccParams.h_CcNode); ++ ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(h_FmPcd), h_MissStatsCounters); ++ ++ REPORT_ERROR(MAJOR, E_NULL_POINTER, NO_MSG); ++ XX_Free(p_IndxHashCcNodeParam); ++ XX_Free(p_ExactMatchCcNodeParam); ++ return NULL; ++ } ++ ++ /* Creating indexed-hash CC node */ ++ p_IndxHashCcNodeParam->extractCcParams.type = e_FM_PCD_EXTRACT_NON_HDR; ++ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.src = ++ e_FM_PCD_EXTRACT_FROM_HASH; ++ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.action = ++ e_FM_PCD_ACTION_INDEXED_LOOKUP; ++ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.icIndxMask = ++ p_Param->hashResMask; ++ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.offset = ++ p_Param->hashShift; ++ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.size = 2; ++ ++ p_IndxHashCcNodeParam->keysParams.maxNumOfKeys = numOfSets; ++ p_IndxHashCcNodeParam->keysParams.maskSupport = FALSE; ++ p_IndxHashCcNodeParam->keysParams.statisticsMode = ++ e_FM_PCD_CC_STATS_MODE_NONE; ++ /* Number of keys of this node is number of sets of the hash */ ++ p_IndxHashCcNodeParam->keysParams.numOfKeys = numOfSets; ++ p_IndxHashCcNodeParam->keysParams.keySize = 2; ++ ++ p_CcNodeHashTbl = FM_PCD_MatchTableSet(h_FmPcd, p_IndxHashCcNodeParam); ++ ++ if (p_CcNodeHashTbl) ++ { ++ p_CcNodeHashTbl->kgHashShift = p_Param->kgHashShift; ++ ++ /* Storing the allocated counters for buckets 'miss' in the hash table ++ and if statistics for miss were enabled. */ ++ p_CcNodeHashTbl->h_MissStatsCounters = h_MissStatsCounters; ++ p_CcNodeHashTbl->statsEnForMiss = statsEnForMiss; ++ } ++ ++ XX_Free(p_IndxHashCcNodeParam); ++ XX_Free(p_ExactMatchCcNodeParam); ++ ++ return p_CcNodeHashTbl; ++} ++ ++t_Error FM_PCD_HashTableDelete(t_Handle h_HashTbl) ++{ ++ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; ++ t_Handle h_FmPcd; ++ t_Handle *p_HashBuckets, h_MissStatsCounters; ++ uint16_t i, numOfBuckets; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); ++ ++ /* Store all hash buckets before the hash is freed */ ++ numOfBuckets = p_HashTbl->numOfKeys; ++ ++ p_HashBuckets = (t_Handle *)XX_Malloc(numOfBuckets * sizeof(t_Handle)); ++ if (!p_HashBuckets) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ ++ for (i = 0; i < numOfBuckets; i++) ++ p_HashBuckets[i] = ++ p_HashTbl->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode; ++ ++ h_FmPcd = p_HashTbl->h_FmPcd; ++ h_MissStatsCounters = p_HashTbl->h_MissStatsCounters; ++ ++ /* Free the hash */ ++ err = FM_PCD_MatchTableDelete(p_HashTbl); ++ ++ /* Free each hash bucket */ ++ for (i = 0; i < numOfBuckets; i++) ++ err |= FM_PCD_MatchTableDelete(p_HashBuckets[i]); ++ ++ XX_Free(p_HashBuckets); ++ ++ /* Free statistics counters for 'miss', if these were allocated */ ++ if (h_MissStatsCounters) ++ FM_MURAM_FreeMem(FmPcdGetMuramHandle(h_FmPcd), h_MissStatsCounters); ++ ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_HashTableAddKey(t_Handle h_HashTbl, uint8_t keySize, ++ t_FmPcdCcKeyParams *p_KeyParams) ++{ ++ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; ++ t_Handle h_HashBucket; ++ uint8_t bucketIndex; ++ uint16_t lastIndex; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_KeyParams->p_Key, E_NULL_POINTER); ++ ++ if (p_KeyParams->p_Mask) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("Keys masks not supported for hash table")); ++ ++ err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl, keySize, ++ p_KeyParams->p_Key, ++ p_HashTbl->kgHashShift, ++ &h_HashBucket, &bucketIndex, ++ &lastIndex); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return FM_PCD_MatchTableAddKey(h_HashBucket, FM_PCD_LAST_KEY_INDEX, keySize, ++ p_KeyParams); ++} ++ ++t_Error FM_PCD_HashTableRemoveKey(t_Handle h_HashTbl, uint8_t keySize, ++ uint8_t *p_Key) ++{ ++ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; ++ t_Handle h_HashBucket; ++ uint8_t bucketIndex; ++ uint16_t lastIndex; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ ++ err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl, keySize, p_Key, ++ p_HashTbl->kgHashShift, ++ &h_HashBucket, &bucketIndex, ++ &lastIndex); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return FM_PCD_MatchTableFindNRemoveKey(h_HashBucket, keySize, p_Key, NULL); ++} ++ ++t_Error FM_PCD_HashTableModifyNextEngine( ++ t_Handle h_HashTbl, uint8_t keySize, uint8_t *p_Key, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; ++ t_Handle h_HashBucket; ++ uint8_t bucketIndex; ++ uint16_t lastIndex; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); ++ ++ err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl, keySize, p_Key, ++ p_HashTbl->kgHashShift, ++ &h_HashBucket, &bucketIndex, ++ &lastIndex); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return FM_PCD_MatchTableFindNModifyNextEngine(h_HashBucket, keySize, p_Key, ++ NULL, ++ p_FmPcdCcNextEngineParams); ++} ++ ++t_Error FM_PCD_HashTableModifyMissNextEngine( ++ t_Handle h_HashTbl, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; ++ t_Handle h_HashBucket; ++ uint8_t i; ++ bool nullifyMissStats = FALSE; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(h_HashTbl, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); ++ ++ if ((!p_HashTbl->h_MissStatsCounters) ++ && (p_FmPcdCcNextEngineParams->statisticsEn)) ++ RETURN_ERROR( ++ MAJOR, ++ E_CONFLICT, ++ ("Statistics are requested for a key, but statistics mode was set" ++ "to 'NONE' upon initialization")); ++ ++ if (p_HashTbl->h_MissStatsCounters) ++ { ++ if ((!p_HashTbl->statsEnForMiss) ++ && (p_FmPcdCcNextEngineParams->statisticsEn)) ++ nullifyMissStats = TRUE; ++ ++ if ((p_HashTbl->statsEnForMiss) ++ && (!p_FmPcdCcNextEngineParams->statisticsEn)) ++ { ++ p_HashTbl->statsEnForMiss = FALSE; ++ p_FmPcdCcNextEngineParams->statisticsEn = TRUE; ++ } ++ } ++ ++ for (i = 0; i < p_HashTbl->numOfKeys; i++) ++ { ++ h_HashBucket = ++ p_HashTbl->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode; ++ ++ err = FM_PCD_MatchTableModifyMissNextEngine(h_HashBucket, ++ p_FmPcdCcNextEngineParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ if (nullifyMissStats) ++ { ++ memset(p_HashTbl->h_MissStatsCounters, 0, ++ (2 * FM_PCD_CC_STATS_COUNTER_SIZE)); ++ memset(p_HashTbl->h_MissStatsCounters, 0, ++ (2 * FM_PCD_CC_STATS_COUNTER_SIZE)); ++ p_HashTbl->statsEnForMiss = TRUE; ++ } ++ ++ return E_OK; ++} ++ ++ ++t_Error FM_PCD_HashTableGetMissNextEngine( ++ t_Handle h_HashTbl, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams) ++{ ++ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; ++ t_FmPcdCcNode *p_HashBucket; ++ ++ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); ++ ++ /* Miss next engine of each bucket was initialized with the next engine of the hash table */ ++ p_HashBucket = ++ p_HashTbl->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode; ++ ++ memcpy(p_FmPcdCcNextEngineParams, ++ &p_HashBucket->keyAndNextEngineParams[p_HashBucket->numOfKeys].nextEngineParams, ++ sizeof(t_FmPcdCcNextEngineParams)); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_HashTableFindNGetKeyStatistics( ++ t_Handle h_HashTbl, uint8_t keySize, uint8_t *p_Key, ++ t_FmPcdCcKeyStatistics *p_KeyStatistics) ++{ ++ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; ++ t_Handle h_HashBucket; ++ uint8_t bucketIndex; ++ uint16_t lastIndex; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_KeyStatistics, E_NULL_POINTER); ++ ++ err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl, keySize, p_Key, ++ p_HashTbl->kgHashShift, ++ &h_HashBucket, &bucketIndex, ++ &lastIndex); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return FM_PCD_MatchTableFindNGetKeyStatistics(h_HashBucket, keySize, p_Key, ++ NULL, p_KeyStatistics); ++} ++ ++t_Error FM_PCD_HashTableGetMissStatistics( ++ t_Handle h_HashTbl, t_FmPcdCcKeyStatistics *p_MissStatistics) ++{ ++ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl; ++ t_Handle h_HashBucket; ++ ++ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_MissStatistics, E_NULL_POINTER); ++ ++ if (!p_HashTbl->statsEnForMiss) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("Statistics were not enabled for miss")); ++ ++ h_HashBucket = ++ p_HashTbl->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode; ++ ++ return FM_PCD_MatchTableGetMissStatistics(h_HashBucket, p_MissStatistics); ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_cc.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_cc.h +new file mode 100644 +index 0000000..3456bb5 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_cc.h +@@ -0,0 +1,399 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_cc.h ++ ++ @Description FM PCD CC ... ++*//***************************************************************************/ ++#ifndef __FM_CC_H ++#define __FM_CC_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++ ++#include "fm_pcd.h" ++ ++ ++/***********************************************************************/ ++/* Coarse classification defines */ ++/***********************************************************************/ ++ ++#define CC_MAX_NUM_OF_KEYS (FM_PCD_MAX_NUM_OF_KEYS + 1) ++ ++#define CC_PC_FF_MACDST 0x00 ++#define CC_PC_FF_MACSRC 0x01 ++#define CC_PC_FF_ETYPE 0x02 ++ ++#define CC_PC_FF_TCI1 0x03 ++#define CC_PC_FF_TCI2 0x04 ++ ++#define CC_PC_FF_MPLS1 0x06 ++#define CC_PC_FF_MPLS_LAST 0x07 ++ ++#define CC_PC_FF_IPV4DST1 0x08 ++#define CC_PC_FF_IPV4DST2 0x16 ++#define CC_PC_FF_IPV4IPTOS_TC1 0x09 ++#define CC_PC_FF_IPV4IPTOS_TC2 0x17 ++#define CC_PC_FF_IPV4PTYPE1 0x0A ++#define CC_PC_FF_IPV4PTYPE2 0x18 ++#define CC_PC_FF_IPV4SRC1 0x0b ++#define CC_PC_FF_IPV4SRC2 0x19 ++#define CC_PC_FF_IPV4SRC1_IPV4DST1 0x0c ++#define CC_PC_FF_IPV4SRC2_IPV4DST2 0x1a ++#define CC_PC_FF_IPV4TTL 0x29 ++ ++ ++#define CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1 0x0d /*TODO - CLASS - what is it? TOS*/ ++#define CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2 0x1b ++#define CC_PC_FF_IPV6PTYPE1 0x0e ++#define CC_PC_FF_IPV6PTYPE2 0x1c ++#define CC_PC_FF_IPV6DST1 0x0f ++#define CC_PC_FF_IPV6DST2 0x1d ++#define CC_PC_FF_IPV6SRC1 0x10 ++#define CC_PC_FF_IPV6SRC2 0x1e ++#define CC_PC_FF_IPV6HOP_LIMIT 0x2a ++#define CC_PC_FF_IPPID 0x24 ++#define CC_PC_FF_IPDSCP 0x76 ++ ++#define CC_PC_FF_GREPTYPE 0x11 ++ ++#define CC_PC_FF_MINENCAP_PTYPE 0x12 ++#define CC_PC_FF_MINENCAP_IPDST 0x13 ++#define CC_PC_FF_MINENCAP_IPSRC 0x14 ++#define CC_PC_FF_MINENCAP_IPSRC_IPDST 0x15 ++ ++#define CC_PC_FF_L4PSRC 0x1f ++#define CC_PC_FF_L4PDST 0x20 ++#define CC_PC_FF_L4PSRC_L4PDST 0x21 ++ ++#define CC_PC_FF_PPPPID 0x05 ++ ++#define CC_PC_PR_SHIM1 0x22 ++#define CC_PC_PR_SHIM2 0x23 ++ ++#define CC_PC_GENERIC_WITHOUT_MASK 0x27 ++#define CC_PC_GENERIC_WITH_MASK 0x28 ++#define CC_PC_GENERIC_IC_GMASK 0x2B ++#define CC_PC_GENERIC_IC_HASH_INDEXED 0x2C ++#define CC_PC_GENERIC_IC_AGING_MASK 0x2D ++ ++#define CC_PR_OFFSET 0x25 ++#define CC_PR_WITHOUT_OFFSET 0x26 ++ ++#define CC_PC_PR_ETH_OFFSET 19 ++#define CC_PC_PR_USER_DEFINED_SHIM1_OFFSET 16 ++#define CC_PC_PR_USER_DEFINED_SHIM2_OFFSET 17 ++#define CC_PC_PR_USER_LLC_SNAP_OFFSET 20 ++#define CC_PC_PR_VLAN1_OFFSET 21 ++#define CC_PC_PR_VLAN2_OFFSET 22 ++#define CC_PC_PR_PPPOE_OFFSET 24 ++#define CC_PC_PR_MPLS1_OFFSET 25 ++#define CC_PC_PR_MPLS_LAST_OFFSET 26 ++#define CC_PC_PR_IP1_OFFSET 27 ++#define CC_PC_PR_IP_LAST_OFFSET 28 ++#define CC_PC_PR_MINENC_OFFSET 28 ++#define CC_PC_PR_L4_OFFSET 30 ++#define CC_PC_PR_GRE_OFFSET 29 ++#define CC_PC_PR_ETYPE_LAST_OFFSET 23 ++#define CC_PC_PR_NEXT_HEADER_OFFSET 31 ++ ++#define CC_PC_ILLEGAL 0xff ++#define CC_SIZE_ILLEGAL 0 ++ ++#define FM_PCD_CC_KEYS_MATCH_TABLE_ALIGN 16 ++#define FM_PCD_CC_AD_TABLE_ALIGN 16 ++#define FM_PCD_CC_AD_ENTRY_SIZE 16 ++#define FM_PCD_CC_NUM_OF_KEYS 255 ++#define FM_PCD_CC_TREE_ADDR_ALIGN 256 ++ ++#define FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE 0x00000000 ++#define FM_PCD_AD_RESULT_DATA_FLOW_TYPE 0x80000000 ++#define FM_PCD_AD_RESULT_PLCR_DIS 0x20000000 ++#define FM_PCD_AD_RESULT_EXTENDED_MODE 0x80000000 ++#define FM_PCD_AD_RESULT_NADEN 0x20000000 ++#define FM_PCD_AD_RESULT_STATISTICS_EN 0x40000000 ++ ++#define FM_PCD_AD_CONT_LOOKUP_TYPE 0x40000000 ++#define FM_PCD_AD_CONT_LOOKUP_LCL_MASK 0x00800000 ++ ++#define FM_PCD_AD_STATS_TYPE 0x40000000 ++#define FM_PCD_AD_STATS_FLR_ADDR_MASK 0x00FFFFFF ++#define FM_PCD_AD_STATS_COUNTERS_ADDR_MASK 0x00FFFFFF ++#define FM_PCD_AD_STATS_NEXT_ACTION_MASK 0xFFFF0000 ++#define FM_PCD_AD_STATS_NEXT_ACTION_SHIFT 12 ++#define FM_PCD_AD_STATS_NAD_EN 0x00008000 ++#define FM_PCD_AD_STATS_OP_CODE 0x00000036 ++#define FM_PCD_AD_STATS_FLR_EN 0x00004000 ++#define FM_PCD_AD_STATS_COND_EN 0x00002000 ++ ++ ++ ++#define FM_PCD_AD_BYPASS_TYPE 0xc0000000 ++ ++#define FM_PCD_AD_TYPE_MASK 0xc0000000 ++#define FM_PCD_AD_OPCODE_MASK 0x0000000f ++ ++#define FM_PCD_AD_PROFILEID_FOR_CNTRL_SHIFT 16 ++#if (DPAA_VERSION >= 11) ++#define FM_PCD_AD_RESULT_VSP_SHIFT 24 ++#define FM_PCD_AD_RESULT_NO_OM_VSPE 0x02000000 ++#define FM_PCD_AD_RESULT_VSP_MASK 0x3f ++#define FM_PCD_AD_NCSPFQIDM_MASK 0x80000000 ++#endif /* (DPAA_VERSION >= 11) */ ++ ++#define GLBL_MASK_FOR_HASH_INDEXED 0xfff00000 ++#define CC_GLBL_MASK_SIZE 4 ++#define CC_AGING_MASK_SIZE 4 ++ ++typedef uint32_t ccPrivateInfo_t; /**< private info of CC: */ ++ ++#define CC_PRIVATE_INFO_NONE 0 ++#define CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP 0x80000000 ++#define CC_PRIVATE_INFO_IC_HASH_EXACT_MATCH 0x40000000 ++#define CC_PRIVATE_INFO_IC_KEY_EXACT_MATCH 0x20000000 ++#define CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP 0x10000000 ++ ++#define CC_BUILD_AGING_MASK(numOfKeys) ((((1LL << ((numOfKeys) + 1)) - 1)) << (31 - (numOfKeys))) ++/***********************************************************************/ ++/* Memory map */ ++/***********************************************************************/ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++typedef struct ++{ ++ volatile uint32_t fqid; ++ volatile uint32_t plcrProfile; ++ volatile uint32_t nia; ++ volatile uint32_t res; ++} t_AdOfTypeResult; ++ ++typedef struct ++{ ++ volatile uint32_t ccAdBase; ++ volatile uint32_t matchTblPtr; ++ volatile uint32_t pcAndOffsets; ++ volatile uint32_t gmask; ++} t_AdOfTypeContLookup; ++ ++typedef struct ++{ ++ volatile uint32_t profileTableAddr; ++ volatile uint32_t reserved; ++ volatile uint32_t nextActionIndx; ++ volatile uint32_t statsTableAddr; ++} t_AdOfTypeStats; ++ ++typedef union ++{ ++ volatile t_AdOfTypeResult adResult; ++ volatile t_AdOfTypeContLookup adContLookup; ++} t_Ad; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/***********************************************************************/ ++/* Driver's internal structures */ ++/***********************************************************************/ ++ ++typedef struct t_FmPcdStatsObj ++{ ++ t_Handle h_StatsAd; ++ t_Handle h_StatsCounters; ++ t_List node; ++} t_FmPcdStatsObj; ++ ++typedef struct ++{ ++ uint8_t key[FM_PCD_MAX_SIZE_OF_KEY]; ++ uint8_t mask[FM_PCD_MAX_SIZE_OF_KEY]; ++ ++ t_FmPcdCcNextEngineParams nextEngineParams; ++ uint32_t requiredAction; ++ uint32_t shadowAction; ++ ++ t_FmPcdStatsObj *p_StatsObj; ++ ++} t_FmPcdCcKeyAndNextEngineParams; ++ ++typedef struct ++{ ++ t_Handle p_Ad; ++ e_FmPcdEngine fmPcdEngine; ++ bool adAllocated; ++ bool isTree; ++ ++ uint32_t myInfo; ++ t_List *h_CcNextNodesLst; ++ t_Handle h_AdditionalInfo; ++ t_Handle h_Node; ++} t_FmPcdModifyCcAdditionalParams; ++ ++typedef struct ++{ ++ t_Handle p_AdTableNew; ++ t_Handle p_KeysMatchTableNew; ++ t_Handle p_AdTableOld; ++ t_Handle p_KeysMatchTableOld; ++ uint16_t numOfKeys; ++ t_Handle h_CurrentNode; ++ uint16_t savedKeyIndex; ++ t_Handle h_NodeForAdd; ++ t_Handle h_NodeForRmv; ++ t_Handle h_ManipForRmv; ++ t_Handle h_ManipForAdd; ++ t_FmPcdStatsObj *p_StatsObjForRmv; ++#if (DPAA_VERSION >= 11) ++ t_Handle h_FrmReplicForAdd; ++ t_Handle h_FrmReplicForRmv; ++#endif /* (DPAA_VERSION >= 11) */ ++ bool tree; ++ ++ t_FmPcdCcKeyAndNextEngineParams keyAndNextEngineParams[CC_MAX_NUM_OF_KEYS]; ++} t_FmPcdModifyCcKeyAdditionalParams; ++ ++typedef struct ++{ ++ t_Handle h_Manip; ++ t_Handle h_CcNode; ++} t_CcNextEngineInfo; ++ ++typedef struct ++{ ++ uint16_t numOfKeys; ++ uint16_t maxNumOfKeys; ++ ++ bool maskSupport; ++ uint32_t keysMatchTableMaxSize; ++ ++ e_FmPcdCcStatsMode statisticsMode; ++ uint32_t numOfStatsFLRs; ++ uint32_t countersArraySize; ++ ++ bool isHashBucket; /**< Valid for match table node that is a bucket of a hash table only */ ++ t_Handle h_MissStatsCounters; /**< Valid for hash table node and match table that is a bucket; ++ Holds the statistics counters allocated by the hash table and ++ are shared by all hash table buckets; */ ++ t_Handle h_PrivMissStatsCounters; /**< Valid for match table node that is a bucket of a hash table only; ++ Holds the statistics counters that were allocated for this node ++ and replaced by the shared counters (allocated by the hash table); */ ++ bool statsEnForMiss; /**< Valid for hash table node only; TRUE is statistics are currently ++ enabled for hash 'miss', FALSE otherwise; This parameter effects the ++ returned statistics count to user, statistics AD always present for 'miss' ++ for all hash buckets; */ ++ bool glblMaskUpdated; ++ t_Handle p_GlblMask; ++ bool lclMask; ++ uint8_t parseCode; ++ uint8_t offset; ++ uint8_t prsArrayOffset; ++ bool ctrlFlow; ++ uint16_t owners; ++ ++ uint8_t ccKeySizeAccExtraction; ++ uint8_t sizeOfExtraction; ++ uint8_t glblMaskSize; ++ ++ t_Handle h_KeysMatchTable; ++ t_Handle h_AdTable; ++ t_Handle h_StatsAds; ++ t_Handle h_TmpAd; ++ t_Handle h_Ad; ++ t_Handle h_StatsFLRs; ++ ++ t_List availableStatsLst; ++ ++ t_List ccPrevNodesLst; ++ ++ t_List ccTreeIdLst; ++ t_List ccTreesLst; ++ ++ t_Handle h_FmPcd; ++ uint32_t shadowAction; ++ uint8_t userSizeOfExtraction; ++ uint8_t userOffset; ++ uint8_t kgHashShift; /* used in hash-table */ ++ ++ t_Handle h_Spinlock; ++ ++ t_FmPcdCcKeyAndNextEngineParams keyAndNextEngineParams[CC_MAX_NUM_OF_KEYS]; ++} t_FmPcdCcNode; ++ ++typedef struct ++{ ++ t_FmPcdCcNode *p_FmPcdCcNode; ++ bool occupied; ++ uint16_t owners; ++ volatile bool lock; ++} t_FmPcdCcNodeArray; ++ ++typedef struct ++{ ++ uint8_t numOfEntriesInGroup; ++ uint32_t totalBitsMask; ++ uint8_t baseGroupEntry; ++} t_FmPcdCcGroupParam; ++ ++typedef struct ++{ ++ t_Handle h_FmPcd; ++ uint8_t netEnvId; ++ uintptr_t ccTreeBaseAddr; ++ uint8_t numOfGrps; ++ t_FmPcdCcGroupParam fmPcdGroupParam[FM_PCD_MAX_NUM_OF_CC_GROUPS]; ++ t_List fmPortsLst; ++ t_FmPcdLock *p_Lock; ++ uint8_t numOfEntries; ++ uint16_t owners; ++ t_Handle h_FmPcdCcSavedManipParams; ++ bool modifiedState; ++ uint32_t requiredAction; ++ t_Handle h_IpReassemblyManip; ++ t_Handle h_CapwapReassemblyManip; ++ ++ t_FmPcdCcKeyAndNextEngineParams keyAndNextEngineParams[FM_PCD_MAX_NUM_OF_CC_GROUPS]; ++} t_FmPcdCcTree; ++ ++ ++t_Error FmPcdCcNodeTreeTryLock(t_Handle h_FmPcd,t_Handle h_FmPcdCcNode, t_List *p_List); ++void FmPcdCcNodeTreeReleaseLock(t_Handle h_FmPcd, t_List *p_List); ++t_Error FmPcdUpdateCcShadow (t_FmPcd *p_FmPcd, uint32_t size, uint32_t align); ++ ++ ++#endif /* __FM_CC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_kg.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_kg.c +new file mode 100644 +index 0000000..720da19 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_kg.c +@@ -0,0 +1,3242 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_kg.c ++ ++ @Description FM PCD ... ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "debug_ext.h" ++#include "net_ext.h" ++#include "fm_port_ext.h" ++ ++#include "fm_common.h" ++#include "fm_pcd.h" ++#include "fm_hc.h" ++#include "fm_pcd_ipc.h" ++#include "fm_kg.h" ++#include "fsl_fman_kg.h" ++ ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++ ++static uint32_t KgHwLock(t_Handle h_FmPcdKg) ++{ ++ ASSERT_COND(h_FmPcdKg); ++ return XX_LockIntrSpinlock(((t_FmPcdKg *)h_FmPcdKg)->h_HwSpinlock); ++} ++ ++static void KgHwUnlock(t_Handle h_FmPcdKg, uint32_t intFlags) ++{ ++ ASSERT_COND(h_FmPcdKg); ++ XX_UnlockIntrSpinlock(((t_FmPcdKg *)h_FmPcdKg)->h_HwSpinlock, intFlags); ++} ++ ++static uint32_t KgSchemeLock(t_Handle h_Scheme) ++{ ++ ASSERT_COND(h_Scheme); ++ return FmPcdLockSpinlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock); ++} ++ ++static void KgSchemeUnlock(t_Handle h_Scheme, uint32_t intFlags) ++{ ++ ASSERT_COND(h_Scheme); ++ FmPcdUnlockSpinlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock, intFlags); ++} ++ ++static bool KgSchemeFlagTryLock(t_Handle h_Scheme) ++{ ++ ASSERT_COND(h_Scheme); ++ return FmPcdLockTryLock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock); ++} ++ ++static void KgSchemeFlagUnlock(t_Handle h_Scheme) ++{ ++ ASSERT_COND(h_Scheme); ++ FmPcdLockUnlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock); ++} ++ ++static t_Error WriteKgarWait(t_FmPcd *p_FmPcd, uint32_t fmkg_ar) ++{ ++ ++ struct fman_kg_regs *regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ ++ if (fman_kg_write_ar_wait(regs, fmkg_ar)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Keygen scheme access violation")); ++ ++ return E_OK; ++} ++ ++static e_FmPcdKgExtractDfltSelect GetGenericSwDefault(t_FmPcdKgExtractDflt swDefaults[], uint8_t numOfSwDefaults, uint8_t code) ++{ ++ int i; ++ ++ switch (code) ++ { ++ case (KG_SCH_GEN_PARSE_RESULT_N_FQID): ++ case (KG_SCH_GEN_DEFAULT): ++ case (KG_SCH_GEN_NEXTHDR): ++ for (i=0 ; ifmRevInfo.majorRev < 6) ++ return KG_SCH_KN_PTYPE2; ++#endif /* FM_KG_NO_IPPID_SUPPORT */ ++ return KG_SCH_KN_IPPID; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index")); ++ return 0; ++ case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL | NET_HEADER_FIELD_IPv6_TC): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1)) ++ return (KG_SCH_KN_IPV6FL1 | KG_SCH_KN_IPTOS_TC1); ++ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST)) ++ return (KG_SCH_KN_IPV6FL2 | KG_SCH_KN_IPTOS_TC2); ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index")); ++ return 0; ++ case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_TC): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1)) ++ return KG_SCH_KN_IPTOS_TC1; ++ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST)) ++ return KG_SCH_KN_IPTOS_TC2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index")); ++ return 0; ++ case (NET_HEADER_FIELD_IPv6_FL): ++ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1)) ++ return KG_SCH_KN_IPV6FL1; ++ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST)) ++ return KG_SCH_KN_IPV6FL2; ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index")); ++ return 0; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_GRE): ++ switch (field.gre) ++ { ++ case (NET_HEADER_FIELD_GRE_TYPE): ++ return KG_SCH_KN_GREPTYPE; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_MINENCAP): ++ switch (field.minencap) ++ { ++ case (NET_HEADER_FIELD_MINENCAP_SRC_IP): ++ return KG_SCH_KN_IPSRC2; ++ case (NET_HEADER_FIELD_MINENCAP_DST_IP): ++ return KG_SCH_KN_IPDST2; ++ case (NET_HEADER_FIELD_MINENCAP_TYPE): ++ return KG_SCH_KN_PTYPE2; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_TCP): ++ switch (field.tcp) ++ { ++ case (NET_HEADER_FIELD_TCP_PORT_SRC): ++ return KG_SCH_KN_L4PSRC; ++ case (NET_HEADER_FIELD_TCP_PORT_DST): ++ return KG_SCH_KN_L4PDST; ++ case (NET_HEADER_FIELD_TCP_FLAGS): ++ return KG_SCH_KN_TFLG; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_UDP): ++ switch (field.udp) ++ { ++ case (NET_HEADER_FIELD_UDP_PORT_SRC): ++ return KG_SCH_KN_L4PSRC; ++ case (NET_HEADER_FIELD_UDP_PORT_DST): ++ return KG_SCH_KN_L4PDST; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_IPSEC_AH): ++ switch (field.ipsecAh) ++ { ++ case (NET_HEADER_FIELD_IPSEC_AH_SPI): ++ return KG_SCH_KN_IPSEC_SPI; ++ case (NET_HEADER_FIELD_IPSEC_AH_NH): ++ return KG_SCH_KN_IPSEC_NH; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_IPSEC_ESP): ++ switch (field.ipsecEsp) ++ { ++ case (NET_HEADER_FIELD_IPSEC_ESP_SPI): ++ return KG_SCH_KN_IPSEC_SPI; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_SCTP): ++ switch (field.sctp) ++ { ++ case (NET_HEADER_FIELD_SCTP_PORT_SRC): ++ return KG_SCH_KN_L4PSRC; ++ case (NET_HEADER_FIELD_SCTP_PORT_DST): ++ return KG_SCH_KN_L4PDST; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_DCCP): ++ switch (field.dccp) ++ { ++ case (NET_HEADER_FIELD_DCCP_PORT_SRC): ++ return KG_SCH_KN_L4PSRC; ++ case (NET_HEADER_FIELD_DCCP_PORT_DST): ++ return KG_SCH_KN_L4PDST; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ case (HEADER_TYPE_PPPoE): ++ switch (field.pppoe) ++ { ++ case (NET_HEADER_FIELD_PPPoE_PID): ++ return KG_SCH_KN_PPPID; ++ case (NET_HEADER_FIELD_PPPoE_SID): ++ return KG_SCH_KN_PPPSID; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++ } ++ default: ++ break; ++ ++ } ++ ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported")); ++ return 0; ++} ++ ++ ++static uint8_t GetKnownFieldId(uint32_t bitMask) ++{ ++ uint8_t cnt = 0; ++ ++ while (bitMask) ++ if (bitMask & 0x80000000) ++ break; ++ else ++ { ++ cnt++; ++ bitMask <<= 1; ++ } ++ return cnt; ++ ++} ++ ++static uint8_t GetExtractedOrMask(uint8_t bitOffset, bool fqid) ++{ ++ uint8_t i, mask, numOfOnesToClear, walking1Mask = 1; ++ ++ /* bitOffset 1-7 --> mask 0x1-0x7F */ ++ if (bitOffset<8) ++ { ++ mask = 0; ++ for (i = 0 ; i < bitOffset ; i++, walking1Mask <<= 1) ++ mask |= walking1Mask; ++ } ++ else ++ { ++ mask = 0xFF; ++ numOfOnesToClear = 0; ++ if (fqid && bitOffset>24) ++ /* bitOffset 25-31 --> mask 0xFE-0x80 */ ++ numOfOnesToClear = (uint8_t)(bitOffset-24); ++ else ++ /* bitOffset 9-15 --> mask 0xFE-0x80 */ ++ if (!fqid && bitOffset>8) ++ numOfOnesToClear = (uint8_t)(bitOffset-8); ++ for (i = 0 ; i < numOfOnesToClear ; i++, walking1Mask <<= 1) ++ mask &= ~walking1Mask; ++ /* bitOffset 8-24 for FQID, 8 for PP --> no mask (0xFF)*/ ++ } ++ return mask; ++} ++ ++static void IncSchemeOwners(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort) ++{ ++ t_FmPcdKg *p_FmPcdKg; ++ t_FmPcdKgScheme *p_Scheme; ++ uint32_t intFlags; ++ uint8_t relativeSchemeId; ++ int i; ++ ++ p_FmPcdKg = p_FmPcd->p_FmPcdKg; ++ ++ /* for each scheme - update owners counters */ ++ for (i = 0; i < p_BindPort->numOfSchemes; i++) ++ { ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]); ++ ASSERT_COND(relativeSchemeId < FM_PCD_KG_NUM_OF_SCHEMES); ++ ++ p_Scheme = &p_FmPcdKg->schemes[relativeSchemeId]; ++ ++ /* increment owners number */ ++ intFlags = KgSchemeLock(p_Scheme); ++ p_Scheme->owners++; ++ KgSchemeUnlock(p_Scheme, intFlags); ++ } ++} ++ ++static void DecSchemeOwners(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort) ++{ ++ t_FmPcdKg *p_FmPcdKg; ++ t_FmPcdKgScheme *p_Scheme; ++ uint32_t intFlags; ++ uint8_t relativeSchemeId; ++ int i; ++ ++ p_FmPcdKg = p_FmPcd->p_FmPcdKg; ++ ++ /* for each scheme - update owners counters */ ++ for (i = 0; i < p_BindPort->numOfSchemes; i++) ++ { ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]); ++ ASSERT_COND(relativeSchemeId < FM_PCD_KG_NUM_OF_SCHEMES); ++ ++ p_Scheme = &p_FmPcdKg->schemes[relativeSchemeId]; ++ ++ /* increment owners number */ ++ ASSERT_COND(p_Scheme->owners); ++ intFlags = KgSchemeLock(p_Scheme); ++ p_Scheme->owners--; ++ KgSchemeUnlock(p_Scheme, intFlags); ++ } ++} ++ ++static void UpdateRequiredActionFlag(t_FmPcdKgScheme *p_Scheme, bool set) ++{ ++ /* this routine is locked by the calling routine */ ++ ASSERT_COND(p_Scheme); ++ ASSERT_COND(p_Scheme->valid); ++ ++ if (set) ++ p_Scheme->requiredActionFlag = TRUE; ++ else ++ { ++ p_Scheme->requiredAction = 0; ++ p_Scheme->requiredActionFlag = FALSE; ++ } ++} ++ ++static t_Error KgWriteSp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint32_t spReg, bool add) ++{ ++ struct fman_kg_regs *p_KgRegs; ++ ++ uint32_t tmpKgarReg = 0, intFlags; ++ t_Error err = E_OK; ++ ++ /* The calling routine had locked the port, so for each port only one core can access ++ * (so we don't need a lock here) */ ++ ++ if (p_FmPcd->h_Hc) ++ return FmHcKgWriteSp(p_FmPcd->h_Hc, hardwarePortId, spReg, add); ++ ++ p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ ++ tmpKgarReg = FmPcdKgBuildReadPortSchemeBindActionReg(hardwarePortId); ++ /* lock a common KG reg */ ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ err = WriteKgarWait(p_FmPcd, tmpKgarReg); ++ if (err) ++ { ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ fman_kg_write_sp(p_KgRegs, spReg, add); ++ ++ tmpKgarReg = FmPcdKgBuildWritePortSchemeBindActionReg(hardwarePortId); ++ ++ err = WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ return err; ++} ++ ++static t_Error KgWriteCpp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint32_t cppReg) ++{ ++ struct fman_kg_regs *p_KgRegs; ++ uint32_t tmpKgarReg, intFlags; ++ t_Error err; ++ ++ p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ ++ if (p_FmPcd->h_Hc) ++ { ++ err = FmHcKgWriteCpp(p_FmPcd->h_Hc, hardwarePortId, cppReg); ++ return err; ++ } ++ ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ fman_kg_write_cpp(p_KgRegs, cppReg); ++ tmpKgarReg = FmPcdKgBuildWritePortClsPlanBindActionReg(hardwarePortId); ++ err = WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ ++ return err; ++} ++ ++static uint32_t BuildCppReg(t_FmPcd *p_FmPcd, uint8_t clsPlanGrpId) ++{ ++ uint32_t tmpKgpeCpp; ++ ++ tmpKgpeCpp = (uint32_t)(p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].baseEntry / 8); ++ tmpKgpeCpp |= (uint32_t)(((p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].sizeOfGrp / 8) - 1) << FM_KG_PE_CPP_MASK_SHIFT); ++ ++ return tmpKgpeCpp; ++} ++ ++static t_Error BindPortToClsPlanGrp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint8_t clsPlanGrpId) ++{ ++ uint32_t tmpKgpeCpp = 0; ++ ++ tmpKgpeCpp = BuildCppReg(p_FmPcd, clsPlanGrpId); ++ return KgWriteCpp(p_FmPcd, hardwarePortId, tmpKgpeCpp); ++} ++ ++static void UnbindPortToClsPlanGrp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId) ++{ ++ KgWriteCpp(p_FmPcd, hardwarePortId, 0); ++} ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++static uint32_t ReadClsPlanBlockActionReg(uint8_t grpId) ++{ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ FM_KG_KGAR_READ | ++ FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY | ++ DUMMY_PORT_ID | ++ ((uint32_t)grpId << FM_PCD_KG_KGAR_NUM_SHIFT) | ++ FM_PCD_KG_KGAR_WSEL_MASK); ++ ++ /* if we ever want to write 1 by 1, use: ++ sel = (uint8_t)(0x01 << (7- (entryId % CLS_PLAN_NUM_PER_GRP))); ++ */ ++} ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++static void PcdKgErrorException(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint32_t event,schemeIndexes = 0, index = 0; ++ struct fman_kg_regs *p_KgRegs; ++ ++ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); ++ p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ fman_kg_get_event(p_KgRegs, &event, &schemeIndexes); ++ ++ if (event & FM_EX_KG_DOUBLE_ECC) ++ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC); ++ if (event & FM_EX_KG_KEYSIZE_OVERFLOW) ++ { ++ if (schemeIndexes) ++ { ++ while (schemeIndexes) ++ { ++ if (schemeIndexes & 0x1) ++ p_FmPcd->f_FmPcdIndexedException(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW, (uint16_t)(31 - index)); ++ schemeIndexes >>= 1; ++ index+=1; ++ } ++ } ++ else /* this should happen only when interrupt is forced. */ ++ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW); ++ } ++} ++ ++static t_Error KgInitGuest(t_FmPcd *p_FmPcd) ++{ ++ t_Error err = E_OK; ++ t_FmPcdIpcKgSchemesParams kgAlloc; ++ uint32_t replyLength; ++ t_FmPcdIpcReply reply; ++ t_FmPcdIpcMsg msg; ++ ++ ASSERT_COND(p_FmPcd->guestId != NCSW_MASTER_ID); ++ ++ /* in GUEST_PARTITION, we use the IPC */ ++ memset(&reply, 0, sizeof(reply)); ++ memset(&msg, 0, sizeof(msg)); ++ memset(&kgAlloc, 0, sizeof(t_FmPcdIpcKgSchemesParams)); ++ kgAlloc.numOfSchemes = p_FmPcd->p_FmPcdKg->numOfSchemes; ++ kgAlloc.guestId = p_FmPcd->guestId; ++ msg.msgId = FM_PCD_ALLOC_KG_SCHEMES; ++ memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc)); ++ replyLength = sizeof(uint32_t) + p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t); ++ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(kgAlloc), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (replyLength != (sizeof(uint32_t) + p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ memcpy(p_FmPcd->p_FmPcdKg->schemesIds, (uint8_t*)(reply.replyBody),p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t)); ++ ++ return (t_Error)reply.error; ++} ++ ++static t_Error KgInitMaster(t_FmPcd *p_FmPcd) ++{ ++ t_Error err = E_OK; ++ struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ ++ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); ++ ++ if (p_FmPcd->exceptions & FM_EX_KG_DOUBLE_ECC) ++ FmEnableRamsEcc(p_FmPcd->h_Fm); ++ ++ fman_kg_init(p_Regs, p_FmPcd->exceptions, GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd)); ++ ++ /* register even if no interrupts enabled, to allow future enablement */ ++ FmRegisterIntr(p_FmPcd->h_Fm, ++ e_FM_MOD_KG, ++ 0, ++ e_FM_INTR_TYPE_ERR, ++ PcdKgErrorException, ++ p_FmPcd); ++ ++ fman_kg_enable_scheme_interrupts(p_Regs); ++ ++ if (p_FmPcd->p_FmPcdKg->numOfSchemes) ++ { ++ err = FmPcdKgAllocSchemes(p_FmPcd, ++ p_FmPcd->p_FmPcdKg->numOfSchemes, ++ p_FmPcd->guestId, ++ p_FmPcd->p_FmPcdKg->schemesIds); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ return E_OK; ++} ++ ++static void ValidateSchemeSw(t_FmPcdKgScheme *p_Scheme) ++{ ++ ASSERT_COND(!p_Scheme->valid); ++ if (p_Scheme->netEnvId != ILLEGAL_NETENV) ++ FmPcdIncNetEnvOwners(p_Scheme->h_FmPcd, p_Scheme->netEnvId); ++ p_Scheme->valid = TRUE; ++} ++ ++static t_Error InvalidateSchemeSw(t_FmPcdKgScheme *p_Scheme) ++{ ++ if (p_Scheme->owners) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Trying to delete a scheme that has ports bound to")); ++ ++ if (p_Scheme->netEnvId != ILLEGAL_NETENV) ++ FmPcdDecNetEnvOwners(p_Scheme->h_FmPcd, p_Scheme->netEnvId); ++ p_Scheme->valid = FALSE; ++ ++ return E_OK; ++} ++ ++static t_Error BuildSchemeRegs(t_FmPcdKgScheme *p_Scheme, ++ t_FmPcdKgSchemeParams *p_SchemeParams, ++ struct fman_kg_scheme_regs *p_SchemeRegs) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)(p_Scheme->h_FmPcd); ++ uint32_t grpBits = 0; ++ uint8_t grpBase; ++ bool direct=TRUE, absolute=FALSE; ++ uint16_t profileId=0, numOfProfiles=0, relativeProfileId; ++ t_Error err = E_OK; ++ int i = 0; ++ t_NetEnvParams netEnvParams; ++ uint32_t tmpReg, fqbTmp = 0, ppcTmp = 0, selectTmp, maskTmp, knownTmp, genTmp; ++ t_FmPcdKgKeyExtractAndHashParams *p_KeyAndHash = NULL; ++ uint8_t j, curr, idx; ++ uint8_t id, shift=0, code=0, offset=0, size=0; ++ t_FmPcdExtractEntry *p_Extract = NULL; ++ t_FmPcdKgExtractedOrParams *p_ExtractOr; ++ bool generic = FALSE; ++ t_KnownFieldsMasks bitMask; ++ e_FmPcdKgExtractDfltSelect swDefault = (e_FmPcdKgExtractDfltSelect)0; ++ t_FmPcdKgSchemesExtracts *p_LocalExtractsArray; ++ uint8_t numOfSwDefaults = 0; ++ t_FmPcdKgExtractDflt swDefaults[NUM_OF_SW_DEFAULTS]; ++ uint8_t currGenId = 0; ++ ++ memset(swDefaults, 0, NUM_OF_SW_DEFAULTS*sizeof(t_FmPcdKgExtractDflt)); ++ memset(p_SchemeRegs, 0, sizeof(struct fman_kg_scheme_regs)); ++ ++ if (p_SchemeParams->netEnvParams.numOfDistinctionUnits > FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("numOfDistinctionUnits should not exceed %d", FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)); ++ ++ /* by netEnv parameters, get match vector */ ++ if (!p_SchemeParams->alwaysDirect) ++ { ++ p_Scheme->netEnvId = FmPcdGetNetEnvId(p_SchemeParams->netEnvParams.h_NetEnv); ++ netEnvParams.netEnvId = p_Scheme->netEnvId; ++ netEnvParams.numOfDistinctionUnits = p_SchemeParams->netEnvParams.numOfDistinctionUnits; ++ memcpy(netEnvParams.unitIds, p_SchemeParams->netEnvParams.unitIds, (sizeof(uint8_t))*p_SchemeParams->netEnvParams.numOfDistinctionUnits); ++ err = PcdGetUnitsVector(p_FmPcd, &netEnvParams); ++ if (err) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ p_Scheme->matchVector = netEnvParams.vector; ++ } ++ else ++ { ++ p_Scheme->matchVector = SCHEME_ALWAYS_DIRECT; ++ p_Scheme->netEnvId = ILLEGAL_NETENV; ++ } ++ ++ if (p_SchemeParams->nextEngine == e_FM_PCD_INVALID) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next Engine of the scheme is not Valid")); ++ ++ if (p_SchemeParams->bypassFqidGeneration) ++ { ++#ifdef FM_KG_NO_BYPASS_FQID_GEN ++ if ((p_FmPcd->fmRevInfo.majorRev != 4) && (p_FmPcd->fmRevInfo.majorRev < 6)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("bypassFqidGeneration.")); ++#endif /* FM_KG_NO_BYPASS_FQID_GEN */ ++ if (p_SchemeParams->baseFqid) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("baseFqid set for a scheme that does not generate an FQID")); ++ } ++ else ++ if (!p_SchemeParams->baseFqid) ++ DBG(WARNING, ("baseFqid is 0.")); ++ ++ if (p_SchemeParams->nextEngine == e_FM_PCD_PLCR) ++ { ++ direct = p_SchemeParams->kgNextEngineParams.plcrProfile.direct; ++ p_Scheme->directPlcr = direct; ++ absolute = (bool)(p_SchemeParams->kgNextEngineParams.plcrProfile.sharedProfile ? TRUE : FALSE); ++ if (!direct && absolute) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Indirect policing is not available when profile is shared.")); ++ ++ if (direct) ++ { ++ profileId = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.directRelativeProfileId; ++ numOfProfiles = 1; ++ } ++ else ++ { ++ profileId = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase; ++ shift = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.fqidOffsetShift; ++ numOfProfiles = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.numOfProfiles; ++ } ++ } ++ ++ if (p_SchemeParams->nextEngine == e_FM_PCD_CC) ++ { ++#ifdef FM_KG_NO_BYPASS_PLCR_PROFILE_GEN ++ if ((p_SchemeParams->kgNextEngineParams.cc.plcrNext) && (p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration)) ++ { ++ if ((p_FmPcd->fmRevInfo.majorRev != 4) && (p_FmPcd->fmRevInfo.majorRev < 6)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("bypassPlcrProfileGeneration.")); ++ } ++#endif /* FM_KG_NO_BYPASS_PLCR_PROFILE_GEN */ ++ ++ err = FmPcdCcGetGrpParams(p_SchemeParams->kgNextEngineParams.cc.h_CcTree, ++ p_SchemeParams->kgNextEngineParams.cc.grpId, ++ &grpBits, ++ &grpBase); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ p_Scheme->ccUnits = grpBits; ++ ++ if ((p_SchemeParams->kgNextEngineParams.cc.plcrNext) && ++ (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration)) ++ { ++ if (p_SchemeParams->kgNextEngineParams.cc.plcrProfile.sharedProfile) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Shared profile may not be used after Coarse classification.")); ++ absolute = FALSE; ++ direct = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.direct; ++ if (direct) ++ { ++ profileId = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.directRelativeProfileId; ++ numOfProfiles = 1; ++ } ++ else ++ { ++ profileId = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase; ++ shift = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.fqidOffsetShift; ++ numOfProfiles = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.numOfProfiles; ++ } ++ } ++ } ++ ++ /* if policer is used directly after KG, or after CC */ ++ if ((p_SchemeParams->nextEngine == e_FM_PCD_PLCR) || ++ ((p_SchemeParams->nextEngine == e_FM_PCD_CC) && ++ (p_SchemeParams->kgNextEngineParams.cc.plcrNext) && ++ (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration))) ++ { ++ /* if private policer profile, it may be uninitialized yet, therefore no checks are done at this stage */ ++ if (absolute) ++ { ++ /* for absolute direct policy only, */ ++ relativeProfileId = profileId; ++ err = FmPcdPlcrGetAbsoluteIdByProfileParams((t_Handle)p_FmPcd,e_FM_PCD_PLCR_SHARED,NULL, relativeProfileId, &profileId); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("Shared profile not valid offset")); ++ if (!FmPcdPlcrIsProfileValid(p_FmPcd, profileId)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Shared profile not valid.")); ++ p_Scheme->relativeProfileId = profileId; ++ } ++ else ++ { ++ /* save relative profile id's for later check */ ++ p_Scheme->nextRelativePlcrProfile = TRUE; ++ p_Scheme->relativeProfileId = profileId; ++ p_Scheme->numOfProfiles = numOfProfiles; ++ } ++ } ++ else ++ { ++ /* if policer is NOT going to be used after KG at all than if bypassFqidGeneration ++ is set, we do not need numOfUsedExtractedOrs and hashDistributionNumOfFqids */ ++ if (p_SchemeParams->bypassFqidGeneration && p_SchemeParams->numOfUsedExtractedOrs) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("numOfUsedExtractedOrs is set in a scheme that does not generate FQID or policer profile ID")); ++ if (p_SchemeParams->bypassFqidGeneration && ++ p_SchemeParams->useHash && ++ p_SchemeParams->keyExtractAndHashParams.hashDistributionNumOfFqids) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("hashDistributionNumOfFqids is set in a scheme that does not generate FQID or policer profile ID")); ++ } ++ ++ /* configure all 21 scheme registers */ ++ tmpReg = KG_SCH_MODE_EN; ++ switch (p_SchemeParams->nextEngine) ++ { ++ case (e_FM_PCD_PLCR): ++ /* add to mode register - NIA */ ++ tmpReg |= KG_SCH_MODE_NIA_PLCR; ++ tmpReg |= NIA_ENG_PLCR; ++ tmpReg |= (uint32_t)(p_SchemeParams->kgNextEngineParams.plcrProfile.sharedProfile ? NIA_PLCR_ABSOLUTE:0); ++ /* initialize policer profile command - */ ++ /* configure kgse_ppc */ ++ if (direct) ++ /* use profileId as base, other fields are 0 */ ++ p_SchemeRegs->kgse_ppc = (uint32_t)profileId; ++ else ++ { ++ if (shift > MAX_PP_SHIFT) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_PP_SHIFT)); ++ ++ if (!numOfProfiles || !POWER_OF_2(numOfProfiles)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2")); ++ ++ ppcTmp = ((uint32_t)shift << KG_SCH_PP_SHIFT_HIGH_SHIFT) & KG_SCH_PP_SHIFT_HIGH; ++ ppcTmp |= ((uint32_t)shift << KG_SCH_PP_SHIFT_LOW_SHIFT) & KG_SCH_PP_SHIFT_LOW; ++ ppcTmp |= ((uint32_t)(numOfProfiles-1) << KG_SCH_PP_MASK_SHIFT); ++ ppcTmp |= (uint32_t)profileId; ++ ++ p_SchemeRegs->kgse_ppc = ppcTmp; ++ } ++ break; ++ case (e_FM_PCD_CC): ++ /* mode reg - define NIA */ ++ tmpReg |= (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC); ++ ++ p_SchemeRegs->kgse_ccbs = grpBits; ++ tmpReg |= (uint32_t)(grpBase << KG_SCH_MODE_CCOBASE_SHIFT); ++ ++ if (p_SchemeParams->kgNextEngineParams.cc.plcrNext) ++ { ++ if (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration) ++ { ++ /* find out if absolute or relative */ ++ if (absolute) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("It is illegal to request a shared profile in a scheme that is in a KG->CC->PLCR flow")); ++ if (direct) ++ { ++ /* mask = 0, base = directProfileId */ ++ p_SchemeRegs->kgse_ppc = (uint32_t)profileId; ++ } ++ else ++ { ++ if (shift > MAX_PP_SHIFT) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_PP_SHIFT)); ++ if (!numOfProfiles || !POWER_OF_2(numOfProfiles)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2")); ++ ++ ppcTmp = ((uint32_t)shift << KG_SCH_PP_SHIFT_HIGH_SHIFT) & KG_SCH_PP_SHIFT_HIGH; ++ ppcTmp |= ((uint32_t)shift << KG_SCH_PP_SHIFT_LOW_SHIFT) & KG_SCH_PP_SHIFT_LOW; ++ ppcTmp |= ((uint32_t)(numOfProfiles-1) << KG_SCH_PP_MASK_SHIFT); ++ ppcTmp |= (uint32_t)profileId; ++ ++ p_SchemeRegs->kgse_ppc = ppcTmp; ++ } ++ } ++ } ++ break; ++ case (e_FM_PCD_DONE): ++ if (p_SchemeParams->kgNextEngineParams.doneAction == e_FM_PCD_DROP_FRAME) ++ tmpReg |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd); ++ else ++ tmpReg |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Next engine not supported")); ++ } ++ p_SchemeRegs->kgse_mode = tmpReg; ++ ++ p_SchemeRegs->kgse_mv = p_Scheme->matchVector; ++ ++#if (DPAA_VERSION >= 11) ++ if (p_SchemeParams->overrideStorageProfile) ++ { ++ p_SchemeRegs->kgse_om |= KG_SCH_OM_VSPE; ++ ++ if (p_SchemeParams->storageProfile.direct) ++ { ++ profileId = p_SchemeParams->storageProfile.profileSelect.directRelativeProfileId; ++ shift = 0; ++ numOfProfiles = 1; ++ } ++ else ++ { ++ profileId = p_SchemeParams->storageProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase; ++ shift = p_SchemeParams->storageProfile.profileSelect.indirectProfile.fqidOffsetShift; ++ numOfProfiles = p_SchemeParams->storageProfile.profileSelect.indirectProfile.numOfProfiles; ++ } ++ if (shift > MAX_SP_SHIFT) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_SP_SHIFT)); ++ ++ if (!numOfProfiles || !POWER_OF_2(numOfProfiles)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2")); ++ ++ tmpReg = (uint32_t)shift << KG_SCH_VSP_SHIFT; ++ tmpReg |= ((uint32_t)(numOfProfiles-1) << KG_SCH_VSP_MASK_SHIFT); ++ tmpReg |= (uint32_t)profileId; ++ ++ ++ p_SchemeRegs->kgse_vsp = tmpReg; ++ ++ p_Scheme->vspe = TRUE; ++ ++ } ++ else ++ p_SchemeRegs->kgse_vsp = KG_SCH_VSP_NO_KSP_EN; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (p_SchemeParams->useHash) ++ { ++ p_KeyAndHash = &p_SchemeParams->keyExtractAndHashParams; ++ ++ if (p_KeyAndHash->numOfUsedExtracts >= FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfUsedExtracts out of range")); ++ ++ /* configure kgse_dv0 */ ++ p_SchemeRegs->kgse_dv0 = p_KeyAndHash->privateDflt0; ++ ++ /* configure kgse_dv1 */ ++ p_SchemeRegs->kgse_dv1 = p_KeyAndHash->privateDflt1; ++ ++ if (!p_SchemeParams->bypassFqidGeneration) ++ { ++ if (!p_KeyAndHash->hashDistributionNumOfFqids || !POWER_OF_2(p_KeyAndHash->hashDistributionNumOfFqids)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashDistributionNumOfFqids must not be 0 and must be a power of 2")); ++ if ((p_KeyAndHash->hashDistributionNumOfFqids-1) & p_SchemeParams->baseFqid) ++ DBG(WARNING, ("baseFqid unaligned. Distribution may result in less than hashDistributionNumOfFqids queues.")); ++ } ++ ++ /* configure kgse_ekdv */ ++ tmpReg = 0; ++ for ( i=0 ;inumOfUsedDflts ; i++) ++ { ++ switch (p_KeyAndHash->dflts[i].type) ++ { ++ case (e_FM_PCD_KG_MAC_ADDR): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_MAC_ADDR_SHIFT); ++ break; ++ case (e_FM_PCD_KG_TCI): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_TCI_SHIFT); ++ break; ++ case (e_FM_PCD_KG_ENET_TYPE): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_ENET_TYPE_SHIFT); ++ break; ++ case (e_FM_PCD_KG_PPP_SESSION_ID): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PPP_SESSION_ID_SHIFT); ++ break; ++ case (e_FM_PCD_KG_PPP_PROTOCOL_ID): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PPP_PROTOCOL_ID_SHIFT); ++ break; ++ case (e_FM_PCD_KG_MPLS_LABEL): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_MPLS_LABEL_SHIFT); ++ break; ++ case (e_FM_PCD_KG_IP_ADDR): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IP_ADDR_SHIFT); ++ break; ++ case (e_FM_PCD_KG_PROTOCOL_TYPE): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PROTOCOL_TYPE_SHIFT); ++ break; ++ case (e_FM_PCD_KG_IP_TOS_TC): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IP_TOS_TC_SHIFT); ++ break; ++ case (e_FM_PCD_KG_IPV6_FLOW_LABEL): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_L4_PORT_SHIFT); ++ break; ++ case (e_FM_PCD_KG_IPSEC_SPI): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IPSEC_SPI_SHIFT); ++ break; ++ case (e_FM_PCD_KG_L4_PORT): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_L4_PORT_SHIFT); ++ break; ++ case (e_FM_PCD_KG_TCP_FLAG): ++ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_TCP_FLAG_SHIFT); ++ break; ++ case (e_FM_PCD_KG_GENERIC_FROM_DATA): ++ swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_FROM_DATA; ++ swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect; ++ numOfSwDefaults ++; ++ break; ++ case (e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V): ++ swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V; ++ swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect; ++ numOfSwDefaults ++; ++ break; ++ case (e_FM_PCD_KG_GENERIC_NOT_FROM_DATA): ++ swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_NOT_FROM_DATA; ++ swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect; ++ numOfSwDefaults ++; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ } ++ p_SchemeRegs->kgse_ekdv = tmpReg; ++ ++ p_LocalExtractsArray = (t_FmPcdKgSchemesExtracts *)XX_Malloc(sizeof(t_FmPcdKgSchemesExtracts)); ++ if (!p_LocalExtractsArray) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); ++ ++ /* configure kgse_ekfc and kgse_gec */ ++ knownTmp = 0; ++ for ( i=0 ;inumOfUsedExtracts ; i++) ++ { ++ p_Extract = &p_KeyAndHash->extractArray[i]; ++ switch (p_Extract->type) ++ { ++ case (e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO): ++ knownTmp |= KG_SCH_KN_PORT_ID; ++ /* save in driver structure */ ++ p_LocalExtractsArray->extractsArray[i].id = GetKnownFieldId(KG_SCH_KN_PORT_ID); ++ p_LocalExtractsArray->extractsArray[i].known = TRUE; ++ break; ++ case (e_FM_PCD_EXTRACT_BY_HDR): ++ switch (p_Extract->extractByHdr.hdr) ++ { ++#if (DPAA_VERSION >= 11) || ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++ case (HEADER_TYPE_UDP_LITE): ++ p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP; ++ break; ++#endif /* (DPAA_VERSION >= 11) || ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) */ ++ case (HEADER_TYPE_UDP_ENCAP_ESP): ++ switch (p_Extract->extractByHdr.type) ++ { ++ case (e_FM_PCD_EXTRACT_FROM_HDR): ++ /* case where extraction from ESP only */ ++ if (p_Extract->extractByHdr.extractByHdrType.fromHdr.offset >= UDP_HEADER_SIZE) ++ { ++ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP); ++ p_Extract->extractByHdr.extractByHdrType.fromHdr.offset -= UDP_HEADER_SIZE; ++ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE; ++ } ++ else ++ { ++ p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP; ++ p_Extract->extractByHdr.ignoreProtocolValidation = FALSE; ++ } ++ break; ++ case (e_FM_PCD_EXTRACT_FROM_FIELD): ++ switch (p_Extract->extractByHdr.extractByHdrType.fromField.field.udpEncapEsp) ++ { ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC): ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST): ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN): ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM): ++ p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP; ++ break; ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI): ++ p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR; ++ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP); ++ /*p_Extract->extractByHdr.extractByHdrType.fromField.offset += ESP_SPI_OFFSET;*/ ++ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE; ++ break; ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM): ++ p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR; ++ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP); ++ p_Extract->extractByHdr.extractByHdrType.fromField.offset += ESP_SEQ_NUM_OFFSET; ++ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE; ++ break; ++ } ++ break; ++ case (e_FM_PCD_EXTRACT_FULL_FIELD): ++ switch (p_Extract->extractByHdr.extractByHdrType.fullField.udpEncapEsp) ++ { ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC): ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST): ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN): ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM): ++ p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP; ++ break; ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI): ++ p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR; ++ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP); ++ p_Extract->extractByHdr.extractByHdrType.fromHdr.size = ESP_SPI_SIZE; ++ p_Extract->extractByHdr.extractByHdrType.fromHdr.offset = ESP_SPI_OFFSET; ++ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE; ++ break; ++ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM): ++ p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR; ++ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP); ++ p_Extract->extractByHdr.extractByHdrType.fromHdr.size = ESP_SEQ_NUM_SIZE; ++ p_Extract->extractByHdr.extractByHdrType.fromHdr.offset = ESP_SEQ_NUM_OFFSET; ++ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE; ++ break; ++ } ++ break; ++ } ++ break; ++ default: ++ break; ++ } ++ switch (p_Extract->extractByHdr.type) ++ { ++ case (e_FM_PCD_EXTRACT_FROM_HDR): ++ generic = TRUE; ++ /* get the header code for the generic extract */ ++ code = GetGenHdrCode(p_Extract->extractByHdr.hdr, p_Extract->extractByHdr.hdrIndex, p_Extract->extractByHdr.ignoreProtocolValidation); ++ /* set generic register fields */ ++ offset = p_Extract->extractByHdr.extractByHdrType.fromHdr.offset; ++ size = p_Extract->extractByHdr.extractByHdrType.fromHdr.size; ++ break; ++ case (e_FM_PCD_EXTRACT_FROM_FIELD): ++ generic = TRUE; ++ /* get the field code for the generic extract */ ++ code = GetGenFieldCode(p_Extract->extractByHdr.hdr, ++ p_Extract->extractByHdr.extractByHdrType.fromField.field, p_Extract->extractByHdr.ignoreProtocolValidation,p_Extract->extractByHdr.hdrIndex); ++ offset = p_Extract->extractByHdr.extractByHdrType.fromField.offset; ++ size = p_Extract->extractByHdr.extractByHdrType.fromField.size; ++ break; ++ case (e_FM_PCD_EXTRACT_FULL_FIELD): ++ if (!p_Extract->extractByHdr.ignoreProtocolValidation) ++ { ++ /* if we have a known field for it - use it, otherwise use generic */ ++ bitMask = GetKnownProtMask(p_FmPcd, p_Extract->extractByHdr.hdr, p_Extract->extractByHdr.hdrIndex, ++ p_Extract->extractByHdr.extractByHdrType.fullField); ++ if (bitMask) ++ { ++ knownTmp |= bitMask; ++ /* save in driver structure */ ++ p_LocalExtractsArray->extractsArray[i].id = GetKnownFieldId(bitMask); ++ p_LocalExtractsArray->extractsArray[i].known = TRUE; ++ } ++ else ++ generic = TRUE; ++ } ++ else ++ generic = TRUE; ++ if (generic) ++ { ++ /* tmp - till we cover more headers under generic */ ++ XX_Free(p_LocalExtractsArray); ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Full header selection not supported")); ++ } ++ break; ++ default: ++ XX_Free(p_LocalExtractsArray); ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ break; ++ case (e_FM_PCD_EXTRACT_NON_HDR): ++ /* use generic */ ++ generic = TRUE; ++ offset = 0; ++ /* get the field code for the generic extract */ ++ code = GetGenCode(p_Extract->extractNonHdr.src, &offset); ++ offset += p_Extract->extractNonHdr.offset; ++ size = p_Extract->extractNonHdr.size; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ if (generic) ++ { ++ /* set generic register fields */ ++ if (currGenId >= FM_KG_NUM_OF_GENERIC_REGS) ++ { ++ XX_Free(p_LocalExtractsArray); ++ RETURN_ERROR(MAJOR, E_FULL, ("Generic registers are fully used")); ++ } ++ if (!code) ++ { ++ XX_Free(p_LocalExtractsArray); ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG); ++ } ++ ++ genTmp = KG_SCH_GEN_VALID; ++ genTmp |= (uint32_t)(code << KG_SCH_GEN_HT_SHIFT); ++ genTmp |= offset; ++ if ((size > MAX_KG_SCH_SIZE) || (size < 1)) ++ { ++ XX_Free(p_LocalExtractsArray); ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal extraction (size out of range)")); ++ } ++ genTmp |= (uint32_t)((size - 1) << KG_SCH_GEN_SIZE_SHIFT); ++ swDefault = GetGenericSwDefault(swDefaults, numOfSwDefaults, code); ++ if (swDefault == e_FM_PCD_KG_DFLT_ILLEGAL) ++ DBG(WARNING, ("No sw default configured")); ++ else ++ genTmp |= swDefault << KG_SCH_GEN_DEF_SHIFT; ++ ++ genTmp |= KG_SCH_GEN_MASK; ++ p_SchemeRegs->kgse_gec[currGenId] = genTmp; ++ /* save in driver structure */ ++ p_LocalExtractsArray->extractsArray[i].id = currGenId++; ++ p_LocalExtractsArray->extractsArray[i].known = FALSE; ++ generic = FALSE; ++ } ++ } ++ p_SchemeRegs->kgse_ekfc = knownTmp; ++ ++ selectTmp = 0; ++ maskTmp = 0xFFFFFFFF; ++ /* configure kgse_bmch, kgse_bmcl and kgse_fqb */ ++ ++ if (p_KeyAndHash->numOfUsedMasks > FM_PCD_KG_NUM_OF_EXTRACT_MASKS) ++ { ++ XX_Free(p_LocalExtractsArray); ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Only %d masks supported", FM_PCD_KG_NUM_OF_EXTRACT_MASKS)); ++ } ++ for ( i=0 ;inumOfUsedMasks ; i++) ++ { ++ /* Get the relative id of the extract (for known 0-0x1f, for generic 0-7) */ ++ id = p_LocalExtractsArray->extractsArray[p_KeyAndHash->masks[i].extractArrayIndex].id; ++ /* Get the shift of the select field (depending on i) */ ++ GET_MASK_SEL_SHIFT(shift,i); ++ if (p_LocalExtractsArray->extractsArray[p_KeyAndHash->masks[i].extractArrayIndex].known) ++ selectTmp |= id << shift; ++ else ++ selectTmp |= (id + MASK_FOR_GENERIC_BASE_ID) << shift; ++ ++ /* Get the shift of the offset field (depending on i) - may ++ be in kgse_bmch or in kgse_fqb (depending on i) */ ++ GET_MASK_OFFSET_SHIFT(shift,i); ++ if (i<=1) ++ selectTmp |= p_KeyAndHash->masks[i].offset << shift; ++ else ++ fqbTmp |= p_KeyAndHash->masks[i].offset << shift; ++ ++ /* Get the shift of the mask field (depending on i) */ ++ GET_MASK_SHIFT(shift,i); ++ /* pass all bits */ ++ maskTmp |= KG_SCH_BITMASK_MASK << shift; ++ /* clear bits that need masking */ ++ maskTmp &= ~(0xFF << shift) ; ++ /* set mask bits */ ++ maskTmp |= (p_KeyAndHash->masks[i].mask << shift) ; ++ } ++ p_SchemeRegs->kgse_bmch = selectTmp; ++ p_SchemeRegs->kgse_bmcl = maskTmp; ++ /* kgse_fqb will be written t the end of the routine */ ++ ++ /* configure kgse_hc */ ++ if (p_KeyAndHash->hashShift > MAX_HASH_SHIFT) ++ { ++ XX_Free(p_LocalExtractsArray); ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashShift must not be larger than %d", MAX_HASH_SHIFT)); ++ } ++ if (p_KeyAndHash->hashDistributionFqidsShift > MAX_DIST_FQID_SHIFT) ++ { ++ XX_Free(p_LocalExtractsArray); ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashDistributionFqidsShift must not be larger than %d", MAX_DIST_FQID_SHIFT)); ++ } ++ ++ tmpReg = 0; ++ ++ tmpReg |= ((p_KeyAndHash->hashDistributionNumOfFqids - 1) << p_KeyAndHash->hashDistributionFqidsShift); ++ tmpReg |= p_KeyAndHash->hashShift << KG_SCH_HASH_CONFIG_SHIFT_SHIFT; ++ ++ if (p_KeyAndHash->symmetricHash) ++ { ++ if ((!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_MACSRC) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_MACDST)) || ++ (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPSRC1) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPDST1)) || ++ (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPSRC2) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPDST2)) || ++ (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_L4PSRC) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_L4PDST))) ++ { ++ XX_Free(p_LocalExtractsArray); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("symmetricHash set but src/dest extractions missing")); ++ } ++ tmpReg |= KG_SCH_HASH_CONFIG_SYM; ++ } ++ p_SchemeRegs->kgse_hc = tmpReg; ++ ++ /* build the return array describing the order of the extractions */ ++ ++ /* the last currGenId places of the array ++ are for generic extracts that are always last. ++ We now sort for the calculation of the order of the known ++ extractions we sort the known extracts between orderedArray[0] and ++ orderedArray[p_KeyAndHash->numOfUsedExtracts - currGenId - 1]. ++ for the calculation of the order of the generic extractions we use: ++ num_of_generic - currGenId ++ num_of_known - p_KeyAndHash->numOfUsedExtracts - currGenId ++ first_generic_index = num_of_known */ ++ curr = 0; ++ for (i=0;inumOfUsedExtracts ; i++) ++ { ++ if (p_LocalExtractsArray->extractsArray[i].known) ++ { ++ ASSERT_COND(curr<(p_KeyAndHash->numOfUsedExtracts - currGenId)); ++ j = curr; ++ /* id is the extract id (port id = 0, mac src = 1 etc.). the value in the array is the original ++ index in the user's extractions array */ ++ /* we compare the id of the current extract with the id of the extract in the orderedArray[j-1] ++ location */ ++ while ((j > 0) && (p_LocalExtractsArray->extractsArray[i].id < ++ p_LocalExtractsArray->extractsArray[p_Scheme->orderedArray[j-1]].id)) ++ { ++ p_Scheme->orderedArray[j] = ++ p_Scheme->orderedArray[j-1]; ++ j--; ++ } ++ p_Scheme->orderedArray[j] = (uint8_t)i; ++ curr++; ++ } ++ else ++ { ++ /* index is first_generic_index + generic index (id) */ ++ idx = (uint8_t)(p_KeyAndHash->numOfUsedExtracts - currGenId + p_LocalExtractsArray->extractsArray[i].id); ++ ASSERT_COND(idx < FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY); ++ p_Scheme->orderedArray[idx]= (uint8_t)i; ++ } ++ } ++ XX_Free(p_LocalExtractsArray); ++ } ++ else ++ { ++ /* clear all unused registers: */ ++ p_SchemeRegs->kgse_ekfc = 0; ++ p_SchemeRegs->kgse_ekdv = 0; ++ p_SchemeRegs->kgse_bmch = 0; ++ p_SchemeRegs->kgse_bmcl = 0; ++ p_SchemeRegs->kgse_hc = 0; ++ p_SchemeRegs->kgse_dv0 = 0; ++ p_SchemeRegs->kgse_dv1 = 0; ++ } ++ ++ if (p_SchemeParams->bypassFqidGeneration) ++ p_SchemeRegs->kgse_hc |= KG_SCH_HASH_CONFIG_NO_FQID; ++ ++ /* configure kgse_spc */ ++ if ( p_SchemeParams->schemeCounter.update) ++ p_SchemeRegs->kgse_spc = p_SchemeParams->schemeCounter.value; ++ ++ ++ /* check that are enough generic registers */ ++ if (p_SchemeParams->numOfUsedExtractedOrs + currGenId > FM_KG_NUM_OF_GENERIC_REGS) ++ RETURN_ERROR(MAJOR, E_FULL, ("Generic registers are fully used")); ++ ++ /* extracted OR mask on Qid */ ++ for ( i=0 ;inumOfUsedExtractedOrs ; i++) ++ { ++ ++ p_Scheme->extractedOrs = TRUE; ++ /* configure kgse_gec[i] */ ++ p_ExtractOr = &p_SchemeParams->extractedOrs[i]; ++ switch (p_ExtractOr->type) ++ { ++ case (e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO): ++ code = KG_SCH_GEN_PARSE_RESULT_N_FQID; ++ offset = 0; ++ break; ++ case (e_FM_PCD_EXTRACT_BY_HDR): ++ /* get the header code for the generic extract */ ++ code = GetGenHdrCode(p_ExtractOr->extractByHdr.hdr, p_ExtractOr->extractByHdr.hdrIndex, p_ExtractOr->extractByHdr.ignoreProtocolValidation); ++ /* set generic register fields */ ++ offset = p_ExtractOr->extractionOffset; ++ break; ++ case (e_FM_PCD_EXTRACT_NON_HDR): ++ /* get the field code for the generic extract */ ++ offset = 0; ++ code = GetGenCode(p_ExtractOr->src, &offset); ++ offset += p_ExtractOr->extractionOffset; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ /* set generic register fields */ ++ if (!code) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG); ++ genTmp = KG_SCH_GEN_EXTRACT_TYPE | KG_SCH_GEN_VALID; ++ genTmp |= (uint32_t)(code << KG_SCH_GEN_HT_SHIFT); ++ genTmp |= offset; ++ if (!!p_ExtractOr->bitOffsetInFqid == !!p_ExtractOr->bitOffsetInPlcrProfile) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" extracted byte must effect either FQID or Policer profile")); ++ ++ /************************************************************************************ ++ bitOffsetInFqid and bitOffsetInPolicerProfile are translated to rotate parameter ++ in the following way: ++ ++ Driver API and implementation: ++ ============================== ++ FQID: extracted OR byte may be shifted right 1-31 bits to effect parts of the FQID. ++ if shifted less than 8 bits, or more than 24 bits a mask is set on the bits that ++ are not overlapping FQID. ++ ------------------------ ++ | FQID (24) | ++ ------------------------ ++ -------- ++ | | extracted OR byte ++ -------- ++ ++ Policer Profile: extracted OR byte may be shifted right 1-15 bits to effect parts of the ++ PP id. Unless shifted exactly 8 bits to overlap the PP id, a mask is set on the bits that ++ are not overlapping PP id. ++ ++ -------- ++ | PP (8) | ++ -------- ++ -------- ++ | | extracted OR byte ++ -------- ++ ++ HW implementation ++ ================= ++ FQID and PP construct a 32 bit word in the way describe below. Extracted byte is located ++ as the highest byte of that word and may be rotated to effect any part os the FQID or ++ the PP. ++ ------------------------ -------- ++ | FQID (24) || PP (8) | ++ ------------------------ -------- ++ -------- ++ | | extracted OR byte ++ -------- ++ ++ ************************************************************************************/ ++ ++ if (p_ExtractOr->bitOffsetInFqid) ++ { ++ if (p_ExtractOr->bitOffsetInFqid > MAX_KG_SCH_FQID_BIT_OFFSET ) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal extraction (bitOffsetInFqid out of range)")); ++ if (p_ExtractOr->bitOffsetInFqid<8) ++ genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInFqid+24) << KG_SCH_GEN_SIZE_SHIFT); ++ else ++ genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInFqid-8) << KG_SCH_GEN_SIZE_SHIFT); ++ p_ExtractOr->mask &= GetExtractedOrMask(p_ExtractOr->bitOffsetInFqid, TRUE); ++ } ++ else /* effect policer profile */ ++ { ++ if (p_ExtractOr->bitOffsetInPlcrProfile > MAX_KG_SCH_PP_BIT_OFFSET ) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal extraction (bitOffsetInPlcrProfile out of range)")); ++ p_Scheme->bitOffsetInPlcrProfile = p_ExtractOr->bitOffsetInPlcrProfile; ++ genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInPlcrProfile+16) << KG_SCH_GEN_SIZE_SHIFT); ++ p_ExtractOr->mask &= GetExtractedOrMask(p_ExtractOr->bitOffsetInPlcrProfile, FALSE); ++ } ++ ++ genTmp |= (uint32_t)(p_ExtractOr->extractionOffset << KG_SCH_GEN_DEF_SHIFT); ++ /* clear bits that need masking */ ++ genTmp &= ~KG_SCH_GEN_MASK ; ++ /* set mask bits */ ++ genTmp |= (uint32_t)(p_ExtractOr->mask << KG_SCH_GEN_MASK_SHIFT); ++ p_SchemeRegs->kgse_gec[currGenId++] = genTmp; ++ ++ } ++ /* clear all unused GEC registers */ ++ for ( i=currGenId ;ikgse_gec[i] = 0; ++ ++ /* add base Qid for this scheme */ ++ /* add configuration for kgse_fqb */ ++ if (p_SchemeParams->baseFqid & ~0x00FFFFFF) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("baseFqid must be between 1 and 2^24-1")); ++ ++ fqbTmp |= p_SchemeParams->baseFqid; ++ p_SchemeRegs->kgse_fqb = fqbTmp; ++ ++ p_Scheme->nextEngine = p_SchemeParams->nextEngine; ++ p_Scheme->doneAction = p_SchemeParams->kgNextEngineParams.doneAction; ++ ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* Inter-module API routines */ ++/*****************************************************************************/ ++ ++t_Error FmPcdKgBuildClsPlanGrp(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_Grp, t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdKgClsPlanGrp *p_ClsPlanGrp; ++ t_FmPcdIpcKgClsPlanParams kgAlloc; ++ t_Error err = E_OK; ++ uint32_t oredVectors = 0; ++ int i, j; ++ ++ /* this routine is protected by the calling routine ! */ ++ if (p_Grp->numOfOptions >= FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Too many classification plan basic options selected.")); ++ ++ /* find a new clsPlan group */ ++ for (i = 0; i < FM_MAX_NUM_OF_PORTS; i++) ++ if (!p_FmPcd->p_FmPcdKg->clsPlanGrps[i].used) ++ break; ++ if (i == FM_MAX_NUM_OF_PORTS) ++ RETURN_ERROR(MAJOR, E_FULL,("No classification plan groups available.")); ++ ++ p_FmPcd->p_FmPcdKg->clsPlanGrps[i].used = TRUE; ++ ++ p_Grp->clsPlanGrpId = (uint8_t)i; ++ ++ if (p_Grp->numOfOptions == 0) ++ p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId = (uint8_t)i; ++ ++ p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[i]; ++ p_ClsPlanGrp->netEnvId = p_Grp->netEnvId; ++ p_ClsPlanGrp->owners = 0; ++ FmPcdSetClsPlanGrpId(p_FmPcd, p_Grp->netEnvId, p_Grp->clsPlanGrpId); ++ if (p_Grp->numOfOptions != 0) ++ FmPcdIncNetEnvOwners(p_FmPcd, p_Grp->netEnvId); ++ ++ p_ClsPlanGrp->sizeOfGrp = (uint16_t)(1 << p_Grp->numOfOptions); ++ /* a minimal group of 8 is required */ ++ if (p_ClsPlanGrp->sizeOfGrp < CLS_PLAN_NUM_PER_GRP) ++ p_ClsPlanGrp->sizeOfGrp = CLS_PLAN_NUM_PER_GRP; ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ { ++ err = KgAllocClsPlanEntries(h_FmPcd, p_ClsPlanGrp->sizeOfGrp, p_FmPcd->guestId, &p_ClsPlanGrp->baseEntry); ++ ++ if (err) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG); ++ } ++ else ++ { ++ t_FmPcdIpcMsg msg; ++ uint32_t replyLength; ++ t_FmPcdIpcReply reply; ++ ++ /* in GUEST_PARTITION, we use the IPC, to also set a private driver group if required */ ++ memset(&reply, 0, sizeof(reply)); ++ memset(&msg, 0, sizeof(msg)); ++ memset(&kgAlloc, 0, sizeof(kgAlloc)); ++ kgAlloc.guestId = p_FmPcd->guestId; ++ kgAlloc.numOfClsPlanEntries = p_ClsPlanGrp->sizeOfGrp; ++ msg.msgId = FM_PCD_ALLOC_KG_CLSPLAN; ++ memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc)); ++ replyLength = (sizeof(uint32_t) + sizeof(p_ClsPlanGrp->baseEntry)); ++ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(kgAlloc), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (replyLength != (sizeof(uint32_t) + sizeof(p_ClsPlanGrp->baseEntry))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ if ((t_Error)reply.error != E_OK) ++ RETURN_ERROR(MINOR, (t_Error)reply.error, NO_MSG); ++ ++ p_ClsPlanGrp->baseEntry = *(uint8_t*)(reply.replyBody); ++ } ++ ++ /* build classification plan entries parameters */ ++ p_ClsPlanSet->baseEntry = p_ClsPlanGrp->baseEntry; ++ p_ClsPlanSet->numOfClsPlanEntries = p_ClsPlanGrp->sizeOfGrp; ++ ++ oredVectors = 0; ++ for (i = 0; inumOfOptions; i++) ++ { ++ oredVectors |= p_Grp->optVectors[i]; ++ /* save an array of used options - the indexes represent the power of 2 index */ ++ p_ClsPlanGrp->optArray[i] = p_Grp->options[i]; ++ } ++ /* set the classification plan relevant entries so that all bits ++ * relevant to the list of options is cleared ++ */ ++ for (j = 0; jsizeOfGrp; j++) ++ p_ClsPlanSet->vectors[j] = ~oredVectors; ++ ++ for (i = 0; inumOfOptions; i++) ++ { ++ /* option i got the place 2^i in the clsPlan array. all entries that ++ * have bit i set, should have the vector bit cleared. So each option ++ * has one location that it is exclusive (1,2,4,8...) and represent the ++ * presence of that option only, and other locations that represent a ++ * combination of options. ++ * e.g: ++ * If ethernet-BC is option 1 it gets entry 2 in the table. Entry 2 ++ * now represents a frame with ethernet-BC header - so the bit ++ * representing ethernet-BC should be set and all other option bits ++ * should be cleared. ++ * Entries 2,3,6,7,10... also have ethernet-BC and therefore have bit ++ * vector[1] set, but they also have other bits set: ++ * 3=1+2, options 0 and 1 ++ * 6=2+4, options 1 and 2 ++ * 7=1+2+4, options 0,1,and 2 ++ * 10=2+8, options 1 and 3 ++ * etc. ++ * */ ++ ++ /* now for each option (i), we set their bits in all entries (j) ++ * that contain bit 2^i. ++ */ ++ for (j = 0; jsizeOfGrp; j++) ++ { ++ if (j & (1<vectors[j] |= p_Grp->optVectors[i]; ++ } ++ } ++ ++ return E_OK; ++} ++ ++void FmPcdKgDestroyClsPlanGrp(t_Handle h_FmPcd, uint8_t grpId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdIpcKgClsPlanParams kgAlloc; ++ t_Error err; ++ t_FmPcdIpcMsg msg; ++ uint32_t replyLength; ++ t_FmPcdIpcReply reply; ++ ++ /* check that no port is bound to this clsPlan */ ++ if (p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].owners) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Trying to delete a clsPlan grp that has ports bound to")); ++ return; ++ } ++ ++ FmPcdSetClsPlanGrpId(p_FmPcd, p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].netEnvId, ILLEGAL_CLS_PLAN); ++ ++ if (grpId == p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId) ++ p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId = ILLEGAL_CLS_PLAN; ++ else ++ FmPcdDecNetEnvOwners(p_FmPcd, p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].netEnvId); ++ ++ /* free blocks */ ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ KgFreeClsPlanEntries(h_FmPcd, ++ p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].sizeOfGrp, ++ p_FmPcd->guestId, ++ p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].baseEntry); ++ else /* in GUEST_PARTITION, we use the IPC, to also set a private driver group if required */ ++ { ++ memset(&reply, 0, sizeof(reply)); ++ memset(&msg, 0, sizeof(msg)); ++ kgAlloc.guestId = p_FmPcd->guestId; ++ kgAlloc.numOfClsPlanEntries = p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].sizeOfGrp; ++ kgAlloc.clsPlanBase = p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].baseEntry; ++ msg.msgId = FM_PCD_FREE_KG_CLSPLAN; ++ memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc)); ++ replyLength = sizeof(uint32_t); ++ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(kgAlloc), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return; ++ } ++ if (replyLength != sizeof(uint32_t)) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return; ++ } ++ if ((t_Error)reply.error != E_OK) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Free KG clsPlan failed")); ++ return; ++ } ++ } ++ ++ /* clear clsPlan driver structure */ ++ memset(&p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId], 0, sizeof(t_FmPcdKgClsPlanGrp)); ++} ++ ++t_Error FmPcdKgBuildBindPortToSchemes(t_Handle h_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort, uint32_t *p_SpReg, bool add) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t j, schemesPerPortVector = 0; ++ t_FmPcdKgScheme *p_Scheme; ++ uint8_t i, relativeSchemeId; ++ uint32_t tmp, walking1Mask; ++ uint8_t swPortIndex = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ ++ /* for each scheme */ ++ for (i = 0; inumOfSchemes; i++) ++ { ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]); ++ if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ ++ if (add) ++ { ++ p_Scheme = &p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId]; ++ if (!FmPcdKgIsSchemeValidSw(p_Scheme)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Requested scheme is invalid.")); ++ /* check netEnvId of the port against the scheme netEnvId */ ++ if ((p_Scheme->netEnvId != p_BindPort->netEnvId) && (p_Scheme->netEnvId != ILLEGAL_NETENV)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port may not be bound to requested scheme - differ in netEnvId")); ++ ++ /* if next engine is private port policer profile, we need to check that it is valid */ ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, p_BindPort->hardwarePortId); ++ if (p_Scheme->nextRelativePlcrProfile) ++ { ++ for (j = 0;jnumOfProfiles;j++) ++ { ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].h_FmPort); ++ if (p_Scheme->relativeProfileId+j >= p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Relative profile not in range")); ++ if (!FmPcdPlcrIsProfileValid(p_FmPcd, (uint16_t)(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase + p_Scheme->relativeProfileId + j))) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Relative profile not valid.")); ++ } ++ } ++ if (!p_BindPort->useClsPlan) ++ { ++ /* This check may be redundant as port is a assigned to the whole NetEnv */ ++ ++ /* if this port does not use clsPlan, it may not be bound to schemes with units that contain ++ cls plan options. Schemes that are used only directly, should not be checked. ++ it also may not be bound to schemes that go to CC with units that are options - so we OR ++ the match vector and the grpBits (= ccUnits) */ ++ if ((p_Scheme->matchVector != SCHEME_ALWAYS_DIRECT) || p_Scheme->ccUnits) ++ { ++ uint8_t netEnvId; ++ walking1Mask = 0x80000000; ++ netEnvId = (p_Scheme->netEnvId == ILLEGAL_NETENV)? p_BindPort->netEnvId:p_Scheme->netEnvId; ++ tmp = (p_Scheme->matchVector == SCHEME_ALWAYS_DIRECT)? 0:p_Scheme->matchVector; ++ tmp |= p_Scheme->ccUnits; ++ while (tmp) ++ { ++ if (tmp & walking1Mask) ++ { ++ tmp &= ~walking1Mask; ++ if (!PcdNetEnvIsUnitWithoutOpts(p_FmPcd, netEnvId, walking1Mask)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port (without clsPlan) may not be bound to requested scheme - uses clsPlan options")); ++ } ++ walking1Mask >>= 1; ++ } ++ } ++ } ++ } ++ /* build vector */ ++ schemesPerPortVector |= 1 << (31 - p_BindPort->schemesIds[i]); ++ } ++ ++ *p_SpReg = schemesPerPortVector; ++ ++ return E_OK; ++} ++ ++t_Error FmPcdKgBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t spReg; ++ t_Error err = E_OK; ++ ++ err = FmPcdKgBuildBindPortToSchemes(h_FmPcd, p_SchemeBind, &spReg, TRUE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ err = KgWriteSp(p_FmPcd, p_SchemeBind->hardwarePortId, spReg, TRUE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ IncSchemeOwners(p_FmPcd, p_SchemeBind); ++ ++ return E_OK; ++} ++ ++t_Error FmPcdKgUnbindPortToSchemes(t_Handle h_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t spReg; ++ t_Error err = E_OK; ++ ++ err = FmPcdKgBuildBindPortToSchemes(p_FmPcd, p_SchemeBind, &spReg, FALSE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ err = KgWriteSp(p_FmPcd, p_SchemeBind->hardwarePortId, spReg, FALSE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ DecSchemeOwners(p_FmPcd, p_SchemeBind); ++ ++ return E_OK; ++} ++ ++bool FmPcdKgIsSchemeValidSw(t_Handle h_Scheme) ++{ ++ t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme*)h_Scheme; ++ ++ return p_Scheme->valid; ++} ++ ++bool KgIsSchemeAlwaysDirect(t_Handle h_FmPcd, uint8_t schemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ if (p_FmPcd->p_FmPcdKg->schemes[schemeId].matchVector == SCHEME_ALWAYS_DIRECT) ++ return TRUE; ++ else ++ return FALSE; ++} ++ ++t_Error FmPcdKgAllocSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint8_t i, j; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE); ++ ++ /* This routine is issued only on master core of master partition - ++ either directly or through IPC, so no need for lock */ ++ ++ for (j = 0, i = 0; i < FM_PCD_KG_NUM_OF_SCHEMES && j < numOfSchemes; i++) ++ { ++ if (!p_FmPcd->p_FmPcdKg->schemesMng[i].allocated) ++ { ++ p_FmPcd->p_FmPcdKg->schemesMng[i].allocated = TRUE; ++ p_FmPcd->p_FmPcdKg->schemesMng[i].ownerId = guestId; ++ p_SchemesIds[j] = i; ++ j++; ++ } ++ } ++ ++ if (j != numOfSchemes) ++ { ++ /* roll back */ ++ for (j--; j; j--) ++ { ++ p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[j]].allocated = FALSE; ++ p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[j]].ownerId = 0; ++ p_SchemesIds[j] = 0; ++ } ++ ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("No schemes found")); ++ } ++ ++ return E_OK; ++} ++ ++t_Error FmPcdKgFreeSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint8_t i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE); ++ ++ /* This routine is issued only on master core of master partition - ++ either directly or through IPC */ ++ ++ for (i = 0; i < numOfSchemes; i++) ++ { ++ if (!p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].allocated) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Scheme was not previously allocated")); ++ } ++ if (p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].ownerId != guestId) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Scheme is not owned by caller. ")); ++ } ++ p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].allocated = FALSE; ++ p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].ownerId = 0; ++ } ++ ++ return E_OK; ++} ++ ++t_Error KgAllocClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t *p_First) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint8_t numOfBlocks, blocksFound=0, first=0; ++ uint8_t i, j; ++ ++ /* This routine is issued only on master core of master partition - ++ either directly or through IPC, so no need for lock */ ++ ++ if (!numOfClsPlanEntries) ++ return E_OK; ++ ++ if ((numOfClsPlanEntries % CLS_PLAN_NUM_PER_GRP) || (!POWER_OF_2(numOfClsPlanEntries))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfClsPlanEntries must be a power of 2 and divisible by 8")); ++ ++ numOfBlocks = (uint8_t)(numOfClsPlanEntries/CLS_PLAN_NUM_PER_GRP); ++ ++ /* try to find consequent blocks */ ++ first = 0; ++ for (i = 0; i < FM_PCD_MAX_NUM_OF_CLS_PLANS/CLS_PLAN_NUM_PER_GRP;) ++ { ++ if (!p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].allocated) ++ { ++ blocksFound++; ++ i++; ++ if (blocksFound == numOfBlocks) ++ break; ++ } ++ else ++ { ++ blocksFound = 0; ++ /* advance i to the next aligned address */ ++ first = i = (uint8_t)(first + numOfBlocks); ++ } ++ } ++ ++ if (blocksFound == numOfBlocks) ++ { ++ *p_First = (uint8_t)(first * CLS_PLAN_NUM_PER_GRP); ++ for (j = first; j < (first + numOfBlocks); j++) ++ { ++ p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[j].allocated = TRUE; ++ p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[j].ownerId = guestId; ++ } ++ return E_OK; ++ } ++ else ++ RETURN_ERROR(MINOR, E_FULL, ("No resources for clsPlan")); ++} ++ ++void KgFreeClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t base) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint8_t numOfBlocks; ++ uint8_t i, baseBlock; ++ ++#ifdef DISABLE_ASSERTIONS ++UNUSED(guestId); ++#endif /* DISABLE_ASSERTIONS */ ++ ++ /* This routine is issued only on master core of master partition - ++ either directly or through IPC, so no need for lock */ ++ ++ numOfBlocks = (uint8_t)(numOfClsPlanEntries/CLS_PLAN_NUM_PER_GRP); ++ ASSERT_COND(!(base%CLS_PLAN_NUM_PER_GRP)); ++ ++ baseBlock = (uint8_t)(base/CLS_PLAN_NUM_PER_GRP); ++ for (i=baseBlock;ip_FmPcdKg->clsPlanBlocksMng[i].allocated); ++ ASSERT_COND(guestId == p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].ownerId); ++ p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].allocated = FALSE; ++ p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].ownerId = 0; ++ } ++} ++ ++void KgEnable(t_FmPcd *p_FmPcd) ++{ ++ struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ ++ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); ++ fman_kg_enable(p_Regs); ++} ++ ++void KgDisable(t_FmPcd *p_FmPcd) ++{ ++ struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ ++ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); ++ fman_kg_disable(p_Regs); ++} ++ ++void KgSetClsPlan(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanSet *p_Set) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ struct fman_kg_cp_regs *p_FmPcdKgPortRegs; ++ uint32_t tmpKgarReg = 0, intFlags; ++ uint16_t i, j; ++ ++ /* This routine is protected by the calling routine ! */ ++ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); ++ p_FmPcdKgPortRegs = &p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->clsPlanRegs; ++ ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ for (i=p_Set->baseEntry;ibaseEntry+p_Set->numOfClsPlanEntries;i+=8) ++ { ++ tmpKgarReg = FmPcdKgBuildWriteClsPlanBlockActionReg((uint8_t)(i / CLS_PLAN_NUM_PER_GRP)); ++ ++ for (j = i; j < i+8; j++) ++ { ++ ASSERT_COND(IN_RANGE(0, (j - p_Set->baseEntry), FM_PCD_MAX_NUM_OF_CLS_PLANS-1)); ++ WRITE_UINT32(p_FmPcdKgPortRegs->kgcpe[j % CLS_PLAN_NUM_PER_GRP],p_Set->vectors[j - p_Set->baseEntry]); ++ } ++ ++ if (WriteKgarWait(p_FmPcd, tmpKgarReg) != E_OK) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("WriteKgarWait FAILED")); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ return; ++ } ++ } ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++} ++ ++t_Handle KgConfig( t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams) ++{ ++ t_FmPcdKg *p_FmPcdKg; ++ ++ UNUSED(p_FmPcd); ++ ++ if (p_FmPcdParams->numOfSchemes > FM_PCD_KG_NUM_OF_SCHEMES) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("numOfSchemes should not exceed %d", FM_PCD_KG_NUM_OF_SCHEMES)); ++ return NULL; ++ } ++ ++ p_FmPcdKg = (t_FmPcdKg *)XX_Malloc(sizeof(t_FmPcdKg)); ++ if (!p_FmPcdKg) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Keygen allocation FAILED")); ++ return NULL; ++ } ++ memset(p_FmPcdKg, 0, sizeof(t_FmPcdKg)); ++ ++ ++ if (FmIsMaster(p_FmPcd->h_Fm)) ++ { ++ p_FmPcdKg->p_FmPcdKgRegs = (struct fman_kg_regs *)UINT_TO_PTR(FmGetPcdKgBaseAddr(p_FmPcdParams->h_Fm)); ++ p_FmPcd->exceptions |= DEFAULT_fmPcdKgErrorExceptions; ++ p_FmPcdKg->p_IndirectAccessRegs = (u_FmPcdKgIndirectAccessRegs *)&p_FmPcdKg->p_FmPcdKgRegs->fmkg_indirect[0]; ++ } ++ ++ p_FmPcdKg->numOfSchemes = p_FmPcdParams->numOfSchemes; ++ if ((p_FmPcd->guestId == NCSW_MASTER_ID) && !p_FmPcdKg->numOfSchemes) ++ { ++ p_FmPcdKg->numOfSchemes = FM_PCD_KG_NUM_OF_SCHEMES; ++ DBG(WARNING, ("numOfSchemes was defined 0 by user, re-defined by driver to FM_PCD_KG_NUM_OF_SCHEMES")); ++ } ++ ++ p_FmPcdKg->emptyClsPlanGrpId = ILLEGAL_CLS_PLAN; ++ ++ return p_FmPcdKg; ++} ++ ++t_Error KgInit(t_FmPcd *p_FmPcd) ++{ ++ t_Error err = E_OK; ++ ++ p_FmPcd->p_FmPcdKg->h_HwSpinlock = XX_InitSpinlock(); ++ if (!p_FmPcd->p_FmPcdKg->h_HwSpinlock) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM KG HW spinlock")); ++ ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ err = KgInitMaster(p_FmPcd); ++ else ++ err = KgInitGuest(p_FmPcd); ++ ++ if (err != E_OK) ++ { ++ if (p_FmPcd->p_FmPcdKg->h_HwSpinlock) ++ XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock); ++ } ++ ++ return err; ++} ++ ++t_Error KgFree(t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdIpcKgSchemesParams kgAlloc; ++ t_Error err = E_OK; ++ t_FmPcdIpcMsg msg; ++ uint32_t replyLength; ++ t_FmPcdIpcReply reply; ++ ++ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_KG, 0, e_FM_INTR_TYPE_ERR); ++ ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ { ++ err = FmPcdKgFreeSchemes(p_FmPcd, ++ p_FmPcd->p_FmPcdKg->numOfSchemes, ++ p_FmPcd->guestId, ++ p_FmPcd->p_FmPcdKg->schemesIds); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (p_FmPcd->p_FmPcdKg->h_HwSpinlock) ++ XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock); ++ ++ return E_OK; ++ } ++ ++ /* guest */ ++ memset(&reply, 0, sizeof(reply)); ++ memset(&msg, 0, sizeof(msg)); ++ kgAlloc.numOfSchemes = p_FmPcd->p_FmPcdKg->numOfSchemes; ++ kgAlloc.guestId = p_FmPcd->guestId; ++ ASSERT_COND(kgAlloc.numOfSchemes < FM_PCD_KG_NUM_OF_SCHEMES); ++ memcpy(kgAlloc.schemesIds, p_FmPcd->p_FmPcdKg->schemesIds, (sizeof(uint8_t))*kgAlloc.numOfSchemes); ++ msg.msgId = FM_PCD_FREE_KG_SCHEMES; ++ memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc)); ++ replyLength = sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(kgAlloc), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ ++ if (p_FmPcd->p_FmPcdKg->h_HwSpinlock) ++ XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock); ++ ++ return (t_Error)reply.error; ++} ++ ++t_Error FmPcdKgSetOrBindToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t netEnvId, protocolOpt_t *p_OptArray, uint8_t *p_ClsPlanGrpId, bool *p_IsEmptyClsPlanGrp) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_FmPcdKgInterModuleClsPlanGrpParams grpParams, *p_GrpParams; ++ t_FmPcdKgClsPlanGrp *p_ClsPlanGrp; ++ t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet; ++ t_Error err; ++ ++ /* This function is issued only from FM_PORT_SetPcd which locked all PCD modules, ++ so no need for lock here */ ++ ++ memset(&grpParams, 0, sizeof(grpParams)); ++ grpParams.clsPlanGrpId = ILLEGAL_CLS_PLAN; ++ p_GrpParams = &grpParams; ++ ++ p_GrpParams->netEnvId = netEnvId; ++ ++ /* Get from the NetEnv the information of the clsPlan (can be already created, ++ * or needs to build) */ ++ err = PcdGetClsPlanGrpParams(h_FmPcd, p_GrpParams); ++ if (err) ++ RETURN_ERROR(MINOR,err,NO_MSG); ++ ++ if (p_GrpParams->grpExists) ++ { ++ /* this group was already updated (at least) in SW */ ++ *p_ClsPlanGrpId = p_GrpParams->clsPlanGrpId; ++ } ++ else ++ { ++ p_ClsPlanSet = (t_FmPcdKgInterModuleClsPlanSet *)XX_Malloc(sizeof(t_FmPcdKgInterModuleClsPlanSet)); ++ if (!p_ClsPlanSet) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Classification plan set")); ++ memset(p_ClsPlanSet, 0, sizeof(t_FmPcdKgInterModuleClsPlanSet)); ++ /* Build (in SW) the clsPlan parameters, including the vectors to be written to HW */ ++ err = FmPcdKgBuildClsPlanGrp(h_FmPcd, p_GrpParams, p_ClsPlanSet); ++ if (err) ++ { ++ XX_Free(p_ClsPlanSet); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ *p_ClsPlanGrpId = p_GrpParams->clsPlanGrpId; ++ ++ if (p_FmPcd->h_Hc) ++ { ++ /* write clsPlan entries to memory */ ++ err = FmHcPcdKgSetClsPlan(p_FmPcd->h_Hc, p_ClsPlanSet); ++ if (err) ++ { ++ XX_Free(p_ClsPlanSet); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ else ++ /* write clsPlan entries to memory */ ++ KgSetClsPlan(p_FmPcd, p_ClsPlanSet); ++ ++ XX_Free(p_ClsPlanSet); ++ } ++ ++ /* Set caller parameters */ ++ ++ /* mark if this is an empty classification group */ ++ if (*p_ClsPlanGrpId == p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId) ++ *p_IsEmptyClsPlanGrp = TRUE; ++ else ++ *p_IsEmptyClsPlanGrp = FALSE; ++ ++ p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[*p_ClsPlanGrpId]; ++ ++ /* increment owners number */ ++ p_ClsPlanGrp->owners++; ++ ++ /* copy options array for port */ ++ memcpy(p_OptArray, &p_FmPcd->p_FmPcdKg->clsPlanGrps[*p_ClsPlanGrpId].optArray, FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)*sizeof(protocolOpt_t)); ++ ++ /* bind port to the new or existing group */ ++ err = BindPortToClsPlanGrp(p_FmPcd, hardwarePortId, p_GrpParams->clsPlanGrpId); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FmPcdKgDeleteOrUnbindPortToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t clsPlanGrpId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_FmPcdKgClsPlanGrp *p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId]; ++ t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet; ++ t_Error err; ++ ++ /* This function is issued only from FM_PORT_DeletePcd which locked all PCD modules, ++ so no need for lock here */ ++ ++ UnbindPortToClsPlanGrp(p_FmPcd, hardwarePortId); ++ ++ /* decrement owners number */ ++ ASSERT_COND(p_ClsPlanGrp->owners); ++ p_ClsPlanGrp->owners--; ++ ++ if (!p_ClsPlanGrp->owners) ++ { ++ if (p_FmPcd->h_Hc) ++ { ++ err = FmHcPcdKgDeleteClsPlan(p_FmPcd->h_Hc, clsPlanGrpId); ++ return err; ++ } ++ else ++ { ++ /* clear clsPlan entries in memory */ ++ p_ClsPlanSet = (t_FmPcdKgInterModuleClsPlanSet *)XX_Malloc(sizeof(t_FmPcdKgInterModuleClsPlanSet)); ++ if (!p_ClsPlanSet) ++ { ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Classification plan set")); ++ } ++ memset(p_ClsPlanSet, 0, sizeof(t_FmPcdKgInterModuleClsPlanSet)); ++ ++ p_ClsPlanSet->baseEntry = p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].baseEntry; ++ p_ClsPlanSet->numOfClsPlanEntries = p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].sizeOfGrp; ++ KgSetClsPlan(p_FmPcd, p_ClsPlanSet); ++ XX_Free(p_ClsPlanSet); ++ ++ FmPcdKgDestroyClsPlanGrp(h_FmPcd, clsPlanGrpId); ++ } ++ } ++ return E_OK; ++} ++ ++uint32_t FmPcdKgGetRequiredAction(t_Handle h_FmPcd, uint8_t schemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid); ++ ++ return p_FmPcd->p_FmPcdKg->schemes[schemeId].requiredAction; ++} ++ ++uint32_t FmPcdKgGetRequiredActionFlag(t_Handle h_FmPcd, uint8_t schemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid); ++ ++ return p_FmPcd->p_FmPcdKg->schemes[schemeId].requiredActionFlag; ++} ++ ++bool FmPcdKgIsDirectPlcr(t_Handle h_FmPcd, uint8_t schemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid); ++ ++ return p_FmPcd->p_FmPcdKg->schemes[schemeId].directPlcr; ++} ++ ++ ++uint16_t FmPcdKgGetRelativeProfileId(t_Handle h_FmPcd, uint8_t schemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid); ++ ++ return p_FmPcd->p_FmPcdKg->schemes[schemeId].relativeProfileId; ++} ++ ++bool FmPcdKgIsDistrOnPlcrProfile(t_Handle h_FmPcd, uint8_t schemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid); ++ ++ if ((p_FmPcd->p_FmPcdKg->schemes[schemeId].extractedOrs && ++ p_FmPcd->p_FmPcdKg->schemes[schemeId].bitOffsetInPlcrProfile) || ++ p_FmPcd->p_FmPcdKg->schemes[schemeId].nextRelativePlcrProfile) ++ return TRUE; ++ else ++ return FALSE; ++ ++} ++ ++e_FmPcdEngine FmPcdKgGetNextEngine(t_Handle h_FmPcd, uint8_t relativeSchemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].valid); ++ ++ return p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine; ++} ++ ++e_FmPcdDoneAction FmPcdKgGetDoneAction(t_Handle h_FmPcd, uint8_t schemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid); ++ ++ return p_FmPcd->p_FmPcdKg->schemes[schemeId].doneAction; ++} ++ ++void FmPcdKgUpdateRequiredAction(t_Handle h_Scheme, uint32_t requiredAction) ++{ ++ t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme *)h_Scheme; ++ ++ /* this routine is protected by calling routine */ ++ ++ ASSERT_COND(p_Scheme->valid); ++ ++ p_Scheme->requiredAction |= requiredAction; ++} ++ ++bool FmPcdKgHwSchemeIsValid(uint32_t schemeModeReg) ++{ ++ return (bool)!!(schemeModeReg & KG_SCH_MODE_EN); ++} ++ ++uint32_t FmPcdKgBuildWriteSchemeActionReg(uint8_t schemeId, bool updateCounter) ++{ ++ return (uint32_t)(((uint32_t)schemeId << FM_PCD_KG_KGAR_NUM_SHIFT) | ++ FM_KG_KGAR_GO | ++ FM_KG_KGAR_WRITE | ++ FM_KG_KGAR_SEL_SCHEME_ENTRY | ++ DUMMY_PORT_ID | ++ (updateCounter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT:0)); ++} ++ ++uint32_t FmPcdKgBuildReadSchemeActionReg(uint8_t schemeId) ++{ ++ return (uint32_t)(((uint32_t)schemeId << FM_PCD_KG_KGAR_NUM_SHIFT) | ++ FM_KG_KGAR_GO | ++ FM_KG_KGAR_READ | ++ FM_KG_KGAR_SEL_SCHEME_ENTRY | ++ DUMMY_PORT_ID | ++ FM_KG_KGAR_SCM_WSEL_UPDATE_CNT); ++ ++} ++ ++uint32_t FmPcdKgBuildWriteClsPlanBlockActionReg(uint8_t grpId) ++{ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ FM_KG_KGAR_WRITE | ++ FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY | ++ DUMMY_PORT_ID | ++ ((uint32_t)grpId << FM_PCD_KG_KGAR_NUM_SHIFT) | ++ FM_PCD_KG_KGAR_WSEL_MASK); ++ ++ /* if we ever want to write 1 by 1, use: ++ sel = (uint8_t)(0x01 << (7- (entryId % CLS_PLAN_NUM_PER_GRP))); ++ */ ++} ++ ++uint32_t FmPcdKgBuildWritePortSchemeBindActionReg(uint8_t hardwarePortId) ++{ ++ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ FM_KG_KGAR_WRITE | ++ FM_PCD_KG_KGAR_SEL_PORT_ENTRY | ++ hardwarePortId | ++ FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP); ++} ++ ++uint32_t FmPcdKgBuildReadPortSchemeBindActionReg(uint8_t hardwarePortId) ++{ ++ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ FM_KG_KGAR_READ | ++ FM_PCD_KG_KGAR_SEL_PORT_ENTRY | ++ hardwarePortId | ++ FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP); ++} ++ ++uint32_t FmPcdKgBuildWritePortClsPlanBindActionReg(uint8_t hardwarePortId) ++{ ++ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ FM_KG_KGAR_WRITE | ++ FM_PCD_KG_KGAR_SEL_PORT_ENTRY | ++ hardwarePortId | ++ FM_PCD_KG_KGAR_SEL_PORT_WSEL_CPP); ++} ++ ++uint8_t FmPcdKgGetClsPlanGrpBase(t_Handle h_FmPcd, uint8_t clsPlanGrp) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ return p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrp].baseEntry; ++} ++ ++uint16_t FmPcdKgGetClsPlanGrpSize(t_Handle h_FmPcd, uint8_t clsPlanGrp) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ return p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrp].sizeOfGrp; ++} ++ ++ ++uint8_t FmPcdKgGetSchemeId(t_Handle h_Scheme) ++{ ++ return ((t_FmPcdKgScheme*)h_Scheme)->schemeId; ++ ++} ++ ++#if (DPAA_VERSION >= 11) ++bool FmPcdKgGetVspe(t_Handle h_Scheme) ++{ ++ return ((t_FmPcdKgScheme*)h_Scheme)->vspe; ++ ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++uint8_t FmPcdKgGetRelativeSchemeId(t_Handle h_FmPcd, uint8_t schemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint8_t i; ++ ++ for (i = 0;ip_FmPcdKg->numOfSchemes;i++) ++ if (p_FmPcd->p_FmPcdKg->schemesIds[i] == schemeId) ++ return i; ++ ++ if (i == p_FmPcd->p_FmPcdKg->numOfSchemes) ++ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, ("Scheme is out of partition range")); ++ ++ return FM_PCD_KG_NUM_OF_SCHEMES; ++} ++ ++t_Handle FmPcdKgGetSchemeHandle(t_Handle h_FmPcd, uint8_t relativeSchemeId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd); ++ ++ /* check that schemeId is in range */ ++ if (relativeSchemeId >= p_FmPcd->p_FmPcdKg->numOfSchemes) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, ("relative-scheme-id %d!", relativeSchemeId)); ++ return NULL; ++ } ++ ++ if (!FmPcdKgIsSchemeValidSw(&p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId])) ++ return NULL; ++ ++ return &p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId]; ++} ++ ++bool FmPcdKgIsSchemeHasOwners(t_Handle h_Scheme) ++{ ++ return (((t_FmPcdKgScheme*)h_Scheme)->owners == 0)?FALSE:TRUE; ++} ++ ++t_Error FmPcdKgCcGetSetParams(t_Handle h_FmPcd, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint8_t relativeSchemeId, physicalSchemeId; ++ uint32_t tmpKgarReg, tmpReg32 = 0, intFlags; ++ t_Error err; ++ t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme*)h_Scheme; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, 0); ++ ++ /* Calling function locked all PCD modules, so no need to lock here */ ++ ++ if (!FmPcdKgIsSchemeValidSw(h_Scheme)) ++ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid")); ++ ++ if (p_FmPcd->h_Hc) ++ { ++ err = FmHcPcdKgCcGetSetParams(p_FmPcd->h_Hc, h_Scheme, requiredAction, value); ++ ++ UpdateRequiredActionFlag(h_Scheme,TRUE); ++ FmPcdKgUpdateRequiredAction(h_Scheme,requiredAction); ++ return err; ++ } ++ ++ physicalSchemeId = p_Scheme->schemeId; ++ ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId); ++ if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ ++ if (!p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].requiredActionFlag || ++ !(p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].requiredAction & requiredAction)) ++ { ++ if (requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) ++ { ++ switch (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine) ++ { ++ case (e_FM_PCD_DONE): ++ if (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].doneAction == e_FM_PCD_ENQ_FRAME) ++ { ++ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId); ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode); ++ ASSERT_COND(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)); ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32 | NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA); ++ /* call indirect command for scheme write */ ++ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ } ++ break; ++ case (e_FM_PCD_PLCR): ++ if (!p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].directPlcr || ++ (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].extractedOrs && ++ p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].bitOffsetInPlcrProfile) || ++ p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextRelativePlcrProfile) ++ { ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("In this situation PP can not be with distribution and has to be shared")); ++ } ++ err = FmPcdPlcrCcGetSetParams(h_FmPcd, p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].relativeProfileId, requiredAction); ++ if (err) ++ { ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("in this situation the next engine after scheme can be or PLCR or ENQ_FRAME")); ++ } ++ } ++ if (requiredAction & UPDATE_KG_NIA_CC_WA) ++ { ++ if (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine == e_FM_PCD_CC) ++ { ++ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId); ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode); ++ ASSERT_COND(tmpReg32 & (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC)); ++ tmpReg32 &= ~NIA_FM_CTL_AC_CC; ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32 | NIA_FM_CTL_AC_PRE_CC); ++ /* call indirect command for scheme write */ ++ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ } ++ } ++ if (requiredAction & UPDATE_KG_OPT_MODE) ++ { ++ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId); ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_om, value); ++ /* call indirect command for scheme write */ ++ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ } ++ if (requiredAction & UPDATE_KG_NIA) ++ { ++ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId); ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode); ++ tmpReg32 &= ~(NIA_ENG_MASK | NIA_AC_MASK); ++ tmpReg32 |= value; ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32); ++ /* call indirect command for scheme write */ ++ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ } ++ } ++ ++ UpdateRequiredActionFlag(h_Scheme, TRUE); ++ FmPcdKgUpdateRequiredAction(h_Scheme, requiredAction); ++ ++ return E_OK; ++} ++/*********************** End of inter-module routines ************************/ ++ ++ ++/****************************************/ ++/* API routines */ ++/****************************************/ ++ ++t_Handle FM_PCD_KgSchemeSet(t_Handle h_FmPcd, t_FmPcdKgSchemeParams *p_SchemeParams) ++{ ++ t_FmPcd *p_FmPcd; ++ struct fman_kg_scheme_regs schemeRegs; ++ struct fman_kg_scheme_regs *p_MemRegs; ++ uint8_t i; ++ t_Error err = E_OK; ++ uint32_t tmpKgarReg; ++ uint32_t intFlags; ++ uint8_t physicalSchemeId, relativeSchemeId = 0; ++ t_FmPcdKgScheme *p_Scheme; ++ ++ if (p_SchemeParams->modify) ++ { ++ p_Scheme = (t_FmPcdKgScheme *)p_SchemeParams->id.h_Scheme; ++ p_FmPcd = p_Scheme->h_FmPcd; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, NULL); ++ ++ if (!FmPcdKgIsSchemeValidSw(p_Scheme)) ++ { ++ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ++ ("Scheme is invalid")); ++ return NULL; ++ } ++ ++ if (!KgSchemeFlagTryLock(p_Scheme)) ++ { ++ DBG(TRACE, ("Scheme Try Lock - BUSY")); ++ /* Signal to caller BUSY condition */ ++ p_SchemeParams->id.h_Scheme = NULL; ++ return NULL; ++ } ++ } ++ else ++ { ++ p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, NULL); ++ ++ relativeSchemeId = p_SchemeParams->id.relativeSchemeId; ++ /* check that schemeId is in range */ ++ if (relativeSchemeId >= p_FmPcd->p_FmPcdKg->numOfSchemes) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, ("relative-scheme-id %d!", relativeSchemeId)); ++ return NULL; ++ } ++ ++ p_Scheme = &p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId]; ++ if (FmPcdKgIsSchemeValidSw(p_Scheme)) ++ { ++ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ++ ("Scheme id (%d)!", relativeSchemeId)); ++ return NULL; ++ } ++ /* Clear all fields, scheme may have beed previously used */ ++ memset(p_Scheme, 0, sizeof(t_FmPcdKgScheme)); ++ ++ p_Scheme->schemeId = p_FmPcd->p_FmPcdKg->schemesIds[relativeSchemeId]; ++ p_Scheme->h_FmPcd = p_FmPcd; ++ ++ p_Scheme->p_Lock = FmPcdAcquireLock(p_FmPcd); ++ if (!p_Scheme->p_Lock) ++ REPORT_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM KG Scheme lock obj!")); ++ } ++ ++ err = BuildSchemeRegs((t_Handle)p_Scheme, p_SchemeParams, &schemeRegs); ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ if (p_SchemeParams->modify) ++ KgSchemeFlagUnlock(p_Scheme); ++ if (!p_SchemeParams->modify && ++ p_Scheme->p_Lock) ++ FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock); ++ return NULL; ++ } ++ ++ if (p_FmPcd->h_Hc) ++ { ++ err = FmHcPcdKgSetScheme(p_FmPcd->h_Hc, ++ (t_Handle)p_Scheme, ++ &schemeRegs, ++ p_SchemeParams->schemeCounter.update); ++ if (p_SchemeParams->modify) ++ KgSchemeFlagUnlock(p_Scheme); ++ if (err) ++ { ++ if (!p_SchemeParams->modify && ++ p_Scheme->p_Lock) ++ FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock); ++ return NULL; ++ } ++ if (!p_SchemeParams->modify) ++ ValidateSchemeSw(p_Scheme); ++ return (t_Handle)p_Scheme; ++ } ++ ++ physicalSchemeId = p_Scheme->schemeId; ++ ++ /* configure all 21 scheme registers */ ++ p_MemRegs = &p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs; ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ WRITE_UINT32(p_MemRegs->kgse_ppc, schemeRegs.kgse_ppc); ++ WRITE_UINT32(p_MemRegs->kgse_ccbs, schemeRegs.kgse_ccbs); ++ WRITE_UINT32(p_MemRegs->kgse_mode, schemeRegs.kgse_mode); ++ WRITE_UINT32(p_MemRegs->kgse_mv, schemeRegs.kgse_mv); ++ WRITE_UINT32(p_MemRegs->kgse_dv0, schemeRegs.kgse_dv0); ++ WRITE_UINT32(p_MemRegs->kgse_dv1, schemeRegs.kgse_dv1); ++ WRITE_UINT32(p_MemRegs->kgse_ekdv, schemeRegs.kgse_ekdv); ++ WRITE_UINT32(p_MemRegs->kgse_ekfc, schemeRegs.kgse_ekfc); ++ WRITE_UINT32(p_MemRegs->kgse_bmch, schemeRegs.kgse_bmch); ++ WRITE_UINT32(p_MemRegs->kgse_bmcl, schemeRegs.kgse_bmcl); ++ WRITE_UINT32(p_MemRegs->kgse_hc, schemeRegs.kgse_hc); ++ WRITE_UINT32(p_MemRegs->kgse_spc, schemeRegs.kgse_spc); ++ WRITE_UINT32(p_MemRegs->kgse_fqb, schemeRegs.kgse_fqb); ++ WRITE_UINT32(p_MemRegs->kgse_om, schemeRegs.kgse_om); ++ WRITE_UINT32(p_MemRegs->kgse_vsp, schemeRegs.kgse_vsp); ++ for (i=0 ; ikgse_gec[i], schemeRegs.kgse_gec[i]); ++ ++ /* call indirect command for scheme write */ ++ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, p_SchemeParams->schemeCounter.update); ++ ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ ++ if (!p_SchemeParams->modify) ++ ValidateSchemeSw(p_Scheme); ++ else ++ KgSchemeFlagUnlock(p_Scheme); ++ ++ return (t_Handle)p_Scheme; ++} ++ ++t_Error FM_PCD_KgSchemeDelete(t_Handle h_Scheme) ++{ ++ t_FmPcd *p_FmPcd; ++ uint8_t physicalSchemeId; ++ uint32_t tmpKgarReg, intFlags; ++ t_Error err = E_OK; ++ t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme *)h_Scheme; ++ ++ SANITY_CHECK_RETURN_ERROR(h_Scheme, E_INVALID_HANDLE); ++ ++ p_FmPcd = (t_FmPcd*)(p_Scheme->h_FmPcd); ++ ++ UpdateRequiredActionFlag(h_Scheme, FALSE); ++ ++ /* check that no port is bound to this scheme */ ++ err = InvalidateSchemeSw(h_Scheme); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ if (p_FmPcd->h_Hc) ++ { ++ err = FmHcPcdKgDeleteScheme(p_FmPcd->h_Hc, h_Scheme); ++ if (p_Scheme->p_Lock) ++ FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock); ++ return err; ++ } ++ ++ physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId; ++ ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ /* clear mode register, including enable bit */ ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, 0); ++ ++ /* call indirect command for scheme write */ ++ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE); ++ ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ ++ if (p_Scheme->p_Lock) ++ FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock); ++ ++ return E_OK; ++} ++ ++uint32_t FM_PCD_KgSchemeGetCounter(t_Handle h_Scheme) ++{ ++ t_FmPcd *p_FmPcd; ++ uint32_t tmpKgarReg, spc, intFlags; ++ uint8_t physicalSchemeId; ++ ++ SANITY_CHECK_RETURN_VALUE(h_Scheme, E_INVALID_HANDLE, 0); ++ ++ p_FmPcd = (t_FmPcd*)(((t_FmPcdKgScheme *)h_Scheme)->h_FmPcd); ++ if (p_FmPcd->h_Hc) ++ return FmHcPcdKgGetSchemeCounter(p_FmPcd->h_Hc, h_Scheme); ++ ++ physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId; ++ ++ if (FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId) == FM_PCD_KG_NUM_OF_SCHEMES) ++ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ ++ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId); ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ if (!(GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode) & KG_SCH_MODE_EN)) ++ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid")); ++ spc = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_spc); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ ++ return spc; ++} ++ ++t_Error FM_PCD_KgSchemeSetCounter(t_Handle h_Scheme, uint32_t value) ++{ ++ t_FmPcd *p_FmPcd; ++ uint32_t tmpKgarReg, intFlags; ++ uint8_t physicalSchemeId; ++ ++ SANITY_CHECK_RETURN_VALUE(h_Scheme, E_INVALID_HANDLE, 0); ++ ++ p_FmPcd = (t_FmPcd*)(((t_FmPcdKgScheme *)h_Scheme)->h_FmPcd); ++ ++ if (!FmPcdKgIsSchemeValidSw(h_Scheme)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Requested scheme is invalid.")); ++ ++ if (p_FmPcd->h_Hc) ++ return FmHcPcdKgSetSchemeCounter(p_FmPcd->h_Hc, h_Scheme, value); ++ ++ physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId; ++ /* check that schemeId is in range */ ++ if (FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId) == FM_PCD_KG_NUM_OF_SCHEMES) ++ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ ++ /* read specified scheme into scheme registers */ ++ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId); ++ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg); ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ if (!(GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode) & KG_SCH_MODE_EN)) ++ { ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid")); ++ } ++ ++ /* change counter value */ ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_spc, value); ++ ++ /* call indirect command for scheme write */ ++ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, TRUE); ++ ++ WriteKgarWait(p_FmPcd, tmpKgarReg); ++ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_KgSetAdditionalDataAfterParsing(t_Handle h_FmPcd, uint8_t payloadOffset) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ struct fman_kg_regs *p_Regs; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs, E_NULL_POINTER); ++ ++ p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ if (!FmIsMaster(p_FmPcd->h_Fm)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_KgSetAdditionalDataAfterParsing - guest mode!")); ++ ++ WRITE_UINT32(p_Regs->fmkg_fdor,payloadOffset); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_KgSetDfltValue(t_Handle h_FmPcd, uint8_t valueId, uint32_t value) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ struct fman_kg_regs *p_Regs; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(((valueId == 0) || (valueId == 1)), E_INVALID_VALUE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs, E_NULL_POINTER); ++ ++ p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs; ++ ++ if (!FmIsMaster(p_FmPcd->h_Fm)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_KgSetDfltValue - guest mode!")); ++ ++ if (valueId == 0) ++ WRITE_UINT32(p_Regs->fmkg_gdv0r,value); ++ else ++ WRITE_UINT32(p_Regs->fmkg_gdv1r,value); ++ return E_OK; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_kg.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_kg.h +new file mode 100644 +index 0000000..cb7521a +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_kg.h +@@ -0,0 +1,206 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_kg.h ++ ++ @Description FM KG private header ++*//***************************************************************************/ ++#ifndef __FM_KG_H ++#define __FM_KG_H ++ ++#include "std_ext.h" ++ ++/***********************************************************************/ ++/* Keygen defines */ ++/***********************************************************************/ ++/* maskes */ ++#if (DPAA_VERSION >= 11) ++#define KG_SCH_VSP_SHIFT_MASK 0x0003f000 ++#define KG_SCH_OM_VSPE 0x00000001 ++#define KG_SCH_VSP_NO_KSP_EN 0x80000000 ++ ++#define MAX_SP_SHIFT 23 ++#define KG_SCH_VSP_MASK_SHIFT 12 ++#define KG_SCH_VSP_SHIFT 24 ++#endif /* (DPAA_VERSION >= 11) */ ++ ++typedef uint32_t t_KnownFieldsMasks; ++#define KG_SCH_KN_PORT_ID 0x80000000 ++#define KG_SCH_KN_MACDST 0x40000000 ++#define KG_SCH_KN_MACSRC 0x20000000 ++#define KG_SCH_KN_TCI1 0x10000000 ++#define KG_SCH_KN_TCI2 0x08000000 ++#define KG_SCH_KN_ETYPE 0x04000000 ++#define KG_SCH_KN_PPPSID 0x02000000 ++#define KG_SCH_KN_PPPID 0x01000000 ++#define KG_SCH_KN_MPLS1 0x00800000 ++#define KG_SCH_KN_MPLS2 0x00400000 ++#define KG_SCH_KN_MPLS_LAST 0x00200000 ++#define KG_SCH_KN_IPSRC1 0x00100000 ++#define KG_SCH_KN_IPDST1 0x00080000 ++#define KG_SCH_KN_PTYPE1 0x00040000 ++#define KG_SCH_KN_IPTOS_TC1 0x00020000 ++#define KG_SCH_KN_IPV6FL1 0x00010000 ++#define KG_SCH_KN_IPSRC2 0x00008000 ++#define KG_SCH_KN_IPDST2 0x00004000 ++#define KG_SCH_KN_PTYPE2 0x00002000 ++#define KG_SCH_KN_IPTOS_TC2 0x00001000 ++#define KG_SCH_KN_IPV6FL2 0x00000800 ++#define KG_SCH_KN_GREPTYPE 0x00000400 ++#define KG_SCH_KN_IPSEC_SPI 0x00000200 ++#define KG_SCH_KN_IPSEC_NH 0x00000100 ++#define KG_SCH_KN_IPPID 0x00000080 ++#define KG_SCH_KN_L4PSRC 0x00000004 ++#define KG_SCH_KN_L4PDST 0x00000002 ++#define KG_SCH_KN_TFLG 0x00000001 ++ ++typedef uint8_t t_GenericCodes; ++#define KG_SCH_GEN_SHIM1 0x70 ++#define KG_SCH_GEN_DEFAULT 0x10 ++#define KG_SCH_GEN_PARSE_RESULT_N_FQID 0x20 ++#define KG_SCH_GEN_START_OF_FRM 0x40 ++#define KG_SCH_GEN_SHIM2 0x71 ++#define KG_SCH_GEN_IP_PID_NO_V 0x72 ++#define KG_SCH_GEN_ETH 0x03 ++#define KG_SCH_GEN_ETH_NO_V 0x73 ++#define KG_SCH_GEN_SNAP 0x04 ++#define KG_SCH_GEN_SNAP_NO_V 0x74 ++#define KG_SCH_GEN_VLAN1 0x05 ++#define KG_SCH_GEN_VLAN1_NO_V 0x75 ++#define KG_SCH_GEN_VLAN2 0x06 ++#define KG_SCH_GEN_VLAN2_NO_V 0x76 ++#define KG_SCH_GEN_ETH_TYPE 0x07 ++#define KG_SCH_GEN_ETH_TYPE_NO_V 0x77 ++#define KG_SCH_GEN_PPP 0x08 ++#define KG_SCH_GEN_PPP_NO_V 0x78 ++#define KG_SCH_GEN_MPLS1 0x09 ++#define KG_SCH_GEN_MPLS2 0x19 ++#define KG_SCH_GEN_MPLS3 0x29 ++#define KG_SCH_GEN_MPLS1_NO_V 0x79 ++#define KG_SCH_GEN_MPLS_LAST 0x0a ++#define KG_SCH_GEN_MPLS_LAST_NO_V 0x7a ++#define KG_SCH_GEN_IPV4 0x0b ++#define KG_SCH_GEN_IPV6 0x1b ++#define KG_SCH_GEN_L3_NO_V 0x7b ++#define KG_SCH_GEN_IPV4_TUNNELED 0x0c ++#define KG_SCH_GEN_IPV6_TUNNELED 0x1c ++#define KG_SCH_GEN_MIN_ENCAP 0x2c ++#define KG_SCH_GEN_IP2_NO_V 0x7c ++#define KG_SCH_GEN_GRE 0x0d ++#define KG_SCH_GEN_GRE_NO_V 0x7d ++#define KG_SCH_GEN_TCP 0x0e ++#define KG_SCH_GEN_UDP 0x1e ++#define KG_SCH_GEN_IPSEC_AH 0x2e ++#define KG_SCH_GEN_SCTP 0x3e ++#define KG_SCH_GEN_DCCP 0x4e ++#define KG_SCH_GEN_IPSEC_ESP 0x6e ++#define KG_SCH_GEN_L4_NO_V 0x7e ++#define KG_SCH_GEN_NEXTHDR 0x7f ++/* shifts */ ++#define KG_SCH_PP_SHIFT_HIGH_SHIFT 27 ++#define KG_SCH_PP_SHIFT_LOW_SHIFT 12 ++#define KG_SCH_PP_MASK_SHIFT 16 ++#define KG_SCH_MODE_CCOBASE_SHIFT 24 ++#define KG_SCH_DEF_MAC_ADDR_SHIFT 30 ++#define KG_SCH_DEF_TCI_SHIFT 28 ++#define KG_SCH_DEF_ENET_TYPE_SHIFT 26 ++#define KG_SCH_DEF_PPP_SESSION_ID_SHIFT 24 ++#define KG_SCH_DEF_PPP_PROTOCOL_ID_SHIFT 22 ++#define KG_SCH_DEF_MPLS_LABEL_SHIFT 20 ++#define KG_SCH_DEF_IP_ADDR_SHIFT 18 ++#define KG_SCH_DEF_PROTOCOL_TYPE_SHIFT 16 ++#define KG_SCH_DEF_IP_TOS_TC_SHIFT 14 ++#define KG_SCH_DEF_IPV6_FLOW_LABEL_SHIFT 12 ++#define KG_SCH_DEF_IPSEC_SPI_SHIFT 10 ++#define KG_SCH_DEF_L4_PORT_SHIFT 8 ++#define KG_SCH_DEF_TCP_FLAG_SHIFT 6 ++#define KG_SCH_HASH_CONFIG_SHIFT_SHIFT 24 ++#define KG_SCH_GEN_MASK_SHIFT 16 ++#define KG_SCH_GEN_HT_SHIFT 8 ++#define KG_SCH_GEN_SIZE_SHIFT 24 ++#define KG_SCH_GEN_DEF_SHIFT 29 ++#define FM_PCD_KG_KGAR_NUM_SHIFT 16 ++ ++/* others */ ++#define NUM_OF_SW_DEFAULTS 3 ++#define MAX_PP_SHIFT 23 ++#define MAX_KG_SCH_SIZE 16 ++#define MASK_FOR_GENERIC_BASE_ID 0x20 ++#define MAX_HASH_SHIFT 40 ++#define MAX_KG_SCH_FQID_BIT_OFFSET 31 ++#define MAX_KG_SCH_PP_BIT_OFFSET 15 ++#define MAX_DIST_FQID_SHIFT 23 ++ ++#define GET_MASK_SEL_SHIFT(shift,i) \ ++switch (i) { \ ++ case (0):shift = 26;break; \ ++ case (1):shift = 20;break; \ ++ case (2):shift = 10;break; \ ++ case (3):shift = 4;break; \ ++ default: \ ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); \ ++} ++ ++#define GET_MASK_OFFSET_SHIFT(shift,i) \ ++switch (i) { \ ++ case (0):shift = 16;break; \ ++ case (1):shift = 0;break; \ ++ case (2):shift = 28;break; \ ++ case (3):shift = 24;break; \ ++ default: \ ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); \ ++} ++ ++#define GET_MASK_SHIFT(shift,i) \ ++switch (i) { \ ++ case (0):shift = 24;break; \ ++ case (1):shift = 16;break; \ ++ case (2):shift = 8;break; \ ++ case (3):shift = 0;break; \ ++ default: \ ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); \ ++} ++ ++/***********************************************************************/ ++/* Keygen defines */ ++/***********************************************************************/ ++ ++#define KG_DOUBLE_MEANING_REGS_OFFSET 0x100 ++#define NO_VALIDATION 0x70 ++#define KG_ACTION_REG_TO 1024 ++#define KG_MAX_PROFILE 255 ++#define SCHEME_ALWAYS_DIRECT 0xFFFFFFFF ++ ++ ++#endif /* __FM_KG_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_manip.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_manip.c +new file mode 100644 +index 0000000..e980320 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_manip.c +@@ -0,0 +1,5564 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_manip.c ++ ++ @Description FM PCD manip ... ++ *//***************************************************************************/ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "debug_ext.h" ++#include "fm_pcd_ext.h" ++#include "fm_port_ext.h" ++#include "fm_muram_ext.h" ++#include "memcpy_ext.h" ++ ++#include "fm_common.h" ++#include "fm_hc.h" ++#include "fm_manip.h" ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++static t_Handle GetManipInfo(t_FmPcdManip *p_Manip, e_ManipInfo manipInfo) ++{ ++ t_FmPcdManip *p_CurManip = p_Manip; ++ ++ if (!MANIP_IS_UNIFIED(p_Manip)) ++ p_CurManip = p_Manip; ++ else ++ { ++ /* go to first unified */ ++ while (MANIP_IS_UNIFIED_NON_FIRST(p_CurManip)) ++ p_CurManip = p_CurManip->h_PrevManip; ++ } ++ ++ switch (manipInfo) ++ { ++ case (e_MANIP_HMCT): ++ return p_CurManip->p_Hmct; ++ case (e_MANIP_HMTD): ++ return p_CurManip->h_Ad; ++ case (e_MANIP_HANDLER_TABLE_OWNER): ++ return (t_Handle)p_CurManip; ++ default: ++ return NULL; ++ } ++} ++ ++static uint16_t GetHmctSize(t_FmPcdManip *p_Manip) ++{ ++ uint16_t size = 0; ++ t_FmPcdManip *p_CurManip = p_Manip; ++ ++ if (!MANIP_IS_UNIFIED(p_Manip)) ++ return p_Manip->tableSize; ++ ++ /* accumulate sizes, starting with the first node */ ++ while (MANIP_IS_UNIFIED_NON_FIRST(p_CurManip)) ++ p_CurManip = p_CurManip->h_PrevManip; ++ ++ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip)) ++ { ++ size += p_CurManip->tableSize; ++ p_CurManip = (t_FmPcdManip *)p_CurManip->h_NextManip; ++ } ++ size += p_CurManip->tableSize; /* add last size */ ++ ++ return (size); ++} ++ ++static uint16_t GetDataSize(t_FmPcdManip *p_Manip) ++{ ++ uint16_t size = 0; ++ t_FmPcdManip *p_CurManip = p_Manip; ++ ++ if (!MANIP_IS_UNIFIED(p_Manip)) ++ return p_Manip->dataSize; ++ ++ /* accumulate sizes, starting with the first node */ ++ while (MANIP_IS_UNIFIED_NON_FIRST(p_CurManip)) ++ p_CurManip = p_CurManip->h_PrevManip; ++ ++ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip)) ++ { ++ size += p_CurManip->dataSize; ++ p_CurManip = (t_FmPcdManip *)p_CurManip->h_NextManip; ++ } ++ size += p_CurManip->dataSize; /* add last size */ ++ ++ return (size); ++} ++ ++static t_Error CalculateTableSize(t_FmPcdManipParams *p_FmPcdManipParams, ++ uint16_t *p_TableSize, uint8_t *p_DataSize) ++{ ++ uint8_t localDataSize, remain, tableSize = 0, dataSize = 0; ++ ++ if (p_FmPcdManipParams->u.hdr.rmv) ++ { ++ switch (p_FmPcdManipParams->u.hdr.rmvParams.type) ++ { ++ case (e_FM_PCD_MANIP_RMV_GENERIC): ++ tableSize += HMCD_BASIC_SIZE; ++ break; ++ case (e_FM_PCD_MANIP_RMV_BY_HDR): ++ switch (p_FmPcdManipParams->u.hdr.rmvParams.u.byHdr.type) ++ { ++ case (e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2): ++#if (DPAA_VERSION >= 11) ++ case (e_FM_PCD_MANIP_RMV_BY_HDR_CAPWAP): ++ case (e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START): ++#endif /* (DPAA_VERSION >= 11) */ ++ tableSize += HMCD_BASIC_SIZE; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ++ ("Unknown byHdr.type")); ++ } ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ++ ("Unknown rmvParams.type")); ++ } ++ } ++ ++ if (p_FmPcdManipParams->u.hdr.insrt) ++ { ++ switch (p_FmPcdManipParams->u.hdr.insrtParams.type) ++ { ++ case (e_FM_PCD_MANIP_INSRT_GENERIC): ++ remain = ++ (uint8_t)(p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size ++ % 4); ++ if (remain) ++ localDataSize = ++ (uint8_t)(p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size ++ + 4 - remain); ++ else ++ localDataSize = ++ p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size; ++ tableSize += (uint8_t)(HMCD_BASIC_SIZE + localDataSize); ++ break; ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR): ++ { ++ switch (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.type) ++ { ++ ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2): ++ tableSize += HMCD_BASIC_SIZE + HMCD_PTR_SIZE; ++ switch (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.specificL2) ++ { ++ case (e_FM_PCD_MANIP_HDR_INSRT_MPLS): ++ dataSize += ++ p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.size; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++ } ++ break; ++#if (DPAA_VERSION >= 11) ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR_IP): ++ tableSize += ++ (HMCD_BASIC_SIZE + HMCD_PTR_SIZE ++ + HMCD_PARAM_SIZE ++ + p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.insrt.size); ++ dataSize += 2; ++ break; ++ ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR_UDP): ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR_UDP_LITE): ++ tableSize += (HMCD_BASIC_SIZE + HMCD_L4_HDR_SIZE); ++ ++ break; ++ ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR_CAPWAP): ++ tableSize += ++ (HMCD_BASIC_SIZE ++ + p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.size); ++ break; ++#endif /* (DPAA_VERSION >= 11) */ ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ++ ("Unknown byHdr.type")); ++ } ++ } ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ++ ("Unknown insrtParams.type")); ++ } ++ } ++ ++ if (p_FmPcdManipParams->u.hdr.fieldUpdate) ++ { ++ switch (p_FmPcdManipParams->u.hdr.fieldUpdateParams.type) ++ { ++ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN): ++ tableSize += HMCD_BASIC_SIZE; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType ++ == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN) ++ { ++ tableSize += HMCD_PTR_SIZE; ++ dataSize += DSCP_TO_VLAN_TABLE_SIZE; ++ } ++ break; ++ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4): ++ tableSize += HMCD_BASIC_SIZE; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates ++ & HDR_MANIP_IPV4_ID) ++ { ++ tableSize += HMCD_PARAM_SIZE; ++ dataSize += 2; ++ } ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates ++ & HDR_MANIP_IPV4_SRC) ++ tableSize += HMCD_IPV4_ADDR_SIZE; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates ++ & HDR_MANIP_IPV4_DST) ++ tableSize += HMCD_IPV4_ADDR_SIZE; ++ break; ++ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6): ++ tableSize += HMCD_BASIC_SIZE; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates ++ & HDR_MANIP_IPV6_SRC) ++ tableSize += HMCD_IPV6_ADDR_SIZE; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates ++ & HDR_MANIP_IPV6_DST) ++ tableSize += HMCD_IPV6_ADDR_SIZE; ++ break; ++ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP): ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates ++ == HDR_MANIP_TCP_UDP_CHECKSUM) ++ /* we implement this case with the update-checksum descriptor */ ++ tableSize += HMCD_BASIC_SIZE; ++ else ++ /* we implement this case with the TCP/UDP-update descriptor */ ++ tableSize += HMCD_BASIC_SIZE + HMCD_PARAM_SIZE; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ++ ("Unknown fieldUpdateParams.type")); ++ } ++ } ++ ++ if (p_FmPcdManipParams->u.hdr.custom) ++ { ++ switch (p_FmPcdManipParams->u.hdr.customParams.type) ++ { ++ case (e_FM_PCD_MANIP_HDR_CUSTOM_IP_REPLACE): ++ { ++ tableSize += HMCD_BASIC_SIZE + HMCD_PARAM_SIZE + HMCD_PARAM_SIZE; ++ dataSize += ++ p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdrSize; ++ if ((p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType ++ == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4) ++ && (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.updateIpv4Id)) ++ dataSize += 2; ++ } ++ break; ++ case (e_FM_PCD_MANIP_HDR_CUSTOM_GEN_FIELD_REPLACE): ++ tableSize += HMCD_BASIC_SIZE + HMCD_PARAM_SIZE; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ++ ("Unknown customParams.type")); ++ } ++ } ++ ++ *p_TableSize = tableSize; ++ *p_DataSize = dataSize; ++ ++ return E_OK; ++} ++ ++static t_Error GetPrOffsetByHeaderOrField(t_FmManipHdrInfo *p_HdrInfo, ++ uint8_t *parseArrayOffset) ++{ ++ e_NetHeaderType hdr = p_HdrInfo->hdr; ++ e_FmPcdHdrIndex hdrIndex = p_HdrInfo->hdrIndex; ++ bool byField = p_HdrInfo->byField; ++ t_FmPcdFields field; ++ ++ if (byField) ++ field = p_HdrInfo->fullField; ++ ++ if (byField) ++ { ++ switch (hdr) ++ { ++ case (HEADER_TYPE_ETH): ++ switch (field.eth) ++ { ++ case (NET_HEADER_FIELD_ETH_TYPE): ++ *parseArrayOffset = CC_PC_PR_ETYPE_LAST_OFFSET; ++ break; ++ default: ++ RETURN_ERROR( ++ MAJOR, ++ E_NOT_SUPPORTED, ++ ("Header manipulation of the type Ethernet with this field not supported")); ++ } ++ break; ++ case (HEADER_TYPE_VLAN): ++ switch (field.vlan) ++ { ++ case (NET_HEADER_FIELD_VLAN_TCI): ++ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) ++ || (hdrIndex == e_FM_PCD_HDR_INDEX_1)) ++ *parseArrayOffset = CC_PC_PR_VLAN1_OFFSET; ++ else ++ if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST) ++ *parseArrayOffset = CC_PC_PR_VLAN2_OFFSET; ++ break; ++ default: ++ RETURN_ERROR( ++ MAJOR, ++ E_NOT_SUPPORTED, ++ ("Header manipulation of the type VLAN with this field not supported")); ++ } ++ break; ++ default: ++ RETURN_ERROR( ++ MAJOR, ++ E_NOT_SUPPORTED, ++ ("Header manipulation of this header by field not supported")); ++ } ++ } ++ else ++ { ++ switch (hdr) ++ { ++ case (HEADER_TYPE_ETH): ++ *parseArrayOffset = (uint8_t)CC_PC_PR_ETH_OFFSET; ++ break; ++ case (HEADER_TYPE_USER_DEFINED_SHIM1): ++ *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM1_OFFSET; ++ break; ++ case (HEADER_TYPE_USER_DEFINED_SHIM2): ++ *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM2_OFFSET; ++ break; ++ case (HEADER_TYPE_LLC_SNAP): ++ *parseArrayOffset = CC_PC_PR_USER_LLC_SNAP_OFFSET; ++ break; ++ case (HEADER_TYPE_PPPoE): ++ *parseArrayOffset = CC_PC_PR_PPPOE_OFFSET; ++ break; ++ case (HEADER_TYPE_MPLS): ++ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) ++ || (hdrIndex == e_FM_PCD_HDR_INDEX_1)) ++ *parseArrayOffset = CC_PC_PR_MPLS1_OFFSET; ++ else ++ if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST) ++ *parseArrayOffset = CC_PC_PR_MPLS_LAST_OFFSET; ++ break; ++ case (HEADER_TYPE_IPv4): ++ case (HEADER_TYPE_IPv6): ++ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) ++ || (hdrIndex == e_FM_PCD_HDR_INDEX_1)) ++ *parseArrayOffset = CC_PC_PR_IP1_OFFSET; ++ else ++ if (hdrIndex == e_FM_PCD_HDR_INDEX_2) ++ *parseArrayOffset = CC_PC_PR_IP_LAST_OFFSET; ++ break; ++ case (HEADER_TYPE_MINENCAP): ++ *parseArrayOffset = CC_PC_PR_MINENC_OFFSET; ++ break; ++ case (HEADER_TYPE_GRE): ++ *parseArrayOffset = CC_PC_PR_GRE_OFFSET; ++ break; ++ case (HEADER_TYPE_TCP): ++ case (HEADER_TYPE_UDP): ++ case (HEADER_TYPE_IPSEC_AH): ++ case (HEADER_TYPE_IPSEC_ESP): ++ case (HEADER_TYPE_DCCP): ++ case (HEADER_TYPE_SCTP): ++ *parseArrayOffset = CC_PC_PR_L4_OFFSET; ++ break; ++ case (HEADER_TYPE_CAPWAP): ++ case (HEADER_TYPE_CAPWAP_DTLS): ++ *parseArrayOffset = CC_PC_PR_NEXT_HEADER_OFFSET; ++ break; ++ default: ++ RETURN_ERROR( ++ MAJOR, ++ E_NOT_SUPPORTED, ++ ("Header manipulation of this header is not supported")); ++ } ++ } ++ return E_OK; ++} ++ ++static t_Error BuildHmct(t_FmPcdManip *p_Manip, ++ t_FmPcdManipParams *p_FmPcdManipParams, ++ uint8_t *p_DestHmct, uint8_t *p_DestData, bool new) ++{ ++ uint32_t *p_TmpHmct = (uint32_t*)p_DestHmct, *p_LocalData; ++ uint32_t tmpReg = 0, *p_Last = NULL, tmp_ipv6_addr; ++ uint8_t remain, i, size = 0, origSize, *p_UsrData = NULL, *p_TmpData = ++ p_DestData; ++ t_Handle h_FmPcd = p_Manip->h_FmPcd; ++ uint8_t j = 0; ++ ++ if (p_FmPcdManipParams->u.hdr.rmv) ++ { ++ if (p_FmPcdManipParams->u.hdr.rmvParams.type ++ == e_FM_PCD_MANIP_RMV_GENERIC) ++ { ++ /* initialize HMCD */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_GENERIC_RMV) << HMCD_OC_SHIFT; ++ /* tmp, should be conditional */ ++ tmpReg |= p_FmPcdManipParams->u.hdr.rmvParams.u.generic.offset ++ << HMCD_RMV_OFFSET_SHIFT; ++ tmpReg |= p_FmPcdManipParams->u.hdr.rmvParams.u.generic.size ++ << HMCD_RMV_SIZE_SHIFT; ++ } ++ else ++ if (p_FmPcdManipParams->u.hdr.rmvParams.type ++ == e_FM_PCD_MANIP_RMV_BY_HDR) ++ { ++ switch (p_FmPcdManipParams->u.hdr.rmvParams.u.byHdr.type) ++ { ++ case (e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2): ++ { ++ uint8_t hmcdOpt; ++ ++ /* initialize HMCD */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_L2_RMV) << HMCD_OC_SHIFT; ++ ++ switch (p_FmPcdManipParams->u.hdr.rmvParams.u.byHdr.u.specificL2) ++ { ++ case (e_FM_PCD_MANIP_HDR_RMV_ETHERNET): ++ hmcdOpt = HMCD_RMV_L2_ETHERNET; ++ break; ++ case (e_FM_PCD_MANIP_HDR_RMV_STACKED_QTAGS): ++ hmcdOpt = HMCD_RMV_L2_STACKED_QTAGS; ++ break; ++ case (e_FM_PCD_MANIP_HDR_RMV_ETHERNET_AND_MPLS): ++ hmcdOpt = HMCD_RMV_L2_ETHERNET_AND_MPLS; ++ break; ++ case (e_FM_PCD_MANIP_HDR_RMV_MPLS): ++ hmcdOpt = HMCD_RMV_L2_MPLS; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++ } ++ tmpReg |= hmcdOpt << HMCD_L2_MODE_SHIFT; ++ break; ++ } ++#if (DPAA_VERSION >= 11) ++ case (e_FM_PCD_MANIP_RMV_BY_HDR_CAPWAP): ++ tmpReg = (uint32_t)(HMCD_OPCODE_CAPWAP_RMV) ++ << HMCD_OC_SHIFT; ++ break; ++ case (e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START): ++ { ++ uint8_t prsArrayOffset; ++ t_Error err = E_OK; ++ ++ tmpReg = (uint32_t)(HMCD_OPCODE_RMV_TILL) ++ << HMCD_OC_SHIFT; ++ ++ err = ++ GetPrOffsetByHeaderOrField( ++ &p_FmPcdManipParams->u.hdr.rmvParams.u.byHdr.u.hdrInfo, ++ &prsArrayOffset); ++ ASSERT_COND(!err); ++ /* was previously checked */ ++ ++ tmpReg |= ((uint32_t)prsArrayOffset << 16); ++ } ++ break; ++#endif /* (DPAA_VERSION >= 11) */ ++ default: ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("manip header remove by hdr type!")); ++ } ++ } ++ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ /* advance to next command */ ++ p_TmpHmct += HMCD_BASIC_SIZE / 4; ++ } ++ ++ if (p_FmPcdManipParams->u.hdr.insrt) ++ { ++ if (p_FmPcdManipParams->u.hdr.insrtParams.type ++ == e_FM_PCD_MANIP_INSRT_GENERIC) ++ { ++ /* initialize HMCD */ ++ if (p_FmPcdManipParams->u.hdr.insrtParams.u.generic.replace) ++ tmpReg = (uint32_t)(HMCD_OPCODE_GENERIC_REPLACE) ++ << HMCD_OC_SHIFT; ++ else ++ tmpReg = (uint32_t)(HMCD_OPCODE_GENERIC_INSRT) << HMCD_OC_SHIFT; ++ ++ tmpReg |= p_FmPcdManipParams->u.hdr.insrtParams.u.generic.offset ++ << HMCD_INSRT_OFFSET_SHIFT; ++ tmpReg |= p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size ++ << HMCD_INSRT_SIZE_SHIFT; ++ ++ size = p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size; ++ p_UsrData = p_FmPcdManipParams->u.hdr.insrtParams.u.generic.p_Data; ++ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE / 4; ++ ++ /* initialize data to be inserted */ ++ /* if size is not a multiple of 4, padd with 0's */ ++ origSize = size; ++ remain = (uint8_t)(size % 4); ++ if (remain) ++ { ++ size += (uint8_t)(4 - remain); ++ p_LocalData = (uint32_t *)XX_Malloc(size); ++ memset((uint8_t *)p_LocalData, 0, size); ++ memcpy((uint8_t *)p_LocalData, p_UsrData, origSize); ++ } ++ else ++ p_LocalData = (uint32_t*)p_UsrData; ++ ++ /* initialize data and advance pointer to next command */ ++ for (i = 0; i < size / 4; i++, p_TmpHmct += HMCD_BASIC_SIZE / 4) ++ WRITE_UINT32(*p_TmpHmct, *(p_LocalData+i)); ++ ++ if (remain) ++ XX_Free(p_LocalData); ++ } ++ ++ else ++ if (p_FmPcdManipParams->u.hdr.insrtParams.type ++ == e_FM_PCD_MANIP_INSRT_BY_HDR) ++ { ++ switch (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.type) ++ { ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2): ++ { ++ uint8_t hmcdOpt; ++ ++ /* initialize HMCD */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_L2_INSRT) ++ << HMCD_OC_SHIFT; ++ ++ switch (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.specificL2) ++ { ++ case (e_FM_PCD_MANIP_HDR_INSRT_MPLS): ++ if (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.update) ++ hmcdOpt = HMCD_INSRT_N_UPDATE_L2_MPLS; ++ else ++ hmcdOpt = HMCD_INSRT_L2_MPLS; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); ++ } ++ tmpReg |= hmcdOpt << HMCD_L2_MODE_SHIFT; ++ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE / 4; ++ ++ /* set size and pointer of user's data */ ++ size = ++ (uint8_t)p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.size; ++ ++ ASSERT_COND(p_TmpData); ++ Mem2IOCpy32( ++ p_TmpData, ++ p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.p_Data, ++ size); ++ tmpReg = ++ (size << HMCD_INSRT_L2_SIZE_SHIFT) ++ | (uint32_t)(XX_VirtToPhys(p_TmpData) ++ - (((t_FmPcd*)h_FmPcd)->physicalMuramBase)); ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ p_TmpHmct += HMCD_PTR_SIZE / 4; ++ p_TmpData += size; ++ } ++ break; ++#if (DPAA_VERSION >= 11) ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR_IP): ++ tmpReg = (uint32_t)(HMCD_OPCODE_IP_INSRT) ++ << HMCD_OC_SHIFT; ++ if (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.calcL4Checksum) ++ tmpReg |= HMCD_IP_L4_CS_CALC; ++ if (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.mappingMode ++ == e_FM_PCD_MANIP_HDR_QOS_MAPPING_AS_IS) ++ tmpReg |= HMCD_IP_OR_QOS; ++ tmpReg |= ++ p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.lastPidOffset ++ & HMCD_IP_LAST_PID_MASK; ++ tmpReg |= ++ ((p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.insrt.size ++ << HMCD_IP_SIZE_SHIFT) ++ & HMCD_IP_SIZE_MASK); ++ if (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.dontFragOverwrite) ++ tmpReg |= HMCD_IP_DF_MODE; ++ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE / 4; ++ ++ /* set IP id */ ++ ASSERT_COND(p_TmpData); ++ WRITE_UINT16( ++ *(uint16_t*)p_TmpData, ++ p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.id); ++ WRITE_UINT32( ++ *p_TmpHmct, ++ (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase))); ++ p_TmpData += 2; ++ p_TmpHmct += HMCD_PTR_SIZE / 4; ++ ++ WRITE_UINT8(*p_TmpHmct, p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.lastDstOffset); ++ p_TmpHmct += HMCD_PARAM_SIZE / 4; ++ ++ Mem2IOCpy32( ++ p_TmpHmct, ++ p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.insrt.p_Data, ++ p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.insrt.size); ++ p_TmpHmct += ++ p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.insrt.size ++ / 4; ++ break; ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR_UDP_LITE): ++ tmpReg = HMCD_INSRT_UDP_LITE; ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR_UDP): ++ tmpReg |= (uint32_t)(HMCD_OPCODE_UDP_INSRT) ++ << HMCD_OC_SHIFT; ++ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE / 4; ++ ++ Mem2IOCpy32( ++ p_TmpHmct, ++ p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.p_Data, ++ p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.size); ++ p_TmpHmct += ++ p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.size ++ / 4; ++ break; ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR_CAPWAP): ++ tmpReg = (uint32_t)(HMCD_OPCODE_CAPWAP_INSRT) ++ << HMCD_OC_SHIFT; ++ tmpReg |= HMCD_CAPWAP_INSRT; ++ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE / 4; ++ ++ Mem2IOCpy32( ++ p_TmpHmct, ++ p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.p_Data, ++ p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.size); ++ p_TmpHmct += ++ p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.size ++ / 4; ++ break; ++#endif /* (DPAA_VERSION >= 11) */ ++ default: ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("manip header insert by header type!")); ++ ++ } ++ } ++ } ++ ++ if (p_FmPcdManipParams->u.hdr.fieldUpdate) ++ { ++ switch (p_FmPcdManipParams->u.hdr.fieldUpdateParams.type) ++ { ++ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN): ++ /* set opcode */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_VLAN_PRI_UPDATE) ++ << HMCD_OC_SHIFT; ++ ++ /* set mode & table pointer */ ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType ++ == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN) ++ { ++ /* set Mode */ ++ tmpReg |= (uint32_t)(HMCD_VLAN_PRI_UPDATE_DSCP_TO_VPRI) ++ << HMCD_VLAN_PRI_REP_MODE_SHIFT; ++ /* set VPRI default */ ++ tmpReg |= ++ p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.vpriDefVal; ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ /* write the table pointer into the Manip descriptor */ ++ p_TmpHmct += HMCD_BASIC_SIZE / 4; ++ ++ tmpReg = 0; ++ ASSERT_COND(p_TmpData); ++ for (i = 0; i < HMCD_DSCP_VALUES; i++) ++ { ++ /* first we build from each 8 values a 32bit register */ ++ tmpReg |= ++ (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.dscpToVpriTable[i]) ++ << (32 - 4 * (j + 1)); ++ j++; ++ /* Than we write this register to the next table word ++ * (i=7-->word 0, i=15-->word 1,... i=63-->word 7) */ ++ if ((i % 8) == 7) ++ { ++ WRITE_UINT32(*((uint32_t*)p_TmpData + (i+1)/8-1), ++ tmpReg); ++ tmpReg = 0; ++ j = 0; ++ } ++ } ++ ++ WRITE_UINT32( ++ *p_TmpHmct, ++ (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase))); ++ p_TmpHmct += HMCD_PTR_SIZE / 4; ++ ++ p_TmpData += DSCP_TO_VLAN_TABLE_SIZE; ++ } ++ else ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType ++ == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_VPRI) ++ { ++ /* set Mode */ ++ /* line commented out as it has no-side-effect ('0' value). */ ++ /*tmpReg |= HMCD_VLAN_PRI_UPDATE << HMCD_VLAN_PRI_REP_MODE_SHIFT*/; ++ /* set VPRI parameter */ ++ tmpReg |= ++ p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.u.vpri; ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ p_TmpHmct += HMCD_BASIC_SIZE / 4; ++ } ++ break; ++ ++ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4): ++ /* set opcode */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_IPV4_UPDATE) << HMCD_OC_SHIFT; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates ++ & HDR_MANIP_IPV4_TTL) ++ tmpReg |= HMCD_IPV4_UPDATE_TTL; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates ++ & HDR_MANIP_IPV4_TOS) ++ { ++ tmpReg |= HMCD_IPV4_UPDATE_TOS; ++ tmpReg |= ++ p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.tos ++ << HMCD_IPV4_UPDATE_TOS_SHIFT; ++ } ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates ++ & HDR_MANIP_IPV4_ID) ++ tmpReg |= HMCD_IPV4_UPDATE_ID; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates ++ & HDR_MANIP_IPV4_SRC) ++ tmpReg |= HMCD_IPV4_UPDATE_SRC; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates ++ & HDR_MANIP_IPV4_DST) ++ tmpReg |= HMCD_IPV4_UPDATE_DST; ++ /* write the first 4 bytes of the descriptor */ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE / 4; ++ ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates ++ & HDR_MANIP_IPV4_ID) ++ { ++ ASSERT_COND(p_TmpData); ++ WRITE_UINT16( ++ *(uint16_t*)p_TmpData, ++ p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.id); ++ WRITE_UINT32( ++ *p_TmpHmct, ++ (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase))); ++ p_TmpData += 2; ++ p_TmpHmct += HMCD_PTR_SIZE / 4; ++ } ++ ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates ++ & HDR_MANIP_IPV4_SRC) ++ { ++ WRITE_UINT32( ++ *p_TmpHmct, ++ p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.src); ++ p_TmpHmct += HMCD_IPV4_ADDR_SIZE / 4; ++ } ++ ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates ++ & HDR_MANIP_IPV4_DST) ++ { ++ WRITE_UINT32( ++ *p_TmpHmct, ++ p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.dst); ++ p_TmpHmct += HMCD_IPV4_ADDR_SIZE / 4; ++ } ++ break; ++ ++ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6): ++ /* set opcode */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_IPV6_UPDATE) << HMCD_OC_SHIFT; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates ++ & HDR_MANIP_IPV6_HL) ++ tmpReg |= HMCD_IPV6_UPDATE_HL; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates ++ & HDR_MANIP_IPV6_TC) ++ { ++ tmpReg |= HMCD_IPV6_UPDATE_TC; ++ tmpReg |= ++ p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.trafficClass ++ << HMCD_IPV6_UPDATE_TC_SHIFT; ++ } ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates ++ & HDR_MANIP_IPV6_SRC) ++ tmpReg |= HMCD_IPV6_UPDATE_SRC; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates ++ & HDR_MANIP_IPV6_DST) ++ tmpReg |= HMCD_IPV6_UPDATE_DST; ++ /* write the first 4 bytes of the descriptor */ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE / 4; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates ++ & HDR_MANIP_IPV6_SRC) ++ { ++ for (i = 0; i < NET_HEADER_FIELD_IPv6_ADDR_SIZE; i += 4) ++ { ++ memcpy(&tmp_ipv6_addr, ++ &p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.src[i], ++ sizeof(uint32_t)); ++ WRITE_UINT32(*p_TmpHmct, tmp_ipv6_addr); ++ p_TmpHmct += HMCD_PTR_SIZE / 4; ++ } ++ } ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates ++ & HDR_MANIP_IPV6_DST) ++ { ++ for (i = 0; i < NET_HEADER_FIELD_IPv6_ADDR_SIZE; i += 4) ++ { ++ memcpy(&tmp_ipv6_addr, ++ &p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.dst[i], ++ sizeof(uint32_t)); ++ WRITE_UINT32(*p_TmpHmct, tmp_ipv6_addr); ++ p_TmpHmct += HMCD_PTR_SIZE / 4; ++ } ++ } ++ break; ++ ++ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP): ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates ++ == HDR_MANIP_TCP_UDP_CHECKSUM) ++ { ++ /* we implement this case with the update-checksum descriptor */ ++ /* set opcode */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_TCP_UDP_CHECKSUM) ++ << HMCD_OC_SHIFT; ++ /* write the first 4 bytes of the descriptor */ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE / 4; ++ } ++ else ++ { ++ /* we implement this case with the TCP/UDP update descriptor */ ++ /* set opcode */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_TCP_UDP_UPDATE) ++ << HMCD_OC_SHIFT; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates ++ & HDR_MANIP_TCP_UDP_DST) ++ tmpReg |= HMCD_TCP_UDP_UPDATE_DST; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates ++ & HDR_MANIP_TCP_UDP_SRC) ++ tmpReg |= HMCD_TCP_UDP_UPDATE_SRC; ++ /* write the first 4 bytes of the descriptor */ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE / 4; ++ ++ tmpReg = 0; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates ++ & HDR_MANIP_TCP_UDP_SRC) ++ tmpReg |= ++ ((uint32_t)p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.src) ++ << HMCD_TCP_UDP_UPDATE_SRC_SHIFT; ++ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates ++ & HDR_MANIP_TCP_UDP_DST) ++ tmpReg |= ++ ((uint32_t)p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.dst); ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ p_TmpHmct += HMCD_PTR_SIZE / 4; ++ } ++ break; ++ ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ++ ("Unknown fieldUpdateParams.type")); ++ } ++ } ++ ++ if (p_FmPcdManipParams->u.hdr.custom) ++ { ++ switch (p_FmPcdManipParams->u.hdr.customParams.type) ++ { ++ case (e_FM_PCD_MANIP_HDR_CUSTOM_IP_REPLACE): ++ /* set opcode */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_REPLACE_IP) << HMCD_OC_SHIFT; ++ ++ if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.decTtlHl) ++ tmpReg |= HMCD_IP_REPLACE_TTL_HL; ++ if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType ++ == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV4_BY_IPV6) ++ /* line commented out as it has no-side-effect ('0' value). */ ++ /*tmpReg |= HMCD_IP_REPLACE_REPLACE_IPV4*/; ++ else ++ if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType ++ == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4) ++ { ++ tmpReg |= HMCD_IP_REPLACE_REPLACE_IPV6; ++ if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.updateIpv4Id) ++ tmpReg |= HMCD_IP_REPLACE_ID; ++ } ++ else ++ RETURN_ERROR( ++ MINOR, ++ E_NOT_SUPPORTED, ++ ("One flag out of HDR_MANIP_IP_REPLACE_IPV4, HDR_MANIP_IP_REPLACE_IPV6 - must be set.")); ++ ++ /* write the first 4 bytes of the descriptor */ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE / 4; ++ ++ size = ++ p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdrSize; ++ ASSERT_COND(p_TmpData); ++ Mem2IOCpy32( ++ p_TmpData, ++ p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdr, ++ size); ++ tmpReg = (uint32_t)(size << HMCD_IP_REPLACE_L3HDRSIZE_SHIFT); ++ tmpReg |= (uint32_t)(XX_VirtToPhys(p_TmpData) ++ - (((t_FmPcd*)h_FmPcd)->physicalMuramBase)); ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ p_TmpHmct += HMCD_PTR_SIZE / 4; ++ p_TmpData += size; ++ ++ if ((p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType ++ == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4) ++ && (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.updateIpv4Id)) ++ { ++ WRITE_UINT16( ++ *(uint16_t*)p_TmpData, ++ p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.id); ++ WRITE_UINT32( ++ *p_TmpHmct, ++ (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase))); ++ p_TmpData += 2; ++ } ++ p_TmpHmct += HMCD_PTR_SIZE / 4; ++ break; ++ case (e_FM_PCD_MANIP_HDR_CUSTOM_GEN_FIELD_REPLACE): ++ /* set opcode */ ++ tmpReg = (uint32_t)(HMCD_OPCODE_GEN_FIELD_REPLACE) << HMCD_OC_SHIFT; ++ tmpReg |= p_FmPcdManipParams->u.hdr.customParams.u.genFieldReplace.size << HMCD_GEN_FIELD_SIZE_SHIFT; ++ tmpReg |= p_FmPcdManipParams->u.hdr.customParams.u.genFieldReplace.srcOffset << HMCD_GEN_FIELD_SRC_OFF_SHIFT; ++ tmpReg |= p_FmPcdManipParams->u.hdr.customParams.u.genFieldReplace.dstOffset << HMCD_GEN_FIELD_DST_OFF_SHIFT; ++ if (p_FmPcdManipParams->u.hdr.customParams.u.genFieldReplace.mask) ++ tmpReg |= HMCD_GEN_FIELD_MASK_EN; ++ ++ /* write the first 4 bytes of the descriptor */ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ /* save a pointer to the "last" indication word */ ++ p_Last = p_TmpHmct; ++ ++ p_TmpHmct += HMCD_BASIC_SIZE/4; ++ ++ if (p_FmPcdManipParams->u.hdr.customParams.u.genFieldReplace.mask) ++ { ++ tmpReg = p_FmPcdManipParams->u.hdr.customParams.u.genFieldReplace.mask << HMCD_GEN_FIELD_MASK_SHIFT; ++ tmpReg |= p_FmPcdManipParams->u.hdr.customParams.u.genFieldReplace.maskOffset << HMCD_GEN_FIELD_MASK_OFF_SHIFT; ++ /* write the next 4 bytes of the descriptor */ ++ WRITE_UINT32(*p_TmpHmct, tmpReg); ++ } ++ p_TmpHmct += HMCD_PARAM_SIZE/4; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ++ ("Unknown customParams.type")); ++ } ++ } ++ ++ /* If this node has a nextManip, and no parsing is required, the old table must be copied to the new table ++ the old table and should be freed */ ++ if (p_FmPcdManipParams->h_NextManip ++ && (p_Manip->nextManipType == e_FM_PCD_MANIP_HDR) ++ && (MANIP_DONT_REPARSE(p_Manip))) ++ { ++ if (new) ++ { ++ /* If this is the first time this manip is created we need to free unused memory. If it ++ * is a dynamic changes case, the memory used is either the CC shadow or the existing ++ * table - no allocation, no free */ ++ MANIP_UPDATE_UNIFIED_POSITION(p_FmPcdManipParams->h_NextManip); ++ ++ p_Manip->unifiedPosition = e_MANIP_UNIFIED_FIRST; ++ } ++ } ++ else ++ { ++ ASSERT_COND(p_Last); ++ /* set the "last" indication on the last command of the current table */ ++ WRITE_UINT32(*p_Last, GET_UINT32(*p_Last) | HMCD_LAST); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error CreateManipActionNew(t_FmPcdManip *p_Manip, ++ t_FmPcdManipParams *p_FmPcdManipParams) ++{ ++ t_FmPcdManip *p_CurManip; ++ t_Error err; ++ uint32_t nextSize = 0, totalSize; ++ uint16_t tmpReg; ++ uint8_t *p_OldHmct, *p_TmpHmctPtr, *p_TmpDataPtr; ++ ++ /* set Manip structure */ ++ ++ p_Manip->dontParseAfterManip = ++ p_FmPcdManipParams->u.hdr.dontParseAfterManip; ++ ++ if (p_FmPcdManipParams->h_NextManip) ++ { /* Next Header manipulation exists */ ++ p_Manip->nextManipType = MANIP_GET_TYPE(p_FmPcdManipParams->h_NextManip); ++ ++ if ((p_Manip->nextManipType == e_FM_PCD_MANIP_HDR) && p_Manip->dontParseAfterManip) ++ nextSize = (uint32_t)(GetHmctSize(p_FmPcdManipParams->h_NextManip) ++ + GetDataSize(p_FmPcdManipParams->h_NextManip)); ++ else /* either parsing is required or next manip is Frag; no table merging. */ ++ p_Manip->cascaded = TRUE; ++ /* pass up the "cascaded" attribute. The whole chain is cascaded ++ * if something is cascaded along the way. */ ++ if (MANIP_IS_CASCADED(p_FmPcdManipParams->h_NextManip)) ++ p_Manip->cascaded = TRUE; ++ } ++ ++ /* Allocate new table */ ++ /* calculate table size according to manip parameters */ ++ err = CalculateTableSize(p_FmPcdManipParams, &p_Manip->tableSize, ++ &p_Manip->dataSize); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ totalSize = (uint16_t)(p_Manip->tableSize + p_Manip->dataSize + nextSize); ++ ++ p_Manip->p_Hmct = (uint8_t*)FM_MURAM_AllocMem( ++ ((t_FmPcd *)p_Manip->h_FmPcd)->h_FmMuram, totalSize, 4); ++ if (!p_Manip->p_Hmct) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc failed")); ++ ++ if (p_Manip->dataSize) ++ p_Manip->p_Data = ++ (uint8_t*)PTR_MOVE(p_Manip->p_Hmct, (p_Manip->tableSize + nextSize)); ++ ++ /* update shadow size to allow runtime replacement of Header manipulation */ ++ /* The allocated shadow is divided as follows: ++ 0 . . . 16 . . . ++ -------------------------------- ++ | Shadow | Shadow HMTD | ++ | HMTD | Match Table | ++ | (16 bytes) | (maximal size) | ++ -------------------------------- ++ */ ++ ++ err = FmPcdUpdateCcShadow(p_Manip->h_FmPcd, (uint32_t)(totalSize + 16), ++ (uint16_t)FM_PCD_CC_AD_TABLE_ALIGN); ++ if (err != E_OK) ++ { ++ FM_MURAM_FreeMem(p_Manip->h_FmPcd, p_Manip->p_Hmct); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("MURAM allocation for HdrManip node shadow")); ++ } ++ ++ if (p_FmPcdManipParams->h_NextManip ++ && (p_Manip->nextManipType == e_FM_PCD_MANIP_HDR) ++ && (MANIP_DONT_REPARSE(p_Manip))) ++ { ++ p_OldHmct = (uint8_t *)GetManipInfo(p_FmPcdManipParams->h_NextManip, ++ e_MANIP_HMCT); ++ p_CurManip = p_FmPcdManipParams->h_NextManip; ++ /* Run till the last Manip (which is the first to configure) */ ++ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip)) ++ p_CurManip = p_CurManip->h_NextManip; ++ ++ while (p_CurManip) ++ { ++ /* If this is a unified table, point to the part of the table ++ * which is the relative offset in HMCT. ++ */ ++ p_TmpHmctPtr = (uint8_t*)PTR_MOVE(p_Manip->p_Hmct, ++ (p_Manip->tableSize + ++ (PTR_TO_UINT(p_CurManip->p_Hmct) - ++ PTR_TO_UINT(p_OldHmct)))); ++ if (p_CurManip->p_Data) ++ p_TmpDataPtr = (uint8_t*)PTR_MOVE(p_Manip->p_Hmct, ++ (p_Manip->tableSize + ++ (PTR_TO_UINT(p_CurManip->p_Data) - ++ PTR_TO_UINT(p_OldHmct)))); ++ else ++ p_TmpDataPtr = NULL; ++ ++ BuildHmct(p_CurManip, &p_CurManip->manipParams, p_TmpHmctPtr, ++ p_TmpDataPtr, FALSE); ++ /* update old manip table pointer */ ++ MANIP_SET_HMCT_PTR(p_CurManip, p_TmpHmctPtr); ++ MANIP_SET_DATA_PTR(p_CurManip, p_TmpDataPtr); ++ ++ p_CurManip = p_CurManip->h_PrevManip; ++ } ++ /* We copied the HMCT to create a new large HMCT so we can free the old one */ ++ FM_MURAM_FreeMem(MANIP_GET_MURAM(p_FmPcdManipParams->h_NextManip), ++ p_OldHmct); ++ } ++ ++ /* Fill table */ ++ err = BuildHmct(p_Manip, p_FmPcdManipParams, p_Manip->p_Hmct, ++ p_Manip->p_Data, TRUE); ++ if (err) ++ { ++ FM_MURAM_FreeMem(p_Manip->h_FmPcd, p_Manip->p_Hmct); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ /* Build HMTD (table descriptor) */ ++ tmpReg = HMTD_CFG_TYPE; /* NADEN = 0 */ ++ ++ /* add parseAfterManip */ ++ if (!p_Manip->dontParseAfterManip) ++ tmpReg |= HMTD_CFG_PRS_AFTER_HM; ++ ++ /* create cascade */ ++ /*if (p_FmPcdManipParams->h_NextManip ++ && (!MANIP_DONT_REPARSE(p_Manip) || (p_Manip->nextManipType != e_FM_PCD_MANIP_HDR)))*/ ++ if (p_Manip->cascaded) ++ { ++ uint16_t nextAd; ++ /* indicate that there's another HM table descriptor */ ++ tmpReg |= HMTD_CFG_NEXT_AD_EN; ++ /* get address of next HMTD (table descriptor; h_Ad). ++ * If the next HMTD was removed due to table unifing, get the address ++ * of the "next next" as written in the h_Ad of the next h_Manip node. ++ */ ++ if (p_Manip->unifiedPosition != e_MANIP_UNIFIED_FIRST) ++ nextAd = (uint16_t)((uint32_t)(XX_VirtToPhys(MANIP_GET_HMTD_PTR(p_FmPcdManipParams->h_NextManip)) - (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase)) >> 4); ++ else ++ nextAd = ((t_Hmtd *)((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad)->nextAdIdx; ++ ++ WRITE_UINT16(((t_Hmtd *)p_Manip->h_Ad)->nextAdIdx, nextAd); ++ } ++ ++ WRITE_UINT16(((t_Hmtd *)p_Manip->h_Ad)->cfg, tmpReg); ++ WRITE_UINT32( ++ ((t_Hmtd *)p_Manip->h_Ad)->hmcdBasePtr, ++ (uint32_t)(XX_VirtToPhys(p_Manip->p_Hmct) - (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase))); ++ ++ WRITE_UINT8(((t_Hmtd *)p_Manip->h_Ad)->opCode, HMAN_OC); ++ ++ if (p_Manip->unifiedPosition == e_MANIP_UNIFIED_FIRST) ++ { ++ /* The HMTD of the next Manip is never going to be used */ ++ if (((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->muramAllocate) ++ FM_MURAM_FreeMem( ++ ((t_FmPcd *)((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_FmPcd)->h_FmMuram, ++ ((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad); ++ else ++ XX_Free(((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad); ++ ((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad = NULL; ++ } ++ ++ return E_OK; ++} ++ ++static t_Error CreateManipActionShadow(t_FmPcdManip *p_Manip, ++ t_FmPcdManipParams *p_FmPcdManipParams) ++{ ++ uint8_t *p_WholeHmct, *p_TmpHmctPtr, newDataSize, *p_TmpDataPtr = NULL; ++ uint16_t newSize; ++ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; ++ t_Error err; ++ t_FmPcdManip *p_CurManip = p_Manip; ++ ++ err = CalculateTableSize(p_FmPcdManipParams, &newSize, &newDataSize); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ /* check coherency of new table parameters */ ++ if (newSize > p_Manip->tableSize) ++ RETURN_ERROR( ++ MINOR, ++ E_INVALID_VALUE, ++ ("New Hdr Manip configuration requires larger size than current one (command table).")); ++ if (newDataSize > p_Manip->dataSize) ++ RETURN_ERROR( ++ MINOR, ++ E_INVALID_VALUE, ++ ("New Hdr Manip configuration requires larger size than current one (data).")); ++ if (p_FmPcdManipParams->h_NextManip) ++ RETURN_ERROR( ++ MINOR, E_INVALID_VALUE, ++ ("New Hdr Manip configuration can not contain h_NextManip.")); ++ if (MANIP_IS_UNIFIED(p_Manip) && (newSize != p_Manip->tableSize)) ++ RETURN_ERROR( ++ MINOR, ++ E_INVALID_VALUE, ++ ("New Hdr Manip configuration in a chained manipulation requires different size than current one.")); ++ if (p_Manip->dontParseAfterManip ++ != p_FmPcdManipParams->u.hdr.dontParseAfterManip) ++ RETURN_ERROR( ++ MINOR, ++ E_INVALID_VALUE, ++ ("New Hdr Manip configuration differs in dontParseAfterManip value.")); ++ ++ p_Manip->tableSize = newSize; ++ p_Manip->dataSize = newDataSize; ++ ++ /* Build the new table in the shadow */ ++ if (!MANIP_IS_UNIFIED(p_Manip)) ++ { ++ p_TmpHmctPtr = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow, 16); ++ if (p_Manip->p_Data) ++ p_TmpDataPtr = ++ (uint8_t*)PTR_MOVE(p_TmpHmctPtr, ++ (PTR_TO_UINT(p_Manip->p_Data) - PTR_TO_UINT(p_Manip->p_Hmct))); ++ ++ BuildHmct(p_Manip, p_FmPcdManipParams, p_TmpHmctPtr, p_Manip->p_Data, ++ FALSE); ++ } ++ else ++ { ++ p_WholeHmct = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMCT); ++ ASSERT_COND(p_WholeHmct); ++ ++ /* Run till the last Manip (which is the first to configure) */ ++ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip)) ++ p_CurManip = p_CurManip->h_NextManip; ++ ++ while (p_CurManip) ++ { ++ /* If this is a non-head node in a unified table, point to the part of the shadow ++ * which is the relative offset in HMCT. ++ * else, point to the beginning of the ++ * shadow table (we save 16 for the HMTD. ++ */ ++ p_TmpHmctPtr = ++ (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow, ++ (16 + PTR_TO_UINT(p_CurManip->p_Hmct) - PTR_TO_UINT(p_WholeHmct))); ++ if (p_CurManip->p_Data) ++ p_TmpDataPtr = ++ (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow, ++ (16 + PTR_TO_UINT(p_CurManip->p_Data) - PTR_TO_UINT(p_WholeHmct))); ++ ++ BuildHmct(p_CurManip, &p_CurManip->manipParams, p_TmpHmctPtr, ++ p_TmpDataPtr, FALSE); ++ p_CurManip = p_CurManip->h_PrevManip; ++ } ++ } ++ ++ return E_OK; ++} ++ ++static t_Error CreateManipActionBackToOrig( ++ t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams) ++{ ++ uint8_t *p_WholeHmct = NULL, *p_TmpHmctPtr, *p_TmpDataPtr; ++ t_FmPcdManip *p_CurManip = p_Manip; ++ ++ /* Build the new table in the shadow */ ++ if (!MANIP_IS_UNIFIED(p_Manip)) ++ BuildHmct(p_Manip, p_FmPcdManipParams, p_Manip->p_Hmct, p_Manip->p_Data, ++ FALSE); ++ else ++ { ++ p_WholeHmct = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMCT); ++ ASSERT_COND(p_WholeHmct); ++ ++ /* Run till the last Manip (which is the first to configure) */ ++ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip)) ++ p_CurManip = p_CurManip->h_NextManip; ++ ++ while (p_CurManip) ++ { ++ /* If this is a unified table, point to the part of the table ++ * which is the relative offset in HMCT. ++ */ ++ p_TmpHmctPtr = p_CurManip->p_Hmct; /*- (uint32_t)p_WholeHmct*/ ++ p_TmpDataPtr = p_CurManip->p_Data; /*- (uint32_t)p_WholeHmct*/ ++ ++ BuildHmct(p_CurManip, &p_CurManip->manipParams, p_TmpHmctPtr, ++ p_TmpDataPtr, FALSE); ++ ++ p_CurManip = p_CurManip->h_PrevManip; ++ } ++ } ++ ++ return E_OK; ++} ++ ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++static t_Error UpdateManipIc(t_Handle h_Manip, uint8_t icOffset) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ t_Handle p_Ad; ++ uint32_t tmpReg32 = 0; ++ SANITY_CHECK_RETURN_ERROR(h_Manip, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad, E_INVALID_HANDLE); ++ ++ switch (p_Manip->opcode) ++ { ++ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ if (p_Manip->updateParams & INTERNAL_CONTEXT_OFFSET) ++ { ++ tmpReg32 = ++ *(uint32_t *)&((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets; ++ tmpReg32 |= (uint32_t)((uint32_t)icOffset << 16); ++ *(uint32_t *)&((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets = ++ tmpReg32; ++ p_Manip->updateParams &= ~INTERNAL_CONTEXT_OFFSET; ++ p_Manip->icOffset = icOffset; ++ } ++ else ++ { ++ if (p_Manip->icOffset != icOffset) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("this manipulation was updated previously by different value");); ++ } ++ break; ++ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): ++ if (p_Manip->h_Frag) ++ { ++ if (p_Manip->updateParams & INTERNAL_CONTEXT_OFFSET) ++ { ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ tmpReg32 |= GET_UINT32(((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets); ++ tmpReg32 |= (uint32_t)((uint32_t)icOffset << 16); ++ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets, tmpReg32); ++ p_Manip->updateParams &= ~INTERNAL_CONTEXT_OFFSET; ++ p_Manip->icOffset = icOffset; ++ } ++ else ++ { ++ if (p_Manip->icOffset != icOffset) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("this manipulation was updated previousely by different value");); ++ } ++ } ++ break; ++ } ++ ++ return E_OK; ++} ++ ++static t_Error UpdateInitMvIntFrameHeaderFromFrameToBufferPrefix( ++ t_Handle h_FmPort, t_FmPcdManip *p_Manip, t_Handle h_Ad, bool validate) ++{ ++ ++ t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)h_Ad; ++ t_FmPortGetSetCcParams fmPortGetSetCcParams; ++ t_Error err; ++ uint32_t tmpReg32; ++ ++ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams)); ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR( ++ (p_Manip->opcode & HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX), ++ E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_Manip->muramAllocate, E_INVALID_STATE); ++ ++ if (p_Manip->updateParams) ++ { ++ if ((!(p_Manip->updateParams & OFFSET_OF_PR)) ++ || (p_Manip->shadowUpdateParams & OFFSET_OF_PR)) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_STATE, ++ ("in this stage parameters from Port has not be updated")); ++ ++ fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams; ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_PSO; ++ fmPortGetSetCcParams.setCcParams.psoSize = 16; ++ ++ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_STATE, ++ ("Parser result offset wasn't configured previousely")); ++#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 ++ ASSERT_COND(!(fmPortGetSetCcParams.getCcParams.prOffset % 16)); ++#endif ++ } ++ else ++ if (validate) ++ { ++ if ((!(p_Manip->shadowUpdateParams & OFFSET_OF_PR)) ++ || (p_Manip->updateParams & OFFSET_OF_PR)) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_STATE, ++ ("in this stage parameters from Port has be updated")); ++ fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams; ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_PSO; ++ fmPortGetSetCcParams.setCcParams.psoSize = 16; ++ ++ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_STATE, ++ ("Parser result offset wasn't configured previousely")); ++ ++ } ++ ++ ASSERT_COND(p_Ad); ++ ++ if (p_Manip->updateParams & OFFSET_OF_PR) ++ { ++ tmpReg32 = 0; ++ tmpReg32 |= fmPortGetSetCcParams.getCcParams.prOffset; ++ WRITE_UINT32(p_Ad->matchTblPtr, ++ (GET_UINT32(p_Ad->matchTblPtr) | tmpReg32)); ++ p_Manip->updateParams &= ~OFFSET_OF_PR; ++ p_Manip->shadowUpdateParams |= OFFSET_OF_PR; ++ } ++ else ++ if (validate) ++ { ++ tmpReg32 = GET_UINT32(p_Ad->matchTblPtr); ++ if ((uint8_t)tmpReg32 != fmPortGetSetCcParams.getCcParams.prOffset) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("this manipulation was updated previousely by different value");); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error UpdateModifyCapwapFragmenation(t_FmPcdManip *p_Manip, t_Handle h_Ad, bool validate,t_Handle h_FmTree) ++{ ++ t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)h_Ad; ++ t_FmPcdCcSavedManipParams *p_SavedManipParams = NULL; ++ uint32_t tmpReg32 = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Frag,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->frag,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(((p_Manip->opcode == HMAN_OC_CAPWAP_FRAGMENTATION) || (p_Manip->opcode == HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER)), E_INVALID_STATE); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Frag; ++ ++ if (p_Manip->updateParams) ++ { ++ ++ if ((!(p_Manip->updateParams & OFFSET_OF_DATA)) || ++ ((p_Manip->shadowUpdateParams & OFFSET_OF_DATA))) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated")); ++ p_SavedManipParams = FmPcdCcTreeGetSavedManipParams(h_FmTree); ++ if (!p_SavedManipParams) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("for this manipulation tree has to be configured previosely with this type")); ++ p_Manip->capwapFragParams.dataOffset = p_SavedManipParams->capwapParams.dataOffset; ++ ++ tmpReg32 = GET_UINT32(p_Ad->pcAndOffsets); ++ tmpReg32 |= ((uint32_t)p_Manip->capwapFragParams.dataOffset<< 16); ++ WRITE_UINT32(p_Ad->pcAndOffsets,tmpReg32); ++ ++ p_Manip->updateParams &= ~OFFSET_OF_DATA; ++ p_Manip->shadowUpdateParams |= OFFSET_OF_DATA; ++ } ++ else if (validate) ++ { ++ ++ p_SavedManipParams = FmPcdCcTreeGetSavedManipParams(h_FmTree); ++ if (!p_SavedManipParams) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("for this manipulation tree has to be configured previosely with this type")); ++ if (p_Manip->capwapFragParams.dataOffset != p_SavedManipParams->capwapParams.dataOffset) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("this manipulation was updated previousely by different value")); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error UpdateInitCapwapFragmentation(t_Handle h_FmPort, ++ t_FmPcdManip *p_Manip, ++ t_Handle h_Ad, ++ bool validate, ++ t_Handle h_FmTree) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ t_FmPortGetSetCcParams fmPortGetSetCcParams; ++ t_Error err; ++ uint32_t tmpReg32 = 0; ++ t_FmPcdCcSavedManipParams *p_SavedManipParams; ++ ++ UNUSED(h_Ad); ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Frag,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->frag,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(((p_Manip->opcode == HMAN_OC_CAPWAP_FRAGMENTATION) || ++ (p_Manip->opcode == HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER)), E_INVALID_STATE); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Frag; ++ ++ if (p_Manip->updateParams) ++ { ++ if ((!(p_Manip->updateParams & OFFSET_OF_DATA)) || ++ ((p_Manip->shadowUpdateParams & OFFSET_OF_DATA))) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated")); ++ fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams; ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN | UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY; ++ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_POP_TO_N_STEP | NIA_ENG_FM_CTL; ++ /* For CAPWAP Rassembly used FMAN_CTRL2 hardcoded - so for fragmentation its better to use FMAN_CTRL1 */ ++ fmPortGetSetCcParams.setCcParams.orFmanCtrl = FPM_PORT_FM_CTL1; ++ ++ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Data offset wasn't configured previousely")); ++ ++ p_SavedManipParams = (t_FmPcdCcSavedManipParams *)XX_Malloc(sizeof(t_FmPcdCcSavedManipParams)); ++ p_SavedManipParams->capwapParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset; ++ ++#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 ++ ASSERT_COND(!(p_SavedManipParams->capwapParams.dataOffset % 16)); ++#endif /* FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 */ ++ ++ FmPcdCcTreeSetSavedManipParams(h_FmTree, (t_Handle)p_SavedManipParams); ++ } ++ else if (validate) ++ { ++ if ((!(p_Manip->shadowUpdateParams & OFFSET_OF_DATA)) || ++ ((p_Manip->updateParams & OFFSET_OF_DATA))) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated")); ++ fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams; ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN | UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY; ++ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_POP_TO_N_STEP | NIA_ENG_FM_CTL; ++ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Data offset wasn't configured previousely")); ++ } ++ ++ if (p_Manip->updateParams) ++ { ++ tmpReg32 = GET_UINT32(p_Ad->pcAndOffsets); ++ tmpReg32 |= ((uint32_t)fmPortGetSetCcParams.getCcParams.dataOffset<< 16); ++ WRITE_UINT32(p_Ad->pcAndOffsets,tmpReg32); ++ ++ p_Manip->updateParams &= ~OFFSET_OF_DATA; ++ p_Manip->shadowUpdateParams |= OFFSET_OF_DATA; ++ p_Manip->capwapFragParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset; ++ } ++ else if (validate) ++ { ++ if (p_Manip->capwapFragParams.dataOffset != fmPortGetSetCcParams.getCcParams.dataOffset) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("this manipulation was updated previousely by different value")); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error UpdateInitCapwapReasm(t_Handle h_FmPcd, ++ t_Handle h_FmPort, ++ t_FmPcdManip *p_Manip, ++ t_Handle h_Ad, ++ bool validate) ++{ ++ t_CapwapReasmPram *p_ReassmTbl; ++ t_Error err; ++ t_FmPortGetSetCcParams fmPortGetSetCcParams; ++ uint8_t i = 0; ++ uint16_t size; ++ uint32_t tmpReg32; ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_FmPcdCcCapwapReassmTimeoutParams ccCapwapReassmTimeoutParams; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Frag,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Manip->frag,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Manip->opcode == HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST), E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc,E_INVALID_HANDLE); ++ ++ if (p_Manip->h_FmPcd != h_FmPcd) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("handler of PCD previously was initiated by different value")); ++ ++ UNUSED(h_Ad); ++ ++ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams)); ++ p_ReassmTbl = (t_CapwapReasmPram *)p_Manip->h_Frag; ++ ++ if (p_Manip->updateParams) ++ { ++ if ((!(p_Manip->updateParams & NUM_OF_TASKS) && ++ !(p_Manip->updateParams & OFFSET_OF_DATA) && ++ !(p_Manip->updateParams & OFFSET_OF_PR) && ++ !(p_Manip->updateParams & HW_PORT_ID)) || ++ ((p_Manip->shadowUpdateParams & NUM_OF_TASKS) || ++ (p_Manip->shadowUpdateParams & OFFSET_OF_DATA) || (p_Manip->shadowUpdateParams & OFFSET_OF_PR) || ++ (p_Manip->shadowUpdateParams & HW_PORT_ID))) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated")); ++ ++ fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams; ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN; ++ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_POP_TO_N_STEP | NIA_ENG_FM_CTL; ++ ++ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (fmPortGetSetCcParams.getCcParams.type & NUM_OF_TASKS) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Num of tasks wasn't configured previousely")); ++ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previousely")); ++ if (fmPortGetSetCcParams.getCcParams.type & HW_PORT_ID) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("hwPortId wasn't updated")); ++#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 ++ ASSERT_COND((fmPortGetSetCcParams.getCcParams.dataOffset % 16) == 0); ++#endif /* FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 */ ++ } ++ else if (validate) ++ { ++ if ((!(p_Manip->shadowUpdateParams & NUM_OF_TASKS) && ++ !(p_Manip->shadowUpdateParams & OFFSET_OF_DATA) && ++ !(p_Manip->shadowUpdateParams & OFFSET_OF_PR) && ++ !(p_Manip->shadowUpdateParams & HW_PORT_ID)) && ++ ((p_Manip->updateParams & NUM_OF_TASKS) || ++ (p_Manip->updateParams & OFFSET_OF_DATA) || (p_Manip->updateParams & OFFSET_OF_PR) || ++ (p_Manip->updateParams & HW_PORT_ID))) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated")); ++ ++ fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams; ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN; ++ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_POP_TO_N_STEP | NIA_ENG_FM_CTL; ++ ++ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (fmPortGetSetCcParams.getCcParams.type & NUM_OF_TASKS) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("NumOfTasks wasn't configured previously")); ++ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previously")); ++ if (fmPortGetSetCcParams.getCcParams.type & HW_PORT_ID) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("hwPortId wasn't updated")); ++ } ++ ++ if (p_Manip->updateParams) ++ { ++ if (p_Manip->updateParams & NUM_OF_TASKS) ++ { ++ /*recommendation of Microcode team - (maxNumFramesInProcess * 2) */ ++ size = (uint16_t)(p_Manip->capwapFragParams.maxNumFramesInProcess*2 + fmPortGetSetCcParams.getCcParams.numOfTasks); ++ if (size > 255) ++ RETURN_ERROR(MAJOR,E_INVALID_VALUE, ("numOfOpenReassmEntries + numOfTasks per port can not be greater than 256")); ++ ++ p_Manip->capwapFragParams.numOfTasks = fmPortGetSetCcParams.getCcParams.numOfTasks; ++ ++ /*p_ReassmFrmDescrIndxPoolTbl*/ ++ p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl = ++ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ (uint32_t)(size + 1), ++ 4); ++ if (!p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly frame buffer index pool table")); ++ ++ IOMemSet32(p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl, 0, (uint32_t)(size + 1)); ++ ++ for ( i = 0; i < size; i++) ++ WRITE_UINT8(*(uint8_t *)PTR_MOVE(p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl, i), (uint8_t)(i+1)); ++ ++ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl) - p_FmPcd->physicalMuramBase); ++ ++ WRITE_UINT32(p_ReassmTbl->reasmFrmDescIndexPoolTblPtr, tmpReg32); ++ ++ /*p_ReassmFrmDescrPoolTbl*/ ++ p_Manip->capwapFragParams.p_ReassmFrmDescrPoolTbl = ++ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ (uint32_t)((size + 1) * FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE), ++ 4); ++ ++ if (!p_Manip->capwapFragParams.p_ReassmFrmDescrPoolTbl) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly frame buffer pool table")); ++ ++ IOMemSet32(p_Manip->capwapFragParams.p_ReassmFrmDescrPoolTbl, 0, (uint32_t)((size +1)* FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE)); ++ ++ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->capwapFragParams.p_ReassmFrmDescrPoolTbl) - p_FmPcd->physicalMuramBase); ++ ++ WRITE_UINT32(p_ReassmTbl->reasmFrmDescPoolTblPtr, tmpReg32); ++ ++ /*p_TimeOutTbl*/ ++ ++ p_Manip->capwapFragParams.p_TimeOutTbl = ++ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ (uint32_t)((size + 1)* FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE), ++ 4); ++ ++ if (!p_Manip->capwapFragParams.p_TimeOutTbl) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly timeout table")); ++ ++ IOMemSet32(p_Manip->capwapFragParams.p_TimeOutTbl, 0, (uint16_t)((size + 1)*FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE)); ++ ++ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->capwapFragParams.p_TimeOutTbl) - p_FmPcd->physicalMuramBase); ++ WRITE_UINT32(p_ReassmTbl->timeOutTblPtr, tmpReg32); ++ ++ p_Manip->updateParams &= ~NUM_OF_TASKS; ++ p_Manip->shadowUpdateParams |= NUM_OF_TASKS; ++ } ++ ++ if (p_Manip->updateParams & OFFSET_OF_DATA) ++ { ++ p_Manip->capwapFragParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset; ++ tmpReg32 = GET_UINT32(p_ReassmTbl->mode); ++ tmpReg32|= p_Manip->capwapFragParams.dataOffset; ++ WRITE_UINT32(p_ReassmTbl->mode, tmpReg32); ++ p_Manip->updateParams &= ~OFFSET_OF_DATA; ++ p_Manip->shadowUpdateParams |= OFFSET_OF_DATA; ++ } ++ ++ if (!(fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR)) ++ { ++ p_Manip->capwapFragParams.prOffset = fmPortGetSetCcParams.getCcParams.prOffset; ++ ++ tmpReg32 = GET_UINT32(p_ReassmTbl->mode); ++ tmpReg32|= FM_PCD_MANIP_CAPWAP_REASM_PR_COPY; ++ WRITE_UINT32(p_ReassmTbl->mode, tmpReg32); ++ ++ tmpReg32 = GET_UINT32(p_ReassmTbl->intStatsTblPtr); ++ tmpReg32 |= (uint32_t)p_Manip->capwapFragParams.prOffset << 24; ++ WRITE_UINT32(p_ReassmTbl->intStatsTblPtr, tmpReg32); ++ p_Manip->updateParams &= ~OFFSET_OF_PR; ++ p_Manip->shadowUpdateParams |= OFFSET_OF_PR; ++ } ++ else ++ { ++ p_Manip->capwapFragParams.prOffset = 0xff; ++ p_Manip->updateParams &= ~OFFSET_OF_PR; ++ p_Manip->shadowUpdateParams |= OFFSET_OF_PR; ++ } ++ ++ p_Manip->capwapFragParams.hwPortId = fmPortGetSetCcParams.getCcParams.hardwarePortId; ++ p_Manip->updateParams &= ~HW_PORT_ID; ++ p_Manip->shadowUpdateParams |= HW_PORT_ID; ++ ++ /*timeout hc */ ++ ccCapwapReassmTimeoutParams.fqidForTimeOutFrames = p_Manip->capwapFragParams.fqidForTimeOutFrames; ++ ccCapwapReassmTimeoutParams.portIdAndCapwapReassmTbl = (uint32_t)p_Manip->capwapFragParams.hwPortId << 24; ++ ccCapwapReassmTimeoutParams.portIdAndCapwapReassmTbl |= (uint32_t)((XX_VirtToPhys(p_ReassmTbl) - p_FmPcd->physicalMuramBase)); ++ ccCapwapReassmTimeoutParams.timeoutRequestTime = (((uint32_t)1<capwapFragParams.bitFor1Micro) * p_Manip->capwapFragParams.timeoutRoutineRequestTime)/2; ++ return FmHcPcdCcCapwapTimeoutReassm(p_FmPcd->h_Hc,&ccCapwapReassmTimeoutParams); ++ } ++ ++ else if (validate) ++ { ++ if (fmPortGetSetCcParams.getCcParams.hardwarePortId != p_Manip->capwapFragParams.hwPortId) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Reassembly manipulation previously was assigned to another port")); ++ if (fmPortGetSetCcParams.getCcParams.numOfTasks != p_Manip->capwapFragParams.numOfTasks) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfTasks for this manipulation previously was defined by another value ")); ++ ++ if (!(fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR)) ++ { ++ if (p_Manip->capwapFragParams.prOffset != fmPortGetSetCcParams.getCcParams.prOffset) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Parse result offset previously was defined by another value ")); ++ } ++ else ++ { ++ if (p_Manip->capwapFragParams.prOffset != 0xff) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Parse result offset previously was defined by another value ")); ++ } ++ if (fmPortGetSetCcParams.getCcParams.dataOffset != p_Manip->capwapFragParams.dataOffset) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Data offset previously was defined by another value ")); ++ } ++ ++ return E_OK; ++} ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ ++t_Error FmPcdRegisterReassmPort(t_Handle h_FmPcd, t_Handle h_ReasmCommonPramTbl) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdCcReassmTimeoutParams ccReassmTimeoutParams = { 0 }; ++ t_Error err = E_OK; ++ uint8_t result; ++ uint32_t bitFor1Micro, tsbs, log2num; ++ ++ ASSERT_COND(p_FmPcd); ++ ASSERT_COND(h_ReasmCommonPramTbl); ++ ++ bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm); ++ if (bitFor1Micro == 0) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Timestamp scale")); ++ ++ bitFor1Micro = 32 - bitFor1Micro; ++ LOG2(FM_PCD_MANIP_REASM_TIMEOUT_THREAD_THRESH, log2num); ++ tsbs = bitFor1Micro - log2num; ++ ++ ccReassmTimeoutParams.iprcpt = (uint32_t)(XX_VirtToPhys( ++ h_ReasmCommonPramTbl) - p_FmPcd->physicalMuramBase); ++ ccReassmTimeoutParams.tsbs = (uint8_t)tsbs; ++ ccReassmTimeoutParams.activate = TRUE; ++ if ((err = FmHcPcdCcTimeoutReassm(p_FmPcd->h_Hc, &ccReassmTimeoutParams, ++ &result)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ switch (result) ++ { ++ case (0): ++ return E_OK; ++ case (1): ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("failed to allocate TNUM")); ++ case (2): ++ RETURN_ERROR( ++ MAJOR, E_NO_MEMORY, ++ ("failed to allocate internal buffer from the HC-Port")); ++ case (3): ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("'Disable Timeout Task' with invalid IPRCPT")); ++ case (4): ++ RETURN_ERROR(MAJOR, E_FULL, ("too many timeout tasks")); ++ case (5): ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("invalid sub command")); ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ } ++ return E_OK; ++} ++ ++static t_Error CreateReassCommonTable(t_FmPcdManip *p_Manip) ++{ ++ uint32_t tmpReg32 = 0, i, bitFor1Micro; ++ uint64_t tmpReg64, size; ++ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; ++ t_Error err = E_OK; ++ ++ bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm); ++ if (bitFor1Micro == 0) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Timestamp scale")); ++ ++ /* Allocation of the Reassembly Common Parameters table. This table is located in the ++ MURAM. Its size is 64 bytes and its base address should be 8-byte aligned. */ ++ p_Manip->reassmParams.p_ReassCommonTbl = ++ (t_ReassCommonTbl *)FM_MURAM_AllocMem( ++ p_FmPcd->h_FmMuram, ++ FM_PCD_MANIP_REASM_COMMON_PARAM_TABLE_SIZE, ++ FM_PCD_MANIP_REASM_COMMON_PARAM_TABLE_ALIGN); ++ ++ if (!p_Manip->reassmParams.p_ReassCommonTbl) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("MURAM alloc for Reassembly common parameters table")); ++ ++ IOMemSet32(p_Manip->reassmParams.p_ReassCommonTbl, 0, ++ FM_PCD_MANIP_REASM_COMMON_PARAM_TABLE_SIZE); ++ ++ /* Setting the TimeOut Mode.*/ ++ tmpReg32 = 0; ++ if (p_Manip->reassmParams.timeOutMode ++ == e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAMES) ++ tmpReg32 |= FM_PCD_MANIP_REASM_TIME_OUT_BETWEEN_FRAMES; ++ ++ /* Setting TimeOut FQID - Frames that time out are enqueued to this FQID. ++ In order to cause TimeOut frames to be discarded, this queue should be configured accordingly*/ ++ tmpReg32 |= p_Manip->reassmParams.fqidForTimeOutFrames; ++ WRITE_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->timeoutModeAndFqid, ++ tmpReg32); ++ ++ /* Calculation the size of IP Reassembly Frame Descriptor - number of frames that are allowed to be reassembled simultaneously + 129.*/ ++ size = p_Manip->reassmParams.maxNumFramesInProcess + 129; ++ ++ /*Allocation of IP Reassembly Frame Descriptor Indexes Pool - This pool resides in the MURAM */ ++ p_Manip->reassmParams.reassFrmDescrIndxPoolTblAddr = ++ PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ (uint32_t)(size * 2), ++ 256)); ++ if (!p_Manip->reassmParams.reassFrmDescrIndxPoolTblAddr) ++ RETURN_ERROR( ++ MAJOR, E_NO_MEMORY, ++ ("MURAM alloc for Reassembly frame descriptor indexes pool")); ++ ++ IOMemSet32(UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrIndxPoolTblAddr), ++ 0, (uint32_t)(size * 2)); ++ ++ /* The entries in IP Reassembly Frame Descriptor Indexes Pool contains indexes starting with 1 up to ++ the maximum number of frames that are allowed to be reassembled simultaneously + 128. ++ The last entry in this pool must contain the index zero*/ ++ for (i = 0; i < (size - 1); i++) ++ WRITE_UINT16( ++ *(uint16_t *)PTR_MOVE(UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrIndxPoolTblAddr), (i<<1)), ++ (uint16_t)(i+1)); ++ ++ /* Sets the IP Reassembly Frame Descriptor Indexes Pool offset from MURAM */ ++ tmpReg32 = (uint32_t)(XX_VirtToPhys( ++ UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrIndxPoolTblAddr)) ++ - p_FmPcd->physicalMuramBase); ++ WRITE_UINT32( ++ p_Manip->reassmParams.p_ReassCommonTbl->reassFrmDescIndexPoolTblPtr, ++ tmpReg32); ++ ++ /* Allocation of the Reassembly Frame Descriptors Pool - This pool resides in external memory. ++ The number of entries in this pool should be equal to the number of entries in IP Reassembly Frame Descriptor Indexes Pool.*/ ++ p_Manip->reassmParams.reassFrmDescrPoolTblAddr = ++ PTR_TO_UINT(XX_MallocSmart((uint32_t)(size * 64), p_Manip->reassmParams.dataMemId, 64)); ++ ++ if (!p_Manip->reassmParams.reassFrmDescrPoolTblAddr) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED")); ++ ++ IOMemSet32(UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrPoolTblAddr), 0, ++ (uint32_t)(size * 64)); ++ ++ /* Sets the Reassembly Frame Descriptors Pool and liodn offset*/ ++ tmpReg64 = (uint64_t)(XX_VirtToPhys( ++ UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrPoolTblAddr))); ++ tmpReg64 |= ((uint64_t)(p_Manip->reassmParams.dataLiodnOffset ++ & FM_PCD_MANIP_REASM_LIODN_MASK) ++ << (uint64_t)FM_PCD_MANIP_REASM_LIODN_SHIFT); ++ tmpReg64 |= ((uint64_t)(p_Manip->reassmParams.dataLiodnOffset ++ & FM_PCD_MANIP_REASM_ELIODN_MASK) ++ << (uint64_t)FM_PCD_MANIP_REASM_ELIODN_SHIFT); ++ WRITE_UINT32( ++ p_Manip->reassmParams.p_ReassCommonTbl->liodnAndReassFrmDescPoolPtrHi, ++ (uint32_t)(tmpReg64 >> 32)); ++ WRITE_UINT32( ++ p_Manip->reassmParams.p_ReassCommonTbl->reassFrmDescPoolPtrLow, ++ (uint32_t)tmpReg64); ++ ++ /*Allocation of the TimeOut table - This table resides in the MURAM. ++ The number of entries in this table is identical to the number of entries in the Reassembly Frame Descriptors Pool*/ ++ p_Manip->reassmParams.timeOutTblAddr = ++ PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, (uint32_t)(size * 8),8)); ++ ++ if (!p_Manip->reassmParams.timeOutTblAddr) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("MURAM alloc for Reassembly timeout table")); ++ ++ IOMemSet32(UINT_TO_PTR(p_Manip->reassmParams.timeOutTblAddr), 0, ++ (uint16_t)(size * 8)); ++ ++ /* Sets the TimeOut table offset from MURAM */ ++ tmpReg32 = (uint32_t)(XX_VirtToPhys( ++ UINT_TO_PTR(p_Manip->reassmParams.timeOutTblAddr)) ++ - p_FmPcd->physicalMuramBase); ++ WRITE_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->timeOutTblPtr, ++ tmpReg32); ++ ++ /* Sets the Expiration Delay */ ++ tmpReg32 = 0; ++ tmpReg32 |= (((uint32_t)(1 << bitFor1Micro)) ++ * p_Manip->reassmParams.timeoutThresholdForReassmProcess); ++ WRITE_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->expirationDelay, ++ tmpReg32); ++ ++ err = FmPcdRegisterReassmPort(p_FmPcd, ++ p_Manip->reassmParams.p_ReassCommonTbl); ++ if (err != E_OK) ++ { ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, ++ p_Manip->reassmParams.p_ReassCommonTbl); ++ RETURN_ERROR(MAJOR, err, ("port registration")); ++ } ++ ++ return err; ++} ++ ++static t_Error CreateReassTable(t_FmPcdManip *p_Manip, e_NetHeaderType hdr) ++{ ++ t_FmPcd *p_FmPcd = p_Manip->h_FmPcd; ++ uint32_t tmpReg32, autoLearnHashTblSize; ++ uint32_t numOfWays, setSize, setSizeCode, keySize; ++ uint32_t waySize, numOfSets, numOfEntries; ++ uint64_t tmpReg64; ++ uint16_t minFragSize; ++ uint16_t maxReassemSize; ++ uintptr_t *p_AutoLearnHashTblAddr, *p_AutoLearnSetLockTblAddr; ++ t_ReassTbl **p_ReassTbl; ++ ++ switch (hdr) ++ { ++ case HEADER_TYPE_IPv4: ++ p_ReassTbl = &p_Manip->reassmParams.ip.p_Ipv4ReassTbl; ++ p_AutoLearnHashTblAddr = ++ &p_Manip->reassmParams.ip.ipv4AutoLearnHashTblAddr; ++ p_AutoLearnSetLockTblAddr = ++ &p_Manip->reassmParams.ip.ipv4AutoLearnSetLockTblAddr; ++ minFragSize = p_Manip->reassmParams.ip.minFragSize[0]; ++ maxReassemSize = 0; ++ numOfWays = p_Manip->reassmParams.ip.numOfFramesPerHashEntry[0]; ++ keySize = 4 + 4 + 1 + 2; /* 3-tuple + IP-Id */ ++ break; ++ case HEADER_TYPE_IPv6: ++ p_ReassTbl = &p_Manip->reassmParams.ip.p_Ipv6ReassTbl; ++ p_AutoLearnHashTblAddr = ++ &p_Manip->reassmParams.ip.ipv6AutoLearnHashTblAddr; ++ p_AutoLearnSetLockTblAddr = ++ &p_Manip->reassmParams.ip.ipv6AutoLearnSetLockTblAddr; ++ minFragSize = p_Manip->reassmParams.ip.minFragSize[1]; ++ maxReassemSize = 0; ++ numOfWays = p_Manip->reassmParams.ip.numOfFramesPerHashEntry[1]; ++ keySize = 16 + 16 + 4; /* 2-tuple + IP-Id */ ++ if (numOfWays > e_FM_PCD_MANIP_SIX_WAYS_HASH) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("num of ways")); ++ break; ++ case HEADER_TYPE_CAPWAP: ++ p_ReassTbl = &p_Manip->reassmParams.capwap.p_ReassTbl; ++ p_AutoLearnHashTblAddr = ++ &p_Manip->reassmParams.capwap.autoLearnHashTblAddr; ++ p_AutoLearnSetLockTblAddr = ++ &p_Manip->reassmParams.capwap.autoLearnSetLockTblAddr; ++ minFragSize = 0; ++ maxReassemSize = p_Manip->reassmParams.capwap.maxRessembledsSize; ++ numOfWays = p_Manip->reassmParams.capwap.numOfFramesPerHashEntry; ++ keySize = 4; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("header type")); ++ } ++ keySize += 2; /* 2 bytes reserved for RFDIndex */ ++#if (DPAA_VERSION >= 11) ++ keySize += 2; /* 2 bytes reserved */ ++#endif /* (DPAA_VERSION >= 11) */ ++ waySize = ROUND_UP(keySize, 8); ++ ++ /* Allocates the Reassembly Parameters Table - This table is located in the MURAM.*/ ++ *p_ReassTbl = (t_ReassTbl *)FM_MURAM_AllocMem( ++ p_FmPcd->h_FmMuram, FM_PCD_MANIP_REASM_TABLE_SIZE, ++ FM_PCD_MANIP_REASM_TABLE_ALIGN); ++ if (!*p_ReassTbl) ++ RETURN_ERROR( MAJOR, E_NO_MEMORY, ++ ("MURAM alloc for Reassembly specific parameters table")); ++ memset(*p_ReassTbl, 0, sizeof(t_ReassTbl)); ++ ++ /* Sets the Reassembly common Parameters table offset from MURAM in the Reassembly Table descriptor*/ ++ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->reassmParams.p_ReassCommonTbl) ++ - p_FmPcd->physicalMuramBase); ++ WRITE_UINT32((*p_ReassTbl)->reassCommonPrmTblPtr, tmpReg32); ++ ++ /* Calculate set size (set size is rounded-up to next power of 2) */ ++ NEXT_POWER_OF_2(numOfWays * waySize, setSize); ++ ++ /* Get set size code */ ++ LOG2(setSize, setSizeCode); ++ ++ /* Sets ways number and set size code */ ++ WRITE_UINT16((*p_ReassTbl)->waysNumAndSetSize, ++ (uint16_t)((numOfWays << 8) | setSizeCode)); ++ ++ /* It is recommended that the total number of entries in this table ++ (number of sets * number of ways) will be twice the number of frames that ++ are expected to be reassembled simultaneously.*/ ++ numOfEntries = (uint32_t)(p_Manip->reassmParams.maxNumFramesInProcess * 2); ++ ++ /* sets number calculation - number of entries = number of sets * number of ways */ ++ numOfSets = numOfEntries / numOfWays; ++ ++ /* Sets AutoLearnHashKeyMask*/ ++ NEXT_POWER_OF_2(numOfSets, numOfSets); ++ ++ WRITE_UINT16((*p_ReassTbl)->autoLearnHashKeyMask, ++ (uint16_t)(numOfSets - 1)); ++ ++ /* Allocation of Reassembly Automatic Learning Hash Table - This table resides in external memory. ++ The size of this table is determined by the number of sets and the set size. ++ Table size = set size * number of sets ++ This table base address should be aligned to SetSize.*/ ++ autoLearnHashTblSize = numOfSets * setSize; ++ ++ *p_AutoLearnHashTblAddr = ++ PTR_TO_UINT(XX_MallocSmart(autoLearnHashTblSize, p_Manip->reassmParams.dataMemId, setSize)); ++ if (!*p_AutoLearnHashTblAddr) ++ { ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, *p_ReassTbl); ++ *p_ReassTbl = NULL; ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED")); ++ } ++ IOMemSet32(UINT_TO_PTR(*p_AutoLearnHashTblAddr), 0, autoLearnHashTblSize); ++ ++ /* Sets the Reassembly Automatic Learning Hash Table and liodn offset */ ++ tmpReg64 = ((uint64_t)(p_Manip->reassmParams.dataLiodnOffset ++ & FM_PCD_MANIP_REASM_LIODN_MASK) ++ << (uint64_t)FM_PCD_MANIP_REASM_LIODN_SHIFT); ++ tmpReg64 |= ((uint64_t)(p_Manip->reassmParams.dataLiodnOffset ++ & FM_PCD_MANIP_REASM_ELIODN_MASK) ++ << (uint64_t)FM_PCD_MANIP_REASM_ELIODN_SHIFT); ++ tmpReg64 |= XX_VirtToPhys(UINT_TO_PTR(*p_AutoLearnHashTblAddr)); ++ WRITE_UINT32( (*p_ReassTbl)->liodnAlAndAutoLearnHashTblPtrHi, ++ (uint32_t)(tmpReg64 >> 32)); ++ WRITE_UINT32((*p_ReassTbl)->autoLearnHashTblPtrLow, (uint32_t)tmpReg64); ++ ++ /* Allocation of the Set Lock table - This table resides in external memory ++ The size of this table is (number of sets in the Reassembly Automatic Learning Hash table)*4 bytes. ++ This table resides in external memory and its base address should be 4-byte aligned */ ++ *p_AutoLearnSetLockTblAddr = ++ PTR_TO_UINT(XX_MallocSmart((uint32_t)(numOfSets * 4), p_Manip->reassmParams.dataMemId, 4)); ++ if (!*p_AutoLearnSetLockTblAddr) ++ { ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, *p_ReassTbl); ++ *p_ReassTbl = NULL; ++ XX_FreeSmart(UINT_TO_PTR(*p_AutoLearnHashTblAddr)); ++ *p_AutoLearnHashTblAddr = 0; ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED")); ++ } ++ IOMemSet32(UINT_TO_PTR(*p_AutoLearnSetLockTblAddr), 0, (numOfSets * 4)); ++ ++ /* sets Set Lock table pointer and liodn offset*/ ++ tmpReg64 = ((uint64_t)(p_Manip->reassmParams.dataLiodnOffset ++ & FM_PCD_MANIP_REASM_LIODN_MASK) ++ << (uint64_t)FM_PCD_MANIP_REASM_LIODN_SHIFT); ++ tmpReg64 |= ((uint64_t)(p_Manip->reassmParams.dataLiodnOffset ++ & FM_PCD_MANIP_REASM_ELIODN_MASK) ++ << (uint64_t)FM_PCD_MANIP_REASM_ELIODN_SHIFT); ++ tmpReg64 |= XX_VirtToPhys(UINT_TO_PTR(*p_AutoLearnSetLockTblAddr)); ++ WRITE_UINT32( (*p_ReassTbl)->liodnSlAndAutoLearnSetLockTblPtrHi, ++ (uint32_t)(tmpReg64 >> 32)); ++ WRITE_UINT32((*p_ReassTbl)->autoLearnSetLockTblPtrLow, (uint32_t)tmpReg64); ++ ++ /* Sets user's requested minimum fragment size (in Bytes) for First/Middle fragment */ ++ WRITE_UINT16((*p_ReassTbl)->minFragSize, minFragSize); ++ ++ WRITE_UINT16((*p_ReassTbl)->maxReassemblySize, maxReassemSize); ++ ++ return E_OK; ++} ++ ++static t_Error UpdateInitReasm(t_Handle h_FmPcd, t_Handle h_PcdParams, ++ t_Handle h_FmPort, t_FmPcdManip *p_Manip, ++ t_Handle h_Ad, bool validate) ++{ ++ t_FmPortGetSetCcParams fmPortGetSetCcParams; ++ uint32_t tmpReg32; ++ t_Error err; ++ t_FmPortPcdParams *p_PcdParams = (t_FmPortPcdParams *)h_PcdParams; ++#if (DPAA_VERSION >= 11) ++ t_FmPcdCtrlParamsPage *p_ParamsPage; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Manip->frag, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR( ++ (p_Manip->opcode == HMAN_OC_IP_REASSEMBLY) || (p_Manip->opcode == HMAN_OC_CAPWAP_REASSEMBLY), ++ E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Manip->updateParams || h_PcdParams, ++ E_INVALID_HANDLE); ++ ++ UNUSED(h_Ad); ++ ++ if (!p_Manip->updateParams) ++ return E_OK; ++ ++ if (p_Manip->h_FmPcd != h_FmPcd) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_STATE, ++ ("handler of PCD previously was initiated by different value")); ++ ++ if (p_Manip->updateParams) ++ { ++ if ((!(p_Manip->updateParams ++ & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK))) ++ || ((p_Manip->shadowUpdateParams ++ & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK)))) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_STATE, ++ ("in this stage parameters from Port has not be updated")); ++ ++ fmPortGetSetCcParams.setCcParams.type = 0; ++ if (p_Manip->opcode == HMAN_OC_CAPWAP_REASSEMBLY) ++ { ++ fmPortGetSetCcParams.setCcParams.type |= UPDATE_OFP_DPTE; ++ fmPortGetSetCcParams.setCcParams.ofpDpde = 0xF; ++ } ++ fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams | FM_REV; ++ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) ++ != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (fmPortGetSetCcParams.getCcParams.type ++ & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK | FM_REV)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("offset of the data wasn't configured previously")); ++ if (p_Manip->updateParams ++ & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK)) ++ { ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint8_t *p_Ptr, i, totalNumOfTnums; ++ ++ totalNumOfTnums = ++ (uint8_t)(fmPortGetSetCcParams.getCcParams.numOfTasks ++ + fmPortGetSetCcParams.getCcParams.numOfExtraTasks); ++ ++ p_Manip->reassmParams.internalBufferPoolAddr = ++ PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ (uint32_t)(totalNumOfTnums * BMI_FIFO_UNITS), ++ BMI_FIFO_UNITS)); ++ if (!p_Manip->reassmParams.internalBufferPoolAddr) ++ RETURN_ERROR( ++ MAJOR, E_NO_MEMORY, ++ ("MURAM alloc for Reassembly internal buffers pool")); ++ IOMemSet32( ++ UINT_TO_PTR(p_Manip->reassmParams.internalBufferPoolAddr), ++ 0, (uint32_t)(totalNumOfTnums * BMI_FIFO_UNITS)); ++ ++ p_Manip->reassmParams.internalBufferPoolManagementIndexAddr = ++ PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ (uint32_t)(5 + totalNumOfTnums), ++ 4)); ++ if (!p_Manip->reassmParams.internalBufferPoolManagementIndexAddr) ++ RETURN_ERROR( ++ MAJOR, ++ E_NO_MEMORY, ++ ("MURAM alloc for Reassembly internal buffers management")); ++ ++ p_Ptr = ++ (uint8_t*)UINT_TO_PTR(p_Manip->reassmParams.internalBufferPoolManagementIndexAddr); ++ WRITE_UINT32( ++ *(uint32_t*)p_Ptr, ++ (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->reassmParams.internalBufferPoolAddr)) - p_FmPcd->physicalMuramBase)); ++ for (i = 0, p_Ptr += 4; i < totalNumOfTnums; i++, p_Ptr++) ++ WRITE_UINT8(*p_Ptr, i); ++ WRITE_UINT8(*p_Ptr, 0xFF); ++ ++ tmpReg32 = ++ (4 << FM_PCD_MANIP_REASM_COMMON_INT_BUFFER_IDX_SHIFT) ++ | ((uint32_t)(XX_VirtToPhys( ++ UINT_TO_PTR(p_Manip->reassmParams.internalBufferPoolManagementIndexAddr)) ++ - p_FmPcd->physicalMuramBase)); ++ WRITE_UINT32( ++ p_Manip->reassmParams.p_ReassCommonTbl->internalBufferManagement, ++ tmpReg32); ++ ++ p_Manip->updateParams &= ~(NUM_OF_TASKS | NUM_OF_EXTRA_TASKS ++ | DISCARD_MASK); ++ p_Manip->shadowUpdateParams |= (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS ++ | DISCARD_MASK); ++ } ++ } ++ ++ if (p_Manip->opcode == HMAN_OC_CAPWAP_REASSEMBLY) ++ { ++ if (p_Manip->reassmParams.capwap.h_Scheme) ++ { ++ p_PcdParams->p_KgParams->h_Schemes[p_PcdParams->p_KgParams->numOfSchemes] = ++ p_Manip->reassmParams.capwap.h_Scheme; ++ p_PcdParams->p_KgParams->numOfSchemes++; ++ } ++ ++ } ++ else ++ { ++ if (p_Manip->reassmParams.ip.h_Ipv4Scheme) ++ { ++ p_PcdParams->p_KgParams->h_Schemes[p_PcdParams->p_KgParams->numOfSchemes] = ++ p_Manip->reassmParams.ip.h_Ipv4Scheme; ++ p_PcdParams->p_KgParams->numOfSchemes++; ++ } ++ if (p_Manip->reassmParams.ip.h_Ipv6Scheme) ++ { ++ p_PcdParams->p_KgParams->h_Schemes[p_PcdParams->p_KgParams->numOfSchemes] = ++ p_Manip->reassmParams.ip.h_Ipv6Scheme; ++ p_PcdParams->p_KgParams->numOfSchemes++; ++ } ++#if (DPAA_VERSION >= 11) ++ if (fmPortGetSetCcParams.getCcParams.revInfo.majorRev >= 6) ++ { ++ if ((err = FmPortSetGprFunc(h_FmPort, e_FM_PORT_GPR_MURAM_PAGE, ++ (void**)&p_ParamsPage)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ tmpReg32 = NIA_ENG_KG; ++ if (p_Manip->reassmParams.ip.h_Ipv4Scheme) ++ { ++ tmpReg32 |= NIA_KG_DIRECT; ++ tmpReg32 |= NIA_KG_CC_EN; ++ tmpReg32 |= FmPcdKgGetSchemeId( ++ p_Manip->reassmParams.ip.h_Ipv4Scheme); ++ WRITE_UINT32(p_ParamsPage->iprIpv4Nia, tmpReg32); ++ } ++ if (p_Manip->reassmParams.ip.h_Ipv6Scheme) ++ { ++ tmpReg32 &= ~NIA_AC_MASK; ++ tmpReg32 |= NIA_KG_DIRECT; ++ tmpReg32 |= NIA_KG_CC_EN; ++ tmpReg32 |= FmPcdKgGetSchemeId( ++ p_Manip->reassmParams.ip.h_Ipv6Scheme); ++ WRITE_UINT32(p_ParamsPage->iprIpv6Nia, tmpReg32); ++ } ++ } ++#else ++ if (fmPortGetSetCcParams.getCcParams.revInfo.majorRev < 6) ++ { ++ WRITE_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->discardMask, ++ fmPortGetSetCcParams.getCcParams.discardMask); ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ return E_OK; ++} ++ ++#if (DPAA_VERSION == 10) ++static t_Error FmPcdFragHcScratchPoolFill(t_Handle h_FmPcd, uint8_t scratchBpid) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdCcFragScratchPoolCmdParams fmPcdCcFragScratchPoolCmdParams; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ memset(&fmPcdCcFragScratchPoolCmdParams, 0, sizeof(t_FmPcdCcFragScratchPoolCmdParams)); ++ ++ fmPcdCcFragScratchPoolCmdParams.numOfBuffers = NUM_OF_SCRATCH_POOL_BUFFERS; ++ fmPcdCcFragScratchPoolCmdParams.bufferPoolId = scratchBpid; ++ if ((err = FmHcPcdCcIpFragScratchPollCmd(p_FmPcd->h_Hc, TRUE, &fmPcdCcFragScratchPoolCmdParams)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (fmPcdCcFragScratchPoolCmdParams.numOfBuffers != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Fill scratch pool failed," ++ "Failed to release %d buffers to the BM (missing FBPRs)", ++ fmPcdCcFragScratchPoolCmdParams.numOfBuffers)); ++ ++ return E_OK; ++} ++ ++static t_Error FmPcdFragHcScratchPoolEmpty(t_Handle h_FmPcd, uint8_t scratchBpid) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdCcFragScratchPoolCmdParams fmPcdCcFragScratchPoolCmdParams; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ memset(&fmPcdCcFragScratchPoolCmdParams, 0, sizeof(t_FmPcdCcFragScratchPoolCmdParams)); ++ ++ fmPcdCcFragScratchPoolCmdParams.bufferPoolId = scratchBpid; ++ if ((err = FmHcPcdCcIpFragScratchPollCmd(p_FmPcd->h_Hc, FALSE, &fmPcdCcFragScratchPoolCmdParams)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return E_OK; ++} ++#endif /* (DPAA_VERSION == 10) */ ++ ++static void ReleaseManipHandler(t_FmPcdManip *p_Manip, t_FmPcd *p_FmPcd) ++{ ++ if (p_Manip->h_Ad) ++ { ++ if (p_Manip->muramAllocate) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->h_Ad); ++ else ++ XX_Free(p_Manip->h_Ad); ++ p_Manip->h_Ad = NULL; ++ } ++ if (p_Manip->p_Template) ++ { ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->p_Template); ++ p_Manip->p_Template = NULL; ++ } ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++ if (p_Manip->h_Frag) ++ { ++ if (p_Manip->capwapFragParams.p_AutoLearnHashTbl) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, ++ p_Manip->capwapFragParams.p_AutoLearnHashTbl); ++ if (p_Manip->capwapFragParams.p_ReassmFrmDescrPoolTbl) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, ++ p_Manip->capwapFragParams.p_ReassmFrmDescrPoolTbl); ++ if (p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, ++ p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl); ++ if (p_Manip->capwapFragParams.p_TimeOutTbl) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, ++ p_Manip->capwapFragParams.p_TimeOutTbl); ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->h_Frag); ++ ++ } ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ if (p_Manip->frag) ++ { ++ if (p_Manip->fragParams.p_Frag) ++ { ++#if (DPAA_VERSION == 10) ++ FmPcdFragHcScratchPoolEmpty((t_Handle)p_FmPcd, p_Manip->fragParams.scratchBpid); ++#endif /* (DPAA_VERSION == 10) */ ++ ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_Frag); ++ } ++ } ++ else ++ if (p_Manip->reassm) ++ { ++ FmPcdUnregisterReassmPort(p_FmPcd, ++ p_Manip->reassmParams.p_ReassCommonTbl); ++ ++ if (p_Manip->reassmParams.timeOutTblAddr) ++ FM_MURAM_FreeMem( ++ p_FmPcd->h_FmMuram, ++ UINT_TO_PTR(p_Manip->reassmParams.timeOutTblAddr)); ++ if (p_Manip->reassmParams.reassFrmDescrPoolTblAddr) ++ XX_FreeSmart( ++ UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrPoolTblAddr)); ++ if (p_Manip->reassmParams.p_ReassCommonTbl) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, ++ p_Manip->reassmParams.p_ReassCommonTbl); ++ if (p_Manip->reassmParams.reassFrmDescrIndxPoolTblAddr) ++ FM_MURAM_FreeMem( ++ p_FmPcd->h_FmMuram, ++ UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrIndxPoolTblAddr)); ++ if (p_Manip->reassmParams.internalBufferPoolManagementIndexAddr) ++ FM_MURAM_FreeMem( ++ p_FmPcd->h_FmMuram, ++ UINT_TO_PTR(p_Manip->reassmParams.internalBufferPoolManagementIndexAddr)); ++ if (p_Manip->reassmParams.internalBufferPoolAddr) ++ FM_MURAM_FreeMem( ++ p_FmPcd->h_FmMuram, ++ UINT_TO_PTR(p_Manip->reassmParams.internalBufferPoolAddr)); ++ if (p_Manip->reassmParams.hdr == HEADER_TYPE_CAPWAP) ++ { ++ ++ } ++ else ++ { ++ if (p_Manip->reassmParams.ip.ipv4AutoLearnHashTblAddr) ++ XX_FreeSmart( ++ UINT_TO_PTR(p_Manip->reassmParams.ip.ipv4AutoLearnHashTblAddr)); ++ if (p_Manip->reassmParams.ip.ipv6AutoLearnHashTblAddr) ++ XX_FreeSmart( ++ UINT_TO_PTR(p_Manip->reassmParams.ip.ipv6AutoLearnHashTblAddr)); ++ if (p_Manip->reassmParams.ip.ipv4AutoLearnSetLockTblAddr) ++ XX_FreeSmart( ++ UINT_TO_PTR(p_Manip->reassmParams.ip.ipv4AutoLearnSetLockTblAddr)); ++ if (p_Manip->reassmParams.ip.ipv6AutoLearnSetLockTblAddr) ++ XX_FreeSmart( ++ UINT_TO_PTR(p_Manip->reassmParams.ip.ipv6AutoLearnSetLockTblAddr)); ++ if (p_Manip->reassmParams.ip.p_Ipv4ReassTbl) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, ++ p_Manip->reassmParams.ip.p_Ipv4ReassTbl); ++ if (p_Manip->reassmParams.ip.p_Ipv6ReassTbl) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, ++ p_Manip->reassmParams.ip.p_Ipv6ReassTbl); ++ if (p_Manip->reassmParams.ip.h_Ipv6Ad) ++ XX_FreeSmart(p_Manip->reassmParams.ip.h_Ipv6Ad); ++ if (p_Manip->reassmParams.ip.h_Ipv4Ad) ++ XX_FreeSmart(p_Manip->reassmParams.ip.h_Ipv4Ad); ++ } ++ } ++ ++ if (p_Manip->p_StatsTbl) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->p_StatsTbl); ++} ++ ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++static t_Error CheckManipParamsAndSetType(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_ManipParams) ++{ ++ if (p_ManipParams->u.hdr.rmv) ++ { ++ switch (p_ManipParams->u.hdr.rmvParams.type) ++ { ++ case (e_FM_PCD_MANIP_RMV_BY_HDR): ++ switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.type) ++ { ++ case (e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START) : ++ if (p_ManipParams->u.hdr.rmvParams.u.byHdr.u.fromStartByHdr.include) ++ { ++ switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.u.fromStartByHdr.hdrInfo.hdr) ++ { ++ case (HEADER_TYPE_CAPWAP_DTLS) : ++ p_Manip->opcode = HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST; ++ p_Manip->muramAllocate = TRUE; ++ if (p_ManipParams->u.hdr.insrt) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for CAPWAP_DTLS_HDR remove can not be insrt manipualtion after")); ++ if (p_ManipParams->fragOrReasm) ++ { ++ if (!p_ManipParams->fragOrReasmParams.frag) ++ { ++ switch (p_ManipParams->fragOrReasmParams.hdr) ++ { ++ case (HEADER_TYPE_CAPWAP): ++ p_Manip->opcode = HMAN_OC_CAPWAP_REASSEMBLY; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("unsupported header for Reassembly")); ++ } ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for this type of manipulation frag can not be TRUE")); ++ } ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("non valid net header of remove location")); ++ } ++ } ++ else ++ { ++ switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.u.fromStartByHdr.hdrInfo.hdr) ++ { ++ case (HEADER_TYPE_CAPWAP_DTLS) : ++ case (HEADER_TYPE_CAPWAP) : ++ if (p_ManipParams->fragOrReasm || p_ManipParams->u.hdr.insrt) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for the type of remove e_FM_PCD_MANIP_RMV_FROM_START_OF_FRAME_TILL_CAPWAP can not be insert or fragOrReasm TRUE")); ++ p_Manip->opcode = HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR; ++ p_Manip->muramAllocate = TRUE; ++ p_ManipParams->u.hdr.insrt = TRUE; //internal frame header ++ break; ++ default : ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation")); ++ } ++ } ++ break; ++ default : ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation")); ++ } ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation")); ++ } ++ } ++ else if (p_ManipParams->u.hdr.insrt) ++ { ++ switch (p_ManipParams->u.hdr.insrtParams.type) ++ { ++ case (e_FM_PCD_MANIP_INSRT_BY_TEMPLATE) : ++ ++ p_Manip->opcode = HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER; ++ p_Manip->muramAllocate = FALSE; ++ if (p_ManipParams->fragOrReasm) ++ { ++ if (p_ManipParams->fragOrReasmParams.frag) ++ { ++ switch (p_ManipParams->fragOrReasmParams.hdr) ++ { ++ case (HEADER_TYPE_CAPWAP): ++ p_Manip->opcode = HMAN_OC_CAPWAP_FRAGMENTATION; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid header for fragmentation")); ++ } ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_STATE,("can not reach this point")); ++ } ++ break; ++ ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for only isert manipulation unsupported type")); ++ } ++ } ++ else if (p_ManipParams->fragOrReasm) ++ { ++ if (p_ManipParams->fragOrReasmParams.frag) ++ { ++ switch (p_ManipParams->fragOrReasmParams.hdr) ++ { ++ case (HEADER_TYPE_CAPWAP): ++ p_Manip->opcode = HMAN_OC_CAPWAP_FRAGMENTATION; ++ p_Manip->muramAllocate = FALSE; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported header for fragmentation")); ++ } ++ } ++ else ++ { ++ switch (p_ManipParams->fragOrReasmParams.hdr) ++ { ++ case (HEADER_TYPE_CAPWAP): ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Reassembly has to be with additional operation - rmv = TRUE, type of remove - e_FM_PCD_MANIP_RMV_FROM_START_OF_FRAME_INCLUDE_SPECIFIC_LOCATION,type = e_FM_PCD_MANIP_LOC_BY_HDR, hdr = HEADER_TYPE_CAPWAP_DTLS")); ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported header for reassembly")); ++ } ++ } ++ ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("User didn't ask for any manipulation")); ++ ++ p_Manip->insrt = p_ManipParams->u.hdr.insrt; ++ p_Manip->rmv = p_ManipParams->u.hdr.rmv; ++ ++ return E_OK; ++} ++ ++#else /* not (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++static t_Error CheckManipParamsAndSetType(t_FmPcdManip *p_Manip, ++ t_FmPcdManipParams *p_ManipParams) ++{ ++ switch (p_ManipParams->type) ++ { ++ case e_FM_PCD_MANIP_HDR: ++ /* Check that next-manip is not already used */ ++ if (p_ManipParams->h_NextManip) ++ { ++ if (!MANIP_IS_FIRST(p_ManipParams->h_NextManip)) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_STATE, ++ ("h_NextManip is already a part of another chain")); ++ if ((MANIP_GET_TYPE(p_ManipParams->h_NextManip) ++ != e_FM_PCD_MANIP_HDR) && ++ (MANIP_GET_TYPE(p_ManipParams->h_NextManip) ++ != e_FM_PCD_MANIP_FRAG)) ++ RETURN_ERROR( ++ MAJOR, ++ E_NOT_SUPPORTED, ++ ("For a Header Manipulation node - no support of h_NextManip of type other than Header Manipulation or Fragmentation.")); ++ } ++ ++ if (p_ManipParams->u.hdr.rmv) ++ { ++ switch (p_ManipParams->u.hdr.rmvParams.type) ++ { ++ case (e_FM_PCD_MANIP_RMV_BY_HDR): ++ switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.type) ++ { ++ case (e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2): ++ break; ++#if (DPAA_VERSION >= 11) ++ case (e_FM_PCD_MANIP_RMV_BY_HDR_CAPWAP): ++ break; ++ case (e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START): ++ { ++ t_Error err; ++ uint8_t prsArrayOffset; ++ ++ err = ++ GetPrOffsetByHeaderOrField( ++ &p_ManipParams->u.hdr.rmvParams.u.byHdr.u.hdrInfo, ++ &prsArrayOffset); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ break; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ default: ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("invalid type of remove manipulation")); ++ } ++ break; ++ case (e_FM_PCD_MANIP_RMV_GENERIC): ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("invalid type of remove manipulation")); ++ } ++ p_Manip->opcode = HMAN_OC; ++ p_Manip->muramAllocate = TRUE; ++ p_Manip->rmv = TRUE; ++ } ++ else ++ if (p_ManipParams->u.hdr.insrt) ++ { ++ switch (p_ManipParams->u.hdr.insrtParams.type) ++ { ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR): ++ { ++ switch (p_ManipParams->u.hdr.insrtParams.u.byHdr.type) ++ { ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2): ++ /* nothing to check */ ++ break; ++#if (DPAA_VERSION >= 11) ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR_IP): ++ if (p_ManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.insrt.size ++ % 4) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("IP inserted header must be of size which is a multiple of four bytes")); ++ break; ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR_CAPWAP): ++ if (p_ManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.size ++ % 4) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("CAPWAP inserted header must be of size which is a multiple of four bytes")); ++ break; ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR_UDP): ++ case (e_FM_PCD_MANIP_INSRT_BY_HDR_UDP_LITE): ++ if (p_ManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.size ++ != 8) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("Inserted header must be of size 8")); ++ break; ++#endif /* (DPAA_VERSION >= 11) */ ++ default: ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("unsupported insert by header type")); ++ } ++ } ++ case (e_FM_PCD_MANIP_INSRT_GENERIC): ++ break; ++ default: ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("for only insert manipulation unsupported type")); ++ } ++ p_Manip->opcode = HMAN_OC; ++ p_Manip->muramAllocate = TRUE; ++ p_Manip->insrt = TRUE; ++ } ++ else ++ if (p_ManipParams->u.hdr.fieldUpdate) ++ { ++ /* Check parameters */ ++ if (p_ManipParams->u.hdr.fieldUpdateParams.type ++ == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN) ++ { ++ if ((p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType ++ == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_VPRI) ++ && (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.u.vpri ++ > 7)) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("vpri should get values of 0-7 ")); ++ if (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType ++ == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN) ++ { ++ int i; ++ ++ if (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.vpriDefVal ++ > 7) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("vpriDefVal should get values of 0-7 ")); ++ for (i = 0; i < FM_PCD_MANIP_DSCP_TO_VLAN_TRANS; ++ i++) ++ if (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.dscpToVpriTable[i] ++ & 0xf0) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("dscpToVpriTabl value out of range (0-15)")); ++ } ++ ++ } ++ ++ p_Manip->opcode = HMAN_OC; ++ p_Manip->muramAllocate = TRUE; ++ p_Manip->fieldUpdate = TRUE; ++ } ++ else ++ if (p_ManipParams->u.hdr.custom) ++ { ++ if (p_ManipParams->u.hdr.customParams.type == e_FM_PCD_MANIP_HDR_CUSTOM_GEN_FIELD_REPLACE) ++ { ++ ++ if ((p_ManipParams->u.hdr.customParams.u.genFieldReplace.size == 0) || ++ (p_ManipParams->u.hdr.customParams.u.genFieldReplace.size > 8)) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("size should get values of 1-8 ")); ++ ++ if (p_ManipParams->u.hdr.customParams.u.genFieldReplace.srcOffset > 7) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("srcOffset should be <= 7")); ++ ++ if ((p_ManipParams->u.hdr.customParams.u.genFieldReplace.srcOffset + ++ p_ManipParams->u.hdr.customParams.u.genFieldReplace.size) > 8) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("(srcOffset + size) should be <= 8")); ++ ++ if ((p_ManipParams->u.hdr.customParams.u.genFieldReplace.dstOffset + ++ p_ManipParams->u.hdr.customParams.u.genFieldReplace.size) > 256) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("(dstOffset + size) should be <= 256")); ++ ++ } ++ ++ p_Manip->opcode = HMAN_OC; ++ p_Manip->muramAllocate = TRUE; ++ p_Manip->custom = TRUE; ++ } ++ break; ++ case e_FM_PCD_MANIP_REASSEM: ++ if (p_ManipParams->h_NextManip) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("next manip with reassembly")); ++ switch (p_ManipParams->u.reassem.hdr) ++ { ++ case (HEADER_TYPE_IPv4): ++ p_Manip->reassmParams.hdr = HEADER_TYPE_IPv4; ++ p_Manip->opcode = HMAN_OC_IP_REASSEMBLY; ++ break; ++ case (HEADER_TYPE_IPv6): ++ p_Manip->reassmParams.hdr = HEADER_TYPE_IPv6; ++ p_Manip->opcode = HMAN_OC_IP_REASSEMBLY; ++ break; ++#if (DPAA_VERSION >= 11) ++ case (HEADER_TYPE_CAPWAP): ++ p_Manip->reassmParams.hdr = HEADER_TYPE_CAPWAP; ++ p_Manip->opcode = HMAN_OC_CAPWAP_REASSEMBLY; ++ break; ++#endif /* (DPAA_VERSION >= 11) */ ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("header for reassembly")); ++ } ++ break; ++ case e_FM_PCD_MANIP_FRAG: ++ if (p_ManipParams->h_NextManip) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("next manip with fragmentation")); ++ switch (p_ManipParams->u.frag.hdr) ++ { ++ case (HEADER_TYPE_IPv4): ++ case (HEADER_TYPE_IPv6): ++ p_Manip->opcode = HMAN_OC_IP_FRAGMENTATION; ++ break; ++#if (DPAA_VERSION >= 11) ++ case (HEADER_TYPE_CAPWAP): ++ p_Manip->opcode = HMAN_OC_CAPWAP_FRAGMENTATION; ++ break; ++#endif /* (DPAA_VERSION >= 11) */ ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("header for fragmentation")); ++ } ++ p_Manip->muramAllocate = TRUE; ++ break; ++ case e_FM_PCD_MANIP_SPECIAL_OFFLOAD: ++ switch (p_ManipParams->u.specialOffload.type) ++ { ++ case (e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC): ++ p_Manip->opcode = HMAN_OC_IPSEC_MANIP; ++ p_Manip->muramAllocate = TRUE; ++ break; ++#if (DPAA_VERSION >= 11) ++ case (e_FM_PCD_MANIP_SPECIAL_OFFLOAD_CAPWAP): ++ p_Manip->opcode = HMAN_OC_CAPWAP_MANIP; ++ p_Manip->muramAllocate = TRUE; ++ break; ++#endif /* (DPAA_VERSION >= 11) */ ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("special offload type")); ++ } ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("manip type")); ++ } ++ ++ return E_OK; ++} ++#endif /* not (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++ ++static t_Error UpdateIndxStats(t_Handle h_FmPcd, ++ t_Handle h_FmPort, ++ t_FmPcdManip *p_Manip) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint32_t tmpReg32 = 0; ++ t_AdOfTypeContLookup *p_Ad; ++ t_FmPortGetSetCcParams fmPortGetSetCcParams; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ if (p_Manip->h_FmPcd != h_FmPcd) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("handler of PCD previously was initiated by different value")); ++ ++ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams)); ++ ++ if (!p_Manip->p_StatsTbl) ++ { ++ ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNDN; ++ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_CC; ++ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ tmpReg32 = GET_UINT32(p_Ad->ccAdBase); ++ ++ p_Manip->p_StatsTbl = ++ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ (uint32_t)p_Manip->owner * FM_PCD_MANIP_INDEXED_STATS_ENTRY_SIZE, ++ 4); ++ if (!p_Manip->p_StatsTbl) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Manipulation indexed statistics table")); ++ ++ IOMemSet32(p_Manip->p_StatsTbl, 0, (uint32_t)(p_Manip->owner * 4)); ++ ++ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->p_StatsTbl) - p_FmPcd->physicalMuramBase); ++ ++ if (p_Manip->cnia) ++ tmpReg32 |= FM_PCD_MANIP_INDEXED_STATS_CNIA; ++ ++ tmpReg32 |= FM_PCD_MANIP_INDEXED_STATS_DPD; ++ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); ++ } ++ else ++ { ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNDN; ++ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_CC; ++ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error RmvHdrTillSpecLocNOrInsrtIntFrmHdr(t_FmPcdManipHdrRmvParams *p_ManipParams, t_FmPcdManip *p_Manip) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ uint32_t tmpReg32 = 0; ++ uint8_t prsArrayOffset = 0; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip,E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_ManipParams,E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ if (p_Manip->rmv) ++ { ++ err = GetPrOffsetByHeaderOrField(&p_ManipParams->u.byHdr.u.fromStartByHdr.hdrInfo, &prsArrayOffset); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ tmpReg32 |= (uint32_t)prsArrayOffset << 24; ++ tmpReg32 |= HMAN_RMV_HDR; ++ } ++ ++ if (p_Manip->insrt) ++ tmpReg32 |= HMAN_INSRT_INT_FRM_HDR; ++ ++ tmpReg32 |= (uint32_t)HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR; ++ ++ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); ++ ++ tmpReg32 = 0; ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); ++ ++ return E_OK; ++} ++ ++static t_Error MvIntFrameHeaderFromFrameToBufferPrefix(t_FmPcdManip *p_Manip, ++ bool caamUsed) ++{ ++ t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ uint32_t tmpReg32 = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Ad, E_INVALID_HANDLE); ++ ++ p_Manip->updateParams |= OFFSET_OF_PR | INTERNAL_CONTEXT_OFFSET; ++ ++ tmpReg32 = 0; ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ *(uint32_t *)&p_Ad->ccAdBase = tmpReg32; ++ ++ tmpReg32 = 0; ++ tmpReg32 |= HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX; ++ tmpReg32 |= (uint32_t)0x16 << 16; ++ *(uint32_t *)&p_Ad->pcAndOffsets = tmpReg32; ++ ++ if (caamUsed) ++ *(uint32_t *)&p_Ad->gmask = 0xf0000000; ++ ++ return E_OK; ++} ++ ++static t_Error CapwapRmvDtlsHdr(t_FmPcd *p_FmPcd, t_FmPcdManip *p_Manip) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ uint32_t tmpReg32 = 0; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ ++ tmpReg32 = 0; ++ tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST; ++ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); ++ ++ tmpReg32 = 0; ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ ++ ++ if (p_Manip->h_Frag) ++ { ++ p_Manip->updateParams |= INTERNAL_CONTEXT_OFFSET; ++ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->h_Frag) - (p_FmPcd->physicalMuramBase)); ++ } ++ ++ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); ++ ++ return err; ++} ++ ++static t_Error CapwapReassembly(t_CapwapReassemblyParams *p_ManipParams, ++ t_FmPcdManip *p_Manip, ++ t_FmPcd *p_FmPcd, ++ uint8_t poolId) ++{ ++ t_Handle p_Table; ++ uint32_t tmpReg32 = 0; ++ int i = 0; ++ uint8_t log2Num; ++ uint8_t numOfSets; ++ uint32_t j = 0; ++ uint32_t bitFor1Micro; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ if (!p_FmPcd->h_Hc) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("hc port has to be initialized in this mode")); ++ if (!POWER_OF_2(p_ManipParams->timeoutRoutineRequestTime)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("timeoutRoutineRequestTime has to be power of 2")); ++ if (!POWER_OF_2(p_ManipParams->maxNumFramesInProcess)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("maxNumFramesInProcess has to be power of 2")); ++ if (!p_ManipParams->timeoutRoutineRequestTime && p_ManipParams->timeoutThresholdForReassmProcess) ++ DBG(WARNING, ("if timeoutRoutineRequestTime 0, timeoutThresholdForReassmProcess is uselessly")); ++ if (p_ManipParams->numOfFramesPerHashEntry == e_FM_PCD_MANIP_FOUR_WAYS_HASH) ++ { ++ if ((p_ManipParams->maxNumFramesInProcess < 4) || ++ (p_ManipParams->maxNumFramesInProcess > 512)) ++ RETURN_ERROR(MAJOR,E_INVALID_VALUE, ("In the case of numOfFramesPerHashEntry = e_FM_PCD_MANIP_EIGHT_WAYS_HASH maxNumFramesInProcess has to be in the range 4-512")); ++ } ++ else ++ { ++ if ((p_ManipParams->maxNumFramesInProcess < 8) || ++ (p_ManipParams->maxNumFramesInProcess > 2048)) ++ RETURN_ERROR(MAJOR,E_INVALID_VALUE, ("In the case of numOfFramesPerHashEntry = e_FM_PCD_MANIP_FOUR_WAYS_HASH maxNumFramesInProcess has to be in the range 8-2048")); ++ } ++ ++ bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm); ++ if (bitFor1Micro == 0) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Timestamp scale")); ++ ++ p_Manip->updateParams |= (NUM_OF_TASKS | OFFSET_OF_PR | OFFSET_OF_DATA | HW_PORT_ID); ++ ++ p_Manip->h_Frag = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE, ++ FM_PCD_MANIP_CAPWAP_REASM_TABLE_ALIGN); ++ if (!p_Manip->h_Frag) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc CAPWAP reassembly parameters table")); ++ ++ IOMemSet32(p_Manip->h_Frag, 0, FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE); ++ ++ p_Table = (t_CapwapReasmPram *)p_Manip->h_Frag; ++ ++ p_Manip->capwapFragParams.p_AutoLearnHashTbl = ++ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ (uint32_t)(p_ManipParams->maxNumFramesInProcess * 2 * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE), ++ FM_PCD_MANIP_CAPWAP_REASM_TABLE_ALIGN); ++ ++ if (!p_Manip->capwapFragParams.p_AutoLearnHashTbl) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY,("MURAM alloc for CAPWAP automatic learning hash table")); ++ ++ IOMemSet32(p_Manip->capwapFragParams.p_AutoLearnHashTbl, 0, (uint32_t)(p_ManipParams->maxNumFramesInProcess * 2 * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE)); ++ ++ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->capwapFragParams.p_AutoLearnHashTbl) - p_FmPcd->physicalMuramBase); ++ ++ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->autoLearnHashTblPtr, tmpReg32); ++ ++ tmpReg32 = 0; ++ if (p_ManipParams->timeOutMode == e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAMES) ++ tmpReg32 |= FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_BETWEEN_FRAMES; ++ if (p_ManipParams->haltOnDuplicationFrag) ++ tmpReg32 |= FM_PCD_MANIP_CAPWAP_REASM_HALT_ON_DUPLICATE_FRAG; ++ if (p_ManipParams->numOfFramesPerHashEntry == e_FM_PCD_MANIP_EIGHT_WAYS_HASH) ++ { ++ i = 8; ++ tmpReg32 |= FM_PCD_MANIP_CAPWAP_REASM_AUTOMATIC_LEARNIN_HASH_8_WAYS; ++ } ++ else ++ i = 4; ++ ++ numOfSets = (uint8_t)((p_ManipParams->maxNumFramesInProcess * 2) / i); ++ LOG2(numOfSets, log2Num); ++ tmpReg32 |= (uint32_t)(log2Num - 1) << 24; ++ ++ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->mode, tmpReg32); ++ ++ for (j=0; jmaxNumFramesInProcess*2; j++) ++ if (((j / i) % 2)== 0) ++ WRITE_UINT32(*(uint32_t *)PTR_MOVE(p_Manip->capwapFragParams.p_AutoLearnHashTbl, j * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE), 0x80000000); ++ ++ tmpReg32 = 0x00008000; ++ tmpReg32 |= (uint32_t)poolId << 16; ++ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->bufferPoolIdAndRisc1SetIndexes, tmpReg32); ++ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->risc23SetIndexes, 0x80008000); ++ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->risc4SetIndexesAndExtendedStatsTblPtr, 0x80000000); ++ ++ p_Manip->capwapFragParams.maxNumFramesInProcess = p_ManipParams->maxNumFramesInProcess; ++ ++ p_Manip->capwapFragParams.sgBpid = poolId; ++ ++ p_Manip->capwapFragParams.fqidForTimeOutFrames = p_ManipParams->fqidForTimeOutFrames; ++ p_Manip->capwapFragParams.timeoutRoutineRequestTime = p_ManipParams->timeoutRoutineRequestTime; ++ p_Manip->capwapFragParams.bitFor1Micro = bitFor1Micro; ++ ++ tmpReg32 = 0; ++ tmpReg32 |= (((uint32_t)1<capwapFragParams.bitFor1Micro) * p_ManipParams->timeoutThresholdForReassmProcess); ++ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->expirationDelay, tmpReg32); ++ ++ return E_OK; ++} ++ ++static t_Error CapwapFragmentation(t_CapwapFragmentationParams *p_ManipParams, ++ t_FmPcdManip *p_Manip, ++ t_FmPcd *p_FmPcd, ++ uint8_t poolId) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ uint32_t tmpReg32 = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); ++ ++ p_Manip->updateParams |= OFFSET_OF_DATA; ++ ++ p_Manip->frag = TRUE; ++ ++ p_Manip->h_Frag = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_Manip->h_Frag) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP fragmentation table descriptor")); ++ ++ IOMemSet32(p_Manip->h_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Frag; ++ ++ tmpReg32 = 0; ++ tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_FRAGMENTATION; ++ ++ if (p_ManipParams->headerOptionsCompr) ++ tmpReg32 |= FM_PCD_MANIP_CAPWAP_FRAG_COMPR_OPTION_FIELD_EN; ++ tmpReg32 |= ((uint32_t)poolId << 8); ++ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); ++ ++ tmpReg32 = 0; ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); ++ ++ p_Manip->sizeForFragmentation = p_ManipParams->sizeForFragmentation; ++ p_Manip->capwapFragParams.sgBpid = poolId; ++ ++ return E_OK; ++} ++ ++static t_Error IndxStats(t_FmPcdStatsParams *p_StatsParams,t_FmPcdManip *p_Manip,t_FmPcd *p_FmPcd) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ uint32_t tmpReg32 = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); ++ ++ UNUSED(p_FmPcd); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ ++ tmpReg32 = 0; ++ tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_INDEXED_STATS; ++ if (p_StatsParams->type == e_FM_PCD_STATS_PER_FLOWID) ++ tmpReg32 |= (uint32_t)0x16 << 16; ++ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); ++ ++ tmpReg32 = 0; ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); ++ ++ return E_OK; ++} ++ ++static t_Error InsrtHdrByTempl(t_FmPcdManipHdrInsrtParams *p_ManipParams, t_FmPcdManip *p_Manip, t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdManipHdrInsrtByTemplateParams *p_InsrtByTemplate = &p_ManipParams->u.byTemplate; ++ uint8_t tmpReg8 = 0xff; ++ t_AdOfTypeContLookup *p_Ad; ++ bool ipModify = FALSE; ++ uint32_t tmpReg32 = 0, tmpRegNia = 0; ++ uint16_t tmpReg16 = 0; ++ t_Error err = E_OK; ++ uint8_t extraAddedBytes = 0, blockSize = 0, extraAddedBytesAlignedToBlockSize = 0, log2Num = 0; ++ uint8_t *p_Template = NULL; ++ ++ SANITY_CHECK_RETURN_ERROR(p_ManipParams,E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_Manip,E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd,E_NULL_POINTER); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ if (p_Manip->insrt) ++ { ++ if ((!p_InsrtByTemplate->size && p_InsrtByTemplate->modifyOuterIp) || ++ (!p_InsrtByTemplate->size && p_InsrtByTemplate->modifyOuterVlan)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : asking for header template modifications with no template for insertion (template size)")); ++ ++ if (p_InsrtByTemplate->size && p_InsrtByTemplate->modifyOuterIp && (p_InsrtByTemplate->size <= p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : size of template < ipOuterOffset")); ++ ++ if (p_InsrtByTemplate->size > 128) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Size of header template for insertion can not be more than 128")); ++ ++ if (p_InsrtByTemplate->size) ++ { ++ p_Manip->p_Template = (uint8_t *)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, ++ p_InsrtByTemplate->size, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if(!p_Manip->p_Template) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED")); ++ ++ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->p_Template) - (p_FmPcd->physicalMuramBase)); ++ tmpReg32 |= (uint32_t)p_InsrtByTemplate->size << 24; ++ *(uint32_t *)&p_Ad->matchTblPtr = tmpReg32; ++ } ++ ++ tmpReg32 = 0; ++ ++ p_Template = (uint8_t *)XX_Malloc(p_InsrtByTemplate->size * sizeof(uint8_t)); ++ ++ if (!p_Template) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("XX_Malloc allocation FAILED")); ++ ++ memcpy(p_Template, p_InsrtByTemplate->hdrTemplate, p_InsrtByTemplate->size * sizeof(uint8_t)); ++ ++ if (p_InsrtByTemplate->modifyOuterIp) ++ { ++ ipModify = TRUE; ++ ++ tmpReg8 = (uint8_t)p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset]; ++ ++ if((tmpReg8 & 0xf0) == 0x40) ++ tmpReg8 = 4; ++ else if((tmpReg8 & 0xf0) == 0x60) ++ tmpReg8 = 6; ++ else ++ tmpReg8 = 0xff; ++ ++ if (tmpReg8 != 0xff) ++ { ++ if(p_InsrtByTemplate->modifyOuterIpParams.dscpEcn & 0xff00) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : IPV4 present in header template, dscpEcn has to be only 1 byte")); ++ if(p_InsrtByTemplate->modifyOuterIpParams.recalculateLength) ++ { ++ ++ if((p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedAlignedToBlockSize + p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedNotAlignedToBlockSize) > 255) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("extra Byte added can not be more than 256 bytes")); ++ extraAddedBytes = (uint8_t) (p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedAlignedToBlockSize + p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedNotAlignedToBlockSize); ++ blockSize = p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.blockSize; ++ extraAddedBytesAlignedToBlockSize = p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedAlignedToBlockSize; ++ /*IP header template - IP totalLength - ++ (1 byte) extraByteForIp = headerTemplateSize - ipOffset + insertedBytesAfterThisStage , ++ in the case of SEC insertedBytesAfterThisStage - SEC trailer (21/31) + header(13) ++ second byte - extraByteForIp = headerTemplate - ipOffset + insertedBytesAfterThisStage*/ ++ } ++ if (blockSize) ++ { ++ if (!POWER_OF_2(blockSize)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("inputFrmPaddingUpToBlockSize has to be power of 2")); ++ } ++ ++ } ++ if (tmpReg8 == 4) ++ { ++ if ((IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP + p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset) > p_InsrtByTemplate->size) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : IP present in header template, user asked for IP modifications but ipOffset + ipTotalLengthFieldOffset in header template bigger than template size")); ++ ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_DSCECN_FIELD_OFFSET_FROM_IP] = (uint8_t)p_InsrtByTemplate->modifyOuterIpParams.dscpEcn; ++ ++ if (blockSize) ++ blockSize -= 1; ++ ++ if ((p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes) > 255) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes has to be less than 255")); ++ ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_TOTALLENGTH_FIELD_OFFSET_FROM_IP + 1] = blockSize; // IPV6 - in AD instead of SEQ IND ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_TOTALLENGTH_FIELD_OFFSET_FROM_IP] = (uint8_t)(p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes);// for IPV6 decrement additional 40 bytes of IPV6 heade size ++ ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_ID_FIELD_OFFSET_FROM_IP] = 0x00; ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_ID_FIELD_OFFSET_FROM_IP + 1] = extraAddedBytesAlignedToBlockSize; ++ ++ /*IP header template - relevant only for ipv4 CheckSum = 0*/ ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP] = 0x00; ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP + 1] = 0x00; ++ ++ /*UDP checksum has to be 0*/ ++ if (p_InsrtByTemplate->modifyOuterIpParams.udpPresent) ++ { ++ if ((p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + UDP_CHECKSUM_FIELD_SIZE) > p_InsrtByTemplate->size) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : UDP present according to user but (UDP offset + UDP header size) < size of header template")); ++ ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP ] = 0x00; ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + 1] = 0x00; ++ ++ } ++ ++ if (p_InsrtByTemplate->modifyOuterIpParams.ipIdentGenId > 7) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("ipIdentGenId has to be one out of 8 sequence number generators (0 - 7) for IP identification field")); ++ ++ tmpRegNia |= (uint32_t)p_InsrtByTemplate->modifyOuterIpParams.ipIdentGenId<<24; ++ } ++ else if (tmpReg8 == 6) ++ { ++ /*TODO - add check for maximum value of blockSize;*/ ++ if (blockSize) ++ LOG2(blockSize, log2Num); ++ tmpRegNia |= (uint32_t)log2Num << 24; ++ ++ // for IPV6 decrement additional 40 bytes of IPV6 heade size - because IPV6 header size is not included in payloadLength ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv6_PAYLOAD_LENGTH_OFFSET_FROM_IP] = (uint8_t)(p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes - 40); ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv6_PAYLOAD_LENGTH_OFFSET_FROM_IP + 1] = extraAddedBytesAlignedToBlockSize; ++ if (p_InsrtByTemplate->modifyOuterIpParams.udpPresent) ++ { ++ if ((p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + UDP_CHECKSUM_FIELD_SIZE) > p_InsrtByTemplate->size) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : UDP present according to user but (UDP offset + UDP header size) < size of header template")); ++ if (p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv6_NEXT_HEADER_OFFSET_FROM_IP] != 0x88) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("OUr suppport is only IPv6/UDPLite")); ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_LENGTH_FIELD_OFFSET_FROM_UDP] = 0x00; ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_LENGTH_FIELD_OFFSET_FROM_UDP + 1] = 0x08; ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP] = 0x00; ++ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + 1] = 0x00; ++ } ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("IP version supported only IPV4")); ++ } ++ ++ tmpReg32 = tmpReg16 = tmpReg8 = 0; ++ /*TODO - check it*/ ++ if (p_InsrtByTemplate->modifyOuterVlan) ++ { ++ if (p_InsrtByTemplate->modifyOuterVlanParams.vpri & ~0x07) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE,("Inconsistent parameters : user asked for VLAN modifications but VPRI more than 3 bits")); ++ ++ memcpy(&tmpReg16, &p_Template[VLAN_TAG_FIELD_OFFSET_FROM_ETH], 2*(sizeof(uint8_t))); ++ if ((tmpReg16 != 0x9100) && (tmpReg16!= 0x9200) && (tmpReg16 != 0x8100)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE,("Inconsistent parameters : user asked for VLAN modifications but Tag Protocol identifier is not VLAN ")); ++ ++ memcpy(&tmpReg8, &p_Template[14],1*(sizeof(uint8_t))); ++ tmpReg8 &= 0x1f; ++ tmpReg8 |= (uint8_t)(p_InsrtByTemplate->modifyOuterVlanParams.vpri << 5); ++ ++ p_Template[14] = tmpReg8; ++ } ++ ++ Mem2IOCpy32(p_Manip->p_Template, p_Template, p_InsrtByTemplate->size); ++ ++ XX_Free(p_Template); ++ } ++ ++ tmpReg32 = 0; ++ if (p_Manip->h_Frag) ++ { ++ tmpRegNia |= (uint32_t)(XX_VirtToPhys(p_Manip->h_Frag) - (p_FmPcd->physicalMuramBase)); ++ tmpReg32 |= (uint32_t)p_Manip->sizeForFragmentation << 16; ++ } ++ else ++ tmpReg32 = 0xffff0000; ++ ++ if (ipModify) ++ tmpReg32 |= (uint32_t)p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset << 8; ++ else ++ tmpReg32 |= (uint32_t)0x0000ff00; ++ ++ tmpReg32 |= (uint32_t)HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER; ++ *(uint32_t *)&p_Ad->pcAndOffsets = tmpReg32; ++ ++ tmpRegNia |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ *(uint32_t *)&p_Ad->ccAdBase = tmpRegNia; ++ ++ return err; ++} ++ ++static t_Error CheckStatsParamsAndSetType(t_FmPcdManip *p_Manip, t_FmPcdStatsParams *p_StatsParams) ++{ ++ ++ switch (p_StatsParams->type) ++ { ++ case (e_FM_PCD_STATS_PER_FLOWID): ++ p_Manip->opcode = HMAN_OC_CAPWAP_INDEXED_STATS; ++ p_Manip->muramAllocate = TRUE; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported statistics type")); ++ } ++ ++ return E_OK; ++} ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ ++static t_Error FillReassmManipParams(t_FmPcdManip *p_Manip, e_NetHeaderType hdr) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; ++ uint32_t tmpReg32; ++ t_Error err = E_OK; ++ ++ /* Creates the Reassembly Parameters table. It contains parameters that are specific to either the IPv4 reassembly ++ function or to the IPv6 reassembly function. If both IPv4 reassembly and IPv6 reassembly are required, then ++ two separate IP Reassembly Parameter tables are required.*/ ++ if ((err = CreateReassTable(p_Manip, hdr)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ /* Sets the first Ad register (ccAdBase) - Action Descriptor Type and Pointer to the Reassembly Parameters Table offset from MURAM*/ ++ tmpReg32 = 0; ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ ++ /* Gets the required Action descriptor table pointer */ ++ switch (hdr) ++ { ++ case HEADER_TYPE_IPv4: ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->reassmParams.ip.h_Ipv4Ad; ++ tmpReg32 |= (uint32_t)(XX_VirtToPhys( ++ p_Manip->reassmParams.ip.p_Ipv4ReassTbl) ++ - (p_FmPcd->physicalMuramBase)); ++ break; ++ case HEADER_TYPE_IPv6: ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->reassmParams.ip.h_Ipv6Ad; ++ tmpReg32 |= (uint32_t)(XX_VirtToPhys( ++ p_Manip->reassmParams.ip.p_Ipv6ReassTbl) ++ - (p_FmPcd->physicalMuramBase)); ++ break; ++ case HEADER_TYPE_CAPWAP: ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->reassmParams.capwap.h_Ad; ++ tmpReg32 |= (uint32_t)(XX_VirtToPhys( ++ p_Manip->reassmParams.capwap.p_ReassTbl) ++ - (p_FmPcd->physicalMuramBase)); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("header type")); ++ } ++ ++ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); ++ ++ /* Sets the second Ad register (matchTblPtr) - Buffer pool ID (BPID for V2) and Scatter/Gather table offset*/ ++ /* mark the Scatter/Gather table offset to be set later on when the port will be known */ ++ p_Manip->updateParams = (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK); ++ ++ if ((hdr == HEADER_TYPE_IPv6) || (hdr == HEADER_TYPE_IPv4)) ++ { ++#if (DPAA_VERSION == 10) ++ tmpReg32 = (uint32_t)(p_Manip->reassmParams.sgBpid << 8); ++ WRITE_UINT32(p_Ad->matchTblPtr, tmpReg32); ++#endif /* (DPAA_VERSION == 10) */ ++#if (DPAA_VERSION >= 11) ++ if (p_Manip->reassmParams.ip.nonConsistentSpFqid != 0) ++ { ++ tmpReg32 = FM_PCD_AD_NCSPFQIDM_MASK ++ | (uint32_t)(p_Manip->reassmParams.ip.nonConsistentSpFqid); ++ WRITE_UINT32(p_Ad->gmask, tmpReg32); ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ /* Sets the third Ad register (pcAndOffsets)- IP Reassemble Operation Code*/ ++ tmpReg32 = 0; ++ tmpReg32 |= (uint32_t)HMAN_OC_IP_REASSEMBLY; ++ } ++#if (DPAA_VERSION >= 11) ++ else ++ if (hdr == HEADER_TYPE_CAPWAP) ++ { ++ tmpReg32 = 0; ++ tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_REASSEMBLY; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); ++ ++ p_Manip->reassm = TRUE; ++ ++ return E_OK; ++} ++ ++static t_Error SetIpv4ReassmManip(t_FmPcdManip *p_Manip) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; ++ ++ /* Allocation if IPv4 Action descriptor */ ++ p_Manip->reassmParams.ip.h_Ipv4Ad = (t_Handle)XX_MallocSmart( ++ FM_PCD_CC_AD_ENTRY_SIZE, p_Manip->reassmParams.dataMemId, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_Manip->reassmParams.ip.h_Ipv4Ad) ++ { ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("Allocation of IPv4 table descriptor")); ++ } ++ ++ memset(p_Manip->reassmParams.ip.h_Ipv4Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* Fill reassembly manipulation parameter in the IP Reassembly Action Descriptor */ ++ return FillReassmManipParams(p_Manip, HEADER_TYPE_IPv4); ++} ++ ++static t_Error SetIpv6ReassmManip(t_FmPcdManip *p_Manip) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; ++ ++ /* Allocation if IPv6 Action descriptor */ ++ p_Manip->reassmParams.ip.h_Ipv6Ad = (t_Handle)XX_MallocSmart( ++ FM_PCD_CC_AD_ENTRY_SIZE, p_Manip->reassmParams.dataMemId, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_Manip->reassmParams.ip.h_Ipv6Ad) ++ { ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("Allocation of IPv6 table descriptor")); ++ } ++ ++ memset(p_Manip->reassmParams.ip.h_Ipv6Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* Fill reassembly manipulation parameter in the IP Reassembly Action Descriptor */ ++ return FillReassmManipParams(p_Manip, HEADER_TYPE_IPv6); ++} ++ ++static t_Error IpReassembly(t_FmPcdManipReassemParams *p_ManipReassmParams, ++ t_FmPcdManip *p_Manip) ++{ ++ uint32_t maxSetNumber = 10000; ++ t_FmPcdManipReassemIpParams reassmManipParams = ++ p_ManipReassmParams->u.ipReassem; ++ t_Error res; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(((t_FmPcd *)p_Manip->h_FmPcd)->h_Hc, ++ E_INVALID_HANDLE); ++ ++ /* Check validation of user's parameter.*/ ++ if ((reassmManipParams.timeoutThresholdForReassmProcess < 1000) ++ || (reassmManipParams.timeoutThresholdForReassmProcess > 8000000)) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("timeoutThresholdForReassmProcess should be 1msec - 8sec")); ++ /* It is recommended that the total number of entries in this table (number of sets * number of ways) ++ will be twice the number of frames that are expected to be reassembled simultaneously.*/ ++ if (reassmManipParams.maxNumFramesInProcess ++ > (reassmManipParams.maxNumFramesInProcess * maxSetNumber / 2)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("maxNumFramesInProcess has to be less than (maximun set number * number of ways / 2)")); ++ ++ if ((p_ManipReassmParams->hdr == HEADER_TYPE_IPv6) ++ && (reassmManipParams.minFragSize[1] < 256)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("minFragSize[1] must be >= 256")); ++ ++ /* Saves user's reassembly manipulation parameters */ ++ p_Manip->reassmParams.ip.relativeSchemeId[0] = ++ reassmManipParams.relativeSchemeId[0]; ++ p_Manip->reassmParams.ip.relativeSchemeId[1] = ++ reassmManipParams.relativeSchemeId[1]; ++ p_Manip->reassmParams.ip.numOfFramesPerHashEntry[0] = ++ reassmManipParams.numOfFramesPerHashEntry[0]; ++ p_Manip->reassmParams.ip.numOfFramesPerHashEntry[1] = ++ reassmManipParams.numOfFramesPerHashEntry[1]; ++ p_Manip->reassmParams.ip.minFragSize[0] = reassmManipParams.minFragSize[0]; ++ p_Manip->reassmParams.ip.minFragSize[1] = reassmManipParams.minFragSize[1]; ++ p_Manip->reassmParams.maxNumFramesInProcess = ++ reassmManipParams.maxNumFramesInProcess; ++ p_Manip->reassmParams.timeOutMode = reassmManipParams.timeOutMode; ++ p_Manip->reassmParams.fqidForTimeOutFrames = ++ reassmManipParams.fqidForTimeOutFrames; ++ p_Manip->reassmParams.timeoutThresholdForReassmProcess = ++ reassmManipParams.timeoutThresholdForReassmProcess; ++ p_Manip->reassmParams.dataMemId = reassmManipParams.dataMemId; ++ p_Manip->reassmParams.dataLiodnOffset = reassmManipParams.dataLiodnOffset; ++#if (DPAA_VERSION == 10) ++ p_Manip->reassmParams.sgBpid = reassmManipParams.sgBpid; ++#endif /* (DPAA_VERSION == 10) */ ++#if (DPAA_VERSION >= 11) ++ if (reassmManipParams.nonConsistentSpFqid != 0) ++ { ++ p_Manip->reassmParams.ip.nonConsistentSpFqid = ++ reassmManipParams.nonConsistentSpFqid; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ /* Creates and initializes the IP Reassembly common parameter table */ ++ CreateReassCommonTable(p_Manip); ++ ++ /* Creation of IPv4 reassembly manipulation */ ++ if ((p_Manip->reassmParams.hdr == HEADER_TYPE_IPv6) ++ || (p_Manip->reassmParams.hdr == HEADER_TYPE_IPv4)) ++ { ++ res = SetIpv4ReassmManip(p_Manip); ++ if (res != E_OK) ++ return res; ++ } ++ ++ /* Creation of IPv6 reassembly manipulation */ ++ if (p_Manip->reassmParams.hdr == HEADER_TYPE_IPv6) ++ { ++ res = SetIpv6ReassmManip(p_Manip); ++ if (res != E_OK) ++ return res; ++ } ++ ++ return E_OK; ++} ++ ++static void setIpReassmSchemeParams(t_FmPcd* p_FmPcd, ++ t_FmPcdKgSchemeParams *p_Scheme, ++ t_Handle h_CcTree, bool ipv4, ++ uint8_t groupId) ++{ ++ uint32_t j; ++ uint8_t res; ++ ++ /* Configures scheme's network environment parameters */ ++ p_Scheme->netEnvParams.numOfDistinctionUnits = 2; ++ if (ipv4) ++ res = FmPcdNetEnvGetUnitId( ++ p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), ++ HEADER_TYPE_IPv4, FALSE, 0); ++ else ++ res = FmPcdNetEnvGetUnitId( ++ p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), ++ HEADER_TYPE_IPv6, FALSE, 0); ++ ASSERT_COND(res != FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ p_Scheme->netEnvParams.unitIds[0] = res; ++ ++ res = FmPcdNetEnvGetUnitId( ++ p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), ++ HEADER_TYPE_USER_DEFINED_SHIM2, FALSE, 0); ++ ASSERT_COND(res != FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ p_Scheme->netEnvParams.unitIds[1] = res; ++ ++ /* Configures scheme's next engine parameters*/ ++ p_Scheme->nextEngine = e_FM_PCD_CC; ++ p_Scheme->kgNextEngineParams.cc.h_CcTree = h_CcTree; ++ p_Scheme->kgNextEngineParams.cc.grpId = groupId; ++ p_Scheme->useHash = TRUE; ++ ++ /* Configures scheme's key*/ ++ if (ipv4 == TRUE) ++ { ++ p_Scheme->keyExtractAndHashParams.numOfUsedExtracts = 4; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].type = ++ e_FM_PCD_EXTRACT_BY_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.type = ++ e_FM_PCD_EXTRACT_FULL_FIELD; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.hdr = ++ HEADER_TYPE_IPv4; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.extractByHdrType.fullField.ipv4 = ++ NET_HEADER_FIELD_IPv4_DST_IP; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].type = ++ e_FM_PCD_EXTRACT_BY_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.type = ++ e_FM_PCD_EXTRACT_FULL_FIELD; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.hdr = ++ HEADER_TYPE_IPv4; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.extractByHdrType.fullField.ipv4 = ++ NET_HEADER_FIELD_IPv4_SRC_IP; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].type = ++ e_FM_PCD_EXTRACT_BY_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.type = ++ e_FM_PCD_EXTRACT_FULL_FIELD; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.hdr = ++ HEADER_TYPE_IPv4; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.extractByHdrType.fullField.ipv4 = ++ NET_HEADER_FIELD_IPv4_PROTO; ++ p_Scheme->keyExtractAndHashParams.extractArray[3].type = ++ e_FM_PCD_EXTRACT_BY_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.hdr = ++ HEADER_TYPE_IPv4; ++ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.type = ++ e_FM_PCD_EXTRACT_FROM_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.ignoreProtocolValidation = ++ FALSE; ++ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.extractByHdrType.fromHdr.size = ++ 2; ++ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.extractByHdrType.fromHdr.offset = ++ 4; ++ } ++ else /* IPv6 */ ++ { ++ p_Scheme->keyExtractAndHashParams.numOfUsedExtracts = 3; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].type = ++ e_FM_PCD_EXTRACT_BY_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.type = ++ e_FM_PCD_EXTRACT_FULL_FIELD; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.hdr = ++ HEADER_TYPE_IPv6; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.extractByHdrType.fullField.ipv6 = ++ NET_HEADER_FIELD_IPv6_DST_IP; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].type = ++ e_FM_PCD_EXTRACT_BY_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.type = ++ e_FM_PCD_EXTRACT_FULL_FIELD; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.hdr = ++ HEADER_TYPE_IPv6; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.extractByHdrType.fullField.ipv6 = ++ NET_HEADER_FIELD_IPv6_SRC_IP; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].type = ++ e_FM_PCD_EXTRACT_BY_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.hdr = ++ HEADER_TYPE_USER_DEFINED_SHIM2; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.type = ++ e_FM_PCD_EXTRACT_FROM_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.extractByHdrType.fromHdr.size = ++ 4; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.extractByHdrType.fromHdr.offset = ++ 4; ++ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.ignoreProtocolValidation = ++ TRUE; ++ } ++ ++ p_Scheme->keyExtractAndHashParams.privateDflt0 = 0x01020304; ++ p_Scheme->keyExtractAndHashParams.privateDflt1 = 0x11121314; ++ p_Scheme->keyExtractAndHashParams.numOfUsedDflts = ++ FM_PCD_KG_NUM_OF_DEFAULT_GROUPS; ++ for (j = 0; j < FM_PCD_KG_NUM_OF_DEFAULT_GROUPS; j++) ++ { ++ p_Scheme->keyExtractAndHashParams.dflts[j].type = ++ (e_FmPcdKgKnownFieldsDfltTypes)j; /* all types */ ++ p_Scheme->keyExtractAndHashParams.dflts[j].dfltSelect = ++ e_FM_PCD_KG_DFLT_GBL_0; ++ } ++} ++ ++static t_Error IpReassemblyStats(t_FmPcdManip *p_Manip, ++ t_FmPcdManipReassemIpStats *p_Stats) ++{ ++ ASSERT_COND(p_Manip); ++ ASSERT_COND(p_Stats); ++ ASSERT_COND(p_Manip->reassmParams.p_ReassCommonTbl); ++ ++ p_Stats->timeout = ++ GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalTimeOutCounter); ++ p_Stats->rfdPoolBusy = ++ GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalRfdPoolBusyCounter); ++ p_Stats->internalBufferBusy = ++ GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalInternalBufferBusy); ++ p_Stats->externalBufferBusy = ++ GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalExternalBufferBusy); ++ p_Stats->sgFragments = ++ GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalSgFragmentCounter); ++ p_Stats->dmaSemaphoreDepletion = ++ GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalDmaSemaphoreDepletionCounter); ++#if (DPAA_VERSION >= 11) ++ p_Stats->nonConsistentSp = ++ GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalNCSPCounter); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (p_Manip->reassmParams.ip.p_Ipv4ReassTbl) ++ { ++ p_Stats->specificHdrStatistics[0].successfullyReassembled = ++ GET_UINT32(p_Manip->reassmParams.ip.p_Ipv4ReassTbl->totalSuccessfullyReasmFramesCounter); ++ p_Stats->specificHdrStatistics[0].validFragments = ++ GET_UINT32(p_Manip->reassmParams.ip.p_Ipv4ReassTbl->totalValidFragmentCounter); ++ p_Stats->specificHdrStatistics[0].processedFragments = ++ GET_UINT32(p_Manip->reassmParams.ip.p_Ipv4ReassTbl->totalProcessedFragCounter); ++ p_Stats->specificHdrStatistics[0].malformedFragments = ++ GET_UINT32(p_Manip->reassmParams.ip.p_Ipv4ReassTbl->totalMalformdFragCounter); ++ p_Stats->specificHdrStatistics[0].autoLearnBusy = ++ GET_UINT32(p_Manip->reassmParams.ip.p_Ipv4ReassTbl->totalSetBusyCounter); ++ p_Stats->specificHdrStatistics[0].discardedFragments = ++ GET_UINT32(p_Manip->reassmParams.ip.p_Ipv4ReassTbl->totalDiscardedFragsCounter); ++ p_Stats->specificHdrStatistics[0].moreThan16Fragments = ++ GET_UINT32(p_Manip->reassmParams.ip.p_Ipv4ReassTbl->totalMoreThan16FramesCounter); ++ } ++ if (p_Manip->reassmParams.ip.p_Ipv6ReassTbl) ++ { ++ p_Stats->specificHdrStatistics[1].successfullyReassembled = ++ GET_UINT32(p_Manip->reassmParams.ip.p_Ipv6ReassTbl->totalSuccessfullyReasmFramesCounter); ++ p_Stats->specificHdrStatistics[1].validFragments = ++ GET_UINT32(p_Manip->reassmParams.ip.p_Ipv6ReassTbl->totalValidFragmentCounter); ++ p_Stats->specificHdrStatistics[1].processedFragments = ++ GET_UINT32(p_Manip->reassmParams.ip.p_Ipv6ReassTbl->totalProcessedFragCounter); ++ p_Stats->specificHdrStatistics[1].malformedFragments = ++ GET_UINT32(p_Manip->reassmParams.ip.p_Ipv6ReassTbl->totalMalformdFragCounter); ++ p_Stats->specificHdrStatistics[1].autoLearnBusy = ++ GET_UINT32(p_Manip->reassmParams.ip.p_Ipv6ReassTbl->totalSetBusyCounter); ++ p_Stats->specificHdrStatistics[1].discardedFragments = ++ GET_UINT32(p_Manip->reassmParams.ip.p_Ipv6ReassTbl->totalDiscardedFragsCounter); ++ p_Stats->specificHdrStatistics[1].moreThan16Fragments = ++ GET_UINT32(p_Manip->reassmParams.ip.p_Ipv6ReassTbl->totalMoreThan16FramesCounter); ++ } ++ return E_OK; ++} ++ ++static t_Error IpFragmentationStats(t_FmPcdManip *p_Manip, ++ t_FmPcdManipFragIpStats *p_Stats) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ ++ ASSERT_COND(p_Manip); ++ ASSERT_COND(p_Stats); ++ ASSERT_COND(p_Manip->h_Ad); ++ ASSERT_COND(p_Manip->fragParams.p_Frag); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ ++ p_Stats->totalFrames = GET_UINT32(p_Ad->gmask); ++ p_Stats->fragmentedFrames = GET_UINT32(p_Manip->fragParams.p_Frag->ccAdBase) ++ & 0x00ffffff; ++ p_Stats->generatedFragments = ++ GET_UINT32(p_Manip->fragParams.p_Frag->matchTblPtr); ++ ++ return E_OK; ++} ++ ++static t_Error IpFragmentation(t_FmPcdManipFragIpParams *p_ManipParams, ++ t_FmPcdManip *p_Manip) ++{ ++ uint32_t pcAndOffsetsReg = 0, ccAdBaseReg = 0, gmaskReg = 0; ++ t_FmPcd *p_FmPcd; ++#if (DPAA_VERSION == 10) ++ t_Error err = E_OK; ++#endif /* (DPAA_VERSION == 10) */ ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_ManipParams->sizeForFragmentation != 0xFFFF, ++ E_INVALID_VALUE); ++ ++ p_FmPcd = p_Manip->h_FmPcd; ++ /* Allocation of fragmentation Action Descriptor */ ++ p_Manip->fragParams.p_Frag = (t_AdOfTypeContLookup *)FM_MURAM_AllocMem( ++ p_FmPcd->h_FmMuram, FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_Manip->fragParams.p_Frag) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("MURAM alloc for Fragmentation table descriptor")); ++ IOMemSet32(p_Manip->fragParams.p_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* Prepare the third Ad register (pcAndOffsets)- OperationCode */ ++ pcAndOffsetsReg = (uint32_t)HMAN_OC_IP_FRAGMENTATION; ++ ++ /* Prepare the first Ad register (ccAdBase) - Don't frag action and Action descriptor type*/ ++ ccAdBaseReg = FM_PCD_AD_CONT_LOOKUP_TYPE; ++ ccAdBaseReg |= (p_ManipParams->dontFragAction ++ << FM_PCD_MANIP_IP_FRAG_DF_SHIFT); ++ ++ ++ /* Set Scatter/Gather BPid */ ++ if (p_ManipParams->sgBpidEn) ++ { ++ ccAdBaseReg |= FM_PCD_MANIP_IP_FRAG_SG_BDID_EN; ++ pcAndOffsetsReg |= ((p_ManipParams->sgBpid ++ << FM_PCD_MANIP_IP_FRAG_SG_BDID_SHIFT) ++ & FM_PCD_MANIP_IP_FRAG_SG_BDID_MASK); ++ } ++ ++ /* Prepare the first Ad register (gmask) - scratch buffer pool id and Pointer to fragment ID */ ++ gmaskReg = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_FmPcd->ipv6FrameIdAddr)) ++ - p_FmPcd->physicalMuramBase); ++#if (DPAA_VERSION == 10) ++ gmaskReg |= p_ManipParams->scratchBpid << FM_PCD_MANIP_IP_FRAG_SCRATCH_BPID; ++#else ++ gmaskReg |= (0xFF) << FM_PCD_MANIP_IP_FRAG_SCRATCH_BPID; ++#endif /* (DPAA_VERSION == 10) */ ++ ++ /* Set all Ad registers */ ++ WRITE_UINT32(p_Manip->fragParams.p_Frag->pcAndOffsets, pcAndOffsetsReg); ++ WRITE_UINT32(p_Manip->fragParams.p_Frag->ccAdBase, ccAdBaseReg); ++ WRITE_UINT32(p_Manip->fragParams.p_Frag->gmask, gmaskReg); ++ ++ /* Saves user's fragmentation manipulation parameters */ ++ p_Manip->frag = TRUE; ++ p_Manip->sizeForFragmentation = p_ManipParams->sizeForFragmentation; ++ ++#if (DPAA_VERSION == 10) ++ p_Manip->fragParams.scratchBpid = p_ManipParams->scratchBpid; ++ ++ /* scratch buffer pool initialization */ ++ if ((err = FmPcdFragHcScratchPoolFill((t_Handle)p_FmPcd, p_ManipParams->scratchBpid)) != E_OK) ++ { ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_Frag); ++ p_Manip->fragParams.p_Frag = NULL; ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++#endif /* (DPAA_VERSION == 10) */ ++ ++ return E_OK; ++} ++ ++static t_Error IPManip(t_FmPcdManip *p_Manip) ++{ ++ t_Error err = E_OK; ++ t_FmPcd *p_FmPcd; ++ t_AdOfTypeContLookup *p_Ad; ++ uint32_t tmpReg32 = 0, tmpRegNia = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); ++ p_FmPcd = p_Manip->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ ++ tmpReg32 = FM_PCD_MANIP_IP_NO_FRAGMENTATION; ++ if (p_Manip->frag == TRUE) ++ { ++ tmpRegNia = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_Frag) ++ - (p_FmPcd->physicalMuramBase)); ++ tmpReg32 = (uint32_t)p_Manip->sizeForFragmentation ++ << FM_PCD_MANIP_IP_MTU_SHIFT; ++ } ++ ++ tmpRegNia |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ tmpReg32 |= HMAN_OC_IP_MANIP; ++ ++#if (DPAA_VERSION >= 11) ++ tmpRegNia |= FM_PCD_MANIP_IP_CNIA; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); ++ WRITE_UINT32(p_Ad->ccAdBase, tmpRegNia); ++ WRITE_UINT32(p_Ad->gmask, 0); ++ /* Total frame counter - MUST be initialized to zero.*/ ++ ++ return err; ++} ++ ++static t_Error UpdateInitIpFrag(t_Handle h_FmPcd, t_Handle h_PcdParams, ++ t_Handle h_FmPort, t_FmPcdManip *p_Manip, ++ t_Handle h_Ad, bool validate) ++{ ++ t_FmPortGetSetCcParams fmPortGetSetCcParams; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Manip->opcode == HMAN_OC_IP_FRAGMENTATION), ++ E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE); ++ ++ UNUSED(h_FmPcd); ++ UNUSED(h_Ad); ++ UNUSED(h_PcdParams); ++ UNUSED(validate); ++ UNUSED(p_Manip); ++ ++ fmPortGetSetCcParams.setCcParams.type = 0; ++ fmPortGetSetCcParams.getCcParams.type = MANIP_EXTRA_SPACE; ++ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (!fmPortGetSetCcParams.getCcParams.internalBufferOffset) ++ DBG(WARNING, ("manipExtraSpace must be larger than '0'")); ++ ++ return E_OK; ++} ++ ++static t_Error IPSecManip(t_FmPcdManipParams *p_ManipParams, ++ t_FmPcdManip *p_Manip) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ t_FmPcdManipSpecialOffloadIPSecParams *p_IPSecParams; ++ t_Error err = E_OK; ++ uint32_t tmpReg32 = 0; ++ uint32_t power; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_ManipParams, E_INVALID_HANDLE); ++ ++ p_IPSecParams = &p_ManipParams->u.specialOffload.u.ipsec; ++ ++ SANITY_CHECK_RETURN_ERROR( ++ !p_IPSecParams->variableIpHdrLen || p_IPSecParams->decryption, ++ E_INVALID_VALUE); ++ SANITY_CHECK_RETURN_ERROR( ++ !p_IPSecParams->variableIpVersion || !p_IPSecParams->decryption, ++ E_INVALID_VALUE); ++ SANITY_CHECK_RETURN_ERROR( ++ !p_IPSecParams->variableIpVersion || p_IPSecParams->outerIPHdrLen, ++ E_INVALID_VALUE); ++ SANITY_CHECK_RETURN_ERROR( ++ !p_IPSecParams->arwSize || p_IPSecParams->arwAddr, ++ E_INVALID_VALUE); ++ SANITY_CHECK_RETURN_ERROR( ++ !p_IPSecParams->arwSize || p_IPSecParams->decryption, ++ E_INVALID_VALUE); ++ SANITY_CHECK_RETURN_ERROR((p_IPSecParams->arwSize % 16) == 0, E_INVALID_VALUE); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ tmpReg32 |= (p_IPSecParams->decryption) ? FM_PCD_MANIP_IPSEC_DEC : 0; ++ tmpReg32 |= (p_IPSecParams->ecnCopy) ? FM_PCD_MANIP_IPSEC_ECN_EN : 0; ++ tmpReg32 |= (p_IPSecParams->dscpCopy) ? FM_PCD_MANIP_IPSEC_DSCP_EN : 0; ++ tmpReg32 |= ++ (p_IPSecParams->variableIpHdrLen) ? FM_PCD_MANIP_IPSEC_VIPL_EN : 0; ++ tmpReg32 |= ++ (p_IPSecParams->variableIpVersion) ? FM_PCD_MANIP_IPSEC_VIPV_EN : 0; ++ if (p_IPSecParams->arwSize) ++ tmpReg32 |= (uint32_t)((XX_VirtToPhys(UINT_TO_PTR(p_IPSecParams->arwAddr))-FM_MM_MURAM) ++ & (FM_MURAM_SIZE-1)); ++ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); ++ ++ tmpReg32 = 0; ++ if (p_IPSecParams->arwSize) { ++ NEXT_POWER_OF_2((p_IPSecParams->arwSize + 32), power); ++ LOG2(power, power); ++ tmpReg32 = (p_IPSecParams->arwSize | (power - 5)) << FM_PCD_MANIP_IPSEC_ARW_SIZE_SHIFT; ++ } ++ ++ if (p_ManipParams->h_NextManip) ++ tmpReg32 |= ++ (uint32_t)(XX_VirtToPhys(((t_FmPcdManip *)p_ManipParams->h_NextManip)->h_Ad)- ++ (((t_FmPcd *)p_Manip->h_FmPcd)->physicalMuramBase)) >> 4; ++ WRITE_UINT32(p_Ad->matchTblPtr, tmpReg32); ++ ++ tmpReg32 = HMAN_OC_IPSEC_MANIP; ++ tmpReg32 |= p_IPSecParams->outerIPHdrLen ++ << FM_PCD_MANIP_IPSEC_IP_HDR_LEN_SHIFT; ++ if (p_ManipParams->h_NextManip) ++ tmpReg32 |= FM_PCD_MANIP_IPSEC_NADEN; ++ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); ++ ++ return err; ++} ++ ++static t_Error SetCapwapReassmManip(t_FmPcdManip *p_Manip) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd; ++ ++ /* Allocation if CAPWAP Action descriptor */ ++ p_Manip->reassmParams.capwap.h_Ad = (t_Handle)XX_MallocSmart( ++ FM_PCD_CC_AD_ENTRY_SIZE, p_Manip->reassmParams.dataMemId, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_Manip->reassmParams.capwap.h_Ad) ++ { ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("Allocation of CAPWAP table descriptor")); ++ } ++ ++ memset(p_Manip->reassmParams.capwap.h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* Fill reassembly manipulation parameter in the Reassembly Action Descriptor */ ++ return FillReassmManipParams(p_Manip, HEADER_TYPE_CAPWAP); ++} ++ ++static void setCapwapReassmSchemeParams(t_FmPcd* p_FmPcd, ++ t_FmPcdKgSchemeParams *p_Scheme, ++ t_Handle h_CcTree, uint8_t groupId) ++{ ++ uint8_t res; ++ ++ /* Configures scheme's network environment parameters */ ++ p_Scheme->netEnvParams.numOfDistinctionUnits = 1; ++ res = FmPcdNetEnvGetUnitId( ++ p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), ++ HEADER_TYPE_USER_DEFINED_SHIM2, FALSE, 0); ++ ASSERT_COND(res != FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ p_Scheme->netEnvParams.unitIds[0] = res; ++ ++ /* Configures scheme's next engine parameters*/ ++ p_Scheme->nextEngine = e_FM_PCD_CC; ++ p_Scheme->kgNextEngineParams.cc.h_CcTree = h_CcTree; ++ p_Scheme->kgNextEngineParams.cc.grpId = groupId; ++ p_Scheme->useHash = TRUE; ++ ++ /* Configures scheme's key*/ ++ p_Scheme->keyExtractAndHashParams.numOfUsedExtracts = 2; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].type = ++ e_FM_PCD_EXTRACT_NON_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].extractNonHdr.src = ++ e_FM_PCD_EXTRACT_FROM_PARSE_RESULT; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].extractNonHdr.action = ++ e_FM_PCD_ACTION_NONE; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].extractNonHdr.offset = 20; ++ p_Scheme->keyExtractAndHashParams.extractArray[0].extractNonHdr.size = 4; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].type = ++ e_FM_PCD_EXTRACT_NON_HDR; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].extractNonHdr.src = ++ e_FM_PCD_EXTRACT_FROM_DFLT_VALUE; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].extractNonHdr.action = ++ e_FM_PCD_ACTION_NONE; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].extractNonHdr.offset = 0; ++ p_Scheme->keyExtractAndHashParams.extractArray[1].extractNonHdr.size = 1; ++ ++ p_Scheme->keyExtractAndHashParams.privateDflt0 = 0x0; ++ p_Scheme->keyExtractAndHashParams.privateDflt1 = 0x0; ++ p_Scheme->keyExtractAndHashParams.numOfUsedDflts = 1; ++ p_Scheme->keyExtractAndHashParams.dflts[0].type = e_FM_PCD_KG_GENERIC_NOT_FROM_DATA; ++ p_Scheme->keyExtractAndHashParams.dflts[0].dfltSelect = e_FM_PCD_KG_DFLT_PRIVATE_0; ++} ++ ++#if (DPAA_VERSION >= 11) ++static t_Error CapwapReassemblyStats(t_FmPcdManip *p_Manip, ++ t_FmPcdManipReassemCapwapStats *p_Stats) ++{ ++ ASSERT_COND(p_Manip); ++ ASSERT_COND(p_Stats); ++ ASSERT_COND(p_Manip->reassmParams.p_ReassCommonTbl); ++ ++ p_Stats->timeout = ++ GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalTimeOutCounter); ++ p_Stats->rfdPoolBusy = ++ GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalRfdPoolBusyCounter); ++ p_Stats->internalBufferBusy = ++ GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalInternalBufferBusy); ++ p_Stats->externalBufferBusy = ++ GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalExternalBufferBusy); ++ p_Stats->sgFragments = ++ GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalSgFragmentCounter); ++ p_Stats->dmaSemaphoreDepletion = ++ GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalDmaSemaphoreDepletionCounter); ++ p_Stats->exceedMaxReassemblyFrameLen = ++ GET_UINT32(p_Manip->reassmParams.p_ReassCommonTbl->totalNCSPCounter); ++ ++ p_Stats->successfullyReassembled = ++ GET_UINT32(p_Manip->reassmParams.capwap.p_ReassTbl->totalSuccessfullyReasmFramesCounter); ++ p_Stats->validFragments = ++ GET_UINT32(p_Manip->reassmParams.capwap.p_ReassTbl->totalValidFragmentCounter); ++ p_Stats->processedFragments = ++ GET_UINT32(p_Manip->reassmParams.capwap.p_ReassTbl->totalProcessedFragCounter); ++ p_Stats->malformedFragments = ++ GET_UINT32(p_Manip->reassmParams.capwap.p_ReassTbl->totalMalformdFragCounter); ++ p_Stats->autoLearnBusy = ++ GET_UINT32(p_Manip->reassmParams.capwap.p_ReassTbl->totalSetBusyCounter); ++ p_Stats->discardedFragments = ++ GET_UINT32(p_Manip->reassmParams.capwap.p_ReassTbl->totalDiscardedFragsCounter); ++ p_Stats->moreThan16Fragments = ++ GET_UINT32(p_Manip->reassmParams.capwap.p_ReassTbl->totalMoreThan16FramesCounter); ++ ++ return E_OK; ++} ++ ++static t_Error CapwapFragmentationStats(t_FmPcdManip *p_Manip, ++ t_FmPcdManipFragCapwapStats *p_Stats) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ ++ ASSERT_COND(p_Manip); ++ ASSERT_COND(p_Stats); ++ ASSERT_COND(p_Manip->h_Ad); ++ ASSERT_COND(p_Manip->fragParams.p_Frag); ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ ++ p_Stats->totalFrames = GET_UINT32(p_Ad->gmask); ++ ++ return E_OK; ++} ++ ++static t_Error CapwapReassembly(t_FmPcdManipReassemParams *p_ManipReassmParams, ++ t_FmPcdManip *p_Manip) ++{ ++ uint32_t maxSetNumber = 10000; ++ t_FmPcdManipReassemCapwapParams reassmManipParams = ++ p_ManipReassmParams->u.capwapReassem; ++ t_Error res; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(((t_FmPcd *)p_Manip->h_FmPcd)->h_Hc, ++ E_INVALID_HANDLE); ++ ++ /* Check validation of user's parameter.*/ ++ if ((reassmManipParams.timeoutThresholdForReassmProcess < 1000) ++ || (reassmManipParams.timeoutThresholdForReassmProcess > 8000000)) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("timeoutThresholdForReassmProcess should be 1msec - 8sec")); ++ /* It is recommended that the total number of entries in this table (number of sets * number of ways) ++ will be twice the number of frames that are expected to be reassembled simultaneously.*/ ++ if (reassmManipParams.maxNumFramesInProcess ++ > (reassmManipParams.maxNumFramesInProcess * maxSetNumber / 2)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("maxNumFramesInProcess has to be less than (maximun set number * number of ways / 2)")); ++ ++ /* Saves user's reassembly manipulation parameters */ ++ p_Manip->reassmParams.capwap.relativeSchemeId = ++ reassmManipParams.relativeSchemeId; ++ p_Manip->reassmParams.capwap.numOfFramesPerHashEntry = ++ reassmManipParams.numOfFramesPerHashEntry; ++ p_Manip->reassmParams.capwap.maxRessembledsSize = ++ reassmManipParams.maxReassembledFrameLength; ++ p_Manip->reassmParams.maxNumFramesInProcess = ++ reassmManipParams.maxNumFramesInProcess; ++ p_Manip->reassmParams.timeOutMode = reassmManipParams.timeOutMode; ++ p_Manip->reassmParams.fqidForTimeOutFrames = ++ reassmManipParams.fqidForTimeOutFrames; ++ p_Manip->reassmParams.timeoutThresholdForReassmProcess = ++ reassmManipParams.timeoutThresholdForReassmProcess; ++ p_Manip->reassmParams.dataMemId = reassmManipParams.dataMemId; ++ p_Manip->reassmParams.dataLiodnOffset = reassmManipParams.dataLiodnOffset; ++ ++ /* Creates and initializes the Reassembly common parameter table */ ++ CreateReassCommonTable(p_Manip); ++ ++ res = SetCapwapReassmManip(p_Manip); ++ if (res != E_OK) ++ return res; ++ ++ return E_OK; ++} ++ ++static t_Error CapwapFragmentation(t_FmPcdManipFragCapwapParams *p_ManipParams, ++ t_FmPcdManip *p_Manip) ++{ ++ t_FmPcd *p_FmPcd; ++ t_AdOfTypeContLookup *p_Ad; ++ uint32_t pcAndOffsetsReg = 0, ccAdBaseReg = 0, gmaskReg = 0; ++ uint32_t tmpReg32 = 0, tmpRegNia = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_ManipParams->sizeForFragmentation != 0xFFFF, ++ E_INVALID_VALUE); ++ p_FmPcd = p_Manip->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ /* Allocation of fragmentation Action Descriptor */ ++ p_Manip->fragParams.p_Frag = (t_AdOfTypeContLookup *)FM_MURAM_AllocMem( ++ p_FmPcd->h_FmMuram, FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_Manip->fragParams.p_Frag) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("MURAM alloc for Fragmentation table descriptor")); ++ IOMemSet32(p_Manip->fragParams.p_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* Prepare the third Ad register (pcAndOffsets)- OperationCode */ ++ pcAndOffsetsReg = (uint32_t)HMAN_OC_CAPWAP_FRAGMENTATION; ++ ++ /* Prepare the first Ad register (ccAdBase) - Don't frag action and Action descriptor type*/ ++ ccAdBaseReg = FM_PCD_AD_CONT_LOOKUP_TYPE; ++ ccAdBaseReg |= ++ (p_ManipParams->compressModeEn) ? FM_PCD_MANIP_CAPWAP_FRAG_COMPRESS_EN : ++ 0; ++ ++ /* Set Scatter/Gather BPid */ ++ if (p_ManipParams->sgBpidEn) ++ { ++ ccAdBaseReg |= FM_PCD_MANIP_CAPWAP_FRAG_SG_BDID_EN; ++ pcAndOffsetsReg |= ((p_ManipParams->sgBpid ++ << FM_PCD_MANIP_CAPWAP_FRAG_SG_BDID_SHIFT) ++ & FM_PCD_MANIP_CAPWAP_FRAG_SG_BDID_MASK); ++ } ++ ++ /* Prepare the first Ad register (gmask) - scratch buffer pool id and Pointer to fragment ID */ ++ gmaskReg = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_FmPcd->capwapFrameIdAddr)) ++ - p_FmPcd->physicalMuramBase); ++ gmaskReg |= (0xFF) << FM_PCD_MANIP_IP_FRAG_SCRATCH_BPID; ++ ++ /* Set all Ad registers */ ++ WRITE_UINT32(p_Manip->fragParams.p_Frag->pcAndOffsets, pcAndOffsetsReg); ++ WRITE_UINT32(p_Manip->fragParams.p_Frag->ccAdBase, ccAdBaseReg); ++ WRITE_UINT32(p_Manip->fragParams.p_Frag->gmask, gmaskReg); ++ ++ /* Saves user's fragmentation manipulation parameters */ ++ p_Manip->frag = TRUE; ++ p_Manip->sizeForFragmentation = p_ManipParams->sizeForFragmentation; ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ ++ tmpRegNia = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_Frag) ++ - (p_FmPcd->physicalMuramBase)); ++ tmpReg32 = (uint32_t)p_Manip->sizeForFragmentation ++ << FM_PCD_MANIP_CAPWAP_FRAG_CHECK_MTU_SHIFT; ++ ++ tmpRegNia |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ tmpReg32 |= HMAN_OC_CAPWAP_FRAG_CHECK; ++ ++ tmpRegNia |= FM_PCD_MANIP_CAPWAP_FRAG_CHECK_CNIA; ++ ++ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); ++ WRITE_UINT32(p_Ad->ccAdBase, tmpRegNia); ++ WRITE_UINT32(p_Ad->gmask, 0); ++ /* Total frame counter - MUST be initialized to zero.*/ ++ ++ return E_OK; ++} ++ ++static t_Error UpdateInitCapwapFrag(t_Handle h_FmPcd, t_Handle h_PcdParams, ++ t_Handle h_FmPort, t_FmPcdManip *p_Manip, ++ t_Handle h_Ad, bool validate) ++{ ++ t_FmPortGetSetCcParams fmPortGetSetCcParams; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Manip->opcode == HMAN_OC_CAPWAP_FRAGMENTATION), ++ E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE); ++ ++ UNUSED(h_FmPcd); ++ UNUSED(h_Ad); ++ UNUSED(h_PcdParams); ++ UNUSED(validate); ++ UNUSED(p_Manip); ++ ++ fmPortGetSetCcParams.setCcParams.type = 0; ++ fmPortGetSetCcParams.getCcParams.type = MANIP_EXTRA_SPACE; ++ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (!fmPortGetSetCcParams.getCcParams.internalBufferOffset) ++ DBG(WARNING, ("manipExtraSpace must be larger than '0'")); ++ ++ return E_OK; ++} ++ ++static t_Error CapwapManip(t_FmPcdManipParams *p_ManipParams, ++ t_FmPcdManip *p_Manip) ++{ ++ t_AdOfTypeContLookup *p_Ad; ++ t_FmPcdManipSpecialOffloadCapwapParams *p_Params; ++ t_Error err = E_OK; ++ uint32_t tmpReg32 = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_ManipParams, E_INVALID_HANDLE); ++ ++ p_Params = &p_ManipParams->u.specialOffload.u.capwap; ++ ++ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad; ++ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE; ++ tmpReg32 |= (p_Params->dtls) ? FM_PCD_MANIP_CAPWAP_DTLS : 0; ++ /* TODO - add 'qosSrc' */ ++ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32); ++ ++ tmpReg32 = HMAN_OC_CAPWAP_MANIP; ++ if (p_ManipParams->h_NextManip) ++ { ++ WRITE_UINT32( ++ p_Ad->matchTblPtr, ++ (uint32_t)(XX_VirtToPhys(((t_FmPcdManip *)p_ManipParams->h_NextManip)->h_Ad)- (((t_FmPcd *)p_Manip->h_FmPcd)->physicalMuramBase)) >> 4); ++ ++ tmpReg32 |= FM_PCD_MANIP_CAPWAP_NADEN; ++ } ++ ++ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32); ++ ++ return err; ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++static t_Handle ManipOrStatsSetNode(t_Handle h_FmPcd, t_Handle *p_Params, ++ bool stats) ++{ ++ t_FmPcdManip *p_Manip; ++ t_Error err; ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ ++ p_Manip = (t_FmPcdManip*)XX_Malloc(sizeof(t_FmPcdManip)); ++ if (!p_Manip) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); ++ return NULL; ++ } ++ memset(p_Manip, 0, sizeof(t_FmPcdManip)); ++ ++ p_Manip->type = ((t_FmPcdManipParams *)p_Params)->type; ++ memcpy((uint8_t*)&p_Manip->manipParams, p_Params, ++ sizeof(p_Manip->manipParams)); ++ ++ if (!stats) ++ err = CheckManipParamsAndSetType(p_Manip, ++ (t_FmPcdManipParams *)p_Params); ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++ else ++ err = CheckStatsParamsAndSetType(p_Manip, (t_FmPcdStatsParams *)p_Params); ++#else /* not (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ else ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Statistics node!")); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Invalid header manipulation type")); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ ++ if ((p_Manip->opcode != HMAN_OC_IP_REASSEMBLY) && (p_Manip->opcode != HMAN_OC_CAPWAP_REASSEMBLY)) ++ { ++ /* In Case of reassembly manipulation the reassembly action descriptor will ++ be defines later on */ ++ if (p_Manip->muramAllocate) ++ { ++ p_Manip->h_Ad = (t_Handle)FM_MURAM_AllocMem( ++ p_FmPcd->h_FmMuram, FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_Manip->h_Ad) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Manipulation action descriptor")); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ ++ IOMemSet32(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ } ++ else ++ { ++ p_Manip->h_Ad = (t_Handle)XX_Malloc( ++ FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t)); ++ if (!p_Manip->h_Ad) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of Manipulation action descriptor")); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ ++ memset(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t)); ++ } ++ } ++ ++ p_Manip->h_FmPcd = h_FmPcd; ++ ++ return p_Manip; ++} ++ ++static void UpdateAdPtrOfNodesWhichPointsOnCrntMdfManip( ++ t_FmPcdManip *p_CrntMdfManip, t_List *h_NodesLst) ++{ ++ t_CcNodeInformation *p_CcNodeInformation; ++ t_FmPcdCcNode *p_NodePtrOnCurrentMdfManip = NULL; ++ t_List *p_Pos; ++ int i = 0; ++ t_Handle p_AdTablePtOnCrntCurrentMdfNode/*, p_AdTableNewModified*/; ++ t_CcNodeInformation ccNodeInfo; ++ ++ LIST_FOR_EACH(p_Pos, &p_CrntMdfManip->nodesLst) ++ { ++ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos); ++ p_NodePtrOnCurrentMdfManip = ++ (t_FmPcdCcNode *)p_CcNodeInformation->h_CcNode; ++ ++ ASSERT_COND(p_NodePtrOnCurrentMdfManip); ++ ++ /* Search in the previous node which exact index points on this current modified node for getting AD */ ++ for (i = 0; i < p_NodePtrOnCurrentMdfManip->numOfKeys + 1; i++) ++ { ++ if (p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].nextEngineParams.nextEngine ++ == e_FM_PCD_CC) ++ { ++ if (p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].nextEngineParams.h_Manip ++ == (t_Handle)p_CrntMdfManip) ++ { ++ if (p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].p_StatsObj) ++ p_AdTablePtOnCrntCurrentMdfNode = ++ p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].p_StatsObj->h_StatsAd; ++ else ++ p_AdTablePtOnCrntCurrentMdfNode = ++ PTR_MOVE(p_NodePtrOnCurrentMdfManip->h_AdTable, i*FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation)); ++ ccNodeInfo.h_CcNode = p_AdTablePtOnCrntCurrentMdfNode; ++ EnqueueNodeInfoToRelevantLst(h_NodesLst, &ccNodeInfo, NULL); ++ } ++ } ++ } ++ ++ ASSERT_COND(i != p_NodePtrOnCurrentMdfManip->numOfKeys); ++ } ++} ++ ++static void BuildHmtd(uint8_t *p_Dest, uint8_t *p_Src, uint8_t *p_Hmcd, ++ t_FmPcd *p_FmPcd) ++{ ++ t_Error err; ++ ++ /* Copy the HMTD */ ++ IO2IOCpy32(p_Dest, (uint8_t*)p_Src, 16); ++ /* Replace the HMCT table pointer */ ++ WRITE_UINT32( ++ ((t_Hmtd *)p_Dest)->hmcdBasePtr, ++ (uint32_t)(XX_VirtToPhys(p_Hmcd) - ((t_FmPcd*)p_FmPcd)->physicalMuramBase)); ++ /* Call Host Command to replace HMTD by a new HMTD */ ++ err = FmHcPcdCcDoDynamicChange( ++ p_FmPcd->h_Hc, ++ (uint32_t)(XX_VirtToPhys(p_Src) - p_FmPcd->physicalMuramBase), ++ (uint32_t)(XX_VirtToPhys(p_Dest) - p_FmPcd->physicalMuramBase)); ++ if (err) ++ REPORT_ERROR(MINOR, err, ("Failed in dynamic manip change, continued to the rest of the owners.")); ++} ++ ++static t_Error FmPcdManipInitUpdate(t_Handle h_FmPcd, t_Handle h_PcdParams, ++ t_Handle h_FmPort, t_Handle h_Manip, ++ t_Handle h_Ad, bool validate, int level, ++ t_Handle h_FmTree) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_Manip, E_INVALID_HANDLE); ++ ++ UNUSED(level); ++ UNUSED(h_FmTree); ++ ++ switch (p_Manip->opcode) ++ { ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): ++ err = UpdateInitMvIntFrameHeaderFromFrameToBufferPrefix(h_FmPort, ++ p_Manip, ++ h_Ad, ++ validate); ++ break; ++ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER): ++ if (!p_Manip->h_Frag) ++ break; ++ case (HMAN_OC_CAPWAP_FRAGMENTATION): ++ err = UpdateInitCapwapFragmentation(h_FmPort, p_Manip, h_Ad, validate, h_FmTree); ++ break; ++ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): ++ if (p_Manip->h_Frag) ++ err = UpdateInitCapwapReasm(h_FmPcd, h_FmPort, p_Manip, h_Ad, validate); ++ break; ++ case (HMAN_OC_CAPWAP_INDEXED_STATS): ++ err = UpdateIndxStats(h_FmPcd, h_FmPort, p_Manip); ++ break; ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ case (HMAN_OC_IP_REASSEMBLY): ++ err = UpdateInitReasm(h_FmPcd, h_PcdParams, h_FmPort, p_Manip, h_Ad, ++ validate); ++ break; ++ case (HMAN_OC_IP_FRAGMENTATION): ++ err = UpdateInitIpFrag(h_FmPcd, h_PcdParams, h_FmPort, p_Manip, ++ h_Ad, validate); ++ break; ++#if (DPAA_VERSION >= 11) ++ case (HMAN_OC_CAPWAP_FRAGMENTATION): ++ err = UpdateInitCapwapFrag(h_FmPcd, h_PcdParams, h_FmPort, p_Manip, ++ h_Ad, validate); ++ break; ++ case (HMAN_OC_CAPWAP_REASSEMBLY): ++ err = UpdateInitReasm(h_FmPcd, h_PcdParams, h_FmPort, p_Manip, h_Ad, ++ validate); ++ break; ++#endif /* (DPAA_VERSION >= 11) */ ++ default: ++ return E_OK; ++ } ++ ++ return err; ++} ++ ++static t_Error FmPcdManipModifyUpdate(t_Handle h_Manip, t_Handle h_Ad, ++ bool validate, int level, ++ t_Handle h_FmTree) ++{ ++ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ t_Error err = E_OK; ++ ++ UNUSED(level); ++ ++ switch (p_Manip->opcode) ++ { ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("modify node with this type of manipulation is not suppported")); ++ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): ++ ++ if (p_Manip->h_Frag) ++ { ++ if (!(p_Manip->shadowUpdateParams & NUM_OF_TASKS) ++ && !(p_Manip->shadowUpdateParams & OFFSET_OF_DATA) ++ && !(p_Manip->shadowUpdateParams & OFFSET_OF_PR)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("modify node with this type of manipulation requires manipulation be updated previously in SetPcd function")); ++ } ++ break; ++ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER): ++ if (p_Manip->h_Frag) ++ err = UpdateModifyCapwapFragmenation(p_Manip, h_Ad, validate, h_FmTree); ++ break; ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ default: ++ return E_OK; ++ } ++ ++ return err; ++} ++ ++/*****************************************************************************/ ++/* Inter-module API routines */ ++/*****************************************************************************/ ++ ++t_Error FmPcdManipUpdate(t_Handle h_FmPcd, t_Handle h_PcdParams, ++ t_Handle h_FmPort, t_Handle h_Manip, t_Handle h_Ad, ++ bool validate, int level, t_Handle h_FmTree, ++ bool modify) ++{ ++ t_Error err; ++ ++ if (!modify) ++ err = FmPcdManipInitUpdate(h_FmPcd, h_PcdParams, h_FmPort, h_Manip, ++ h_Ad, validate, level, h_FmTree); ++ else ++ err = FmPcdManipModifyUpdate(h_Manip, h_Ad, validate, level, h_FmTree); ++ ++ return err; ++} ++ ++void FmPcdManipUpdateOwner(t_Handle h_Manip, bool add) ++{ ++ ++ uint32_t intFlags; ++ ++ intFlags = XX_LockIntrSpinlock(((t_FmPcdManip *)h_Manip)->h_Spinlock); ++ if (add) ++ ((t_FmPcdManip *)h_Manip)->owner++; ++ else ++ { ++ ASSERT_COND(((t_FmPcdManip *)h_Manip)->owner); ++ ((t_FmPcdManip *)h_Manip)->owner--; ++ } ++ XX_UnlockIntrSpinlock(((t_FmPcdManip *)h_Manip)->h_Spinlock, intFlags); ++} ++ ++t_List *FmPcdManipGetNodeLstPointedOnThisManip(t_Handle h_Manip) ++{ ++ ASSERT_COND(h_Manip); ++ return &((t_FmPcdManip *)h_Manip)->nodesLst; ++} ++ ++t_List *FmPcdManipGetSpinlock(t_Handle h_Manip) ++{ ++ ASSERT_COND(h_Manip); ++ return ((t_FmPcdManip *)h_Manip)->h_Spinlock; ++} ++ ++t_Error FmPcdManipCheckParamsForCcNextEngine( ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams, ++ uint32_t *requiredAction) ++{ ++ t_FmPcdManip *p_Manip; ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++ t_Error err = E_OK; ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10))*/ ++ bool pointFromCc = TRUE; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams->h_Manip, ++ E_NULL_POINTER); ++ ++ p_Manip = (t_FmPcdManip *)(p_FmPcdCcNextEngineParams->h_Manip); ++ *requiredAction = 0; ++ ++ while (p_Manip) ++ { ++ switch (p_Manip->opcode) ++ { ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++ case (HMAN_OC_CAPWAP_INDEXED_STATS): ++ if (p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_DONE) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE")); ++ if (p_FmPcdCcNextEngineParams->params.enqueueParams.overrideFqid) ++ p_Manip->cnia = TRUE; ++ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): ++ *requiredAction = UPDATE_NIA_ENQ_WITHOUT_DMA; ++ case (HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR): ++ p_Manip->ownerTmp++; ++ break; ++ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER): ++ if ((p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_DONE) ++ && !p_FmPcdCcNextEngineParams->params.enqueueParams.overrideFqid) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE with fqidForCtrlFlow FALSE")); ++ p_Manip->ownerTmp++; ++ break; ++ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): ++ if ((p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_CC) ++ && (FmPcdCcGetParseCode(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode) ++ != CC_PC_GENERIC_IC_HASH_INDEXED)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of header manipulation next engine has to be CC and action = e_FM_PCD_ACTION_INDEXED_LOOKUP")); ++ err = UpdateManipIc(p_FmPcdCcNextEngineParams->h_Manip, ++ FmPcdCcGetOffset(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode)); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ *requiredAction = UPDATE_NIA_ENQ_WITHOUT_DMA; ++ break; ++ #endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ case (HMAN_OC_IP_FRAGMENTATION): ++ case (HMAN_OC_IP_REASSEMBLY): ++#if (DPAA_VERSION >= 11) ++ case (HMAN_OC_CAPWAP_REASSEMBLY): ++ case (HMAN_OC_CAPWAP_FRAGMENTATION): ++#endif /* (DPAA_VERSION >= 11) */ ++ if (p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_DONE) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE")); ++ p_Manip->ownerTmp++; ++ break; ++ case (HMAN_OC_IPSEC_MANIP): ++#if (DPAA_VERSION >= 11) ++ case (HMAN_OC_CAPWAP_MANIP): ++#endif /* (DPAA_VERSION >= 11) */ ++ p_Manip->ownerTmp++; ++ break; ++ case (HMAN_OC): ++ if ((p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_CC) ++ && MANIP_IS_CASCADED(p_Manip)) ++ RETURN_ERROR( ++ MINOR, ++ E_INVALID_STATE, ++ ("Can't have a cascaded manipulation when and Next Engine is CC")); ++ if (!MANIP_IS_FIRST(p_Manip) && pointFromCc) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("h_Manip is already used and may not be shared (no sharing of non-head manip nodes)")); ++ break; ++ default: ++ RETURN_ERROR( ++ MAJOR, E_INVALID_STATE, ++ ("invalid type of header manipulation for this state")); ++ } ++ p_Manip = p_Manip->h_NextManip; ++ pointFromCc = FALSE; ++ } ++ return E_OK; ++} ++ ++ ++t_Error FmPcdManipCheckParamsWithCcNodeParams(t_Handle h_Manip, ++ t_Handle h_FmPcdCcNode) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_Manip, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcNode, E_INVALID_HANDLE); ++ ++ switch (p_Manip->opcode) ++ { ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++ case (HMAN_OC_CAPWAP_INDEXED_STATS): ++ if (p_Manip->ownerTmp != FmPcdCcGetNumOfKeys(h_FmPcdCcNode)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("The manipulation of the type statistics flowId if exist has to be pointed by all numOfKeys")); ++ break; ++ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): ++ if (p_Manip->h_Frag) ++ { ++ if (p_Manip->ownerTmp != FmPcdCcGetNumOfKeys(h_FmPcdCcNode)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("The manipulation of the type remove DTLS if exist has to be pointed by all numOfKeys")); ++ err = UpdateManipIc(h_Manip, FmPcdCcGetOffset(h_FmPcdCcNode)); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ break; ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ default: ++ break; ++ } ++ ++ return err; ++} ++ ++void FmPcdManipUpdateAdResultForCc( ++ t_Handle h_Manip, t_FmPcdCcNextEngineParams *p_CcNextEngineParams, ++ t_Handle p_Ad, t_Handle *p_AdNewPtr) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ ++ /* This routine creates a Manip AD and can return in "p_AdNewPtr" ++ * either the new descriptor or NULL if it writes the Manip AD into p_AD (into the match table) */ ++ ++ ASSERT_COND(p_Manip); ++ ASSERT_COND(p_CcNextEngineParams); ++ ASSERT_COND(p_Ad); ++ ASSERT_COND(p_AdNewPtr); ++ ++ FmPcdManipUpdateOwner(h_Manip, TRUE); ++ ++ /* According to "type", either build & initialize a new AD (p_AdNew) or initialize ++ * p_Ad ( the AD in the match table) and set p_AdNew = NULL. */ ++ switch (p_Manip->opcode) ++ { ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++ case (HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR): ++ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): ++ case (HMAN_OC_CAPWAP_INDEXED_STATS): ++ *p_AdNewPtr = p_Manip->h_Ad; ++ break; ++ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER): ++ case (HMAN_OC_CAPWAP_FRAGMENTATION): ++ WRITE_UINT32(((t_AdOfTypeResult *)p_Ad)->fqid, ++ ((t_AdOfTypeResult *)(p_Manip->h_Ad))->fqid); ++ WRITE_UINT32(((t_AdOfTypeResult *)p_Ad)->plcrProfile, ++ ((t_AdOfTypeResult *)(p_Manip->h_Ad))->plcrProfile); ++ WRITE_UINT32(((t_AdOfTypeResult *)p_Ad)->nia, ++ ((t_AdOfTypeResult *)(p_Manip->h_Ad))->nia); ++ *p_AdNewPtr = NULL; ++ break; ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ case (HMAN_OC_IPSEC_MANIP): ++#if (DPAA_VERSION >= 11) ++ case (HMAN_OC_CAPWAP_MANIP): ++#endif /* (DPAA_VERSION >= 11) */ ++ *p_AdNewPtr = p_Manip->h_Ad; ++ break; ++ case (HMAN_OC_IP_FRAGMENTATION): ++#if (DPAA_VERSION >= 11) ++ case (HMAN_OC_CAPWAP_FRAGMENTATION): ++#endif /* (DPAA_VERSION >= 11) */ ++ if ((p_CcNextEngineParams->nextEngine == e_FM_PCD_DONE) ++ && (!p_CcNextEngineParams->params.enqueueParams.overrideFqid)) ++ { ++ memcpy((uint8_t *)p_Ad, (uint8_t *)p_Manip->h_Ad, ++ sizeof(t_AdOfTypeContLookup)); ++#if (DPAA_VERSION >= 11) ++ WRITE_UINT32( ++ ((t_AdOfTypeContLookup *)p_Ad)->ccAdBase, ++ GET_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase) & ~FM_PCD_MANIP_IP_CNIA); ++#endif /* (DPAA_VERSION >= 11) */ ++ *p_AdNewPtr = NULL; ++ } ++ else ++ *p_AdNewPtr = p_Manip->h_Ad; ++ break; ++ case (HMAN_OC_IP_REASSEMBLY): ++ if (FmPcdManipIpReassmIsIpv6Hdr(p_Manip)) ++ { ++ if (!p_Manip->reassmParams.ip.ipv6Assigned) ++ { ++ *p_AdNewPtr = p_Manip->reassmParams.ip.h_Ipv6Ad; ++ p_Manip->reassmParams.ip.ipv6Assigned = TRUE; ++ FmPcdManipUpdateOwner(h_Manip, FALSE); ++ } ++ else ++ { ++ *p_AdNewPtr = p_Manip->reassmParams.ip.h_Ipv4Ad; ++ p_Manip->reassmParams.ip.ipv6Assigned = FALSE; ++ } ++ } ++ else ++ *p_AdNewPtr = p_Manip->reassmParams.ip.h_Ipv4Ad; ++ memcpy((uint8_t *)p_Ad, (uint8_t *)*p_AdNewPtr, ++ sizeof(t_AdOfTypeContLookup)); ++ *p_AdNewPtr = NULL; ++ break; ++#if (DPAA_VERSION >= 11) ++ case (HMAN_OC_CAPWAP_REASSEMBLY): ++ *p_AdNewPtr = p_Manip->reassmParams.capwap.h_Ad; ++ memcpy((uint8_t *)p_Ad, (uint8_t *)*p_AdNewPtr, ++ sizeof(t_AdOfTypeContLookup)); ++ *p_AdNewPtr = NULL; ++ break; ++#endif /* (DPAA_VERSION >= 11) */ ++ case (HMAN_OC): ++ /* Allocate and initialize HMTD */ ++ *p_AdNewPtr = p_Manip->h_Ad; ++ break; ++ default: ++ break; ++ } ++} ++ ++void FmPcdManipUpdateAdContLookupForCc(t_Handle h_Manip, t_Handle p_Ad, ++ t_Handle *p_AdNewPtr, ++ uint32_t adTableOffset) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ ++ /* This routine creates a Manip AD and can return in "p_AdNewPtr" ++ * either the new descriptor or NULL if it writes the Manip AD into p_AD (into the match table) */ ++ ASSERT_COND(p_Manip); ++ ++ FmPcdManipUpdateOwner(h_Manip, TRUE); ++ ++ switch (p_Manip->opcode) ++ { ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): ++ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase, ++ ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->ccAdBase); ++ WRITE_UINT32( ++ ((t_AdOfTypeContLookup *)p_Ad)->matchTblPtr, ++ ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->matchTblPtr); ++ WRITE_UINT32( ++ ((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets, ++ ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->pcAndOffsets); ++ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->gmask, ++ ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->gmask); ++ WRITE_UINT32( ++ ((t_AdOfTypeContLookup *)p_Ad)->ccAdBase, ++ (GET_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase) | adTableOffset)); ++ *p_AdNewPtr = NULL; ++ break; ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ case (HMAN_OC): ++ /* Initialize HMTD within the match table*/ ++ IOMemSet32(p_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ /* copy the existing HMTD *//* ask Alla - memcpy??? */ ++ memcpy((uint8_t*)p_Ad, p_Manip->h_Ad, sizeof(t_Hmtd)); ++ /* update NADEN to be "1"*/ ++ WRITE_UINT16( ++ ((t_Hmtd *)p_Ad)->cfg, ++ (uint16_t)(GET_UINT16(((t_Hmtd *)p_Ad)->cfg) | HMTD_CFG_NEXT_AD_EN)); ++ /* update next action descriptor */ ++ WRITE_UINT16(((t_Hmtd *)p_Ad)->nextAdIdx, ++ (uint16_t)(adTableOffset >> 4)); ++ /* mark that Manip's HMTD is not used */ ++ *p_AdNewPtr = NULL; ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++t_Error FmPcdManipBuildIpReassmScheme(t_FmPcd *p_FmPcd, t_Handle h_NetEnv, ++ t_Handle h_CcTree, t_Handle h_Manip, ++ bool isIpv4, uint8_t groupId) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ t_FmPcdKgSchemeParams *p_SchemeParams = NULL; ++ t_Handle h_Scheme; ++ ++ ASSERT_COND(p_FmPcd); ++ ASSERT_COND(h_NetEnv); ++ ASSERT_COND(p_Manip); ++ ++ /* scheme was already build, no need to check for IPv6 */ ++ if (p_Manip->reassmParams.ip.h_Ipv4Scheme) ++ return E_OK; ++ ++ if (isIpv4) { ++ h_Scheme = FmPcdKgGetSchemeHandle(p_FmPcd, p_Manip->reassmParams.ip.relativeSchemeId[0]); ++ if (h_Scheme) { ++ /* scheme was found */ ++ p_Manip->reassmParams.ip.h_Ipv4Scheme = h_Scheme; ++ return E_OK; ++ } ++ } else { ++ h_Scheme = FmPcdKgGetSchemeHandle(p_FmPcd, p_Manip->reassmParams.ip.relativeSchemeId[1]); ++ if (h_Scheme) { ++ /* scheme was found */ ++ p_Manip->reassmParams.ip.h_Ipv6Scheme = h_Scheme; ++ return E_OK; ++ } ++ } ++ ++ p_SchemeParams = XX_Malloc(sizeof(t_FmPcdKgSchemeParams)); ++ if (!p_SchemeParams) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("Memory allocation failed for scheme")); ++ ++ /* Configures the IPv4 or IPv6 scheme*/ ++ memset(p_SchemeParams, 0, sizeof(t_FmPcdKgSchemeParams)); ++ p_SchemeParams->netEnvParams.h_NetEnv = h_NetEnv; ++ p_SchemeParams->id.relativeSchemeId = (uint8_t)( ++ (isIpv4 == TRUE) ? p_Manip->reassmParams.ip.relativeSchemeId[0] : ++ p_Manip->reassmParams.ip.relativeSchemeId[1]); ++ p_SchemeParams->schemeCounter.update = TRUE; ++#if (DPAA_VERSION >= 11) ++ p_SchemeParams->alwaysDirect = TRUE; ++ p_SchemeParams->bypassFqidGeneration = TRUE; ++#else ++ p_SchemeParams->keyExtractAndHashParams.hashDistributionNumOfFqids = 1; ++ p_SchemeParams->baseFqid = 0xFFFFFF; /*TODO- baseFqid*/ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ setIpReassmSchemeParams(p_FmPcd, p_SchemeParams, h_CcTree, isIpv4, groupId); ++ ++ /* Sets the new scheme */ ++ if (isIpv4) ++ p_Manip->reassmParams.ip.h_Ipv4Scheme = FM_PCD_KgSchemeSet( ++ p_FmPcd, p_SchemeParams); ++ else ++ p_Manip->reassmParams.ip.h_Ipv6Scheme = FM_PCD_KgSchemeSet( ++ p_FmPcd, p_SchemeParams); ++ ++ XX_Free(p_SchemeParams); ++ ++ return E_OK; ++} ++ ++t_Error FmPcdManipDeleteIpReassmSchemes(t_Handle h_Manip) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ ++ ASSERT_COND(p_Manip); ++ ++ if ((p_Manip->reassmParams.ip.h_Ipv4Scheme) && ++ !FmPcdKgIsSchemeHasOwners(p_Manip->reassmParams.ip.h_Ipv4Scheme)) ++ FM_PCD_KgSchemeDelete(p_Manip->reassmParams.ip.h_Ipv4Scheme); ++ ++ if ((p_Manip->reassmParams.ip.h_Ipv6Scheme) && ++ !FmPcdKgIsSchemeHasOwners(p_Manip->reassmParams.ip.h_Ipv6Scheme)) ++ FM_PCD_KgSchemeDelete(p_Manip->reassmParams.ip.h_Ipv6Scheme); ++ ++ return E_OK; ++} ++ ++bool FmPcdManipIpReassmIsIpv6Hdr(t_Handle h_Manip) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ ++ ASSERT_COND(p_Manip); ++ ++ return (p_Manip->reassmParams.hdr == HEADER_TYPE_IPv6); ++} ++ ++t_Error FmPcdManipBuildCapwapReassmScheme(t_FmPcd *p_FmPcd, t_Handle h_NetEnv, ++ t_Handle h_CcTree, t_Handle h_Manip, ++ uint8_t groupId) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ t_FmPcdKgSchemeParams *p_SchemeParams = NULL; ++ ++ ASSERT_COND(p_FmPcd); ++ ASSERT_COND(h_NetEnv); ++ ASSERT_COND(p_Manip); ++ ++ /* scheme was already build, no need to check for IPv6 */ ++ if (p_Manip->reassmParams.capwap.h_Scheme) ++ return E_OK; ++ ++ p_SchemeParams = XX_Malloc(sizeof(t_FmPcdKgSchemeParams)); ++ if (!p_SchemeParams) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ++ ("Memory allocation failed for scheme")); ++ ++ memset(p_SchemeParams, 0, sizeof(t_FmPcdKgSchemeParams)); ++ p_SchemeParams->netEnvParams.h_NetEnv = h_NetEnv; ++ p_SchemeParams->id.relativeSchemeId = ++ (uint8_t)p_Manip->reassmParams.capwap.relativeSchemeId; ++ p_SchemeParams->schemeCounter.update = TRUE; ++ p_SchemeParams->bypassFqidGeneration = TRUE; ++ ++ setCapwapReassmSchemeParams(p_FmPcd, p_SchemeParams, h_CcTree, groupId); ++ ++ p_Manip->reassmParams.capwap.h_Scheme = FM_PCD_KgSchemeSet(p_FmPcd, ++ p_SchemeParams); ++ ++ XX_Free(p_SchemeParams); ++ ++ return E_OK; ++} ++ ++t_Error FmPcdManipDeleteCapwapReassmSchemes(t_Handle h_Manip) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ ++ ASSERT_COND(p_Manip); ++ ++ if (p_Manip->reassmParams.capwap.h_Scheme) ++ FM_PCD_KgSchemeDelete(p_Manip->reassmParams.capwap.h_Scheme); ++ ++ return E_OK; ++} ++ ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++t_Handle FmPcdManipApplSpecificBuild(void) ++{ ++ t_FmPcdManip *p_Manip; ++ ++ p_Manip = (t_FmPcdManip*)XX_Malloc(sizeof(t_FmPcdManip)); ++ if (!p_Manip) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); ++ return NULL; ++ } ++ memset(p_Manip, 0, sizeof(t_FmPcdManip)); ++ ++ p_Manip->opcode = HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX; ++ p_Manip->muramAllocate = FALSE; ++ ++ p_Manip->h_Ad = (t_Handle)XX_Malloc(FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t)); ++ if (!p_Manip->h_Ad) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of Manipulation action descriptor")); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ ++ memset(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t)); ++ ++ /*treatFdStatusFieldsAsErrors = TRUE hardcoded - assumption its always come after CAAM*/ ++ /*Application specific = type of flowId index, move internal frame header from data to IC, ++ SEC errors check*/ ++ if (MvIntFrameHeaderFromFrameToBufferPrefix(p_Manip, TRUE)!= E_OK) ++ { ++ XX_Free(p_Manip->h_Ad); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ return p_Manip; ++} ++ ++bool FmPcdManipIsCapwapApplSpecific(t_Handle h_Manip) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip; ++ ASSERT_COND(h_Manip); ++ ++ return (bool)((p_Manip->opcode == HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST) ? TRUE : FALSE); ++} ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++/*********************** End of inter-module routines ************************/ ++ ++/****************************************/ ++/* API Init unit functions */ ++/****************************************/ ++ ++t_Handle FM_PCD_ManipNodeSet(t_Handle h_FmPcd, ++ t_FmPcdManipParams *p_ManipParams) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_FmPcdManip *p_Manip; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_ManipParams, E_INVALID_HANDLE, NULL); ++ ++ p_Manip = ManipOrStatsSetNode(h_FmPcd, (t_Handle)p_ManipParams, FALSE); ++ if (!p_Manip) ++ return NULL; ++ ++ if (((p_Manip->opcode == HMAN_OC_IP_REASSEMBLY) ++ || (p_Manip->opcode == HMAN_OC_IP_FRAGMENTATION) ++ || (p_Manip->opcode == HMAN_OC) ++ || (p_Manip->opcode == HMAN_OC_IPSEC_MANIP) ++#if (DPAA_VERSION >= 11) ++ || (p_Manip->opcode == HMAN_OC_CAPWAP_MANIP) ++ || (p_Manip->opcode == HMAN_OC_CAPWAP_FRAGMENTATION) ++ || (p_Manip->opcode == HMAN_OC_CAPWAP_REASSEMBLY) ++#endif /* (DPAA_VERSION >= 11) */ ++ ) && (!FmPcdIsAdvancedOffloadSupported(p_FmPcd))) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Advanced-offload must be enabled")); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ p_Manip->h_Spinlock = XX_InitSpinlock(); ++ if (!p_Manip->h_Spinlock) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE")); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ }INIT_LIST(&p_Manip->nodesLst); ++ ++ switch (p_Manip->opcode) ++ { ++ case (HMAN_OC_IP_REASSEMBLY): ++ /* IpReassembly */ ++ err = IpReassembly(&p_ManipParams->u.reassem, p_Manip); ++ break; ++ case (HMAN_OC_IP_FRAGMENTATION): ++ /* IpFragmentation */ ++ err = IpFragmentation(&p_ManipParams->u.frag.u.ipFrag, p_Manip); ++ if (err) ++ break; ++ err = IPManip(p_Manip); ++ break; ++ case (HMAN_OC_IPSEC_MANIP): ++ err = IPSecManip(p_ManipParams, p_Manip); ++ break; ++#if (DPAA_VERSION >= 11) ++ case (HMAN_OC_CAPWAP_REASSEMBLY): ++ /* CapwapReassembly */ ++ err = CapwapReassembly(&p_ManipParams->u.reassem, p_Manip); ++ break; ++ case (HMAN_OC_CAPWAP_FRAGMENTATION): ++ /* CapwapFragmentation */ ++ err = CapwapFragmentation(&p_ManipParams->u.frag.u.capwapFrag, ++ p_Manip); ++ break; ++ case (HMAN_OC_CAPWAP_MANIP): ++ err = CapwapManip(p_ManipParams, p_Manip); ++ break; ++#endif /* (DPAA_VERSION >= 11) */ ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++ case (HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR): ++ /* HmanType1 */ ++ err = RmvHdrTillSpecLocNOrInsrtIntFrmHdr(&p_ManipParams->u.hdr.rmvParams, p_Manip); ++ break; ++ case (HMAN_OC_CAPWAP_FRAGMENTATION): ++ err = CapwapFragmentation(&p_ManipParams->fragOrReasmParams.u.capwapFragParams, ++ p_Manip, ++ p_FmPcd, ++ p_ManipParams->fragOrReasmParams.sgBpid); ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE")); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ if (p_Manip->insrt) ++ p_Manip->opcode = HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER; ++ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER): ++ /* HmanType2 + if user asked only for fragmentation still need to allocate HmanType2 */ ++ err = InsrtHdrByTempl(&p_ManipParams->u.hdr.insrtParams, p_Manip, p_FmPcd); ++ break; ++ case (HMAN_OC_CAPWAP_REASSEMBLY): ++ err = CapwapReassembly(&p_ManipParams->fragOrReasmParams.u.capwapReasmParams, ++ p_Manip, ++ p_FmPcd, ++ p_ManipParams->fragOrReasmParams.sgBpid); ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE")); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ if (p_Manip->rmv) ++ p_Manip->opcode = HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST; ++ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST): ++ /*CAPWAP decapsulation + if user asked only for reassembly still need to allocate CAPWAP decapsulation*/ ++ err = CapwapRmvDtlsHdr(p_FmPcd, p_Manip); ++ break; ++ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX): ++ /*Application Specific type 1*/ ++ err = MvIntFrameHeaderFromFrameToBufferPrefix(p_Manip, TRUE); ++ break; ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ case (HMAN_OC): ++ /* New Manip */ ++ err = CreateManipActionNew(p_Manip, p_ManipParams); ++ break; ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE")); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ ++ if (p_ManipParams->h_NextManip) ++ { ++ /* in the check routine we've verified that h_NextManip has no owners ++ * and that only supported types are allowed. */ ++ p_Manip->h_NextManip = p_ManipParams->h_NextManip; ++ /* save a "prev" pointer in h_NextManip */ ++ MANIP_SET_PREV(p_Manip->h_NextManip, p_Manip); ++ FmPcdManipUpdateOwner(p_Manip->h_NextManip, TRUE); ++ } ++ ++ return p_Manip; ++} ++ ++t_Error FM_PCD_ManipNodeReplace(t_Handle h_Manip, ++ t_FmPcdManipParams *p_ManipParams) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip, *p_FirstManip; ++ t_FmPcd *p_FmPcd = (t_FmPcd *)(p_Manip->h_FmPcd); ++ t_Error err; ++ uint8_t *p_WholeHmct = NULL, *p_ShadowHmct = NULL, *p_Hmtd = NULL; ++ t_List lstOfNodeshichPointsOnCrntMdfManip, *p_Pos; ++ t_CcNodeInformation *p_CcNodeInfo; ++ SANITY_CHECK_RETURN_ERROR(h_Manip, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_ManipParams, E_INVALID_HANDLE); ++ ++ INIT_LIST(&lstOfNodeshichPointsOnCrntMdfManip); ++ ++ if ((p_ManipParams->type != e_FM_PCD_MANIP_HDR) ++ || (p_Manip->type != e_FM_PCD_MANIP_HDR)) ++ RETURN_ERROR( ++ MINOR, ++ E_NOT_SUPPORTED, ++ ("FM_PCD_ManipNodeReplace Functionality supported only for Header Manipulation.")); ++ ++ ASSERT_COND(p_Manip->opcode == HMAN_OC); ++ ASSERT_COND(p_Manip->manipParams.h_NextManip == p_Manip->h_NextManip); ++ memcpy((uint8_t*)&p_Manip->manipParams, p_ManipParams, ++ sizeof(p_Manip->manipParams)); ++ p_Manip->manipParams.h_NextManip = p_Manip->h_NextManip; ++ ++ /* The replacement of the HdrManip depends on the node type.*/ ++ /* ++ * (1) If this is an independent node, all its owners should be updated. ++ * ++ * (2) If it is the head of a cascaded chain (it does not have a "prev" but ++ * it has a "next" and it has a "cascaded" indication), the next ++ * node remains unchanged, and the behavior is as in (1). ++ * ++ * (3) If it is not the head, but a part of a cascaded chain, in can be ++ * also replaced as a regular node with just one owner. ++ * ++ * (4) If it is a part of a chain implemented as a unified table, the ++ * whole table is replaced and the owners of the head node must be updated. ++ * ++ */ ++ /* lock shadow */ ++ if (!p_FmPcd->p_CcShadow) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("CC Shadow not allocated")); ++ ++ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ return ERROR_CODE(E_BUSY); ++ ++ /* this routine creates a new manip action in the CC Shadow. */ ++ err = CreateManipActionShadow(p_Manip, p_ManipParams); ++ if (err) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ /* If the owners list is empty (these are NOT the "owners" counter, but pointers from CC) ++ * replace only HMTD and no lcok is required. Otherwise ++ * lock the whole PCD ++ * In case 4 MANIP_IS_UNIFIED_NON_FIRST(p_Manip) - Use the head node instead. */ ++ if (!FmPcdLockTryLockAll(p_FmPcd)) ++ { ++ DBG(TRACE, ("FmPcdLockTryLockAll failed")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ p_ShadowHmct = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow, 16); ++ ++ p_FirstManip = (t_FmPcdManip*)GetManipInfo(p_Manip, ++ e_MANIP_HANDLER_TABLE_OWNER); ++ ASSERT_COND(p_FirstManip); ++ ++ if (!LIST_IsEmpty(&p_FirstManip->nodesLst)) ++ UpdateAdPtrOfNodesWhichPointsOnCrntMdfManip( ++ p_FirstManip, &lstOfNodeshichPointsOnCrntMdfManip); ++ ++ p_Hmtd = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMTD); ++ ASSERT_COND(p_Hmtd); ++ BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_Hmtd, p_ShadowHmct, ++ ((t_FmPcd*)(p_Manip->h_FmPcd))); ++ ++ LIST_FOR_EACH(p_Pos, &lstOfNodeshichPointsOnCrntMdfManip) ++ { ++ p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos); ++ BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_CcNodeInfo->h_CcNode, ++ p_ShadowHmct, ((t_FmPcd*)(p_Manip->h_FmPcd))); ++ } ++ ++ p_WholeHmct = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMCT); ++ ASSERT_COND(p_WholeHmct); ++ ++ /* re-build the HMCT n the original location */ ++ err = CreateManipActionBackToOrig(p_Manip, p_ManipParams); ++ if (err) ++ { ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ p_Hmtd = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMTD); ++ ASSERT_COND(p_Hmtd); ++ BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_Hmtd, p_WholeHmct, ++ ((t_FmPcd*)p_Manip->h_FmPcd)); ++ ++ /* If LIST > 0, create a list of p_Ad's that point to the HMCT. Join also t_HMTD to this list. ++ * For each p_Hmct (from list+fixed): ++ * call Host Command to replace HMTD by a new one */LIST_FOR_EACH(p_Pos, &lstOfNodeshichPointsOnCrntMdfManip) ++ { ++ p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos); ++ BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_CcNodeInfo->h_CcNode, ++ p_WholeHmct, ((t_FmPcd*)(p_Manip->h_FmPcd))); ++ } ++ ++ ++ ReleaseLst(&lstOfNodeshichPointsOnCrntMdfManip); ++ ++ FmPcdLockUnlockAll(p_FmPcd); ++ ++ /* unlock shadow */ ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_ManipNodeDelete(t_Handle h_ManipNode) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_ManipNode; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); ++ ++ if (p_Manip->owner) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("This manipulation node not be removed because this node is occupied, first - unbind this node ")); ++ ++ if (p_Manip->h_NextManip) ++ { ++ MANIP_SET_PREV(p_Manip->h_NextManip, NULL); ++ FmPcdManipUpdateOwner(p_Manip->h_NextManip, FALSE); ++ } ++ ++ if (p_Manip->p_Hmct ++ && (MANIP_IS_UNIFIED_FIRST(p_Manip) || !MANIP_IS_UNIFIED(p_Manip))) ++ FM_MURAM_FreeMem(((t_FmPcd *)p_Manip->h_FmPcd)->h_FmMuram, ++ p_Manip->p_Hmct); ++ ++ if (p_Manip->h_Spinlock) ++ { ++ XX_FreeSpinlock(p_Manip->h_Spinlock); ++ p_Manip->h_Spinlock = NULL; ++ } ++ ++ ReleaseManipHandler(p_Manip, p_Manip->h_FmPcd); ++ ++ XX_Free(h_ManipNode); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_ManipGetStatistics(t_Handle h_ManipNode, ++ t_FmPcdManipStats *p_FmPcdManipStats) ++{ ++ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_ManipNode; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdManipStats, E_NULL_POINTER); ++ ++ switch (p_Manip->opcode) ++ { ++ case (HMAN_OC_IP_REASSEMBLY): ++ return IpReassemblyStats(p_Manip, ++ &p_FmPcdManipStats->u.reassem.u.ipReassem); ++ case (HMAN_OC_IP_FRAGMENTATION): ++ return IpFragmentationStats(p_Manip, ++ &p_FmPcdManipStats->u.frag.u.ipFrag); ++#if (DPAA_VERSION >= 11) ++ case (HMAN_OC_CAPWAP_REASSEMBLY): ++ return CapwapReassemblyStats( ++ p_Manip, &p_FmPcdManipStats->u.reassem.u.capwapReassem); ++ case (HMAN_OC_CAPWAP_FRAGMENTATION): ++ return CapwapFragmentationStats( ++ p_Manip, &p_FmPcdManipStats->u.frag.u.capwapFrag); ++#endif /* (DPAA_VERSION >= 11) */ ++ default: ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("no statistics to this type of manip")); ++ } ++ ++ return E_OK; ++} ++ ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++t_Handle FM_PCD_StatisticsSetNode(t_Handle h_FmPcd, t_FmPcdStatsParams *p_StatsParams) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_FmPcdManip *p_Manip; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE,NULL); ++ SANITY_CHECK_RETURN_VALUE(p_StatsParams,E_INVALID_HANDLE,NULL); ++ ++ p_Manip = ManipOrStatsSetNode(h_FmPcd, (t_Handle)p_StatsParams, TRUE); ++ if (!p_Manip) ++ return NULL; ++ ++ switch (p_Manip->opcode) ++ { ++ case (HMAN_OC_CAPWAP_INDEXED_STATS): ++ /* Indexed statistics */ ++ err = IndxStats(p_StatsParams, p_Manip, p_FmPcd); ++ break; ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED Statistics type")); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ ReleaseManipHandler(p_Manip, p_FmPcd); ++ XX_Free(p_Manip); ++ return NULL; ++ } ++ ++ return p_Manip; ++} ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_manip.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_manip.h +new file mode 100644 +index 0000000..ebafd63 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_manip.h +@@ -0,0 +1,553 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_manip.h ++ ++ @Description FM PCD manip... ++*//***************************************************************************/ ++#ifndef __FM_MANIP_H ++#define __FM_MANIP_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++ ++#include "fm_cc.h" ++ ++ ++/***********************************************************************/ ++/* Header manipulations defines */ ++/***********************************************************************/ ++ ++#define NUM_OF_SCRATCH_POOL_BUFFERS 1000 /*TODO - Change it!!*/ ++ ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++#define HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR 0x2e ++#define HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER 0x31 ++#define HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX 0x2f ++#define HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST 0x30 ++#define HMAN_OC_CAPWAP_REASSEMBLY 0x11 /* dummy */ ++#define HMAN_OC_CAPWAP_INDEXED_STATS 0x32 /* dummy */ ++#define HMAN_OC_CAPWAP_FRAGMENTATION 0x33 ++#else ++#define HMAN_OC_CAPWAP_MANIP 0x2F ++#define HMAN_OC_CAPWAP_FRAG_CHECK 0x2E ++#define HMAN_OC_CAPWAP_FRAGMENTATION 0x33 ++#define HMAN_OC_CAPWAP_REASSEMBLY 0x30 ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++#define HMAN_OC_IP_MANIP 0x34 ++#define HMAN_OC_IP_FRAGMENTATION 0x74 ++#define HMAN_OC_IP_REASSEMBLY 0xB4 ++#define HMAN_OC_IPSEC_MANIP 0xF4 ++#define HMAN_OC 0x35 ++ ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++#define HMAN_RMV_HDR 0x80000000 ++#define HMAN_INSRT_INT_FRM_HDR 0x40000000 ++ ++#define UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP 6 ++#define UDP_CHECKSUM_FIELD_SIZE 2 ++#define UDP_LENGTH_FIELD_OFFSET_FROM_UDP 4 ++ ++#define IPv4_DSCECN_FIELD_OFFSET_FROM_IP 1 ++#define IPv4_TOTALLENGTH_FIELD_OFFSET_FROM_IP 2 ++#define IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP 10 ++#define VLAN_TAG_FIELD_OFFSET_FROM_ETH 12 ++#define IPv4_ID_FIELD_OFFSET_FROM_IP 4 ++ ++#define IPv6_PAYLOAD_LENGTH_OFFSET_FROM_IP 4 ++#define IPv6_NEXT_HEADER_OFFSET_FROM_IP 6 ++ ++#define FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE 0x80 ++#define FM_PCD_MANIP_CAPWAP_REASM_TABLE_ALIGN 8 ++#define FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE 32 ++#define FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE 4 ++#define FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE 8 ++ ++ ++#define FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_BETWEEN_FRAMES 0x40000000 ++#define FM_PCD_MANIP_CAPWAP_REASM_HALT_ON_DUPLICATE_FRAG 0x10000000 ++#define FM_PCD_MANIP_CAPWAP_REASM_AUTOMATIC_LEARNIN_HASH_8_WAYS 0x08000000 ++#define FM_PCD_MANIP_CAPWAP_REASM_PR_COPY 0x00800000 ++ ++#define FM_PCD_MANIP_CAPWAP_FRAG_COMPR_OPTION_FIELD_EN 0x80000000 ++ ++#define FM_PCD_MANIP_INDEXED_STATS_ENTRY_SIZE 4 ++#define FM_PCD_MANIP_INDEXED_STATS_CNIA 0x20000000 ++#define FM_PCD_MANIP_INDEXED_STATS_DPD 0x10000000 ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ ++#if (DPAA_VERSION >= 11) ++#define FM_PCD_MANIP_CAPWAP_DTLS 0x00040000 ++#define FM_PCD_MANIP_CAPWAP_NADEN 0x20000000 ++ ++#define FM_PCD_MANIP_CAPWAP_FRAG_CHECK_MTU_SHIFT 16 ++#define FM_PCD_MANIP_CAPWAP_FRAG_CHECK_NO_FRAGMENTATION 0xFFFF0000 ++#define FM_PCD_MANIP_CAPWAP_FRAG_CHECK_CNIA 0x20000000 ++ ++#define FM_PCD_MANIP_CAPWAP_FRAG_COMPRESS_EN 0x04000000 ++#define FM_PCD_MANIP_CAPWAP_FRAG_SCRATCH_BPID 24 ++#define FM_PCD_MANIP_CAPWAP_FRAG_SG_BDID_EN 0x08000000 ++#define FM_PCD_MANIP_CAPWAP_FRAG_SG_BDID_MASK 0xFF000000 ++#define FM_PCD_MANIP_CAPWAP_FRAG_SG_BDID_SHIFT 24 ++#endif /* (DPAA_VERSION >= 11) */ ++ ++#define FM_PCD_MANIP_REASM_TABLE_SIZE 0x40 ++#define FM_PCD_MANIP_REASM_TABLE_ALIGN 8 ++ ++#define FM_PCD_MANIP_REASM_COMMON_PARAM_TABLE_SIZE 64 ++#define FM_PCD_MANIP_REASM_COMMON_PARAM_TABLE_ALIGN 8 ++#define FM_PCD_MANIP_REASM_TIME_OUT_BETWEEN_FRAMES 0x80000000 ++#define FM_PCD_MANIP_REASM_COUPLING_ENABLE 0x40000000 ++#define FM_PCD_MANIP_REASM_COUPLING_MASK 0xFF000000 ++#define FM_PCD_MANIP_REASM_COUPLING_SHIFT 24 ++#define FM_PCD_MANIP_REASM_LIODN_MASK 0x0000003F ++#define FM_PCD_MANIP_REASM_LIODN_SHIFT 56 ++#define FM_PCD_MANIP_REASM_ELIODN_MASK 0x000003c0 ++#define FM_PCD_MANIP_REASM_ELIODN_SHIFT 38 ++#define FM_PCD_MANIP_REASM_COMMON_INT_BUFFER_IDX_MASK 0x000000FF ++#define FM_PCD_MANIP_REASM_COMMON_INT_BUFFER_IDX_SHIFT 24 ++#define FM_PCD_MANIP_REASM_TIMEOUT_THREAD_THRESH 1024 ++ ++#define FM_PCD_MANIP_IP_MTU_SHIFT 16 ++#define FM_PCD_MANIP_IP_NO_FRAGMENTATION 0xFFFF0000 ++#define FM_PCD_MANIP_IP_CNIA 0x20000000 ++ ++#define FM_PCD_MANIP_IP_FRAG_DF_SHIFT 28 ++#define FM_PCD_MANIP_IP_FRAG_SCRATCH_BPID 24 ++#define FM_PCD_MANIP_IP_FRAG_SG_BDID_EN 0x08000000 ++#define FM_PCD_MANIP_IP_FRAG_SG_BDID_MASK 0xFF000000 ++#define FM_PCD_MANIP_IP_FRAG_SG_BDID_SHIFT 24 ++ ++#define FM_PCD_MANIP_IPSEC_DEC 0x10000000 ++#define FM_PCD_MANIP_IPSEC_VIPV_EN 0x08000000 ++#define FM_PCD_MANIP_IPSEC_ECN_EN 0x04000000 ++#define FM_PCD_MANIP_IPSEC_DSCP_EN 0x02000000 ++#define FM_PCD_MANIP_IPSEC_VIPL_EN 0x01000000 ++#define FM_PCD_MANIP_IPSEC_NADEN 0x20000000 ++ ++#define FM_PCD_MANIP_IPSEC_IP_HDR_LEN_MASK 0x00FF0000 ++#define FM_PCD_MANIP_IPSEC_IP_HDR_LEN_SHIFT 16 ++ ++#define FM_PCD_MANIP_IPSEC_ARW_SIZE_MASK 0xFFFF0000 ++#define FM_PCD_MANIP_IPSEC_ARW_SIZE_SHIFT 16 ++ ++#define e_FM_MANIP_IP_INDX 1 ++ ++#define HMCD_OPCODE_GENERIC_RMV 0x01 ++#define HMCD_OPCODE_GENERIC_INSRT 0x02 ++#define HMCD_OPCODE_GENERIC_REPLACE 0x05 ++#define HMCD_OPCODE_L2_RMV 0x08 ++#define HMCD_OPCODE_L2_INSRT 0x09 ++#define HMCD_OPCODE_VLAN_PRI_UPDATE 0x0B ++#define HMCD_OPCODE_IPV4_UPDATE 0x0C ++#define HMCD_OPCODE_IPV6_UPDATE 0x10 ++#define HMCD_OPCODE_TCP_UDP_UPDATE 0x0E ++#define HMCD_OPCODE_TCP_UDP_CHECKSUM 0x14 ++#define HMCD_OPCODE_REPLACE_IP 0x12 ++#define HMCD_OPCODE_RMV_TILL 0x15 ++#define HMCD_OPCODE_UDP_INSRT 0x16 ++#define HMCD_OPCODE_IP_INSRT 0x17 ++#define HMCD_OPCODE_CAPWAP_RMV 0x18 ++#define HMCD_OPCODE_CAPWAP_INSRT 0x18 ++#define HMCD_OPCODE_GEN_FIELD_REPLACE 0x19 ++ ++#define HMCD_LAST 0x00800000 ++ ++#define HMCD_DSCP_VALUES 64 ++ ++#define HMCD_BASIC_SIZE 4 ++#define HMCD_PTR_SIZE 4 ++#define HMCD_PARAM_SIZE 4 ++#define HMCD_IPV4_ADDR_SIZE 4 ++#define HMCD_IPV6_ADDR_SIZE 0x10 ++#define HMCD_L4_HDR_SIZE 8 ++ ++#define HMCD_CAPWAP_INSRT 0x00010000 ++#define HMCD_INSRT_UDP_LITE 0x00010000 ++#define HMCD_IP_ID_MASK 0x0000FFFF ++#define HMCD_IP_SIZE_MASK 0x0000FF00 ++#define HMCD_IP_SIZE_SHIFT 8 ++#define HMCD_IP_LAST_PID_MASK 0x000000FF ++#define HMCD_IP_OR_QOS 0x00010000 ++#define HMCD_IP_L4_CS_CALC 0x00040000 ++#define HMCD_IP_DF_MODE 0x00400000 ++ ++ ++#define HMCD_OC_SHIFT 24 ++ ++#define HMCD_RMV_OFFSET_SHIFT 0 ++#define HMCD_RMV_SIZE_SHIFT 8 ++ ++#define HMCD_INSRT_OFFSET_SHIFT 0 ++#define HMCD_INSRT_SIZE_SHIFT 8 ++ ++#define HMTD_CFG_TYPE 0x4000 ++#define HMTD_CFG_EXT_HMCT 0x0080 ++#define HMTD_CFG_PRS_AFTER_HM 0x0040 ++#define HMTD_CFG_NEXT_AD_EN 0x0020 ++ ++#define HMCD_RMV_L2_ETHERNET 0 ++#define HMCD_RMV_L2_STACKED_QTAGS 1 ++#define HMCD_RMV_L2_ETHERNET_AND_MPLS 2 ++#define HMCD_RMV_L2_MPLS 3 ++ ++#define HMCD_INSRT_L2_MPLS 0 ++#define HMCD_INSRT_N_UPDATE_L2_MPLS 1 ++#define HMCD_INSRT_L2_SIZE_SHIFT 24 ++ ++#define HMCD_L2_MODE_SHIFT 16 ++ ++#define HMCD_VLAN_PRI_REP_MODE_SHIFT 16 ++#define HMCD_VLAN_PRI_UPDATE 0 ++#define HMCD_VLAN_PRI_UPDATE_DSCP_TO_VPRI 1 ++ ++#define HMCD_IPV4_UPDATE_TTL 0x00000001 ++#define HMCD_IPV4_UPDATE_TOS 0x00000002 ++#define HMCD_IPV4_UPDATE_DST 0x00000020 ++#define HMCD_IPV4_UPDATE_SRC 0x00000040 ++#define HMCD_IPV4_UPDATE_ID 0x00000080 ++#define HMCD_IPV4_UPDATE_TOS_SHIFT 8 ++ ++#define HMCD_IPV6_UPDATE_HL 0x00000001 ++#define HMCD_IPV6_UPDATE_TC 0x00000002 ++#define HMCD_IPV6_UPDATE_DST 0x00000040 ++#define HMCD_IPV6_UPDATE_SRC 0x00000080 ++#define HMCD_IPV6_UPDATE_TC_SHIFT 8 ++ ++#define HMCD_TCP_UDP_UPDATE_DST 0x00004000 ++#define HMCD_TCP_UDP_UPDATE_SRC 0x00008000 ++#define HMCD_TCP_UDP_UPDATE_SRC_SHIFT 16 ++ ++#define HMCD_IP_REPLACE_REPLACE_IPV4 0x00000000 ++#define HMCD_IP_REPLACE_REPLACE_IPV6 0x00010000 ++#define HMCD_IP_REPLACE_TTL_HL 0x00200000 ++#define HMCD_IP_REPLACE_ID 0x00400000 ++ ++#define HMCD_IP_REPLACE_L3HDRSIZE_SHIFT 24 ++ ++#define HMCD_GEN_FIELD_SIZE_SHIFT 16 ++#define HMCD_GEN_FIELD_SRC_OFF_SHIFT 8 ++#define HMCD_GEN_FIELD_DST_OFF_SHIFT 0 ++#define HMCD_GEN_FIELD_MASK_EN 0x00400000 ++ ++#define HMCD_GEN_FIELD_MASK_OFF_SHIFT 16 ++#define HMCD_GEN_FIELD_MASK_SHIFT 24 ++ ++#define DSCP_TO_VLAN_TABLE_SIZE 32 ++ ++#define MANIP_GET_HMCT_SIZE(h_Manip) (((t_FmPcdManip *)h_Manip)->tableSize) ++#define MANIP_GET_DATA_SIZE(h_Manip) (((t_FmPcdManip *)h_Manip)->dataSize) ++ ++#define MANIP_GET_HMCT_PTR(h_Manip) (((t_FmPcdManip *)h_Manip)->p_Hmct) ++#define MANIP_GET_DATA_PTR(h_Manip) (((t_FmPcdManip *)h_Manip)->p_Data) ++ ++#define MANIP_SET_HMCT_PTR(h_Manip, h_NewPtr) (((t_FmPcdManip *)h_Manip)->p_Hmct = h_NewPtr) ++#define MANIP_SET_DATA_PTR(h_Manip, h_NewPtr) (((t_FmPcdManip *)h_Manip)->p_Data = h_NewPtr) ++ ++#define MANIP_GET_HMTD_PTR(h_Manip) (((t_FmPcdManip *)h_Manip)->h_Ad) ++#define MANIP_DONT_REPARSE(h_Manip) (((t_FmPcdManip *)h_Manip)->dontParseAfterManip) ++#define MANIP_SET_PREV(h_Manip, h_Prev) (((t_FmPcdManip *)h_Manip)->h_PrevManip = h_Prev) ++#define MANIP_GET_OWNERS(h_Manip) (((t_FmPcdManip *)h_Manip)->owner) ++#define MANIP_GET_TYPE(h_Manip) (((t_FmPcdManip *)h_Manip)->type) ++#define MANIP_SET_UNIFIED_TBL_PTR_INDICATION(h_Manip) (((t_FmPcdManip *)h_Manip)->unifiedTablePtr = TRUE) ++#define MANIP_GET_MURAM(h_Manip) (((t_FmPcd *)((t_FmPcdManip *)h_Manip)->h_FmPcd)->h_FmMuram) ++#define MANIP_FREE_HMTD(h_Manip) \ ++ {if (((t_FmPcdManip *)h_Manip)->muramAllocate) \ ++ FM_MURAM_FreeMem(((t_FmPcd *)((t_FmPcdManip *)h_Manip)->h_FmPcd)->h_FmMuram, ((t_FmPcdManip *)h_Manip)->h_Ad);\ ++ else \ ++ XX_Free(((t_FmPcdManip *)h_Manip)->h_Ad); \ ++ ((t_FmPcdManip *)h_Manip)->h_Ad = NULL; \ ++ } ++/* position regarding Manip SW structure */ ++#define MANIP_IS_FIRST(h_Manip) (!(((t_FmPcdManip *)h_Manip)->h_PrevManip)) ++#define MANIP_IS_CASCADED(h_Manip) (((t_FmPcdManip *)h_Manip)->cascaded) ++#define MANIP_IS_UNIFIED(h_Manip) (!(((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_NONE)) ++#define MANIP_IS_UNIFIED_NON_FIRST(h_Manip) ((((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_MID) || \ ++ (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_LAST)) ++#define MANIP_IS_UNIFIED_NON_LAST(h_Manip) ((((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_FIRST) ||\ ++ (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_MID)) ++#define MANIP_IS_UNIFIED_FIRST(h_Manip) (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_FIRST) ++#define MANIP_IS_UNIFIED_LAST(h_Manip) (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_LAST) ++ ++#define MANIP_UPDATE_UNIFIED_POSITION(h_Manip) (((t_FmPcdManip *)h_Manip)->unifiedPosition = \ ++ (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_NONE)? \ ++ e_MANIP_UNIFIED_LAST : e_MANIP_UNIFIED_MID) ++ ++typedef enum e_ManipUnifiedPosition { ++ e_MANIP_UNIFIED_NONE = 0, ++ e_MANIP_UNIFIED_FIRST, ++ e_MANIP_UNIFIED_MID, ++ e_MANIP_UNIFIED_LAST ++} e_ManipUnifiedPosition; ++ ++typedef enum e_ManipInfo { ++ e_MANIP_HMTD, ++ e_MANIP_HMCT, ++ e_MANIP_HANDLER_TABLE_OWNER ++}e_ManipInfo; ++/***********************************************************************/ ++/* Memory map */ ++/***********************************************************************/ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++typedef struct t_CapwapReasmPram { ++ volatile uint32_t mode; ++ volatile uint32_t autoLearnHashTblPtr; ++ volatile uint32_t intStatsTblPtr; ++ volatile uint32_t reasmFrmDescPoolTblPtr; ++ volatile uint32_t reasmFrmDescIndexPoolTblPtr; ++ volatile uint32_t timeOutTblPtr; ++ volatile uint32_t bufferPoolIdAndRisc1SetIndexes; ++ volatile uint32_t risc23SetIndexes; ++ volatile uint32_t risc4SetIndexesAndExtendedStatsTblPtr; ++ volatile uint32_t extendedStatsTblPtr; ++ volatile uint32_t expirationDelay; ++ volatile uint32_t totalProcessedFragCounter; ++ volatile uint32_t totalUnsuccessfulReasmFramesCounter; ++ volatile uint32_t totalDuplicatedFragCounter; ++ volatile uint32_t totalMalformdFragCounter; ++ volatile uint32_t totalTimeOutCounter; ++ volatile uint32_t totalSetBusyCounter; ++ volatile uint32_t totalRfdPoolBusyCounter; ++ volatile uint32_t totalDiscardedFragsCounter; ++ volatile uint32_t totalMoreThan16FramesCounter; ++ volatile uint32_t internalBufferBusy; ++ volatile uint32_t externalBufferBusy; ++ volatile uint32_t reserved1[4]; ++} t_CapwapReasmPram; ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ ++typedef _Packed struct t_ReassTbl { ++ volatile uint16_t waysNumAndSetSize; ++ volatile uint16_t autoLearnHashKeyMask; ++ volatile uint32_t reassCommonPrmTblPtr; ++ volatile uint32_t liodnAlAndAutoLearnHashTblPtrHi; ++ volatile uint32_t autoLearnHashTblPtrLow; ++ volatile uint32_t liodnSlAndAutoLearnSetLockTblPtrHi; ++ volatile uint32_t autoLearnSetLockTblPtrLow; ++ volatile uint16_t minFragSize; /* Not relevant for CAPWAP*/ ++ volatile uint16_t maxReassemblySize; /* Only relevant for CAPWAP*/ ++ volatile uint32_t totalSuccessfullyReasmFramesCounter; ++ volatile uint32_t totalValidFragmentCounter; ++ volatile uint32_t totalProcessedFragCounter; ++ volatile uint32_t totalMalformdFragCounter; ++ volatile uint32_t totalSetBusyCounter; ++ volatile uint32_t totalDiscardedFragsCounter; ++ volatile uint32_t totalMoreThan16FramesCounter; ++ volatile uint32_t reserved2[2]; ++} _PackedType t_ReassTbl; ++ ++typedef struct t_ReassCommonTbl { ++ volatile uint32_t timeoutModeAndFqid; ++ volatile uint32_t reassFrmDescIndexPoolTblPtr; ++ volatile uint32_t liodnAndReassFrmDescPoolPtrHi; ++ volatile uint32_t reassFrmDescPoolPtrLow; ++ volatile uint32_t timeOutTblPtr; ++ volatile uint32_t expirationDelay; ++ volatile uint32_t internalBufferManagement; ++ volatile uint32_t reserved2; ++ volatile uint32_t totalTimeOutCounter; ++ volatile uint32_t totalRfdPoolBusyCounter; ++ volatile uint32_t totalInternalBufferBusy; ++ volatile uint32_t totalExternalBufferBusy; ++ volatile uint32_t totalSgFragmentCounter; ++ volatile uint32_t totalDmaSemaphoreDepletionCounter; ++ volatile uint32_t totalNCSPCounter; ++ volatile uint32_t discardMask; ++} t_ReassCommonTbl; ++ ++typedef _Packed struct t_Hmtd { ++ volatile uint16_t cfg; ++ volatile uint8_t eliodnOffset; ++ volatile uint8_t extHmcdBasePtrHi; ++ volatile uint32_t hmcdBasePtr; ++ volatile uint16_t nextAdIdx; ++ volatile uint8_t res1; ++ volatile uint8_t opCode; ++ volatile uint32_t res2; ++} _PackedType t_Hmtd; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/***********************************************************************/ ++/* Driver's internal structures */ ++/***********************************************************************/ ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++typedef struct ++{ ++ t_Handle p_AutoLearnHashTbl; ++ t_Handle p_ReassmFrmDescrPoolTbl; ++ t_Handle p_ReassmFrmDescrIndxPoolTbl; ++ t_Handle p_TimeOutTbl; ++ uint16_t maxNumFramesInProcess; ++ uint8_t numOfTasks; ++ //uint8_t poolId; ++ uint8_t prOffset; ++ uint16_t dataOffset; ++ uint8_t sgBpid; ++ uint8_t hwPortId; ++ uint32_t fqidForTimeOutFrames; ++ uint32_t timeoutRoutineRequestTime; ++ uint32_t bitFor1Micro; ++} t_CapwapFragParams; ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ ++typedef struct ++{ ++ t_AdOfTypeContLookup *p_Frag; ++#if (DPAA_VERSION == 10) ++ uint8_t scratchBpid; ++#endif /* (DPAA_VERSION == 10) */ ++} t_FragParams; ++ ++typedef struct t_ReassmParams ++{ ++ e_NetHeaderType hdr; /* Header selection */ ++ t_ReassCommonTbl *p_ReassCommonTbl; ++ uintptr_t reassFrmDescrIndxPoolTblAddr; ++ uintptr_t reassFrmDescrPoolTblAddr; ++ uintptr_t timeOutTblAddr; ++ uintptr_t internalBufferPoolManagementIndexAddr; ++ uintptr_t internalBufferPoolAddr; ++ uint32_t maxNumFramesInProcess; ++ uint8_t sgBpid; ++ uint8_t dataMemId; ++ uint16_t dataLiodnOffset; ++ uint32_t fqidForTimeOutFrames; ++ e_FmPcdManipReassemTimeOutMode timeOutMode; ++ uint32_t timeoutThresholdForReassmProcess; ++ union { ++ struct { ++ t_Handle h_Ipv4Ad; ++ t_Handle h_Ipv6Ad; ++ bool ipv6Assigned; ++ t_ReassTbl *p_Ipv4ReassTbl; ++ t_ReassTbl *p_Ipv6ReassTbl; ++ uintptr_t ipv4AutoLearnHashTblAddr; ++ uintptr_t ipv6AutoLearnHashTblAddr; ++ uintptr_t ipv4AutoLearnSetLockTblAddr; ++ uintptr_t ipv6AutoLearnSetLockTblAddr; ++ uint16_t minFragSize[2]; ++ e_FmPcdManipReassemWaysNumber numOfFramesPerHashEntry[2]; ++ uint8_t relativeSchemeId[2]; ++ t_Handle h_Ipv4Scheme; ++ t_Handle h_Ipv6Scheme; ++ uint32_t nonConsistentSpFqid; ++ } ip; ++ struct { ++ t_Handle h_Ad; ++ t_ReassTbl *p_ReassTbl; ++ uintptr_t autoLearnHashTblAddr; ++ uintptr_t autoLearnSetLockTblAddr; ++ uint16_t maxRessembledsSize; ++ e_FmPcdManipReassemWaysNumber numOfFramesPerHashEntry; ++ uint8_t relativeSchemeId; ++ t_Handle h_Scheme; ++ } capwap; ++ }; ++} t_ReassmParams; ++ ++typedef struct{ ++ e_FmPcdManipType type; ++ t_FmPcdManipParams manipParams; ++ bool muramAllocate; ++ t_Handle h_Ad; ++ uint32_t opcode; ++ bool rmv; ++ bool insrt; ++ t_Handle h_NextManip; ++ t_Handle h_PrevManip; ++ e_FmPcdManipType nextManipType; ++ /* HdrManip parameters*/ ++ uint8_t *p_Hmct; ++ uint8_t *p_Data; ++ bool dontParseAfterManip; ++ bool fieldUpdate; ++ bool custom; ++ uint16_t tableSize; ++ uint8_t dataSize; ++ bool cascaded; ++ e_ManipUnifiedPosition unifiedPosition; ++ /* end HdrManip */ ++ uint8_t *p_Template; ++ uint16_t owner; ++ uint32_t updateParams; ++ uint32_t shadowUpdateParams; ++ bool frag; ++ bool reassm; ++ uint16_t sizeForFragmentation; ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++ t_Handle h_Frag; ++ t_CapwapFragParams capwapFragParams; ++#endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ ++ union { ++ t_ReassmParams reassmParams; ++ t_FragParams fragParams; ++ }; ++ uint8_t icOffset; ++ uint16_t ownerTmp; ++ bool cnia; ++ t_Handle p_StatsTbl; ++ t_Handle h_FmPcd; ++ t_List nodesLst; ++ t_Handle h_Spinlock; ++} t_FmPcdManip; ++ ++typedef struct t_FmPcdCcSavedManipParams ++{ ++ union ++ { ++ struct ++ { ++ uint16_t dataOffset; ++ //uint8_t poolId; ++ }capwapParams; ++ struct ++ { ++ uint16_t dataOffset; ++ uint8_t poolId; ++ }ipParams; ++ }; ++ ++} t_FmPcdCcSavedManipParams; ++ ++ ++#endif /* __FM_MANIP_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_pcd.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_pcd.c +new file mode 100644 +index 0000000..1534331 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_pcd.c +@@ -0,0 +1,2094 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_pcd.c ++ ++ @Description FM PCD ... ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "xx_ext.h" ++#include "sprint_ext.h" ++#include "debug_ext.h" ++#include "net_ext.h" ++#include "fm_ext.h" ++#include "fm_pcd_ext.h" ++ ++#include "fm_common.h" ++#include "fm_pcd.h" ++#include "fm_pcd_ipc.h" ++#include "fm_hc.h" ++#include "fm_muram_ext.h" ++ ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++ ++static t_Error CheckFmPcdParameters(t_FmPcd *p_FmPcd) ++{ ++ if (!p_FmPcd->h_Fm) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("h_Fm has to be initialized")); ++ ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ { ++ if (p_FmPcd->p_FmPcdKg && !p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Something WRONG")); ++ ++ if (p_FmPcd->p_FmPcdPlcr && !p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Something WRONG")); ++ ++ if (!p_FmPcd->f_Exception) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("f_FmPcdExceptions has to be initialized")); ++ ++ if ((!p_FmPcd->f_FmPcdIndexedException) && (p_FmPcd->p_FmPcdPlcr || p_FmPcd->p_FmPcdKg)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("f_FmPcdIndexedException has to be initialized")); ++ ++ if (p_FmPcd->p_FmPcdDriverParam->prsMaxParseCycleLimit > PRS_MAX_CYCLE_LIMIT) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("prsMaxParseCycleLimit has to be less than 8191")); ++ } ++ ++ return E_OK; ++} ++ ++static volatile bool blockingFlag = FALSE; ++static void IpcMsgCompletionCB(t_Handle h_FmPcd, ++ uint8_t *p_Msg, ++ uint8_t *p_Reply, ++ uint32_t replyLength, ++ t_Error status) ++{ ++ UNUSED(h_FmPcd);UNUSED(p_Msg);UNUSED(p_Reply);UNUSED(replyLength);UNUSED(status); ++ blockingFlag = FALSE; ++} ++ ++static t_Error IpcMsgHandlerCB(t_Handle h_FmPcd, ++ uint8_t *p_Msg, ++ uint32_t msgLength, ++ uint8_t *p_Reply, ++ uint32_t *p_ReplyLength) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_Error err = E_OK; ++ t_FmPcdIpcMsg *p_IpcMsg = (t_FmPcdIpcMsg*)p_Msg; ++ t_FmPcdIpcReply *p_IpcReply = (t_FmPcdIpcReply*)p_Reply; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((msgLength >= sizeof(uint32_t)), E_INVALID_VALUE); ++ ++#ifdef DISABLE_SANITY_CHECKS ++ UNUSED(msgLength); ++#endif /* DISABLE_SANITY_CHECKS */ ++ ++ ASSERT_COND(p_Msg); ++ ++ memset(p_IpcReply, 0, (sizeof(uint8_t) * FM_PCD_MAX_REPLY_SIZE)); ++ *p_ReplyLength = 0; ++ ++ switch (p_IpcMsg->msgId) ++ { ++ case (FM_PCD_MASTER_IS_ALIVE): ++ *(uint8_t*)(p_IpcReply->replyBody) = 1; ++ p_IpcReply->error = E_OK; ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ break; ++ case (FM_PCD_MASTER_IS_ENABLED): ++ /* count partitions registrations */ ++ if (p_FmPcd->enabled) ++ p_FmPcd->numOfEnabledGuestPartitionsPcds++; ++ *(uint8_t*)(p_IpcReply->replyBody) = (uint8_t)p_FmPcd->enabled; ++ p_IpcReply->error = E_OK; ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ break; ++ case (FM_PCD_GUEST_DISABLE): ++ if (p_FmPcd->numOfEnabledGuestPartitionsPcds) ++ { ++ p_FmPcd->numOfEnabledGuestPartitionsPcds--; ++ p_IpcReply->error = E_OK; ++ } ++ else ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE,("Trying to disable an unregistered partition")); ++ p_IpcReply->error = E_INVALID_STATE; ++ } ++ *p_ReplyLength = sizeof(uint32_t); ++ break; ++ case (FM_PCD_GET_COUNTER): ++ { ++ e_FmPcdCounters inCounter; ++ uint32_t outCounter; ++ ++ memcpy((uint8_t*)&inCounter, p_IpcMsg->msgBody, sizeof(uint32_t)); ++ outCounter = FM_PCD_GetCounter(h_FmPcd, inCounter); ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&outCounter, sizeof(uint32_t)); ++ p_IpcReply->error = E_OK; ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ break; ++ } ++ case (FM_PCD_ALLOC_KG_SCHEMES): ++ { ++ t_FmPcdIpcKgSchemesParams ipcSchemesParams; ++ ++ memcpy((uint8_t*)&ipcSchemesParams, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcKgSchemesParams)); ++ err = FmPcdKgAllocSchemes(h_FmPcd, ++ ipcSchemesParams.numOfSchemes, ++ ipcSchemesParams.guestId, ++ p_IpcReply->replyBody); ++ p_IpcReply->error = err; ++ *p_ReplyLength = sizeof(uint32_t) + ipcSchemesParams.numOfSchemes*sizeof(uint8_t); ++ break; ++ } ++ case (FM_PCD_FREE_KG_SCHEMES): ++ { ++ t_FmPcdIpcKgSchemesParams ipcSchemesParams; ++ ++ memcpy((uint8_t*)&ipcSchemesParams, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcKgSchemesParams)); ++ err = FmPcdKgFreeSchemes(h_FmPcd, ++ ipcSchemesParams.numOfSchemes, ++ ipcSchemesParams.guestId, ++ ipcSchemesParams.schemesIds); ++ p_IpcReply->error = err; ++ *p_ReplyLength = sizeof(uint32_t); ++ break; ++ } ++ case (FM_PCD_ALLOC_KG_CLSPLAN): ++ { ++ t_FmPcdIpcKgClsPlanParams ipcKgClsPlanParams; ++ ++ memcpy((uint8_t*)&ipcKgClsPlanParams, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcKgClsPlanParams)); ++ err = KgAllocClsPlanEntries(h_FmPcd, ++ ipcKgClsPlanParams.numOfClsPlanEntries, ++ ipcKgClsPlanParams.guestId, ++ p_IpcReply->replyBody); ++ p_IpcReply->error = err; ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ break; ++ } ++ case (FM_PCD_FREE_KG_CLSPLAN): ++ { ++ t_FmPcdIpcKgClsPlanParams ipcKgClsPlanParams; ++ ++ memcpy((uint8_t*)&ipcKgClsPlanParams, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcKgClsPlanParams)); ++ KgFreeClsPlanEntries(h_FmPcd, ++ ipcKgClsPlanParams.numOfClsPlanEntries, ++ ipcKgClsPlanParams.guestId, ++ ipcKgClsPlanParams.clsPlanBase); ++ *p_ReplyLength = sizeof(uint32_t); ++ break; ++ } ++ case (FM_PCD_ALLOC_PROFILES): ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ uint16_t base; ++ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams)); ++ base = PlcrAllocProfilesForPartition(h_FmPcd, ++ ipcAllocParams.base, ++ ipcAllocParams.num, ++ ipcAllocParams.guestId); ++ memcpy(p_IpcReply->replyBody, (uint16_t*)&base, sizeof(uint16_t)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint16_t); ++ break; ++ } ++ case (FM_PCD_FREE_PROFILES): ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams)); ++ PlcrFreeProfilesForPartition(h_FmPcd, ++ ipcAllocParams.base, ++ ipcAllocParams.num, ++ ipcAllocParams.guestId); ++ break; ++ } ++ case (FM_PCD_SET_PORT_PROFILES): ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams)); ++ PlcrSetPortProfiles(h_FmPcd, ++ ipcAllocParams.guestId, ++ ipcAllocParams.num, ++ ipcAllocParams.base); ++ break; ++ } ++ case (FM_PCD_CLEAR_PORT_PROFILES): ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams)); ++ PlcrClearPortProfiles(h_FmPcd, ++ ipcAllocParams.guestId); ++ break; ++ } ++ case (FM_PCD_GET_SW_PRS_OFFSET): ++ { ++ t_FmPcdIpcSwPrsLable ipcSwPrsLable; ++ uint32_t swPrsOffset; ++ ++ memcpy((uint8_t*)&ipcSwPrsLable, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcSwPrsLable)); ++ swPrsOffset = ++ FmPcdGetSwPrsOffset(h_FmPcd, ++ (e_NetHeaderType)ipcSwPrsLable.enumHdr, ++ ipcSwPrsLable.indexPerHdr); ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&swPrsOffset, sizeof(uint32_t)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ break; ++ } ++ case (FM_PCD_PRS_INC_PORT_STATS): ++ { ++ t_FmPcdIpcPrsIncludePort ipcPrsIncludePort; ++ ++ memcpy((uint8_t*)&ipcPrsIncludePort, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcPrsIncludePort)); ++ PrsIncludePortInStatistics(h_FmPcd, ++ ipcPrsIncludePort.hardwarePortId, ++ ipcPrsIncludePort.include); ++ break; ++ } ++ default: ++ *p_ReplyLength = 0; ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!")); ++ } ++ return E_OK; ++} ++ ++static uint32_t NetEnvLock(t_Handle h_NetEnv) ++{ ++ ASSERT_COND(h_NetEnv); ++ return XX_LockIntrSpinlock(((t_FmPcdNetEnv*)h_NetEnv)->h_Spinlock); ++} ++ ++static void NetEnvUnlock(t_Handle h_NetEnv, uint32_t intFlags) ++{ ++ ASSERT_COND(h_NetEnv); ++ XX_UnlockIntrSpinlock(((t_FmPcdNetEnv*)h_NetEnv)->h_Spinlock, intFlags); ++} ++ ++static void EnqueueLockToFreeLst(t_FmPcd *p_FmPcd, t_FmPcdLock *p_Lock) ++{ ++ uint32_t intFlags; ++ ++ intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock); ++ LIST_AddToTail(&p_Lock->node, &p_FmPcd->freeLocksLst); ++ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags); ++} ++ ++static t_FmPcdLock * DequeueLockFromFreeLst(t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdLock *p_Lock = NULL; ++ uint32_t intFlags; ++ ++ intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock); ++ if (!LIST_IsEmpty(&p_FmPcd->freeLocksLst)) ++ { ++ p_Lock = FM_PCD_LOCK_OBJ(p_FmPcd->freeLocksLst.p_Next); ++ LIST_DelAndInit(&p_Lock->node); ++ } ++ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags); ++ ++ return p_Lock; ++} ++ ++static void EnqueueLockToAcquiredLst(t_FmPcd *p_FmPcd, t_FmPcdLock *p_Lock) ++{ ++ uint32_t intFlags; ++ ++ intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock); ++ LIST_AddToTail(&p_Lock->node, &p_FmPcd->acquiredLocksLst); ++ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags); ++} ++ ++static t_Error FillFreeLocksLst(t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdLock *p_Lock; ++ int i; ++ ++ for (i=0; i<10; i++) ++ { ++ p_Lock = (t_FmPcdLock *)XX_Malloc(sizeof(t_FmPcdLock)); ++ if (!p_Lock) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("FM-PCD lock obj!")); ++ memset(p_Lock, 0, sizeof(t_FmPcdLock)); ++ INIT_LIST(&p_Lock->node); ++ p_Lock->h_Spinlock = XX_InitSpinlock(); ++ if (!p_Lock->h_Spinlock) ++ { ++ XX_Free(p_Lock); ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("FM-PCD spinlock obj!")); ++ } ++ EnqueueLockToFreeLst(p_FmPcd, p_Lock); ++ } ++ ++ return E_OK; ++} ++ ++static void ReleaseFreeLocksLst(t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdLock *p_Lock; ++ ++ p_Lock = DequeueLockFromFreeLst(p_FmPcd); ++ while (p_Lock) ++ { ++ XX_FreeSpinlock(p_Lock->h_Spinlock); ++ XX_Free(p_Lock); ++ p_Lock = DequeueLockFromFreeLst(p_FmPcd); ++ } ++} ++ ++ ++ ++/*****************************************************************************/ ++/* Inter-module API routines */ ++/*****************************************************************************/ ++ ++void FmPcdSetClsPlanGrpId(t_FmPcd *p_FmPcd, uint8_t netEnvId, uint8_t clsPlanGrpId) ++{ ++ ASSERT_COND(p_FmPcd); ++ p_FmPcd->netEnvs[netEnvId].clsPlanGrpId = clsPlanGrpId; ++} ++ ++t_Error PcdGetClsPlanGrpParams(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_GrpParams) ++{ ++ uint8_t netEnvId = p_GrpParams->netEnvId; ++ int i, k, j; ++ ++ ASSERT_COND(p_FmPcd); ++ if (p_FmPcd->netEnvs[netEnvId].clsPlanGrpId != ILLEGAL_CLS_PLAN) ++ { ++ p_GrpParams->grpExists = TRUE; ++ p_GrpParams->clsPlanGrpId = p_FmPcd->netEnvs[netEnvId].clsPlanGrpId; ++ return E_OK; ++ } ++ ++ for (i=0; ((i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE)); i++) ++ { ++ for (k=0; ((k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE)); k++) ++ { ++ /* if an option exists, add it to the opts list */ ++ if (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt) ++ { ++ /* check if this option already exists, add if it doesn't */ ++ for (j = 0;jnumOfOptions;j++) ++ { ++ if (p_GrpParams->options[j] == p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt) ++ break; ++ } ++ p_GrpParams->optVectors[j] |= p_FmPcd->netEnvs[netEnvId].unitsVectors[i]; ++ if (j == p_GrpParams->numOfOptions) ++ { ++ p_GrpParams->options[p_GrpParams->numOfOptions] = p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt; ++ p_GrpParams->numOfOptions++; ++ } ++ } ++ } ++ } ++ ++ if (p_GrpParams->numOfOptions == 0) ++ { ++ if (p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId != ILLEGAL_CLS_PLAN) ++ { ++ p_GrpParams->grpExists = TRUE; ++ p_GrpParams->clsPlanGrpId = p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId; ++ } ++ } ++ ++ return E_OK; ++ ++} ++ ++t_Error PcdGetVectorForOpt(t_FmPcd *p_FmPcd, uint8_t netEnvId, protocolOpt_t opt, uint32_t *p_Vector) ++{ ++ uint8_t j,k; ++ ++ *p_Vector = 0; ++ ++ ASSERT_COND(p_FmPcd); ++ for (j=0; ((j < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) && ++ (p_FmPcd->netEnvs[netEnvId].units[j].hdrs[0].hdr != HEADER_TYPE_NONE)); j++) ++ { ++ for (k=0; ((k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) && ++ (p_FmPcd->netEnvs[netEnvId].units[j].hdrs[k].hdr != HEADER_TYPE_NONE)); k++) ++ { ++ if (p_FmPcd->netEnvs[netEnvId].units[j].hdrs[k].opt == opt) ++ *p_Vector |= p_FmPcd->netEnvs[netEnvId].unitsVectors[j]; ++ } ++ } ++ ++ if (!*p_Vector) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Requested option was not defined for this Network Environment Characteristics module")); ++ else ++ return E_OK; ++} ++ ++t_Error PcdGetUnitsVector(t_FmPcd *p_FmPcd, t_NetEnvParams *p_Params) ++{ ++ int i; ++ ++ ASSERT_COND(p_FmPcd); ++ ASSERT_COND(p_Params->netEnvId < FM_MAX_NUM_OF_PORTS); ++ ++ p_Params->vector = 0; ++ for (i=0; inumOfDistinctionUnits ;i++) ++ { ++ if (p_FmPcd->netEnvs[p_Params->netEnvId].units[p_Params->unitIds[i]].hdrs[0].hdr == HEADER_TYPE_NONE) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Requested unit was not defined for this Network Environment Characteristics module")); ++ ASSERT_COND(p_FmPcd->netEnvs[p_Params->netEnvId].unitsVectors[p_Params->unitIds[i]]); ++ p_Params->vector |= p_FmPcd->netEnvs[p_Params->netEnvId].unitsVectors[p_Params->unitIds[i]]; ++ } ++ ++ return E_OK; ++} ++ ++bool PcdNetEnvIsUnitWithoutOpts(t_FmPcd *p_FmPcd, uint8_t netEnvId, uint32_t unitVector) ++{ ++ int i=0, k; ++ ++ ASSERT_COND(p_FmPcd); ++ /* check whether a given unit may be used by non-clsPlan users. */ ++ /* first, recognize the unit by its vector */ ++ while (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE) ++ { ++ if (p_FmPcd->netEnvs[netEnvId].unitsVectors[i] == unitVector) ++ { ++ for (k=0; ++ ((k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE)); ++ k++) ++ /* check that no option exists */ ++ if ((protocolOpt_t)p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt) ++ return FALSE; ++ break; ++ } ++ i++; ++ } ++ /* assert that a unit was found to mach the vector */ ++ ASSERT_COND(p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); ++ ++ return TRUE; ++} ++bool FmPcdNetEnvIsHdrExist(t_Handle h_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ int i, k; ++ ++ ASSERT_COND(p_FmPcd); ++ ++ for (i=0; ((i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE)); i++) ++ { ++ for (k=0; ((k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE)); k++) ++ if (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr == hdr) ++ return TRUE; ++ } ++ for (i=0; ((i < FM_PCD_MAX_NUM_OF_ALIAS_HDRS) && ++ (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr != HEADER_TYPE_NONE)); i++) ++ { ++ if (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr == hdr) ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++uint8_t FmPcdNetEnvGetUnitId(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr, bool interchangeable, protocolOpt_t opt) ++{ ++ uint8_t i, k; ++ ++ ASSERT_COND(p_FmPcd); ++ ++ if (interchangeable) ++ { ++ for (i=0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++) ++ { ++ for (k=0; (k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE); k++) ++ { ++ if ((p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr == hdr) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt == opt)) ++ ++ return i; ++ } ++ } ++ } ++ else ++ { ++ for (i=0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++) ++ if ((p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr == hdr) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].opt == opt) && ++ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[1].hdr == HEADER_TYPE_NONE)) ++ return i; ++ ++ for (i=0; (i < FM_PCD_MAX_NUM_OF_ALIAS_HDRS) && ++ (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr != HEADER_TYPE_NONE); i++) ++ if ((p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr == hdr) && ++ (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].opt == opt)) ++ return p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].aliasHdr; ++ } ++ ++ return FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS; ++} ++ ++t_Error FmPcdUnregisterReassmPort(t_Handle h_FmPcd, t_Handle h_ReasmCommonPramTbl) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdCcReassmTimeoutParams ccReassmTimeoutParams = {0}; ++ uint8_t result; ++ t_Error err = E_OK; ++ ++ ASSERT_COND(p_FmPcd); ++ ASSERT_COND(h_ReasmCommonPramTbl); ++ ++ ccReassmTimeoutParams.iprcpt = (uint32_t)(XX_VirtToPhys(h_ReasmCommonPramTbl) - p_FmPcd->physicalMuramBase); ++ ccReassmTimeoutParams.activate = FALSE; /*Disable Timeout Task*/ ++ ++ if ((err = FmHcPcdCcTimeoutReassm(p_FmPcd->h_Hc, &ccReassmTimeoutParams, &result)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ switch (result) ++ { ++ case (0): ++ return E_OK; ++ case (1): ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("")); ++ case (2): ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("")); ++ case (3): ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("Disable Timeout Task with invalid IPRCPT")); ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ } ++ ++ return E_OK; ++} ++ ++e_NetHeaderType FmPcdGetAliasHdr(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr) ++{ ++ int i; ++ ++ ASSERT_COND(p_FmPcd); ++ ASSERT_COND(netEnvId < FM_MAX_NUM_OF_PORTS); ++ ++ for (i=0; (i < FM_PCD_MAX_NUM_OF_ALIAS_HDRS) ++ && (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr != HEADER_TYPE_NONE); i++) ++ { ++ if (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr == hdr) ++ return p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].aliasHdr; ++ } ++ ++ return HEADER_TYPE_NONE; ++} ++ ++void FmPcdPortRegister(t_Handle h_FmPcd, t_Handle h_FmPort, uint8_t hardwarePortId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint16_t swPortIndex = 0; ++ ++ ASSERT_COND(h_FmPcd); ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].h_FmPort = h_FmPort; ++} ++ ++uint32_t FmPcdGetLcv(t_Handle h_FmPcd, uint32_t netEnvId, uint8_t hdrNum) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(h_FmPcd); ++ return p_FmPcd->netEnvs[netEnvId].lcvs[hdrNum]; ++} ++ ++uint32_t FmPcdGetMacsecLcv(t_Handle h_FmPcd, uint32_t netEnvId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(h_FmPcd); ++ return p_FmPcd->netEnvs[netEnvId].macsecVector; ++} ++ ++uint8_t FmPcdGetNetEnvId(t_Handle h_NetEnv) ++{ ++ return ((t_FmPcdNetEnv*)h_NetEnv)->netEnvId; ++} ++ ++void FmPcdIncNetEnvOwners(t_Handle h_FmPcd, uint8_t netEnvId) ++{ ++ uint32_t intFlags; ++ ++ ASSERT_COND(h_FmPcd); ++ ++ intFlags = NetEnvLock(&((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId]); ++ ((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId].owners++; ++ NetEnvUnlock(&((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId], intFlags); ++} ++ ++void FmPcdDecNetEnvOwners(t_Handle h_FmPcd, uint8_t netEnvId) ++{ ++ uint32_t intFlags; ++ ++ ASSERT_COND(h_FmPcd); ++ ASSERT_COND(((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId].owners); ++ ++ intFlags = NetEnvLock(&((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId]); ++ ((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId].owners--; ++ NetEnvUnlock(&((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId], intFlags); ++} ++ ++uint32_t FmPcdLock(t_Handle h_FmPcd) ++{ ++ ASSERT_COND(h_FmPcd); ++ return XX_LockIntrSpinlock(((t_FmPcd*)h_FmPcd)->h_Spinlock); ++} ++ ++void FmPcdUnlock(t_Handle h_FmPcd, uint32_t intFlags) ++{ ++ ASSERT_COND(h_FmPcd); ++ XX_UnlockIntrSpinlock(((t_FmPcd*)h_FmPcd)->h_Spinlock, intFlags); ++} ++ ++t_FmPcdLock * FmPcdAcquireLock(t_Handle h_FmPcd) ++{ ++ t_FmPcdLock *p_Lock; ++ ASSERT_COND(h_FmPcd); ++ p_Lock = DequeueLockFromFreeLst((t_FmPcd*)h_FmPcd); ++ if (!p_Lock) ++ { ++ FillFreeLocksLst(h_FmPcd); ++ p_Lock = DequeueLockFromFreeLst((t_FmPcd*)h_FmPcd); ++ } ++ ++ if (p_Lock) ++ EnqueueLockToAcquiredLst((t_FmPcd*)h_FmPcd, p_Lock); ++ return p_Lock; ++} ++ ++void FmPcdReleaseLock(t_Handle h_FmPcd, t_FmPcdLock *p_Lock) ++{ ++ uint32_t intFlags; ++ ASSERT_COND(h_FmPcd); ++ intFlags = FmPcdLock(h_FmPcd); ++ LIST_DelAndInit(&p_Lock->node); ++ FmPcdUnlock(h_FmPcd, intFlags); ++ EnqueueLockToFreeLst((t_FmPcd*)h_FmPcd, p_Lock); ++} ++ ++bool FmPcdLockTryLockAll(t_Handle h_FmPcd) ++{ ++ uint32_t intFlags; ++ t_List *p_Pos, *p_SavedPos=NULL; ++ ++ ASSERT_COND(h_FmPcd); ++ intFlags = FmPcdLock(h_FmPcd); ++ LIST_FOR_EACH(p_Pos, &((t_FmPcd*)h_FmPcd)->acquiredLocksLst) ++ { ++ t_FmPcdLock *p_Lock = FM_PCD_LOCK_OBJ(p_Pos); ++ if (!FmPcdLockTryLock(p_Lock)) ++ { ++ p_SavedPos = p_Pos; ++ break; ++ } ++ } ++ if (p_SavedPos) ++ { ++ LIST_FOR_EACH(p_Pos, &((t_FmPcd*)h_FmPcd)->acquiredLocksLst) ++ { ++ t_FmPcdLock *p_Lock = FM_PCD_LOCK_OBJ(p_Pos); ++ if (p_Pos == p_SavedPos) ++ break; ++ FmPcdLockUnlock(p_Lock); ++ } ++ } ++ FmPcdUnlock(h_FmPcd, intFlags); ++ ++ CORE_MemoryBarrier(); ++ ++ if (p_SavedPos) ++ return FALSE; ++ ++ return TRUE; ++} ++ ++void FmPcdLockUnlockAll(t_Handle h_FmPcd) ++{ ++ uint32_t intFlags; ++ t_List *p_Pos; ++ ++ ASSERT_COND(h_FmPcd); ++ intFlags = FmPcdLock(h_FmPcd); ++ LIST_FOR_EACH(p_Pos, &((t_FmPcd*)h_FmPcd)->acquiredLocksLst) ++ { ++ t_FmPcdLock *p_Lock = FM_PCD_LOCK_OBJ(p_Pos); ++ p_Lock->flag = FALSE; ++ } ++ FmPcdUnlock(h_FmPcd, intFlags); ++ ++ CORE_MemoryBarrier(); ++} ++ ++t_Error FmPcdHcSync(t_Handle h_FmPcd) ++{ ++ ASSERT_COND(h_FmPcd); ++ ASSERT_COND(((t_FmPcd*)h_FmPcd)->h_Hc); ++ ++ return FmHcPcdSync(((t_FmPcd*)h_FmPcd)->h_Hc); ++} ++ ++t_Handle FmPcdGetHcHandle(t_Handle h_FmPcd) ++{ ++ ASSERT_COND(h_FmPcd); ++ return ((t_FmPcd*)h_FmPcd)->h_Hc; ++} ++ ++bool FmPcdIsAdvancedOffloadSupported(t_Handle h_FmPcd) ++{ ++ ASSERT_COND(h_FmPcd); ++ return ((t_FmPcd*)h_FmPcd)->advancedOffloadSupport; ++} ++/*********************** End of inter-module routines ************************/ ++ ++ ++/****************************************/ ++/* API Init unit functions */ ++/****************************************/ ++ ++t_Handle FM_PCD_Config(t_FmPcdParams *p_FmPcdParams) ++{ ++ t_FmPcd *p_FmPcd = NULL; ++ t_FmPhysAddr physicalMuramBase; ++ uint8_t i; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPcdParams, E_INVALID_HANDLE,NULL); ++ ++ p_FmPcd = (t_FmPcd *) XX_Malloc(sizeof(t_FmPcd)); ++ if (!p_FmPcd) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD")); ++ return NULL; ++ } ++ memset(p_FmPcd, 0, sizeof(t_FmPcd)); ++ ++ p_FmPcd->p_FmPcdDriverParam = (t_FmPcdDriverParam *) XX_Malloc(sizeof(t_FmPcdDriverParam)); ++ if (!p_FmPcd->p_FmPcdDriverParam) ++ { ++ XX_Free(p_FmPcd); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD Driver Param")); ++ return NULL; ++ } ++ memset(p_FmPcd->p_FmPcdDriverParam, 0, sizeof(t_FmPcdDriverParam)); ++ ++ p_FmPcd->h_Fm = p_FmPcdParams->h_Fm; ++ p_FmPcd->guestId = FmGetGuestId(p_FmPcd->h_Fm); ++ p_FmPcd->h_FmMuram = FmGetMuramHandle(p_FmPcd->h_Fm); ++ if (p_FmPcd->h_FmMuram) ++ { ++ FmGetPhysicalMuramBase(p_FmPcdParams->h_Fm, &physicalMuramBase); ++ p_FmPcd->physicalMuramBase = (uint64_t)((uint64_t)(&physicalMuramBase)->low | ((uint64_t)(&physicalMuramBase)->high << 32)); ++ } ++ ++ for (i = 0; inetEnvs[i].clsPlanGrpId = ILLEGAL_CLS_PLAN; ++ ++ if (p_FmPcdParams->useHostCommand) ++ { ++ t_FmHcParams hcParams; ++ ++ memset(&hcParams, 0, sizeof(hcParams)); ++ hcParams.h_Fm = p_FmPcd->h_Fm; ++ hcParams.h_FmPcd = (t_Handle)p_FmPcd; ++ memcpy((uint8_t*)&hcParams.params, (uint8_t*)&p_FmPcdParams->hc, sizeof(t_FmPcdHcParams)); ++ p_FmPcd->h_Hc = FmHcConfigAndInit(&hcParams); ++ if (!p_FmPcd->h_Hc) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD HC")); ++ FM_PCD_Free(p_FmPcd); ++ return NULL; ++ } ++ } ++ else if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("No Host Command defined for a guest partition.")); ++ ++ if (p_FmPcdParams->kgSupport) ++ { ++ p_FmPcd->p_FmPcdKg = (t_FmPcdKg *)KgConfig(p_FmPcd, p_FmPcdParams); ++ if (!p_FmPcd->p_FmPcdKg) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD Keygen")); ++ FM_PCD_Free(p_FmPcd); ++ return NULL; ++ } ++ } ++ ++ if (p_FmPcdParams->plcrSupport) ++ { ++ p_FmPcd->p_FmPcdPlcr = (t_FmPcdPlcr *)PlcrConfig(p_FmPcd, p_FmPcdParams); ++ if (!p_FmPcd->p_FmPcdPlcr) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD Policer")); ++ FM_PCD_Free(p_FmPcd); ++ return NULL; ++ } ++ } ++ ++ if (p_FmPcdParams->prsSupport) ++ { ++ p_FmPcd->p_FmPcdPrs = (t_FmPcdPrs *)PrsConfig(p_FmPcd, p_FmPcdParams); ++ if (!p_FmPcd->p_FmPcdPrs) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD Parser")); ++ FM_PCD_Free(p_FmPcd); ++ return NULL; ++ } ++ } ++ ++ p_FmPcd->h_Spinlock = XX_InitSpinlock(); ++ if (!p_FmPcd->h_Spinlock) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD spinlock")); ++ FM_PCD_Free(p_FmPcd); ++ return NULL; ++ } ++ INIT_LIST(&p_FmPcd->freeLocksLst); ++ INIT_LIST(&p_FmPcd->acquiredLocksLst); ++ ++ p_FmPcd->numOfEnabledGuestPartitionsPcds = 0; ++ ++ p_FmPcd->f_Exception = p_FmPcdParams->f_Exception; ++ p_FmPcd->f_FmPcdIndexedException = p_FmPcdParams->f_ExceptionId; ++ p_FmPcd->h_App = p_FmPcdParams->h_App; ++ ++ p_FmPcd->p_CcShadow = NULL; ++ p_FmPcd->ccShadowSize = 0; ++ p_FmPcd->ccShadowAlign = 0; ++ ++ p_FmPcd->h_ShadowSpinlock = XX_InitSpinlock(); ++ if (!p_FmPcd->h_ShadowSpinlock) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD shadow spinlock")); ++ FM_PCD_Free(p_FmPcd); ++ return NULL; ++ } ++ ++ return p_FmPcd; ++} ++ ++t_Error FM_PCD_Init(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_Error err = E_OK; ++ t_FmPcdIpcMsg msg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); ++ ++ FM_GetRevision(p_FmPcd->h_Fm, &p_FmPcd->fmRevInfo); ++ ++ if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ { ++ memset(p_FmPcd->fmPcdIpcHandlerModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE); ++ if (Sprint (p_FmPcd->fmPcdIpcHandlerModuleName, "FM_PCD_%d_%d", FmGetId(p_FmPcd->h_Fm), NCSW_MASTER_ID) != 10) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ memset(p_FmPcd->fmPcdModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE); ++ if (Sprint (p_FmPcd->fmPcdModuleName, "FM_PCD_%d_%d",FmGetId(p_FmPcd->h_Fm), p_FmPcd->guestId) != (p_FmPcd->guestId<10 ? 10:11)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ ++ p_FmPcd->h_IpcSession = XX_IpcInitSession(p_FmPcd->fmPcdIpcHandlerModuleName, p_FmPcd->fmPcdModuleName); ++ if (p_FmPcd->h_IpcSession) ++ { ++ t_FmPcdIpcReply reply; ++ uint32_t replyLength; ++ uint8_t isMasterAlive = 0; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_PCD_MASTER_IS_ALIVE; ++ msg.msgBody[0] = p_FmPcd->guestId; ++ blockingFlag = TRUE; ++ ++ do ++ { ++ replyLength = sizeof(uint32_t) + sizeof(isMasterAlive); ++ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(p_FmPcd->guestId), ++ (uint8_t*)&reply, ++ &replyLength, ++ IpcMsgCompletionCB, ++ h_FmPcd)) != E_OK) ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ while (blockingFlag) ; ++ if (replyLength != (sizeof(uint32_t) + sizeof(isMasterAlive))) ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ isMasterAlive = *(uint8_t*)(reply.replyBody); ++ } while (!isMasterAlive); ++ } ++ } ++ ++ CHECK_INIT_PARAMETERS(p_FmPcd, CheckFmPcdParameters); ++ ++ if (p_FmPcd->p_FmPcdKg) ++ { ++ err = KgInit(p_FmPcd); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ if (p_FmPcd->p_FmPcdPlcr) ++ { ++ err = PlcrInit(p_FmPcd); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ if (p_FmPcd->p_FmPcdPrs) ++ { ++ err = PrsInit(p_FmPcd); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ { ++ /* register to inter-core messaging mechanism */ ++ memset(p_FmPcd->fmPcdModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE); ++ if (Sprint (p_FmPcd->fmPcdModuleName, "FM_PCD_%d_%d",FmGetId(p_FmPcd->h_Fm),NCSW_MASTER_ID) != 10) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ err = XX_IpcRegisterMsgHandler(p_FmPcd->fmPcdModuleName, IpcMsgHandlerCB, p_FmPcd, FM_PCD_MAX_REPLY_SIZE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ /* IPv6 Frame-Id used for fragmentation */ ++ p_FmPcd->ipv6FrameIdAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, 4, 4)); ++ if (!p_FmPcd->ipv6FrameIdAddr) ++ { ++ FM_PCD_Free(p_FmPcd); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for IPv6 Frame-Id")); ++ } ++ IOMemSet32(UINT_TO_PTR(p_FmPcd->ipv6FrameIdAddr), 0, 4); ++ ++ /* CAPWAP Frame-Id used for fragmentation */ ++ p_FmPcd->capwapFrameIdAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, 2, 4)); ++ if (!p_FmPcd->capwapFrameIdAddr) ++ { ++ FM_PCD_Free(p_FmPcd); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CAPWAP Frame-Id")); ++ } ++ IOMemSet32(UINT_TO_PTR(p_FmPcd->capwapFrameIdAddr), 0, 2); ++ ++ XX_Free(p_FmPcd->p_FmPcdDriverParam); ++ p_FmPcd->p_FmPcdDriverParam = NULL; ++ ++ FmRegisterPcd(p_FmPcd->h_Fm, p_FmPcd); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_Free(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd =(t_FmPcd *)h_FmPcd; ++ t_Error err = E_OK; ++ ++ if (p_FmPcd->ipv6FrameIdAddr) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_FmPcd->ipv6FrameIdAddr)); ++ ++ if (p_FmPcd->capwapFrameIdAddr) ++ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_FmPcd->capwapFrameIdAddr)); ++ ++ if (p_FmPcd->enabled) ++ FM_PCD_Disable(p_FmPcd); ++ ++ if (p_FmPcd->p_FmPcdDriverParam) ++ { ++ XX_Free(p_FmPcd->p_FmPcdDriverParam); ++ p_FmPcd->p_FmPcdDriverParam = NULL; ++ } ++ ++ if (p_FmPcd->p_FmPcdKg) ++ { ++ if ((err = KgFree(p_FmPcd)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ XX_Free(p_FmPcd->p_FmPcdKg); ++ p_FmPcd->p_FmPcdKg = NULL; ++ } ++ ++ if (p_FmPcd->p_FmPcdPlcr) ++ { ++ PlcrFree(p_FmPcd); ++ XX_Free(p_FmPcd->p_FmPcdPlcr); ++ p_FmPcd->p_FmPcdPlcr = NULL; ++ } ++ ++ if (p_FmPcd->p_FmPcdPrs) ++ { ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ PrsFree(p_FmPcd); ++ XX_Free(p_FmPcd->p_FmPcdPrs); ++ p_FmPcd->p_FmPcdPrs = NULL; ++ } ++ ++ if (p_FmPcd->h_Hc) ++ { ++ FmHcFree(p_FmPcd->h_Hc); ++ p_FmPcd->h_Hc = NULL; ++ } ++ ++ XX_IpcUnregisterMsgHandler(p_FmPcd->fmPcdModuleName); ++ ++ FmUnregisterPcd(p_FmPcd->h_Fm); ++ ++ ReleaseFreeLocksLst(p_FmPcd); ++ ++ if (p_FmPcd->h_Spinlock) ++ XX_FreeSpinlock(p_FmPcd->h_Spinlock); ++ ++ if (p_FmPcd->h_ShadowSpinlock) ++ XX_FreeSpinlock(p_FmPcd->h_ShadowSpinlock); ++ ++ XX_Free(p_FmPcd); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_ConfigException(t_Handle h_FmPcd, e_FmPcdExceptions exception, bool enable) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ConfigException - guest mode!")); ++ ++ GET_FM_PCD_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_FmPcd->exceptions |= bitMask; ++ else ++ p_FmPcd->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_ConfigHcFramesDataMemory(t_Handle h_FmPcd, uint8_t memId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE); ++ ++ return FmHcSetFramesDataMemory(p_FmPcd->h_Hc, memId); ++} ++ ++t_Error FM_PCD_Enable(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ ++ if (p_FmPcd->enabled) ++ return E_OK; ++ ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ p_FmPcd->h_IpcSession) ++ { ++ uint8_t enabled; ++ t_FmPcdIpcMsg msg; ++ t_FmPcdIpcReply reply; ++ uint32_t replyLength; ++ ++ memset(&reply, 0, sizeof(reply)); ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_PCD_MASTER_IS_ENABLED; ++ replyLength = sizeof(uint32_t) + sizeof(enabled); ++ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t) + sizeof(enabled)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ p_FmPcd->enabled = (bool)!!(*(uint8_t*)(reply.replyBody)); ++ if (!p_FmPcd->enabled) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM-PCD master should be enabled first!")); ++ ++ return E_OK; ++ } ++ else if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++ ++ if (p_FmPcd->p_FmPcdKg) ++ KgEnable(p_FmPcd); ++ ++ if (p_FmPcd->p_FmPcdPlcr) ++ PlcrEnable(p_FmPcd); ++ ++ if (p_FmPcd->p_FmPcdPrs) ++ PrsEnable(p_FmPcd); ++ ++ p_FmPcd->enabled = TRUE; ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_Disable(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ ++ if (!p_FmPcd->enabled) ++ return E_OK; ++ ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ p_FmPcd->h_IpcSession) ++ { ++ t_FmPcdIpcMsg msg; ++ t_FmPcdIpcReply reply; ++ uint32_t replyLength; ++ ++ memset(&reply, 0, sizeof(reply)); ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_PCD_GUEST_DISABLE; ++ replyLength = sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ if (reply.error == E_OK) ++ p_FmPcd->enabled = FALSE; ++ ++ return (t_Error)(reply.error); ++ } ++ else if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++ ++ if (p_FmPcd->numOfEnabledGuestPartitionsPcds != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("Trying to disable a master partition PCD while" ++ "guest partitions are still enabled!")); ++ ++ if (p_FmPcd->p_FmPcdKg) ++ KgDisable(p_FmPcd); ++ ++ if (p_FmPcd->p_FmPcdPlcr) ++ PlcrDisable(p_FmPcd); ++ ++ if (p_FmPcd->p_FmPcdPrs) ++ PrsDisable(p_FmPcd); ++ ++ p_FmPcd->enabled = FALSE; ++ ++ return E_OK; ++} ++ ++t_Handle FM_PCD_NetEnvCharacteristicsSet(t_Handle h_FmPcd, t_FmPcdNetEnvParams *p_NetEnvParams) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t intFlags, specialUnits = 0; ++ uint8_t bitId = 0; ++ uint8_t i, j, k; ++ uint8_t netEnvCurrId; ++ uint8_t ipsecAhUnit = 0,ipsecEspUnit = 0; ++ bool ipsecAhExists = FALSE, ipsecEspExists = FALSE, shim1Selected = FALSE; ++ uint8_t hdrNum; ++ t_FmPcdNetEnvParams *p_ModifiedNetEnvParams; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_STATE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_NetEnvParams, E_NULL_POINTER, NULL); ++ ++ intFlags = FmPcdLock(p_FmPcd); ++ ++ /* find a new netEnv */ ++ for (i = 0; i < FM_MAX_NUM_OF_PORTS; i++) ++ if (!p_FmPcd->netEnvs[i].used) ++ break; ++ ++ if (i== FM_MAX_NUM_OF_PORTS) ++ { ++ REPORT_ERROR(MAJOR, E_FULL,("No more than %d netEnv's allowed.", FM_MAX_NUM_OF_PORTS)); ++ FmPcdUnlock(p_FmPcd, intFlags); ++ return NULL; ++ } ++ ++ p_FmPcd->netEnvs[i].used = TRUE; ++ FmPcdUnlock(p_FmPcd, intFlags); ++ ++ /* As anyone doesn't have handle of this netEnv yet, no need ++ to protect it with spinlocks */ ++ ++ p_ModifiedNetEnvParams = (t_FmPcdNetEnvParams *)XX_Malloc(sizeof(t_FmPcdNetEnvParams)); ++ if (!p_ModifiedNetEnvParams) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FmPcdNetEnvParams")); ++ return NULL; ++ } ++ ++ memcpy(p_ModifiedNetEnvParams, p_NetEnvParams, sizeof(t_FmPcdNetEnvParams)); ++ p_NetEnvParams = p_ModifiedNetEnvParams; ++ ++ netEnvCurrId = (uint8_t)i; ++ ++ /* clear from previous use */ ++ memset(&p_FmPcd->netEnvs[netEnvCurrId].units, 0, FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS * sizeof(t_FmPcdIntDistinctionUnit)); ++ memset(&p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs, 0, FM_PCD_MAX_NUM_OF_ALIAS_HDRS * sizeof(t_FmPcdNetEnvAliases)); ++ memcpy(&p_FmPcd->netEnvs[netEnvCurrId].units, p_NetEnvParams->units, p_NetEnvParams->numOfDistinctionUnits*sizeof(t_FmPcdIntDistinctionUnit)); ++ ++ p_FmPcd->netEnvs[netEnvCurrId].netEnvId = netEnvCurrId; ++ p_FmPcd->netEnvs[netEnvCurrId].h_FmPcd = p_FmPcd; ++ ++ p_FmPcd->netEnvs[netEnvCurrId].clsPlanGrpId = ILLEGAL_CLS_PLAN; ++ ++ /* check that header with opt is not interchanged with the same header */ ++ for (i = 0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) ++ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++) ++ { ++ for (k = 0; (k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) ++ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE); k++) ++ { ++ /* if an option exists, check that other headers are not the same header ++ without option */ ++ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt) ++ { ++ for (j = 0; (j < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) ++ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[j].hdr != HEADER_TYPE_NONE); j++) ++ { ++ if ((p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[j].hdr == p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr) && ++ !p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[j].opt) ++ { ++ REPORT_ERROR(MINOR, E_FULL, ++ ("Illegal unit - header with opt may not be interchangeable with the same header without opt")); ++ XX_Free(p_ModifiedNetEnvParams); ++ return NULL; ++ } ++ } ++ } ++ } ++ } ++ ++ /* Specific headers checking */ ++ for (i = 0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) ++ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++) ++ { ++ for (k = 0; (k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) ++ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE); k++) ++ { ++ /* Some headers pairs may not be defined on different units as the parser ++ doesn't distinguish */ ++ /* IPSEC_AH and IPSEC_SPI can't be 2 units, */ ++ /* check that header with opt is not interchanged with the same header */ ++ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_IPSEC_AH) ++ { ++ if (ipsecEspExists && (ipsecEspUnit != i)) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("HEADER_TYPE_IPSEC_AH and HEADER_TYPE_IPSEC_ESP may not be defined in separate units")); ++ XX_Free(p_ModifiedNetEnvParams); ++ return NULL; ++ } ++ else ++ { ++ ipsecAhUnit = i; ++ ipsecAhExists = TRUE; ++ } ++ } ++ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_IPSEC_ESP) ++ { ++ if (ipsecAhExists && (ipsecAhUnit != i)) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("HEADER_TYPE_IPSEC_AH and HEADER_TYPE_IPSEC_ESP may not be defined in separate units")); ++ XX_Free(p_ModifiedNetEnvParams); ++ return NULL; ++ } ++ else ++ { ++ ipsecEspUnit = i; ++ ipsecEspExists = TRUE; ++ } ++ } ++ /* ENCAP_ESP */ ++ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_UDP_ENCAP_ESP) ++ { ++ /* IPSec UDP encapsulation is currently set to use SHIM1 */ ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_UDP_ENCAP_ESP; ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_USER_DEFINED_SHIM1; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_USER_DEFINED_SHIM1; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0; ++ } ++#if (DPAA_VERSION >= 11) || ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++ /* UDP_LITE */ ++ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_UDP_LITE) ++ { ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_UDP_LITE; ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_UDP; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_UDP; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0; ++ } ++#endif /* (DPAA_VERSION >= 11) || ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) */ ++ ++ /* IP FRAG */ ++ if ((p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_IPv4) && ++ (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt == IPV4_FRAG_1)) ++ { ++ /* If IPv4+Frag, we need to set 2 units - SHIM 2 and IPv4. We first set SHIM2, and than check if ++ * IPv4 exists. If so we don't need to set an extra unit ++ * We consider as "having IPv4" any IPv4 without interchangable headers ++ * but including any options. */ ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_IPv4; ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].opt = IPV4_FRAG_1; ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_USER_DEFINED_SHIM2; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_USER_DEFINED_SHIM2; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0; ++ ++ /* check if IPv4 header exists by itself */ ++ if (FmPcdNetEnvGetUnitId(p_FmPcd, netEnvCurrId, HEADER_TYPE_IPv4, FALSE, 0) == FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) ++ { ++ p_FmPcd->netEnvs[netEnvCurrId].units[p_NetEnvParams->numOfDistinctionUnits].hdrs[0].hdr = HEADER_TYPE_IPv4; ++ p_FmPcd->netEnvs[netEnvCurrId].units[p_NetEnvParams->numOfDistinctionUnits++].hdrs[0].opt = 0; ++ } ++ } ++ if ((p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_IPv6) && ++ (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt == IPV6_FRAG_1)) ++ { ++ /* If IPv6+Frag, we need to set 2 units - SHIM 2 and IPv6. We first set SHIM2, and than check if ++ * IPv4 exists. If so we don't need to set an extra unit ++ * We consider as "having IPv6" any IPv6 without interchangable headers ++ * but including any options. */ ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_IPv6; ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].opt = IPV6_FRAG_1; ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_USER_DEFINED_SHIM2; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_USER_DEFINED_SHIM2; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0; ++ ++ /* check if IPv6 header exists by itself */ ++ if (FmPcdNetEnvGetUnitId(p_FmPcd, netEnvCurrId, HEADER_TYPE_IPv6, FALSE, 0) == FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) ++ { ++ p_FmPcd->netEnvs[netEnvCurrId].units[p_NetEnvParams->numOfDistinctionUnits].hdrs[0].hdr = HEADER_TYPE_IPv6; ++ p_FmPcd->netEnvs[netEnvCurrId].units[p_NetEnvParams->numOfDistinctionUnits++].hdrs[0].opt = 0; ++ } ++ } ++#if (DPAA_VERSION >= 11) ++ /* CAPWAP FRAG */ ++ if ((p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_CAPWAP) && ++ (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt == CAPWAP_FRAG_1)) ++ { ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_CAPWAP; ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].opt = CAPWAP_FRAG_1; ++ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_USER_DEFINED_SHIM2; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_USER_DEFINED_SHIM2; ++ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ } ++ ++ /* if private header (shim), check that no other headers specified */ ++ for (i = 0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) ++ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++) ++ { ++ if (IS_PRIVATE_HEADER(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr)) ++ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[1].hdr != HEADER_TYPE_NONE) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("SHIM header may not be interchanged with other headers")); ++ XX_Free(p_ModifiedNetEnvParams); ++ return NULL; ++ } ++ } ++ ++ for (i = 0; i < p_NetEnvParams->numOfDistinctionUnits; i++) ++ { ++ if (IS_PRIVATE_HEADER(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr)) ++ switch (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr) ++ { ++ case (HEADER_TYPE_USER_DEFINED_SHIM1): ++ if (shim1Selected) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("SHIM header cannot be selected with UDP_IPSEC_ESP")); ++ XX_Free(p_ModifiedNetEnvParams); ++ return NULL; ++ } ++ shim1Selected = TRUE; ++ p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i] = 0x00000001; ++ break; ++ case (HEADER_TYPE_USER_DEFINED_SHIM2): ++ p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i] = 0x00000002; ++ break; ++ default: ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Requested SHIM not supported")); ++ } ++ else ++ { ++ p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i] = (uint32_t)(0x80000000 >> bitId++); ++ ++ if (IS_SPECIAL_HEADER(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr)) ++ p_FmPcd->netEnvs[netEnvCurrId].macsecVector = p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i]; ++ } ++ } ++ ++ /* define a set of hardware parser LCV's according to the defined netenv */ ++ ++ /* set an array of LCV's for each header in the netEnv */ ++ for (i = 0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) ++ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++) ++ { ++ /* private headers have no LCV in the hard parser */ ++ if (!IS_PRIVATE_HEADER(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr)) ++ { ++ for (k = 0; (k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) ++ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE); k++) ++ { ++ hdrNum = GetPrsHdrNum(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr); ++ if ((hdrNum == ILLEGAL_HDR_NUM) || (hdrNum == NO_HDR_NUM)) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG); ++ XX_Free(p_ModifiedNetEnvParams); ++ return NULL; ++ } ++ p_FmPcd->netEnvs[netEnvCurrId].lcvs[hdrNum] |= p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i]; ++ } ++ } ++ } ++ XX_Free(p_ModifiedNetEnvParams); ++ ++ p_FmPcd->netEnvs[netEnvCurrId].h_Spinlock = XX_InitSpinlock(); ++ if (!p_FmPcd->netEnvs[netEnvCurrId].h_Spinlock) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Pcd NetEnv spinlock")); ++ return NULL; ++ } ++ return &p_FmPcd->netEnvs[netEnvCurrId]; ++} ++ ++t_Error FM_PCD_NetEnvCharacteristicsDelete(t_Handle h_NetEnv) ++{ ++ t_FmPcdNetEnv *p_NetEnv = (t_FmPcdNetEnv*)h_NetEnv; ++ t_FmPcd *p_FmPcd = p_NetEnv->h_FmPcd; ++ uint32_t intFlags; ++ uint8_t netEnvId = p_NetEnv->netEnvId; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ ++ /* check that no port is bound to this netEnv */ ++ if (p_FmPcd->netEnvs[netEnvId].owners) ++ { ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ++ ("Trying to delete a netEnv that has ports/schemes/trees/clsPlanGrps bound to")); ++ } ++ ++ intFlags = FmPcdLock(p_FmPcd); ++ ++ p_FmPcd->netEnvs[netEnvId].used = FALSE; ++ p_FmPcd->netEnvs[netEnvId].clsPlanGrpId = ILLEGAL_CLS_PLAN; ++ ++ memset(p_FmPcd->netEnvs[netEnvId].units, 0, sizeof(t_FmPcdIntDistinctionUnit)*FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ memset(p_FmPcd->netEnvs[netEnvId].unitsVectors, 0, sizeof(uint32_t)*FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ memset(p_FmPcd->netEnvs[netEnvId].lcvs, 0, sizeof(uint32_t)*FM_PCD_PRS_NUM_OF_HDRS); ++ ++ if (p_FmPcd->netEnvs[netEnvId].h_Spinlock) ++ XX_FreeSpinlock(p_FmPcd->netEnvs[netEnvId].h_Spinlock); ++ ++ FmPcdUnlock(p_FmPcd, intFlags); ++ return E_OK; ++} ++ ++void FM_PCD_HcTxConf(t_Handle h_FmPcd, t_DpaaFD *p_Fd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN(h_FmPcd, E_INVALID_STATE); ++ ++ FmHcTxConf(p_FmPcd->h_Hc, p_Fd); ++} ++ ++t_Error FM_PCD_SetAdvancedOffloadSupport(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmCtrlCodeRevisionInfo revInfo; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->enabled, E_INVALID_STATE); ++ ++ if ((err = FM_GetFmanCtrlCodeRevision(p_FmPcd->h_Fm, &revInfo)) != E_OK) ++ { ++ DBG(WARNING, ("FM in guest-mode without IPC, can't validate firmware revision.")); ++ revInfo.packageRev = IP_OFFLOAD_PACKAGE_NUMBER; ++ } ++ if (!IS_OFFLOAD_PACKAGE(revInfo.packageRev)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Fman ctrl code package")); ++ ++ if (!p_FmPcd->h_Hc) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("HC must be initialized in this mode")); ++ ++ p_FmPcd->advancedOffloadSupport = TRUE; ++ ++ return E_OK; ++} ++ ++uint32_t FM_PCD_GetCounter(t_Handle h_FmPcd, e_FmPcdCounters counter) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t outCounter = 0; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, 0); ++ ++ switch (counter) ++ { ++ case (e_FM_PCD_KG_COUNTERS_TOTAL): ++ if (!p_FmPcd->p_FmPcdKg) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("KeyGen is not activated")); ++ return 0; ++ } ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ !p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs && ++ !p_FmPcd->h_IpcSession) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without neither IPC nor mapped register!")); ++ return 0; ++ } ++ break; ++ ++ case (e_FM_PCD_PLCR_COUNTERS_YELLOW): ++ case (e_FM_PCD_PLCR_COUNTERS_RED): ++ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED): ++ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW): ++ case (e_FM_PCD_PLCR_COUNTERS_TOTAL): ++ case (e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH): ++ if (!p_FmPcd->p_FmPcdPlcr) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Policer is not activated")); ++ return 0; ++ } ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ !p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs && ++ !p_FmPcd->h_IpcSession) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in \"guest-mode\" without neither IPC nor mapped register!")); ++ return 0; ++ } ++ ++ /* check that counters are enabled */ ++ if (p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs && ++ !(GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr) & FM_PCD_PLCR_GCR_STEN)) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled")); ++ return 0; ++ } ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs || ++ ((p_FmPcd->guestId != NCSW_MASTER_ID) && p_FmPcd->h_IpcSession)); ++ break; ++ ++ case (e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH): ++ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED): ++ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED): ++ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED): ++ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED): ++ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR): ++ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR): ++ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR): ++ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR): ++ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES): ++ if (!p_FmPcd->p_FmPcdPrs) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Parser is not activated")); ++ return 0; ++ } ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ !p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs && ++ !p_FmPcd->h_IpcSession) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without neither IPC nor mapped register!")); ++ return 0; ++ } ++ break; ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported type of counter")); ++ return 0; ++ } ++ ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ p_FmPcd->h_IpcSession) ++ { ++ t_FmPcdIpcMsg msg; ++ t_FmPcdIpcReply reply; ++ uint32_t replyLength; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_PCD_GET_COUNTER; ++ memcpy(msg.msgBody, (uint8_t *)&counter, sizeof(uint32_t)); ++ replyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) +sizeof(uint32_t), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t) + sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ ++ memcpy((uint8_t*)&outCounter, reply.replyBody, sizeof(uint32_t)); ++ return outCounter; ++ } ++ ++ switch (counter) ++ { ++ /* Parser statistics */ ++ case (e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_pds); ++ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l2rrs); ++ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l3rrs); ++ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l4rrs); ++ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_srrs); ++ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l2rres); ++ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l3rres); ++ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l4rres); ++ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_srres); ++ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_spcs); ++ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_spscs); ++ case (e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_hxscs); ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mrcs); ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mrscs); ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mwcs); ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mwscs); ++ case (e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES): ++ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_fcscs); ++ case (e_FM_PCD_KG_COUNTERS_TOTAL): ++ return GET_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_tpc); ++ ++ /* Policer statistics */ ++ case (e_FM_PCD_PLCR_COUNTERS_YELLOW): ++ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ypcnt); ++ case (e_FM_PCD_PLCR_COUNTERS_RED): ++ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rpcnt); ++ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED): ++ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rrpcnt); ++ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW): ++ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rypcnt); ++ case (e_FM_PCD_PLCR_COUNTERS_TOTAL): ++ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_tpcnt); ++ case (e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH): ++ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_flmcnt); ++ } ++ return 0; ++} ++ ++t_Error FM_PCD_SetException(t_Handle h_FmPcd, e_FmPcdExceptions exception, bool enable) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t bitMask = 0, tmpReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_SetException - guest mode!")); ++ ++ GET_FM_PCD_EXCEPTION_FLAG(bitMask, exception); ++ ++ if (bitMask) ++ { ++ if (enable) ++ p_FmPcd->exceptions |= bitMask; ++ else ++ p_FmPcd->exceptions &= ~bitMask; ++ ++ switch (exception) ++ { ++ case (e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC): ++ case (e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW): ++ if (!p_FmPcd->p_FmPcdKg) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - keygen is not working")); ++ break; ++ case (e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC): ++ case (e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR): ++ case (e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE): ++ case (e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE): ++ if (!p_FmPcd->p_FmPcdPlcr) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - policer is not working")); ++ break; ++ case (e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC): ++ case (e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC): ++ if (!p_FmPcd->p_FmPcdPrs) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - parser is not working")); ++ break; ++ } ++ ++ switch (exception) ++ { ++ case (e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC): ++ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_eeer); ++ if (enable) ++ tmpReg |= FM_EX_KG_DOUBLE_ECC; ++ else ++ tmpReg &= ~FM_EX_KG_DOUBLE_ECC; ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_eeer, tmpReg); ++ break; ++ case (e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW): ++ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_eeer); ++ if (enable) ++ tmpReg |= FM_EX_KG_KEYSIZE_OVERFLOW; ++ else ++ tmpReg &= ~FM_EX_KG_KEYSIZE_OVERFLOW; ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_eeer, tmpReg); ++ break; ++ case (e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC): ++ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_perer); ++ if (enable) ++ tmpReg |= FM_PCD_PRS_DOUBLE_ECC; ++ else ++ tmpReg &= ~FM_PCD_PRS_DOUBLE_ECC; ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_perer, tmpReg); ++ break; ++ case (e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC): ++ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_pever); ++ if (enable) ++ tmpReg |= FM_PCD_PRS_SINGLE_ECC; ++ else ++ tmpReg &= ~FM_PCD_PRS_SINGLE_ECC; ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_pever, tmpReg); ++ break; ++ case (e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC): ++ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier); ++ if (enable) ++ tmpReg |= FM_PCD_PLCR_DOUBLE_ECC; ++ else ++ tmpReg &= ~FM_PCD_PLCR_DOUBLE_ECC; ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier, tmpReg); ++ break; ++ case (e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR): ++ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier); ++ if (enable) ++ tmpReg |= FM_PCD_PLCR_INIT_ENTRY_ERROR; ++ else ++ tmpReg &= ~FM_PCD_PLCR_INIT_ENTRY_ERROR; ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier, tmpReg); ++ break; ++ case (e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE): ++ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier); ++ if (enable) ++ tmpReg |= FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE; ++ else ++ tmpReg &= ~FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE; ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier, tmpReg); ++ break; ++ case (e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE): ++ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier); ++ if (enable) ++ tmpReg |= FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE; ++ else ++ tmpReg &= ~FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE; ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier, tmpReg); ++ break; ++ } ++ /* for ECC exceptions driver automatically enables ECC mechanism, if disabled. ++ Driver may disable them automatically, depending on driver's status */ ++ if (enable && ((exception == e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC) | ++ (exception == e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC) | ++ (exception == e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC) | ++ (exception == e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC))) ++ FmEnableRamsEcc(p_FmPcd->h_Fm); ++ if (!enable && ((exception == e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC) | ++ (exception == e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC) | ++ (exception == e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC) | ++ (exception == e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC))) ++ FmDisableRamsEcc(p_FmPcd->h_Fm); ++ } ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_ForceIntr (t_Handle h_FmPcd, e_FmPcdExceptions exception) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ForceIntr - guest mode!")); ++ ++ switch (exception) ++ { ++ case (e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC): ++ case (e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW): ++ if (!p_FmPcd->p_FmPcdKg) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - keygen is not working")); ++ break; ++ case (e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC): ++ case (e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR): ++ case (e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE): ++ case (e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE): ++ if (!p_FmPcd->p_FmPcdPlcr) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - policer is not working")); ++ break; ++ case (e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC): ++ case (e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC): ++ if (!p_FmPcd->p_FmPcdPrs) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt -parsrer is not working")); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid interrupt requested")); ++ } ++ switch (exception) ++ { ++ case e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC: ++ if (!(p_FmPcd->exceptions & FM_PCD_EX_PRS_DOUBLE_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ break; ++ case e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC: ++ if (!(p_FmPcd->exceptions & FM_PCD_EX_PRS_SINGLE_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ break; ++ case e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC: ++ if (!(p_FmPcd->exceptions & FM_EX_KG_DOUBLE_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_feer, FM_EX_KG_DOUBLE_ECC); ++ break; ++ case e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW: ++ if (!(p_FmPcd->exceptions & FM_EX_KG_KEYSIZE_OVERFLOW)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_feer, FM_EX_KG_KEYSIZE_OVERFLOW); ++ break; ++ case e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC: ++ if (!(p_FmPcd->exceptions & FM_PCD_EX_PLCR_DOUBLE_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr, FM_PCD_PLCR_DOUBLE_ECC); ++ break; ++ case e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR: ++ if (!(p_FmPcd->exceptions & FM_PCD_EX_PLCR_INIT_ENTRY_ERROR)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr, FM_PCD_PLCR_INIT_ENTRY_ERROR); ++ break; ++ case e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE: ++ if (!(p_FmPcd->exceptions & FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr, FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE); ++ break; ++ case e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE: ++ if (!(p_FmPcd->exceptions & FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr, FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE); ++ break; ++ } ++ ++ return E_OK; ++} ++ ++ ++t_Error FM_PCD_ModifyCounter(t_Handle h_FmPcd, e_FmPcdCounters counter, uint32_t value) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ModifyCounter - guest mode!")); ++ ++ switch (counter) ++ { ++ case (e_FM_PCD_KG_COUNTERS_TOTAL): ++ if (!p_FmPcd->p_FmPcdKg) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Invalid counters - KeyGen is not working")); ++ break; ++ case (e_FM_PCD_PLCR_COUNTERS_YELLOW): ++ case (e_FM_PCD_PLCR_COUNTERS_RED): ++ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED): ++ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW): ++ case (e_FM_PCD_PLCR_COUNTERS_TOTAL): ++ case (e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH): ++ if (!p_FmPcd->p_FmPcdPlcr) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Invalid counters - Policer is not working")); ++ if (!(GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr) & FM_PCD_PLCR_GCR_STEN)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled")); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH): ++ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED): ++ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED): ++ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED): ++ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED): ++ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR): ++ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR): ++ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR): ++ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR): ++ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES): ++ case (e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES): ++ if (!p_FmPcd->p_FmPcdPrs) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported type of counter")); ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported type of counter")); ++ } ++ switch (counter) ++ { ++ case (e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_pds, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l2rrs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l3rrs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l4rrs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_srrs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l2rres, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l3rres, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l4rres, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_srres, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_spcs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_spscs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_hxscs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mrcs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mrscs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mwcs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mwscs, value); ++ break; ++ case (e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_fcscs, value); ++ break; ++ case (e_FM_PCD_KG_COUNTERS_TOTAL): ++ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_tpc,value); ++ break; ++ ++ /*Policer counters*/ ++ case (e_FM_PCD_PLCR_COUNTERS_YELLOW): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ypcnt, value); ++ break; ++ case (e_FM_PCD_PLCR_COUNTERS_RED): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rpcnt, value); ++ break; ++ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rrpcnt, value); ++ break; ++ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rypcnt, value); ++ break; ++ case (e_FM_PCD_PLCR_COUNTERS_TOTAL): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_tpcnt, value); ++ break; ++ case (e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH): ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_flmcnt, value); ++ break; ++ } ++ ++ return E_OK; ++} ++ ++t_Handle FM_PCD_GetHcPort(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ return FmHcGetPort(p_FmPcd->h_Hc); ++} ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_pcd.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_pcd.h +new file mode 100644 +index 0000000..27ec9c5 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_pcd.h +@@ -0,0 +1,543 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_pcd.h ++ ++ @Description FM PCD ... ++*//***************************************************************************/ ++#ifndef __FM_PCD_H ++#define __FM_PCD_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++#include "fm_pcd_ext.h" ++#include "fm_common.h" ++#include "fsl_fman_prs.h" ++#include "fsl_fman_kg.h" ++ ++#define __ERR_MODULE__ MODULE_FM_PCD ++ ++ ++/****************************/ ++/* Defaults */ ++/****************************/ ++#define DEFAULT_plcrAutoRefresh FALSE ++#define DEFAULT_fmPcdKgErrorExceptions (FM_EX_KG_DOUBLE_ECC | FM_EX_KG_KEYSIZE_OVERFLOW) ++#define DEFAULT_fmPcdPlcrErrorExceptions (FM_PCD_EX_PLCR_DOUBLE_ECC | FM_PCD_EX_PLCR_INIT_ENTRY_ERROR) ++#define DEFAULT_fmPcdPlcrExceptions 0 ++#define DEFAULT_fmPcdPrsErrorExceptions (FM_PCD_EX_PRS_DOUBLE_ECC) ++ ++#define DEFAULT_fmPcdPrsExceptions FM_PCD_EX_PRS_SINGLE_ECC ++#define DEFAULT_numOfUsedProfilesPerWindow 16 ++#define DEFAULT_numOfSharedPlcrProfiles 4 ++ ++/****************************/ ++/* Network defines */ ++/****************************/ ++#define UDP_HEADER_SIZE 8 ++ ++#define ESP_SPI_OFFSET 0 ++#define ESP_SPI_SIZE 4 ++#define ESP_SEQ_NUM_OFFSET ESP_SPI_SIZE ++#define ESP_SEQ_NUM_SIZE 4 ++ ++/****************************/ ++/* General defines */ ++/****************************/ ++#define ILLEGAL_CLS_PLAN 0xff ++#define ILLEGAL_NETENV 0xff ++ ++#define FM_PCD_MAX_NUM_OF_ALIAS_HDRS 3 ++ ++/****************************/ ++/* Error defines */ ++/****************************/ ++ ++#define FM_PCD_EX_PLCR_DOUBLE_ECC 0x20000000 ++#define FM_PCD_EX_PLCR_INIT_ENTRY_ERROR 0x10000000 ++#define FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE 0x08000000 ++#define FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE 0x04000000 ++ ++#define GET_FM_PCD_EXCEPTION_FLAG(bitMask, exception) \ ++switch (exception){ \ ++ case e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC: \ ++ bitMask = FM_EX_KG_DOUBLE_ECC; break; \ ++ case e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC: \ ++ bitMask = FM_PCD_EX_PLCR_DOUBLE_ECC; break; \ ++ case e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW: \ ++ bitMask = FM_EX_KG_KEYSIZE_OVERFLOW; break; \ ++ case e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR: \ ++ bitMask = FM_PCD_EX_PLCR_INIT_ENTRY_ERROR; break; \ ++ case e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE: \ ++ bitMask = FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE; break; \ ++ case e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE: \ ++ bitMask = FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE; break; \ ++ case e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC: \ ++ bitMask = FM_PCD_EX_PRS_DOUBLE_ECC; break; \ ++ case e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC: \ ++ bitMask = FM_PCD_EX_PRS_SINGLE_ECC; break; \ ++ default: bitMask = 0;break;} ++ ++/***********************************************************************/ ++/* Policer defines */ ++/***********************************************************************/ ++#define FM_PCD_PLCR_GCR_STEN 0x40000000 ++#define FM_PCD_PLCR_DOUBLE_ECC 0x80000000 ++#define FM_PCD_PLCR_INIT_ENTRY_ERROR 0x40000000 ++#define FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE 0x80000000 ++#define FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE 0x40000000 ++ ++/***********************************************************************/ ++/* Memory map */ ++/***********************************************************************/ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++typedef struct { ++/* General Configuration and Status Registers */ ++ volatile uint32_t fmpl_gcr; /* 0x000 FMPL_GCR - FM Policer General Configuration */ ++ volatile uint32_t fmpl_gsr; /* 0x004 FMPL_GSR - FM Policer Global Status Register */ ++ volatile uint32_t fmpl_evr; /* 0x008 FMPL_EVR - FM Policer Event Register */ ++ volatile uint32_t fmpl_ier; /* 0x00C FMPL_IER - FM Policer Interrupt Enable Register */ ++ volatile uint32_t fmpl_ifr; /* 0x010 FMPL_IFR - FM Policer Interrupt Force Register */ ++ volatile uint32_t fmpl_eevr; /* 0x014 FMPL_EEVR - FM Policer Error Event Register */ ++ volatile uint32_t fmpl_eier; /* 0x018 FMPL_EIER - FM Policer Error Interrupt Enable Register */ ++ volatile uint32_t fmpl_eifr; /* 0x01C FMPL_EIFR - FM Policer Error Interrupt Force Register */ ++/* Global Statistic Counters */ ++ volatile uint32_t fmpl_rpcnt; /* 0x020 FMPL_RPC - FM Policer RED Packets Counter */ ++ volatile uint32_t fmpl_ypcnt; /* 0x024 FMPL_YPC - FM Policer YELLOW Packets Counter */ ++ volatile uint32_t fmpl_rrpcnt; /* 0x028 FMPL_RRPC - FM Policer Recolored RED Packet Counter */ ++ volatile uint32_t fmpl_rypcnt; /* 0x02C FMPL_RYPC - FM Policer Recolored YELLOW Packet Counter */ ++ volatile uint32_t fmpl_tpcnt; /* 0x030 FMPL_TPC - FM Policer Total Packet Counter */ ++ volatile uint32_t fmpl_flmcnt; /* 0x034 FMPL_FLMC - FM Policer Frame Length Mismatch Counter */ ++ volatile uint32_t fmpl_res0[21]; /* 0x038 - 0x08B Reserved */ ++/* Profile RAM Access Registers */ ++ volatile uint32_t fmpl_par; /* 0x08C FMPL_PAR - FM Policer Profile Action Register*/ ++ t_FmPcdPlcrProfileRegs profileRegs; ++/* Error Capture Registers */ ++ volatile uint32_t fmpl_serc; /* 0x100 FMPL_SERC - FM Policer Soft Error Capture */ ++ volatile uint32_t fmpl_upcr; /* 0x104 FMPL_UPCR - FM Policer Uninitialized Profile Capture Register */ ++ volatile uint32_t fmpl_res2; /* 0x108 Reserved */ ++/* Debug Registers */ ++ volatile uint32_t fmpl_res3[61]; /* 0x10C-0x200 Reserved Debug*/ ++/* Profile Selection Mapping Registers Per Port-ID (n=1-11, 16) */ ++ volatile uint32_t fmpl_dpmr; /* 0x200 FMPL_DPMR - FM Policer Default Mapping Register */ ++ volatile uint32_t fmpl_pmr[63]; /*+default 0x204-0x2FF FMPL_PMR1 - FMPL_PMR63, - FM Policer Profile Mapping Registers. ++ (for port-ID 1-11, only for supported Port-ID registers) */ ++} t_FmPcdPlcrRegs; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/***********************************************************************/ ++/* Driver's internal structures */ ++/***********************************************************************/ ++ ++typedef struct { ++ bool known; ++ uint8_t id; ++} t_FmPcdKgSchemesExtractsEntry; ++ ++typedef struct { ++ t_FmPcdKgSchemesExtractsEntry extractsArray[FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY]; ++} t_FmPcdKgSchemesExtracts; ++ ++typedef struct { ++ t_Handle h_Manip; ++ bool keepRes; ++ e_FmPcdEngine nextEngine; ++ uint8_t parseCode; ++} t_FmPcdInfoForManip; ++ ++/**************************************************************************//** ++ @Description A structure of parameters to communicate ++ between the port and PCD regarding the KG scheme. ++*//***************************************************************************/ ++typedef struct { ++ uint8_t netEnvId; /* in */ ++ uint8_t numOfDistinctionUnits; /* in */ ++ uint8_t unitIds[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; /* in */ ++ uint32_t vector; /* out */ ++} t_NetEnvParams; ++ ++typedef struct { ++ bool allocated; ++ uint8_t ownerId; /* guestId for KG in multi-partition only. ++ portId for PLCR in any environment */ ++} t_FmPcdAllocMng; ++ ++typedef struct { ++ volatile bool lock; ++ bool used; ++ uint8_t owners; ++ uint8_t netEnvId; ++ uint8_t guestId; ++ uint8_t baseEntry; ++ uint16_t sizeOfGrp; ++ protocolOpt_t optArray[FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)]; ++} t_FmPcdKgClsPlanGrp; ++ ++typedef struct { ++ t_Handle h_FmPcd; ++ uint8_t schemeId; ++ t_FmPcdLock *p_Lock; ++ bool valid; ++ uint8_t netEnvId; ++ uint8_t owners; ++ uint32_t matchVector; ++ uint32_t ccUnits; ++ bool nextRelativePlcrProfile; ++ uint16_t relativeProfileId; ++ uint16_t numOfProfiles; ++ t_FmPcdKgKeyOrder orderedArray; ++ e_FmPcdEngine nextEngine; ++ e_FmPcdDoneAction doneAction; ++ bool requiredActionFlag; ++ uint32_t requiredAction; ++ bool extractedOrs; ++ uint8_t bitOffsetInPlcrProfile; ++ bool directPlcr; ++#if (DPAA_VERSION >= 11) ++ bool vspe; ++#endif ++} t_FmPcdKgScheme; ++ ++typedef union { ++ struct fman_kg_scheme_regs schemeRegs; ++ struct fman_kg_pe_regs portRegs; ++ struct fman_kg_cp_regs clsPlanRegs; ++} u_FmPcdKgIndirectAccessRegs; ++ ++typedef struct { ++ struct fman_kg_regs *p_FmPcdKgRegs; ++ uint32_t schemeExceptionsBitMask; ++ uint8_t numOfSchemes; ++ t_Handle h_HwSpinlock; ++ uint8_t schemesIds[FM_PCD_KG_NUM_OF_SCHEMES]; ++ t_FmPcdKgScheme schemes[FM_PCD_KG_NUM_OF_SCHEMES]; ++ t_FmPcdKgClsPlanGrp clsPlanGrps[FM_MAX_NUM_OF_PORTS]; ++ uint8_t emptyClsPlanGrpId; ++ t_FmPcdAllocMng schemesMng[FM_PCD_KG_NUM_OF_SCHEMES]; /* only for MASTER ! */ ++ t_FmPcdAllocMng clsPlanBlocksMng[FM_PCD_MAX_NUM_OF_CLS_PLANS/CLS_PLAN_NUM_PER_GRP]; ++ u_FmPcdKgIndirectAccessRegs *p_IndirectAccessRegs; ++} t_FmPcdKg; ++ ++typedef struct { ++ uint16_t profilesBase; ++ uint16_t numOfProfiles; ++ t_Handle h_FmPort; ++} t_FmPcdPlcrMapParam; ++ ++typedef struct { ++ uint16_t absoluteProfileId; ++ t_Handle h_FmPcd; ++ bool valid; ++ t_FmPcdLock *p_Lock; ++ t_FmPcdAllocMng profilesMng; ++ bool requiredActionFlag; ++ uint32_t requiredAction; ++ e_FmPcdEngine nextEngineOnGreen; /**< Green next engine type */ ++ u_FmPcdPlcrNextEngineParams paramsOnGreen; /**< Green next engine params */ ++ ++ e_FmPcdEngine nextEngineOnYellow; /**< Yellow next engine type */ ++ u_FmPcdPlcrNextEngineParams paramsOnYellow; /**< Yellow next engine params */ ++ ++ e_FmPcdEngine nextEngineOnRed; /**< Red next engine type */ ++ u_FmPcdPlcrNextEngineParams paramsOnRed; /**< Red next engine params */ ++} t_FmPcdPlcrProfile; ++ ++typedef struct { ++ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs; ++ uint16_t partPlcrProfilesBase; ++ uint16_t partNumOfPlcrProfiles; ++ t_FmPcdPlcrProfile profiles[FM_PCD_PLCR_NUM_ENTRIES]; ++ uint16_t numOfSharedProfiles; ++ uint16_t sharedProfilesIds[FM_PCD_PLCR_NUM_ENTRIES]; ++ t_FmPcdPlcrMapParam portsMapping[FM_MAX_NUM_OF_PORTS]; ++ t_Handle h_HwSpinlock; ++ t_Handle h_SwSpinlock; ++} t_FmPcdPlcr; ++ ++typedef struct { ++ uint32_t *p_SwPrsCode; ++ uint32_t *p_CurrSwPrs; ++ uint8_t currLabel; ++ struct fman_prs_regs *p_FmPcdPrsRegs; ++ t_FmPcdPrsLabelParams labelsTable[FM_PCD_PRS_NUM_OF_LABELS]; ++ uint32_t fmPcdPrsPortIdStatistics; ++} t_FmPcdPrs; ++ ++typedef struct { ++ struct { ++ e_NetHeaderType hdr; ++ protocolOpt_t opt; /* only one option !! */ ++ } hdrs[FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS]; ++} t_FmPcdIntDistinctionUnit; ++ ++typedef struct { ++ e_NetHeaderType hdr; ++ protocolOpt_t opt; /* only one option !! */ ++ e_NetHeaderType aliasHdr; ++} t_FmPcdNetEnvAliases; ++ ++typedef struct { ++ uint8_t netEnvId; ++ t_Handle h_FmPcd; ++ t_Handle h_Spinlock; ++ bool used; ++ uint8_t owners; ++ uint8_t clsPlanGrpId; ++ t_FmPcdIntDistinctionUnit units[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; ++ uint32_t unitsVectors[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; ++ uint32_t lcvs[FM_PCD_PRS_NUM_OF_HDRS]; ++ uint32_t macsecVector; ++ t_FmPcdNetEnvAliases aliasHdrs[FM_PCD_MAX_NUM_OF_ALIAS_HDRS]; ++} t_FmPcdNetEnv; ++ ++typedef struct { ++ struct fman_prs_cfg dfltCfg; ++ bool plcrAutoRefresh; ++ uint16_t prsMaxParseCycleLimit; ++} t_FmPcdDriverParam; ++ ++typedef struct { ++ t_Handle h_Fm; ++ t_Handle h_FmMuram; ++ t_FmRevisionInfo fmRevInfo; ++ ++ uint64_t physicalMuramBase; ++ ++ t_Handle h_Spinlock; ++ t_List freeLocksLst; ++ t_List acquiredLocksLst; ++ ++ t_Handle h_IpcSession; /* relevant for guest only */ ++ bool enabled; ++ uint8_t guestId; /**< Guest Partition Id */ ++ uint8_t numOfEnabledGuestPartitionsPcds; ++ char fmPcdModuleName[MODULE_NAME_SIZE]; ++ char fmPcdIpcHandlerModuleName[MODULE_NAME_SIZE]; /* relevant for guest only - this is the master's name */ ++ t_FmPcdNetEnv netEnvs[FM_MAX_NUM_OF_PORTS]; ++ t_FmPcdKg *p_FmPcdKg; ++ t_FmPcdPlcr *p_FmPcdPlcr; ++ t_FmPcdPrs *p_FmPcdPrs; ++ ++ void *p_CcShadow; /**< CC MURAM shadow */ ++ uint32_t ccShadowSize; ++ uint32_t ccShadowAlign; ++ volatile bool shadowLock; ++ t_Handle h_ShadowSpinlock; ++ ++ t_Handle h_Hc; ++ ++ uint32_t exceptions; ++ t_FmPcdExceptionCallback *f_Exception; ++ t_FmPcdIdExceptionCallback *f_FmPcdIndexedException; ++ t_Handle h_App; ++ uintptr_t ipv6FrameIdAddr; ++ uintptr_t capwapFrameIdAddr; ++ bool advancedOffloadSupport; ++ ++ t_FmPcdDriverParam *p_FmPcdDriverParam; ++} t_FmPcd; ++ ++#if (DPAA_VERSION >= 11) ++typedef uint8_t t_FmPcdFrmReplicUpdateType; ++#define FRM_REPLIC_UPDATE_COUNTER 0x01 ++#define FRM_REPLIC_UPDATE_INFO 0x02 ++#endif /* (DPAA_VERSION >= 11) */ ++/***********************************************************************/ ++/* PCD internal routines */ ++/***********************************************************************/ ++ ++t_Error PcdGetVectorForOpt(t_FmPcd *p_FmPcd, uint8_t netEnvId, protocolOpt_t opt, uint32_t *p_Vector); ++t_Error PcdGetUnitsVector(t_FmPcd *p_FmPcd, t_NetEnvParams *p_Params); ++bool PcdNetEnvIsUnitWithoutOpts(t_FmPcd *p_FmPcd, uint8_t netEnvId, uint32_t unitVector); ++t_Error PcdGetClsPlanGrpParams(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_GrpParams); ++void FmPcdSetClsPlanGrpId(t_FmPcd *p_FmPcd, uint8_t netEnvId, uint8_t clsPlanGrpId); ++e_NetHeaderType FmPcdGetAliasHdr(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr); ++uint8_t FmPcdNetEnvGetUnitIdForSingleHdr(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr); ++uint8_t FmPcdNetEnvGetUnitId(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr, bool interchangeable, protocolOpt_t opt); ++ ++t_Error FmPcdManipBuildIpReassmScheme(t_FmPcd *p_FmPcd, t_Handle h_NetEnv, t_Handle h_CcTree, t_Handle h_Manip, bool isIpv4, uint8_t groupId); ++t_Error FmPcdManipDeleteIpReassmSchemes(t_Handle h_Manip); ++t_Error FmPcdManipBuildCapwapReassmScheme(t_FmPcd *p_FmPcd, t_Handle h_NetEnv, t_Handle h_CcTree, t_Handle h_Manip, uint8_t groupId); ++t_Error FmPcdManipDeleteCapwapReassmSchemes(t_Handle h_Manip); ++bool FmPcdManipIpReassmIsIpv6Hdr(t_Handle h_Manip); ++ ++t_Handle KgConfig( t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams); ++t_Error KgInit(t_FmPcd *p_FmPcd); ++t_Error KgFree(t_FmPcd *p_FmPcd); ++void KgSetClsPlan(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanSet *p_Set); ++bool KgIsSchemeAlwaysDirect(t_Handle h_FmPcd, uint8_t schemeId); ++void KgEnable(t_FmPcd *p_FmPcd); ++void KgDisable(t_FmPcd *p_FmPcd); ++t_Error KgAllocClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t *p_First); ++void KgFreeClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t base); ++ ++/* only for MULTI partittion */ ++t_Error FmPcdKgAllocSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds); ++t_Error FmPcdKgFreeSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds); ++/* only for SINGLE partittion */ ++t_Error KgBindPortToSchemes(t_Handle h_FmPcd , uint8_t hardwarePortId, uint32_t spReg); ++ ++t_FmPcdLock *FmPcdAcquireLock(t_Handle h_FmPcd); ++void FmPcdReleaseLock(t_Handle h_FmPcd, t_FmPcdLock *p_Lock); ++ ++t_Handle PlcrConfig(t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams); ++t_Error PlcrInit(t_FmPcd *p_FmPcd); ++t_Error PlcrFree(t_FmPcd *p_FmPcd); ++void PlcrEnable(t_FmPcd *p_FmPcd); ++void PlcrDisable(t_FmPcd *p_FmPcd); ++uint16_t PlcrAllocProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId); ++void PlcrFreeProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId); ++t_Error PlcrSetPortProfiles(t_FmPcd *p_FmPcd, ++ uint8_t hardwarePortId, ++ uint16_t numOfProfiles, ++ uint16_t base); ++t_Error PlcrClearPortProfiles(t_FmPcd *p_FmPcd, uint8_t hardwarePortId); ++ ++t_Handle PrsConfig(t_FmPcd *p_FmPcd,t_FmPcdParams *p_FmPcdParams); ++t_Error PrsInit(t_FmPcd *p_FmPcd); ++void PrsEnable(t_FmPcd *p_FmPcd); ++void PrsDisable(t_FmPcd *p_FmPcd); ++void PrsFree(t_FmPcd *p_FmPcd ); ++t_Error PrsIncludePortInStatistics(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, bool include); ++ ++t_Error FmPcdCcGetGrpParams(t_Handle treeId, uint8_t grpId, uint32_t *p_GrpBits, uint8_t *p_GrpBase); ++uint8_t FmPcdCcGetOffset(t_Handle h_CcNode); ++uint8_t FmPcdCcGetParseCode(t_Handle h_CcNode); ++uint16_t FmPcdCcGetNumOfKeys(t_Handle h_CcNode); ++t_Error ValidateNextEngineParams(t_Handle h_FmPcd, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams, e_FmPcdCcStatsMode supportedStatsMode); ++ ++void FmPcdManipUpdateOwner(t_Handle h_Manip, bool add); ++t_Error FmPcdManipCheckParamsForCcNextEngine(t_FmPcdCcNextEngineParams *p_InfoForManip, uint32_t *requiredAction); ++void FmPcdManipUpdateAdResultForCc(t_Handle h_Manip, ++ t_FmPcdCcNextEngineParams *p_CcNextEngineParams, ++ t_Handle p_Ad, ++ t_Handle *p_AdNewPtr); ++void FmPcdManipUpdateAdContLookupForCc(t_Handle h_Manip, t_Handle p_Ad, t_Handle *p_AdNew, uint32_t adTableOffset); ++void FmPcdManipUpdateOwner(t_Handle h_Manip, bool add); ++t_Error FmPcdManipCheckParamsWithCcNodeParams(t_Handle h_Manip, t_Handle h_FmPcdCcNode); ++#ifdef FM_CAPWAP_SUPPORT ++t_Handle FmPcdManipApplSpecificBuild(void); ++bool FmPcdManipIsCapwapApplSpecific(t_Handle h_Manip); ++#endif /* FM_CAPWAP_SUPPORT */ ++#if (DPAA_VERSION >= 11) ++void * FrmReplicGroupGetSourceTableDescriptor(t_Handle h_ReplicGroup); ++void FrmReplicGroupUpdateOwner(t_Handle h_ReplicGroup, bool add); ++void FrmReplicGroupUpdateAd(t_Handle h_ReplicGroup, void *p_Ad, t_Handle *h_AdNew); ++ ++void FmPcdCcGetAdTablesThatPointOnReplicGroup(t_Handle h_Node, ++ t_Handle h_ReplicGroup, ++ t_List *p_AdTables, ++ uint32_t *p_NumOfAdTables); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++void EnqueueNodeInfoToRelevantLst(t_List *p_List, t_CcNodeInformation *p_CcInfo, t_Handle h_Spinlock); ++void DequeueNodeInfoFromRelevantLst(t_List *p_List, t_Handle h_Info, t_Handle h_Spinlock); ++t_CcNodeInformation* FindNodeInfoInReleventLst(t_List *p_List, t_Handle h_Info, t_Handle h_Spinlock); ++t_List *FmPcdManipGetSpinlock(t_Handle h_Manip); ++t_List *FmPcdManipGetNodeLstPointedOnThisManip(t_Handle h_Manip); ++ ++typedef struct ++{ ++ t_Handle h_StatsAd; ++ t_Handle h_StatsCounters; ++#if (DPAA_VERSION >= 11) ++ t_Handle h_StatsFLRs; ++#endif /* (DPAA_VERSION >= 11) */ ++} t_FmPcdCcStatsParams; ++ ++void NextStepAd(t_Handle h_Ad, ++ t_FmPcdCcStatsParams *p_FmPcdCcStatsParams, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams, ++ t_FmPcd *p_FmPcd); ++void ReleaseLst(t_List *p_List); ++ ++static __inline__ t_Handle FmPcdGetMuramHandle(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ASSERT_COND(p_FmPcd); ++ return p_FmPcd->h_FmMuram; ++} ++ ++static __inline__ uint64_t FmPcdGetMuramPhysBase(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ASSERT_COND(p_FmPcd); ++ return p_FmPcd->physicalMuramBase; ++} ++ ++static __inline__ uint32_t FmPcdLockSpinlock(t_FmPcdLock *p_Lock) ++{ ++ ASSERT_COND(p_Lock); ++ return XX_LockIntrSpinlock(p_Lock->h_Spinlock); ++} ++ ++static __inline__ void FmPcdUnlockSpinlock(t_FmPcdLock *p_Lock, uint32_t flags) ++{ ++ ASSERT_COND(p_Lock); ++ XX_UnlockIntrSpinlock(p_Lock->h_Spinlock, flags); ++} ++ ++static __inline__ bool FmPcdLockTryLock(t_FmPcdLock *p_Lock) ++{ ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_Lock); ++ intFlags = XX_LockIntrSpinlock(p_Lock->h_Spinlock); ++ if (p_Lock->flag) ++ { ++ XX_UnlockIntrSpinlock(p_Lock->h_Spinlock, intFlags); ++ return FALSE; ++ } ++ p_Lock->flag = TRUE; ++ XX_UnlockIntrSpinlock(p_Lock->h_Spinlock, intFlags); ++ return TRUE; ++} ++ ++static __inline__ void FmPcdLockUnlock(t_FmPcdLock *p_Lock) ++{ ++ ASSERT_COND(p_Lock); ++ p_Lock->flag = FALSE; ++} ++ ++ ++#endif /* __FM_PCD_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_pcd_ipc.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_pcd_ipc.h +new file mode 100644 +index 0000000..325d3e3 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_pcd_ipc.h +@@ -0,0 +1,280 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File fm_pcd_ipc.h ++ ++ @Description FM PCD Inter-Partition prototypes, structures and definitions. ++*//***************************************************************************/ ++#ifndef __FM_PCD_IPC_H ++#define __FM_PCD_IPC_H ++ ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/**************************************************************************//** ++ @Description Structure for getting a sw parser address according to a label ++ Fields commented 'IN' are passed by the port module to be used ++ by the FM module. ++ Fields commented 'OUT' will be filled by FM before returning to port. ++*//***************************************************************************/ ++typedef _Packed struct t_FmPcdIpcSwPrsLable ++{ ++ uint32_t enumHdr; /**< IN. The existence of this header will invoke ++ the sw parser code. */ ++ uint8_t indexPerHdr; /**< IN. Normally 0, if more than one sw parser ++ attachments for the same header, use this ++ ++ index to distinguish between them. */ ++} _PackedType t_FmPcdIpcSwPrsLable; ++ ++/**************************************************************************//** ++ @Description Structure for port-PCD communication. ++ Fields commented 'IN' are passed by the port module to be used ++ by the FM module. ++ Fields commented 'OUT' will be filled by FM before returning to port. ++ Some fields are optional (depending on configuration) and ++ will be analized by the port and FM modules accordingly. ++*//***************************************************************************/ ++ ++typedef struct t_FmPcdIpcKgSchemesParams ++{ ++ uint8_t guestId; ++ uint8_t numOfSchemes; ++ uint8_t schemesIds[FM_PCD_KG_NUM_OF_SCHEMES]; ++} _PackedType t_FmPcdIpcKgSchemesParams; ++ ++typedef struct t_FmPcdIpcKgClsPlanParams ++{ ++ uint8_t guestId; ++ uint16_t numOfClsPlanEntries; ++ uint8_t clsPlanBase; ++} _PackedType t_FmPcdIpcKgClsPlanParams; ++ ++typedef _Packed struct t_FmPcdIpcPrsIncludePort ++{ ++ uint8_t hardwarePortId; ++ bool include; ++} _PackedType t_FmPcdIpcPrsIncludePort; ++ ++ ++#define FM_PCD_MAX_REPLY_SIZE 16 ++#define FM_PCD_MAX_MSG_SIZE 36 ++#define FM_PCD_MAX_REPLY_BODY_SIZE 36 ++ ++typedef _Packed struct { ++ uint32_t msgId; ++ uint8_t msgBody[FM_PCD_MAX_MSG_SIZE]; ++} _PackedType t_FmPcdIpcMsg; ++ ++typedef _Packed struct t_FmPcdIpcReply { ++ uint32_t error; ++ uint8_t replyBody[FM_PCD_MAX_REPLY_BODY_SIZE]; ++} _PackedType t_FmPcdIpcReply; ++ ++typedef _Packed struct t_FmIpcResourceAllocParams { ++ uint8_t guestId; ++ uint16_t base; ++ uint16_t num; ++}_PackedType t_FmIpcResourceAllocParams; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++ ++/**************************************************************************//** ++ @Function FM_PCD_ALLOC_KG_SCHEMES ++ ++ @Description Used by FM PCD front-end in order to allocate KG resources ++ ++ @Param[in/out] t_FmPcdIpcKgAllocParams Pointer ++*//***************************************************************************/ ++#define FM_PCD_ALLOC_KG_SCHEMES 3 ++ ++/**************************************************************************//** ++ @Function FM_PCD_FREE_KG_SCHEMES ++ ++ @Description Used by FM PCD front-end in order to Free KG resources ++ ++ @Param[in/out] t_FmPcdIpcKgSchemesParams Pointer ++*//***************************************************************************/ ++#define FM_PCD_FREE_KG_SCHEMES 4 ++ ++/**************************************************************************//** ++ @Function FM_PCD_ALLOC_PROFILES ++ ++ @Description Used by FM PCD front-end in order to allocate Policer profiles ++ ++ @Param[in/out] t_FmIpcResourceAllocParams Pointer ++*//***************************************************************************/ ++#define FM_PCD_ALLOC_PROFILES 5 ++ ++/**************************************************************************//** ++ @Function FM_PCD_FREE_PROFILES ++ ++ @Description Used by FM PCD front-end in order to Free Policer profiles ++ ++ @Param[in/out] t_FmIpcResourceAllocParams Pointer ++*//***************************************************************************/ ++#define FM_PCD_FREE_PROFILES 6 ++ ++/**************************************************************************//** ++ @Function FM_PCD_SET_PORT_PROFILES ++ ++ @Description Used by FM PCD front-end in order to allocate Policer profiles ++ for specific port ++ ++ @Param[in/out] t_FmIpcResourceAllocParams Pointer ++*//***************************************************************************/ ++#define FM_PCD_SET_PORT_PROFILES 7 ++ ++/**************************************************************************//** ++ @Function FM_PCD_CLEAR_PORT_PROFILES ++ ++ @Description Used by FM PCD front-end in order to allocate Policer profiles ++ for specific port ++ ++ @Param[in/out] t_FmIpcResourceAllocParams Pointer ++*//***************************************************************************/ ++#define FM_PCD_CLEAR_PORT_PROFILES 8 ++ ++/**************************************************************************//** ++ @Function FM_PCD_GET_PHYS_MURAM_BASE ++ ++ @Description Used by FM PCD front-end in order to get MURAM base address ++ ++ @Param[in/out] t_FmPcdIcPhysAddr Pointer ++*//***************************************************************************/ ++#define FM_PCD_GET_PHYS_MURAM_BASE 9 ++ ++/**************************************************************************//** ++ @Function FM_PCD_GET_SW_PRS_OFFSET ++ ++ @Description Used by FM front-end to get the SW parser offset of the start of ++ code relevant to a given label. ++ ++ @Param[in/out] t_FmPcdIpcSwPrsLable Pointer ++*//***************************************************************************/ ++#define FM_PCD_GET_SW_PRS_OFFSET 10 ++ ++/**************************************************************************//** ++ @Function FM_PCD_MASTER_IS_ENABLED ++ ++ @Description Used by FM front-end in order to verify ++ PCD enablement. ++ ++ @Param[in] bool Pointer ++*//***************************************************************************/ ++#define FM_PCD_MASTER_IS_ENABLED 15 ++ ++/**************************************************************************//** ++ @Function FM_PCD_GUEST_DISABLE ++ ++ @Description Used by FM front-end to inform back-end when ++ front-end PCD is disabled ++ ++ @Param[in] None ++*//***************************************************************************/ ++#define FM_PCD_GUEST_DISABLE 16 ++ ++/**************************************************************************//** ++ @Function FM_PCD_FREE_KG_CLSPLAN ++ ++ @Description Used by FM PCD front-end in order to Free KG classification plan entries ++ ++ @Param[in/out] t_FmPcdIpcKgClsPlanParams Pointer ++*//***************************************************************************/ ++#define FM_PCD_FREE_KG_CLSPLAN 22 ++ ++/**************************************************************************//** ++ @Function FM_PCD_ALLOC_KG_CLSPLAN ++ ++ @Description Used by FM PCD front-end in order to allocate KG classification plan entries ++ ++ @Param[in/out] t_FmPcdIpcKgClsPlanParams Pointer ++*//***************************************************************************/ ++#define FM_PCD_ALLOC_KG_CLSPLAN 23 ++ ++/**************************************************************************//** ++ @Function FM_PCD_MASTER_IS_ALIVE ++ ++ @Description Used by FM front-end to check that back-end exists ++ ++ @Param[in] None ++*//***************************************************************************/ ++#define FM_PCD_MASTER_IS_ALIVE 24 ++ ++/**************************************************************************//** ++ @Function FM_PCD_GET_COUNTER ++ ++ @Description Used by FM front-end to read PCD counters ++ ++ @Param[in/out] t_FmPcdIpcGetCounter Pointer ++*//***************************************************************************/ ++#define FM_PCD_GET_COUNTER 25 ++ ++/**************************************************************************//** ++ @Function FM_PCD_PRS_INC_PORT_STATS ++ ++ @Description Used by FM front-end to set/clear statistics for port ++ ++ @Param[in/out] t_FmPcdIpcPrsIncludePort Pointer ++*//***************************************************************************/ ++#define FM_PCD_PRS_INC_PORT_STATS 26 ++ ++#if (DPAA_VERSION >= 11) ++/* TODO - doc */ ++#define FM_PCD_ALLOC_SP 27 ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ ++/** @} */ /* end of FM_PCD_IPC_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++#endif /* __FM_PCD_IPC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_plcr.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_plcr.c +new file mode 100644 +index 0000000..cf17618 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_plcr.c +@@ -0,0 +1,1846 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_plcr.c ++ ++ @Description FM PCD POLICER... ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "debug_ext.h" ++#include "net_ext.h" ++#include "fm_ext.h" ++ ++#include "fm_common.h" ++#include "fm_pcd.h" ++#include "fm_hc.h" ++#include "fm_pcd_ipc.h" ++#include "fm_plcr.h" ++ ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++ ++static uint32_t PlcrProfileLock(t_Handle h_Profile) ++{ ++ ASSERT_COND(h_Profile); ++ return FmPcdLockSpinlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock); ++} ++ ++static void PlcrProfileUnlock(t_Handle h_Profile, uint32_t intFlags) ++{ ++ ASSERT_COND(h_Profile); ++ FmPcdUnlockSpinlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock, intFlags); ++} ++ ++static bool PlcrProfileFlagTryLock(t_Handle h_Profile) ++{ ++ ASSERT_COND(h_Profile); ++ return FmPcdLockTryLock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock); ++} ++ ++static void PlcrProfileFlagUnlock(t_Handle h_Profile) ++{ ++ ASSERT_COND(h_Profile); ++ FmPcdLockUnlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock); ++} ++ ++static uint32_t PlcrHwLock(t_Handle h_FmPcdPlcr) ++{ ++ ASSERT_COND(h_FmPcdPlcr); ++ return XX_LockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_HwSpinlock); ++} ++ ++static void PlcrHwUnlock(t_Handle h_FmPcdPlcr, uint32_t intFlags) ++{ ++ ASSERT_COND(h_FmPcdPlcr); ++ XX_UnlockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_HwSpinlock, intFlags); ++} ++ ++static uint32_t PlcrSwLock(t_Handle h_FmPcdPlcr) ++{ ++ ASSERT_COND(h_FmPcdPlcr); ++ return XX_LockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_SwSpinlock); ++} ++ ++static void PlcrSwUnlock(t_Handle h_FmPcdPlcr, uint32_t intFlags) ++{ ++ ASSERT_COND(h_FmPcdPlcr); ++ XX_UnlockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_SwSpinlock, intFlags); ++} ++ ++static bool IsProfileShared(t_Handle h_FmPcd, uint16_t absoluteProfileId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint16_t i; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, FALSE); ++ ++ for (i=0;ip_FmPcdPlcr->numOfSharedProfiles;i++) ++ if (p_FmPcd->p_FmPcdPlcr->sharedProfilesIds[i] == absoluteProfileId) ++ return TRUE; ++ return FALSE; ++} ++ ++static t_Error SetProfileNia(t_FmPcd *p_FmPcd, e_FmPcdEngine nextEngine, u_FmPcdPlcrNextEngineParams *p_NextEngineParams, uint32_t *nextAction) ++{ ++ uint32_t nia; ++ uint16_t absoluteProfileId; ++ uint8_t relativeSchemeId, physicalSchemeId; ++ ++ nia = FM_PCD_PLCR_NIA_VALID; ++ ++ switch (nextEngine) ++ { ++ case e_FM_PCD_DONE : ++ switch (p_NextEngineParams->action) ++ { ++ case e_FM_PCD_DROP_FRAME : ++ nia |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd); ++ break; ++ case e_FM_PCD_ENQ_FRAME: ++ nia |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ break; ++ case e_FM_PCD_KG: ++ physicalSchemeId = FmPcdKgGetSchemeId(p_NextEngineParams->h_DirectScheme); ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId); ++ if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG); ++ if (!FmPcdKgIsSchemeValidSw(p_NextEngineParams->h_DirectScheme)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid direct scheme.")); ++ if (!KgIsSchemeAlwaysDirect(p_FmPcd, relativeSchemeId)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Policer Profile may point only to a scheme that is always direct.")); ++ nia |= NIA_ENG_KG | NIA_KG_DIRECT | physicalSchemeId; ++ break; ++ case e_FM_PCD_PLCR: ++ absoluteProfileId = ((t_FmPcdPlcrProfile *)p_NextEngineParams->h_Profile)->absoluteProfileId; ++ if (!IsProfileShared(p_FmPcd, absoluteProfileId)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next profile must be a shared profile")); ++ if (!FmPcdPlcrIsProfileValid(p_FmPcd, absoluteProfileId)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid profile ")); ++ nia |= NIA_ENG_PLCR | NIA_PLCR_ABSOLUTE | absoluteProfileId; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ *nextAction = nia; ++ ++ return E_OK; ++} ++ ++static uint32_t CalcFPP(uint32_t fpp) ++{ ++ if (fpp > 15) ++ return 15 - (0x1f - fpp); ++ else ++ return 16 + fpp; ++} ++ ++static void GetInfoRateReg(e_FmPcdPlcrRateMode rateMode, ++ uint32_t rate, ++ uint64_t tsuInTenthNano, ++ uint32_t fppShift, ++ uint64_t *p_Integer, ++ uint64_t *p_Fraction) ++{ ++ uint64_t tmp, div; ++ ++ if (rateMode == e_FM_PCD_PLCR_BYTE_MODE) ++ { ++ /* now we calculate the initial integer for the bigger rate */ ++ /* from Kbps to Bytes/TSU */ ++ tmp = (uint64_t)rate; ++ tmp *= 1000; /* kb --> b */ ++ tmp *= tsuInTenthNano; /* bps --> bpTsu(in 10nano) */ ++ ++ div = 1000000000; /* nano */ ++ div *= 10; /* 10 nano */ ++ div *= 8; /* bit to byte */ ++ } ++ else ++ { ++ /* now we calculate the initial integer for the bigger rate */ ++ /* from Kbps to Bytes/TSU */ ++ tmp = (uint64_t)rate; ++ tmp *= tsuInTenthNano; /* bps --> bpTsu(in 10nano) */ ++ ++ div = 1000000000; /* nano */ ++ div *= 10; /* 10 nano */ ++ } ++ *p_Integer = (tmp<committedInfoRate > p_NonPassthroughAlgParam->peakOrExcessInfoRate) ++ GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->committedInfoRate, tsuInTenthNanos, 0, &integer, &fraction); ++ else ++ GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->peakOrExcessInfoRate, tsuInTenthNanos, 0, &integer, &fraction); ++ ++ /* we shift integer, as in cir/pir it is represented by the MSB 16 bits, and ++ * the LSB bits are for the fraction */ ++ temp = (uint32_t)((integer<<16) & 0x00000000FFFFFFFF); ++ /* temp is effected by the rate. For low rates it may be as low as 0, and then we'll ++ * take max FP = 31. ++ * For high rates it will never exceed the 32 bit reg (after the 16 shift), as it is ++ * limited by the 10G physical port. ++ */ ++ if (temp != 0) ++ { ++ /* In this case, the largest rate integer is non 0, if it does not occupy all (high) 16 ++ * bits of the PIR_EIR we can use this fact and enlarge it to occupy all 16 bits. ++ * The logic is to have as many bits for integer in the higher rates, but if we have "0"s ++ * in the integer part of the cir/pir register, than these bits are wasted. So we want ++ * to use these bits for the fraction. in this way we will have for fraction - the number ++ * of "0" bits and the rest - for integer. ++ * In other words: For each bit we shift it in PIR_EIR, we move the FP in the TS ++ * one bit to the left - preserving the relationship and achieving more bits ++ * for integer in the TS. ++ */ ++ ++ /* count zeroes left of the higher used bit (in order to shift the value such that ++ * unused bits may be used for fraction). ++ */ ++ while ((temp & 0x80000000) == 0) ++ { ++ temp = temp << 1; ++ fppShift++; ++ } ++ if (fppShift > 15) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, ("timeStampPeriod to Information rate ratio is too small")); ++ return; ++ } ++ } ++ else ++ { ++ temp = (uint32_t)fraction; /* fraction will alyas be smaller than 2^16 */ ++ if (!temp) ++ /* integer and fraction are 0, we set FP to its max val */ ++ fppShift = 31; ++ else ++ { ++ /* integer was 0 but fraction is not. FP is 16 for the fraction, ++ * + all left zeroes of the fraction. */ ++ fppShift=16; ++ /* count zeroes left of the higher used bit (in order to shift the value such that ++ * unused bits may be used for fraction). ++ */ ++ while ((temp & 0x8000) == 0) ++ { ++ temp = temp << 1; ++ fppShift++; ++ } ++ } ++ } ++ ++ /* ++ * This means that the FM TS register will now be used so that 'fppShift' bits are for ++ * fraction and the rest for integer */ ++ /* now we re-calculate cir and pir_eir with the calculated FP */ ++ GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->committedInfoRate, tsuInTenthNanos, fppShift, &integer, &fraction); ++ *cir = (uint32_t)(integer << 16 | (fraction & 0xFFFF)); ++ GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->peakOrExcessInfoRate, tsuInTenthNanos, fppShift, &integer, &fraction); ++ *pir_eir = (uint32_t)(integer << 16 | (fraction & 0xFFFF)); ++ ++ *cbs = p_NonPassthroughAlgParam->committedBurstSize; ++ *pbs_ebs = p_NonPassthroughAlgParam->peakOrExcessBurstSize; ++ ++ /* convert FP as it should be written to reg. ++ * 0-15 --> 16-31 ++ * 16-31 --> 0-15 ++ */ ++ *fpp = CalcFPP(fppShift); ++} ++ ++static void WritePar(t_FmPcd *p_FmPcd, uint32_t par) ++{ ++ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ ++ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); ++ WRITE_UINT32(p_FmPcdPlcrRegs->fmpl_par, par); ++ ++ while (GET_UINT32(p_FmPcdPlcrRegs->fmpl_par) & FM_PCD_PLCR_PAR_GO) ; ++} ++ ++static t_Error BuildProfileRegs(t_FmPcd *p_FmPcd, ++ t_FmPcdPlcrProfileParams *p_ProfileParams, ++ t_FmPcdPlcrProfileRegs *p_PlcrRegs) ++{ ++ t_Error err = E_OK; ++ uint32_t pemode, gnia, ynia, rnia, bitFor1Micro; ++ ++ ASSERT_COND(p_FmPcd); ++ ++ bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm); ++ if (bitFor1Micro == 0) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Timestamp scale")); ++ ++/* Set G, Y, R Nia */ ++ err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnGreen, &(p_ProfileParams->paramsOnGreen), &gnia); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnYellow, &(p_ProfileParams->paramsOnYellow), &ynia); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnRed, &(p_ProfileParams->paramsOnRed), &rnia); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++/* Mode fmpl_pemode */ ++ pemode = FM_PCD_PLCR_PEMODE_PI; ++ ++ switch (p_ProfileParams->algSelection) ++ { ++ case e_FM_PCD_PLCR_PASS_THROUGH: ++ p_PlcrRegs->fmpl_pecir = 0; ++ p_PlcrRegs->fmpl_pecbs = 0; ++ p_PlcrRegs->fmpl_pepepir_eir = 0; ++ p_PlcrRegs->fmpl_pepbs_ebs = 0; ++ p_PlcrRegs->fmpl_pelts = 0; ++ p_PlcrRegs->fmpl_pects = 0; ++ p_PlcrRegs->fmpl_pepts_ets = 0; ++ pemode &= ~FM_PCD_PLCR_PEMODE_ALG_MASK; ++ switch (p_ProfileParams->colorMode) ++ { ++ case e_FM_PCD_PLCR_COLOR_BLIND: ++ pemode |= FM_PCD_PLCR_PEMODE_CBLND; ++ switch (p_ProfileParams->color.dfltColor) ++ { ++ case e_FM_PCD_PLCR_GREEN: ++ pemode &= ~FM_PCD_PLCR_PEMODE_DEFC_MASK; ++ break; ++ case e_FM_PCD_PLCR_YELLOW: ++ pemode |= FM_PCD_PLCR_PEMODE_DEFC_Y; ++ break; ++ case e_FM_PCD_PLCR_RED: ++ pemode |= FM_PCD_PLCR_PEMODE_DEFC_R; ++ break; ++ case e_FM_PCD_PLCR_OVERRIDE: ++ pemode |= FM_PCD_PLCR_PEMODE_DEFC_OVERRIDE; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ break; ++ case e_FM_PCD_PLCR_COLOR_AWARE: ++ pemode &= ~FM_PCD_PLCR_PEMODE_CBLND; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ break; ++ ++ case e_FM_PCD_PLCR_RFC_2698: ++ /* Select algorithm MODE[ALG] = "01" */ ++ pemode |= FM_PCD_PLCR_PEMODE_ALG_RFC2698; ++ if (p_ProfileParams->nonPassthroughAlgParams.committedInfoRate > p_ProfileParams->nonPassthroughAlgParams.peakOrExcessInfoRate) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("in RFC2698 Peak rate must be equal or larger than committedInfoRate.")); ++ goto cont_rfc; ++ case e_FM_PCD_PLCR_RFC_4115: ++ /* Select algorithm MODE[ALG] = "10" */ ++ pemode |= FM_PCD_PLCR_PEMODE_ALG_RFC4115; ++cont_rfc: ++ /* Select Color-Blind / Color-Aware operation (MODE[CBLND]) */ ++ switch (p_ProfileParams->colorMode) ++ { ++ case e_FM_PCD_PLCR_COLOR_BLIND: ++ pemode |= FM_PCD_PLCR_PEMODE_CBLND; ++ break; ++ case e_FM_PCD_PLCR_COLOR_AWARE: ++ pemode &= ~FM_PCD_PLCR_PEMODE_CBLND; ++ /*In color aware more select override color interpretation (MODE[OVCLR]) */ ++ switch (p_ProfileParams->color.override) ++ { ++ case e_FM_PCD_PLCR_GREEN: ++ pemode &= ~FM_PCD_PLCR_PEMODE_OVCLR_MASK; ++ break; ++ case e_FM_PCD_PLCR_YELLOW: ++ pemode |= FM_PCD_PLCR_PEMODE_OVCLR_Y; ++ break; ++ case e_FM_PCD_PLCR_RED: ++ pemode |= FM_PCD_PLCR_PEMODE_OVCLR_R; ++ break; ++ case e_FM_PCD_PLCR_OVERRIDE: ++ pemode |= FM_PCD_PLCR_PEMODE_OVCLR_G_NC; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ /* Select Measurement Unit Mode to BYTE or PACKET (MODE[PKT]) */ ++ switch (p_ProfileParams->nonPassthroughAlgParams.rateMode) ++ { ++ case e_FM_PCD_PLCR_BYTE_MODE : ++ pemode &= ~FM_PCD_PLCR_PEMODE_PKT; ++ switch (p_ProfileParams->nonPassthroughAlgParams.byteModeParams.frameLengthSelection) ++ { ++ case e_FM_PCD_PLCR_L2_FRM_LEN: ++ pemode |= FM_PCD_PLCR_PEMODE_FLS_L2; ++ break; ++ case e_FM_PCD_PLCR_L3_FRM_LEN: ++ pemode |= FM_PCD_PLCR_PEMODE_FLS_L3; ++ break; ++ case e_FM_PCD_PLCR_L4_FRM_LEN: ++ pemode |= FM_PCD_PLCR_PEMODE_FLS_L4; ++ break; ++ case e_FM_PCD_PLCR_FULL_FRM_LEN: ++ pemode |= FM_PCD_PLCR_PEMODE_FLS_FULL; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ switch (p_ProfileParams->nonPassthroughAlgParams.byteModeParams.rollBackFrameSelection) ++ { ++ case e_FM_PCD_PLCR_ROLLBACK_L2_FRM_LEN: ++ pemode &= ~FM_PCD_PLCR_PEMODE_RBFLS; ++ break; ++ case e_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN: ++ pemode |= FM_PCD_PLCR_PEMODE_RBFLS; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ break; ++ case e_FM_PCD_PLCR_PACKET_MODE : ++ pemode |= FM_PCD_PLCR_PEMODE_PKT; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ /* Select timeStamp floating point position (MODE[FPP]) to fit the actual traffic rates. For PACKET ++ mode with low traffic rates move the fixed point to the left to increase fraction accuracy. For BYTE ++ mode with high traffic rates move the fixed point to the right to increase integer accuracy. */ ++ ++ /* Configure Traffic Parameters*/ ++ { ++ uint32_t cir=0, cbs=0, pir_eir=0, pbs_ebs=0, fpp=0; ++ ++ CalcRates(bitFor1Micro, &p_ProfileParams->nonPassthroughAlgParams, &cir, &cbs, &pir_eir, &pbs_ebs, &fpp); ++ ++ /* Set Committed Information Rate (CIR) */ ++ p_PlcrRegs->fmpl_pecir = cir; ++ /* Set Committed Burst Size (CBS). */ ++ p_PlcrRegs->fmpl_pecbs = cbs; ++ /* Set Peak Information Rate (PIR_EIR used as PIR) */ ++ p_PlcrRegs->fmpl_pepepir_eir = pir_eir; ++ /* Set Peak Burst Size (PBS_EBS used as PBS) */ ++ p_PlcrRegs->fmpl_pepbs_ebs = pbs_ebs; ++ ++ /* Initialize the Metering Buckets to be full (write them with 0xFFFFFFFF. */ ++ /* Peak Rate Token Bucket Size (PTS_ETS used as PTS) */ ++ p_PlcrRegs->fmpl_pepts_ets = 0xFFFFFFFF; ++ /* Committed Rate Token Bucket Size (CTS) */ ++ p_PlcrRegs->fmpl_pects = 0xFFFFFFFF; ++ ++ /* Set the FPP based on calculation */ ++ pemode |= (fpp << FM_PCD_PLCR_PEMODE_FPP_SHIFT); ++ } ++ break; /* FM_PCD_PLCR_PEMODE_ALG_RFC2698 , FM_PCD_PLCR_PEMODE_ALG_RFC4115 */ ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ p_PlcrRegs->fmpl_pemode = pemode; ++ ++ p_PlcrRegs->fmpl_pegnia = gnia; ++ p_PlcrRegs->fmpl_peynia = ynia; ++ p_PlcrRegs->fmpl_pernia = rnia; ++ ++ /* Zero Counters */ ++ p_PlcrRegs->fmpl_pegpc = 0; ++ p_PlcrRegs->fmpl_peypc = 0; ++ p_PlcrRegs->fmpl_perpc = 0; ++ p_PlcrRegs->fmpl_perypc = 0; ++ p_PlcrRegs->fmpl_perrpc = 0; ++ ++ return E_OK; ++} ++ ++static t_Error AllocSharedProfiles(t_FmPcd *p_FmPcd, uint16_t numOfProfiles, uint16_t *profilesIds) ++{ ++ uint32_t profilesFound; ++ uint16_t i, k=0; ++ uint32_t intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ if (!numOfProfiles) ++ return E_OK; ++ ++ if (numOfProfiles>FM_PCD_PLCR_NUM_ENTRIES) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles is too big.")); ++ ++ intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr); ++ /* Find numOfProfiles free profiles (may be spread) */ ++ profilesFound = 0; ++ for (i=0;ip_FmPcdPlcr->profiles[i].profilesMng.allocated) ++ { ++ profilesFound++; ++ profilesIds[k] = i; ++ k++; ++ if (profilesFound == numOfProfiles) ++ break; ++ } ++ ++ if (profilesFound != numOfProfiles) ++ { ++ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE,NO_MSG); ++ } ++ ++ for (i = 0;ip_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated = TRUE; ++ p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.ownerId = 0; ++ } ++ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ ++ return E_OK; ++} ++ ++static void FreeSharedProfiles(t_FmPcd *p_FmPcd, uint16_t numOfProfiles, uint16_t *profilesIds) ++{ ++ uint16_t i; ++ ++ SANITY_CHECK_RETURN(p_FmPcd, E_INVALID_HANDLE); ++ ++ ASSERT_COND(numOfProfiles); ++ ++ for (i=0; i < numOfProfiles; i++) ++ { ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated); ++ p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated = FALSE; ++ p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.ownerId = p_FmPcd->guestId; ++ } ++} ++ ++static void UpdateRequiredActionFlag(t_Handle h_FmPcd, uint16_t absoluteProfileId, bool set) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ /* this routine is protected by calling routine */ ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); ++ ++ if (set) ++ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredActionFlag = TRUE; ++ else ++ { ++ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredAction = 0; ++ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredActionFlag = FALSE; ++ } ++} ++ ++/*********************************************/ ++/*............Policer Exception..............*/ ++/*********************************************/ ++static void EventsCB(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint32_t event, mask, force; ++ ++ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); ++ event = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_evr); ++ mask = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier); ++ ++ event &= mask; ++ ++ /* clear the forced events */ ++ force = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr); ++ if (force & event) ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr, force & ~event); ++ ++ ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_evr, event); ++ ++ if (event & FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE) ++ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE); ++ if (event & FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE) ++ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE); ++} ++ ++/* ..... */ ++ ++static void ErrorExceptionsCB(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint32_t event, force, captureReg, mask; ++ ++ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm)); ++ event = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eevr); ++ mask = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier); ++ ++ event &= mask; ++ ++ /* clear the forced events */ ++ force = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr); ++ if (force & event) ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr, force & ~event); ++ ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eevr, event); ++ ++ if (event & FM_PCD_PLCR_DOUBLE_ECC) ++ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC); ++ if (event & FM_PCD_PLCR_INIT_ENTRY_ERROR) ++ { ++ captureReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_upcr); ++ /*ASSERT_COND(captureReg & PLCR_ERR_UNINIT_CAP); ++ p_UnInitCapt->profileNum = (uint8_t)(captureReg & PLCR_ERR_UNINIT_NUM_MASK); ++ p_UnInitCapt->portId = (uint8_t)((captureReg & PLCR_ERR_UNINIT_PID_MASK) >>PLCR_ERR_UNINIT_PID_SHIFT) ; ++ p_UnInitCapt->absolute = (bool)(captureReg & PLCR_ERR_UNINIT_ABSOLUTE_MASK);*/ ++ p_FmPcd->f_FmPcdIndexedException(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR,(uint16_t)(captureReg & PLCR_ERR_UNINIT_NUM_MASK)); ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_upcr, PLCR_ERR_UNINIT_CAP); ++ } ++} ++ ++ ++/*****************************************************************************/ ++/* Inter-module API routines */ ++/*****************************************************************************/ ++ ++t_Handle PlcrConfig(t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams) ++{ ++ t_FmPcdPlcr *p_FmPcdPlcr; ++ uint16_t i=0; ++ ++ UNUSED(p_FmPcd); ++ UNUSED(p_FmPcdParams); ++ ++ p_FmPcdPlcr = (t_FmPcdPlcr *) XX_Malloc(sizeof(t_FmPcdPlcr)); ++ if (!p_FmPcdPlcr) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer structure allocation FAILED")); ++ return NULL; ++ } ++ memset(p_FmPcdPlcr, 0, sizeof(t_FmPcdPlcr)); ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ { ++ p_FmPcdPlcr->p_FmPcdPlcrRegs = (t_FmPcdPlcrRegs *)UINT_TO_PTR(FmGetPcdPlcrBaseAddr(p_FmPcdParams->h_Fm)); ++ p_FmPcd->p_FmPcdDriverParam->plcrAutoRefresh = DEFAULT_plcrAutoRefresh; ++ p_FmPcd->exceptions |= (DEFAULT_fmPcdPlcrExceptions | DEFAULT_fmPcdPlcrErrorExceptions); ++ } ++ ++ p_FmPcdPlcr->numOfSharedProfiles = DEFAULT_numOfSharedPlcrProfiles; ++ ++ p_FmPcdPlcr->partPlcrProfilesBase = p_FmPcdParams->partPlcrProfilesBase; ++ p_FmPcdPlcr->partNumOfPlcrProfiles = p_FmPcdParams->partNumOfPlcrProfiles; ++ /* for backward compatabilty. if no policer profile, will set automatically to the max */ ++ if ((p_FmPcd->guestId == NCSW_MASTER_ID) && ++ (p_FmPcdPlcr->partNumOfPlcrProfiles == 0)) ++ p_FmPcdPlcr->partNumOfPlcrProfiles = FM_PCD_PLCR_NUM_ENTRIES; ++ ++ for (i=0; iprofiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE; ++ ++ return p_FmPcdPlcr; ++} ++ ++t_Error PlcrInit(t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdDriverParam *p_Param = p_FmPcd->p_FmPcdDriverParam; ++ t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr; ++ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ t_Error err = E_OK; ++ uint32_t tmpReg32 = 0; ++ uint16_t base; ++ ++ if ((p_FmPcdPlcr->partPlcrProfilesBase + p_FmPcdPlcr->partNumOfPlcrProfiles) > FM_PCD_PLCR_NUM_ENTRIES) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partPlcrProfilesBase+partNumOfPlcrProfiles out of range!!!")); ++ ++ p_FmPcdPlcr->h_HwSpinlock = XX_InitSpinlock(); ++ if (!p_FmPcdPlcr->h_HwSpinlock) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer HW spinlock")); ++ ++ p_FmPcdPlcr->h_SwSpinlock = XX_InitSpinlock(); ++ if (!p_FmPcdPlcr->h_SwSpinlock) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer SW spinlock")); ++ ++ base = PlcrAllocProfilesForPartition(p_FmPcd, ++ p_FmPcdPlcr->partPlcrProfilesBase, ++ p_FmPcdPlcr->partNumOfPlcrProfiles, ++ p_FmPcd->guestId); ++ if (base == (uint16_t)ILLEGAL_BASE) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ ++ if (p_FmPcdPlcr->numOfSharedProfiles) ++ { ++ err = AllocSharedProfiles(p_FmPcd, ++ p_FmPcdPlcr->numOfSharedProfiles, ++ p_FmPcdPlcr->sharedProfilesIds); ++ if (err) ++ RETURN_ERROR(MAJOR, err,NO_MSG); ++ } ++ ++ if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ return E_OK; ++ ++ /**********************FMPL_GCR******************/ ++ tmpReg32 = 0; ++ tmpReg32 |= FM_PCD_PLCR_GCR_STEN; ++ if (p_Param->plcrAutoRefresh) ++ tmpReg32 |= FM_PCD_PLCR_GCR_DAR; ++ tmpReg32 |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd); ++ ++ WRITE_UINT32(p_Regs->fmpl_gcr, tmpReg32); ++ /**********************FMPL_GCR******************/ ++ ++ /**********************FMPL_EEVR******************/ ++ WRITE_UINT32(p_Regs->fmpl_eevr, (FM_PCD_PLCR_DOUBLE_ECC | FM_PCD_PLCR_INIT_ENTRY_ERROR)); ++ /**********************FMPL_EEVR******************/ ++ /**********************FMPL_EIER******************/ ++ tmpReg32 = 0; ++ if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_DOUBLE_ECC) ++ { ++ FmEnableRamsEcc(p_FmPcd->h_Fm); ++ tmpReg32 |= FM_PCD_PLCR_DOUBLE_ECC; ++ } ++ if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_INIT_ENTRY_ERROR) ++ tmpReg32 |= FM_PCD_PLCR_INIT_ENTRY_ERROR; ++ WRITE_UINT32(p_Regs->fmpl_eier, tmpReg32); ++ /**********************FMPL_EIER******************/ ++ ++ /**********************FMPL_EVR******************/ ++ WRITE_UINT32(p_Regs->fmpl_evr, (FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE | FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE)); ++ /**********************FMPL_EVR******************/ ++ /**********************FMPL_IER******************/ ++ tmpReg32 = 0; ++ if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE) ++ tmpReg32 |= FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE; ++ if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE) ++ tmpReg32 |= FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE; ++ WRITE_UINT32(p_Regs->fmpl_ier, tmpReg32); ++ /**********************FMPL_IER******************/ ++ ++ /* register even if no interrupts enabled, to allow future enablement */ ++ FmRegisterIntr(p_FmPcd->h_Fm, ++ e_FM_MOD_PLCR, ++ 0, ++ e_FM_INTR_TYPE_ERR, ++ ErrorExceptionsCB, ++ p_FmPcd); ++ FmRegisterIntr(p_FmPcd->h_Fm, ++ e_FM_MOD_PLCR, ++ 0, ++ e_FM_INTR_TYPE_NORMAL, ++ EventsCB, ++ p_FmPcd); ++ ++ /* driver initializes one DFLT profile at the last entry*/ ++ /**********************FMPL_DPMR******************/ ++ tmpReg32 = 0; ++ WRITE_UINT32(p_Regs->fmpl_dpmr, tmpReg32); ++ p_FmPcd->p_FmPcdPlcr->profiles[0].profilesMng.allocated = TRUE; ++ ++ return E_OK; ++} ++ ++t_Error PlcrFree(t_FmPcd *p_FmPcd) ++{ ++ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PLCR, 0, e_FM_INTR_TYPE_ERR); ++ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PLCR, 0, e_FM_INTR_TYPE_NORMAL); ++ ++ if (p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles) ++ FreeSharedProfiles(p_FmPcd, ++ p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles, ++ p_FmPcd->p_FmPcdPlcr->sharedProfilesIds); ++ ++ if (p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles) ++ PlcrFreeProfilesForPartition(p_FmPcd, ++ p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase, ++ p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles, ++ p_FmPcd->guestId); ++ ++ if (p_FmPcd->p_FmPcdPlcr->h_SwSpinlock) ++ XX_FreeSpinlock(p_FmPcd->p_FmPcdPlcr->h_SwSpinlock); ++ ++ if (p_FmPcd->p_FmPcdPlcr->h_HwSpinlock) ++ XX_FreeSpinlock(p_FmPcd->p_FmPcdPlcr->h_HwSpinlock); ++ ++ return E_OK; ++} ++ ++void PlcrEnable(t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ ++ WRITE_UINT32(p_Regs->fmpl_gcr, GET_UINT32(p_Regs->fmpl_gcr) | FM_PCD_PLCR_GCR_EN); ++} ++ ++void PlcrDisable(t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ ++ WRITE_UINT32(p_Regs->fmpl_gcr, GET_UINT32(p_Regs->fmpl_gcr) & ~FM_PCD_PLCR_GCR_EN); ++} ++ ++uint16_t PlcrAllocProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId) ++{ ++ uint32_t intFlags; ++ uint16_t profilesFound = 0; ++ int i = 0; ++ ++ ASSERT_COND(p_FmPcd); ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr); ++ ++ if (!numOfProfiles) ++ return 0; ++ ++ if ((numOfProfiles > FM_PCD_PLCR_NUM_ENTRIES) || ++ (base + numOfProfiles > FM_PCD_PLCR_NUM_ENTRIES)) ++ return (uint16_t)ILLEGAL_BASE; ++ ++ if (p_FmPcd->h_IpcSession) ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ t_FmPcdIpcMsg msg; ++ t_FmPcdIpcReply reply; ++ t_Error err; ++ uint32_t replyLength; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); ++ ipcAllocParams.guestId = p_FmPcd->guestId; ++ ipcAllocParams.num = p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles; ++ ipcAllocParams.base = p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase; ++ msg.msgId = FM_PCD_ALLOC_PROFILES; ++ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); ++ replyLength = sizeof(uint32_t) + sizeof(uint16_t); ++ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if ((err != E_OK) || ++ (replyLength != (sizeof(uint32_t) + sizeof(uint16_t)))) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return (uint16_t)ILLEGAL_BASE; ++ } ++ else ++ memcpy((uint8_t*)&p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase, reply.replyBody, sizeof(uint16_t)); ++ if (p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase == (uint16_t)ILLEGAL_BASE) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return (uint16_t)ILLEGAL_BASE; ++ } ++ } ++ else if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ { ++ DBG(WARNING, ("FM Guest mode, without IPC - can't validate Policer-profiles range!")); ++ return (uint16_t)ILLEGAL_BASE; ++ } ++ ++ intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock); ++ for (i=base; i<(base+numOfProfiles); i++) ++ if (p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == (uint8_t)ILLEGAL_BASE) ++ profilesFound++; ++ else ++ break; ++ ++ if (profilesFound == numOfProfiles) ++ for (i=base; i<(base+numOfProfiles); i++) ++ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = guestId; ++ else ++ { ++ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags); ++ return (uint16_t)ILLEGAL_BASE; ++ } ++ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags); ++ ++ return base; ++} ++ ++void PlcrFreeProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId) ++{ ++ int i = 0; ++ ++ ASSERT_COND(p_FmPcd); ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr); ++ ++ if (p_FmPcd->h_IpcSession) ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ t_FmPcdIpcMsg msg; ++ t_Error err; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); ++ ipcAllocParams.guestId = p_FmPcd->guestId; ++ ipcAllocParams.num = p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles; ++ ipcAllocParams.base = p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase; ++ msg.msgId = FM_PCD_FREE_PROFILES; ++ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); ++ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return; ++ } ++ else if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ { ++ DBG(WARNING, ("FM Guest mode, without IPC - can't validate Policer-profiles range!")); ++ return; ++ } ++ ++ for (i=base; i<(base+numOfProfiles); i++) ++ { ++ if (p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == guestId) ++ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE; ++ else ++ DBG(WARNING, ("Request for freeing storage profile window which wasn't allocated to this partition")); ++ } ++} ++ ++t_Error PlcrSetPortProfiles(t_FmPcd *p_FmPcd, ++ uint8_t hardwarePortId, ++ uint16_t numOfProfiles, ++ uint16_t base) ++{ ++ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ uint32_t log2Num, tmpReg32; ++ ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ !p_Regs && ++ p_FmPcd->h_IpcSession) ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ t_FmPcdIpcMsg msg; ++ t_Error err; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); ++ ipcAllocParams.guestId = hardwarePortId; ++ ipcAllocParams.num = numOfProfiles; ++ ipcAllocParams.base = base; ++ msg.msgId = FM_PCD_SET_PORT_PROFILES; ++ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); ++ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ return E_OK; ++ } ++ else if (!p_Regs) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ ++ if (GET_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1]) & FM_PCD_PLCR_PMR_V) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("The requesting port has already an allocated profiles window.")); ++ ++ /**********************FMPL_PMRx******************/ ++ LOG2((uint64_t)numOfProfiles, log2Num); ++ tmpReg32 = base; ++ tmpReg32 |= log2Num << 16; ++ tmpReg32 |= FM_PCD_PLCR_PMR_V; ++ WRITE_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1], tmpReg32); ++ ++ return E_OK; ++} ++ ++t_Error PlcrClearPortProfiles(t_FmPcd *p_FmPcd, uint8_t hardwarePortId) ++{ ++ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ !p_Regs && ++ p_FmPcd->h_IpcSession) ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ t_FmPcdIpcMsg msg; ++ t_Error err; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); ++ ipcAllocParams.guestId = hardwarePortId; ++ msg.msgId = FM_PCD_CLEAR_PORT_PROFILES; ++ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); ++ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ return E_OK; ++ } ++ else if (!p_Regs) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ WRITE_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1], 0); ++ ++ return E_OK; ++} ++ ++t_Error FmPcdPlcrAllocProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId, uint16_t numOfProfiles) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_Error err = E_OK; ++ uint32_t profilesFound; ++ uint32_t intFlags; ++ uint16_t i, first, swPortIndex = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ if (!numOfProfiles) ++ return E_OK; ++ ++ ASSERT_COND(hardwarePortId); ++ ++ if (numOfProfiles>FM_PCD_PLCR_NUM_ENTRIES) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles is too big.")); ++ ++ if (!POWER_OF_2(numOfProfiles)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numProfiles must be a power of 2.")); ++ ++ first = 0; ++ profilesFound = 0; ++ intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr); ++ ++ for (i=0; ip_FmPcdPlcr->profiles[i].profilesMng.allocated) ++ { ++ profilesFound++; ++ i++; ++ if (profilesFound == numOfProfiles) ++ break; ++ } ++ else ++ { ++ profilesFound = 0; ++ /* advance i to the next aligned address */ ++ i = first = (uint16_t)(first + numOfProfiles); ++ } ++ } ++ ++ if (profilesFound == numOfProfiles) ++ { ++ for (i=first; ip_FmPcdPlcr->profiles[i].profilesMng.allocated = TRUE; ++ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = hardwarePortId; ++ } ++ } ++ else ++ { ++ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ RETURN_ERROR(MINOR, E_FULL, ("No profiles.")); ++ } ++ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ ++ err = PlcrSetPortProfiles(p_FmPcd, hardwarePortId, numOfProfiles, first); ++ if (err) ++ { ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ ++ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles = numOfProfiles; ++ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase = first; ++ ++ return E_OK; ++} ++ ++t_Error FmPcdPlcrFreeProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_Error err = E_OK; ++ uint32_t intFlags; ++ uint16_t i, swPortIndex = 0; ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); ++ ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ ++ err = PlcrClearPortProfiles(p_FmPcd, hardwarePortId); ++ if (err) ++ RETURN_ERROR(MAJOR, err,NO_MSG); ++ ++ intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr); ++ for (i=p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase; ++ i<(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase + ++ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles); ++ i++) ++ { ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == hardwarePortId); ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated); ++ ++ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated = FALSE; ++ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = p_FmPcd->guestId; ++ } ++ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ ++ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles = 0; ++ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase = 0; ++ ++ return E_OK; ++} ++ ++t_Error FmPcdPlcrCcGetSetParams(t_Handle h_FmPcd, uint16_t profileIndx ,uint32_t requiredAction) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr; ++ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs = p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ uint32_t tmpReg32, intFlags; ++ t_Error err; ++ ++ /* Calling function locked all PCD modules, so no need to lock here */ ++ ++ if (profileIndx >= FM_PCD_PLCR_NUM_ENTRIES) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Policer profile out of range")); ++ ++ if (!FmPcdPlcrIsProfileValid(p_FmPcd, profileIndx)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Policer profile is not valid")); ++ ++ /*intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx]);*/ ++ ++ if (p_FmPcd->h_Hc) ++ { ++ err = FmHcPcdPlcrCcGetSetParams(p_FmPcd->h_Hc, profileIndx, requiredAction); ++ ++ UpdateRequiredActionFlag(p_FmPcd, profileIndx, TRUE); ++ FmPcdPlcrUpdateRequiredAction(p_FmPcd, profileIndx, requiredAction); ++ ++ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ ++ return err; ++ } ++ ++ /* lock the HW because once we read the registers we don't want them to be changed ++ * by another access. (We can copy to a tmp location and release the lock!) */ ++ ++ intFlags = PlcrHwLock(p_FmPcdPlcr); ++ WritePar(p_FmPcd, FmPcdPlcrBuildReadPlcrActionReg(profileIndx)); ++ ++ if (!p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].requiredActionFlag || ++ !(p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].requiredAction & requiredAction)) ++ { ++ if (requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) ++ { ++ if ((p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnGreen!= e_FM_PCD_DONE) || ++ (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnYellow!= e_FM_PCD_DONE) || ++ (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnRed!= e_FM_PCD_DONE)) ++ { ++ PlcrHwUnlock(p_FmPcdPlcr, intFlags); ++ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ ++ RETURN_ERROR (MAJOR, E_OK, ("In this case the next engine can be e_FM_PCD_DONE")); ++ } ++ ++ if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnGreen.action == e_FM_PCD_ENQ_FRAME) ++ { ++ tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia); ++ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))) ++ { ++ PlcrHwUnlock(p_FmPcdPlcr, intFlags); ++ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE")); ++ } ++ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia, tmpReg32); ++ tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx); ++ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEGNIA; ++ WritePar(p_FmPcd, tmpReg32); ++ } ++ ++ if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnYellow.action == e_FM_PCD_ENQ_FRAME) ++ { ++ tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia); ++ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))) ++ { ++ PlcrHwUnlock(p_FmPcdPlcr, intFlags); ++ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE")); ++ } ++ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia, tmpReg32); ++ tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx); ++ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEYNIA; ++ WritePar(p_FmPcd, tmpReg32); ++ PlcrHwUnlock(p_FmPcdPlcr, intFlags); ++ } ++ ++ if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnRed.action == e_FM_PCD_ENQ_FRAME) ++ { ++ tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia); ++ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))) ++ { ++ PlcrHwUnlock(p_FmPcdPlcr, intFlags); ++ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE")); ++ } ++ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA; ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia, tmpReg32); ++ tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx); ++ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PERNIA; ++ WritePar(p_FmPcd, tmpReg32); ++ ++ } ++ } ++ } ++ PlcrHwUnlock(p_FmPcdPlcr, intFlags); ++ ++ UpdateRequiredActionFlag(p_FmPcd, profileIndx, TRUE); ++ FmPcdPlcrUpdateRequiredAction(p_FmPcd, profileIndx, requiredAction); ++ ++ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/ ++ ++ return E_OK; ++} ++ ++uint32_t FmPcdPlcrGetRequiredActionFlag(t_Handle h_FmPcd, uint16_t absoluteProfileId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); ++ ++ return p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredActionFlag; ++} ++ ++uint32_t FmPcdPlcrGetRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); ++ ++ return p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredAction; ++} ++ ++bool FmPcdPlcrIsProfileValid(t_Handle h_FmPcd, uint16_t absoluteProfileId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr; ++ ++ ASSERT_COND(absoluteProfileId < FM_PCD_PLCR_NUM_ENTRIES); ++ ++ return p_FmPcdPlcr->profiles[absoluteProfileId].valid; ++} ++ ++void FmPcdPlcrValidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t intFlags; ++ ++ ASSERT_COND(!p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); ++ ++ intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId]); ++ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid = TRUE; ++ PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId], intFlags); ++} ++ ++void FmPcdPlcrInvalidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); ++ ++ intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId]); ++ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid = FALSE; ++ PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId], intFlags); ++} ++ ++uint16_t FmPcdPlcrProfileGetAbsoluteId(t_Handle h_Profile) ++{ ++ return ((t_FmPcdPlcrProfile*)h_Profile)->absoluteProfileId; ++} ++ ++t_Error FmPcdPlcrGetAbsoluteIdByProfileParams(t_Handle h_FmPcd, ++ e_FmPcdProfileTypeSelection profileType, ++ t_Handle h_FmPort, ++ uint16_t relativeProfile, ++ uint16_t *p_AbsoluteId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr; ++ uint8_t i; ++ ++ switch (profileType) ++ { ++ case e_FM_PCD_PLCR_PORT_PRIVATE: ++ /* get port PCD id from port handle */ ++ for (i=0;ip_FmPcdPlcr->portsMapping[i].h_FmPort == h_FmPort) ++ break; ++ if (i == FM_MAX_NUM_OF_PORTS) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE , ("Invalid port handle.")); ++ ++ if (!p_FmPcd->p_FmPcdPlcr->portsMapping[i].numOfProfiles) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Port has no allocated profiles")); ++ if (relativeProfile >= p_FmPcd->p_FmPcdPlcr->portsMapping[i].numOfProfiles) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Profile id is out of range")); ++ *p_AbsoluteId = (uint16_t)(p_FmPcd->p_FmPcdPlcr->portsMapping[i].profilesBase + relativeProfile); ++ break; ++ case e_FM_PCD_PLCR_SHARED: ++ if (relativeProfile >= p_FmPcdPlcr->numOfSharedProfiles) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Profile id is out of range")); ++ *p_AbsoluteId = (uint16_t)(p_FmPcdPlcr->sharedProfilesIds[relativeProfile]); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Invalid policer profile type")); ++ } ++ ++ return E_OK; ++} ++ ++uint16_t FmPcdPlcrGetPortProfilesBase(t_Handle h_FmPcd, uint8_t hardwarePortId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint16_t swPortIndex = 0; ++ ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ ++ return p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase; ++} ++ ++uint16_t FmPcdPlcrGetPortNumOfProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint16_t swPortIndex = 0; ++ ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ ++ return p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles; ++ ++} ++uint32_t FmPcdPlcrBuildWritePlcrActionReg(uint16_t absoluteProfileId) ++{ ++ return (uint32_t)(FM_PCD_PLCR_PAR_GO | ++ ((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT)); ++} ++ ++uint32_t FmPcdPlcrBuildWritePlcrActionRegs(uint16_t absoluteProfileId) ++{ ++ return (uint32_t)(FM_PCD_PLCR_PAR_GO | ++ ((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT) | ++ FM_PCD_PLCR_PAR_PWSEL_MASK); ++} ++ ++bool FmPcdPlcrHwProfileIsValid(uint32_t profileModeReg) ++{ ++ ++ if (profileModeReg & FM_PCD_PLCR_PEMODE_PI) ++ return TRUE; ++ else ++ return FALSE; ++} ++ ++uint32_t FmPcdPlcrBuildReadPlcrActionReg(uint16_t absoluteProfileId) ++{ ++ return (uint32_t)(FM_PCD_PLCR_PAR_GO | ++ FM_PCD_PLCR_PAR_R | ++ ((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT) | ++ FM_PCD_PLCR_PAR_PWSEL_MASK); ++} ++ ++uint32_t FmPcdPlcrBuildCounterProfileReg(e_FmPcdPlcrProfileCounters counter) ++{ ++ switch (counter) ++ { ++ case (e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER): ++ return FM_PCD_PLCR_PAR_PWSEL_PEGPC; ++ case (e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER): ++ return FM_PCD_PLCR_PAR_PWSEL_PEYPC; ++ case (e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER) : ++ return FM_PCD_PLCR_PAR_PWSEL_PERPC; ++ case (e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER) : ++ return FM_PCD_PLCR_PAR_PWSEL_PERYPC; ++ case (e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER) : ++ return FM_PCD_PLCR_PAR_PWSEL_PERRPC; ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ return 0; ++ } ++} ++ ++uint32_t FmPcdPlcrBuildNiaProfileReg(bool green, bool yellow, bool red) ++{ ++ ++ uint32_t tmpReg32 = 0; ++ ++ if (green) ++ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEGNIA; ++ if (yellow) ++ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEYNIA; ++ if (red) ++ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PERNIA; ++ ++ return tmpReg32; ++} ++ ++void FmPcdPlcrUpdateRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId, uint32_t requiredAction) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ /* this routine is protected by calling routine */ ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid); ++ ++ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredAction |= requiredAction; ++} ++ ++/*********************** End of inter-module routines ************************/ ++ ++ ++/**************************************************/ ++/*............Policer API.........................*/ ++/**************************************************/ ++ ++t_Error FM_PCD_ConfigPlcrAutoRefreshMode(t_Handle h_FmPcd, bool enable) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE); ++ ++ if (!FmIsMaster(p_FmPcd->h_Fm)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ConfigPlcrAutoRefreshMode - guest mode!")); ++ ++ p_FmPcd->p_FmPcdDriverParam->plcrAutoRefresh = enable; ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_ConfigPlcrNumOfSharedProfiles(t_Handle h_FmPcd, uint16_t numOfSharedPlcrProfiles) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE); ++ ++ p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles = numOfSharedPlcrProfiles; ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_SetPlcrStatistics(t_Handle h_FmPcd, bool enable) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t tmpReg32; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE); ++ ++ if (!FmIsMaster(p_FmPcd->h_Fm)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_SetPlcrStatistics - guest mode!")); ++ ++ tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr); ++ if (enable) ++ tmpReg32 |= FM_PCD_PLCR_GCR_STEN; ++ else ++ tmpReg32 &= ~FM_PCD_PLCR_GCR_STEN; ++ ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr, tmpReg32); ++ return E_OK; ++} ++ ++t_Handle FM_PCD_PlcrProfileSet(t_Handle h_FmPcd, ++ t_FmPcdPlcrProfileParams *p_ProfileParams) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs; ++ t_FmPcdPlcrProfileRegs plcrProfileReg; ++ uint32_t intFlags; ++ uint16_t absoluteProfileId; ++ t_Error err = E_OK; ++ uint32_t tmpReg32; ++ t_FmPcdPlcrProfile *p_Profile; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL); ++ ++ if (p_ProfileParams->modify) ++ { ++ p_Profile = (t_FmPcdPlcrProfile *)p_ProfileParams->id.h_Profile; ++ p_FmPcd = p_Profile->h_FmPcd; ++ absoluteProfileId = p_Profile->absoluteProfileId; ++ if (absoluteProfileId >= FM_PCD_PLCR_NUM_ENTRIES) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big ")); ++ return NULL; ++ } ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE, NULL); ++ ++ /* Try lock profile using flag */ ++ if (!PlcrProfileFlagTryLock(p_Profile)) ++ { ++ DBG(TRACE, ("Profile Try Lock - BUSY")); ++ /* Signal to caller BUSY condition */ ++ p_ProfileParams->id.h_Profile = NULL; ++ return NULL; ++ } ++ } ++ else ++ { ++ p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE, NULL); ++ ++ /* SMP: needs to be protected only if another core now changes the windows */ ++ err = FmPcdPlcrGetAbsoluteIdByProfileParams(h_FmPcd, ++ p_ProfileParams->id.newParams.profileType, ++ p_ProfileParams->id.newParams.h_FmPort, ++ p_ProfileParams->id.newParams.relativeProfileId, ++ &absoluteProfileId); ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return NULL; ++ } ++ ++ if (absoluteProfileId >= FM_PCD_PLCR_NUM_ENTRIES) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big ")); ++ return NULL; ++ } ++ ++ if (FmPcdPlcrIsProfileValid(p_FmPcd, absoluteProfileId)) ++ { ++ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("Policer Profile is already used")); ++ return NULL; ++ } ++ ++ /* initialize profile struct */ ++ p_Profile = &p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId]; ++ ++ p_Profile->h_FmPcd = p_FmPcd; ++ p_Profile->absoluteProfileId = absoluteProfileId; ++ ++ p_Profile->p_Lock = FmPcdAcquireLock(p_FmPcd); ++ if (!p_Profile->p_Lock) ++ REPORT_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM Policer Profile lock obj!")); ++ } ++ ++ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, NULL); ++ ++ p_Profile->nextEngineOnGreen = p_ProfileParams->nextEngineOnGreen; ++ memcpy(&p_Profile->paramsOnGreen, &(p_ProfileParams->paramsOnGreen), sizeof(u_FmPcdPlcrNextEngineParams)); ++ ++ p_Profile->nextEngineOnYellow = p_ProfileParams->nextEngineOnYellow; ++ memcpy(&p_Profile->paramsOnYellow, &(p_ProfileParams->paramsOnYellow), sizeof(u_FmPcdPlcrNextEngineParams)); ++ ++ p_Profile->nextEngineOnRed = p_ProfileParams->nextEngineOnRed; ++ memcpy(&p_Profile->paramsOnRed, &(p_ProfileParams->paramsOnRed), sizeof(u_FmPcdPlcrNextEngineParams)); ++ ++ memset(&plcrProfileReg, 0, sizeof(t_FmPcdPlcrProfileRegs)); ++ ++ /* build the policer profile registers */ ++ err = BuildProfileRegs(h_FmPcd, p_ProfileParams, &plcrProfileReg); ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ if (p_ProfileParams->modify) ++ /* unlock */ ++ PlcrProfileFlagUnlock(p_Profile); ++ if (!p_ProfileParams->modify && ++ p_Profile->p_Lock) ++ /* release allocated Profile lock */ ++ FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock); ++ return NULL; ++ } ++ ++ if (p_FmPcd->h_Hc) ++ { ++ err = FmHcPcdPlcrSetProfile(p_FmPcd->h_Hc, (t_Handle)p_Profile, &plcrProfileReg); ++ if (p_ProfileParams->modify) ++ PlcrProfileFlagUnlock(p_Profile); ++ if (err) ++ { ++ /* release the allocated scheme lock */ ++ if (!p_ProfileParams->modify && ++ p_Profile->p_Lock) ++ FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock); ++ ++ return NULL; ++ } ++ if (!p_ProfileParams->modify) ++ FmPcdPlcrValidateProfileSw(p_FmPcd,absoluteProfileId); ++ return (t_Handle)p_Profile; ++ } ++ ++ p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ SANITY_CHECK_RETURN_VALUE(p_FmPcdPlcrRegs, E_INVALID_HANDLE, NULL); ++ ++ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pemode , plcrProfileReg.fmpl_pemode); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia , plcrProfileReg.fmpl_pegnia); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia , plcrProfileReg.fmpl_peynia); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia , plcrProfileReg.fmpl_pernia); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pecir , plcrProfileReg.fmpl_pecir); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pecbs , plcrProfileReg.fmpl_pecbs); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepepir_eir,plcrProfileReg.fmpl_pepepir_eir); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepbs_ebs,plcrProfileReg.fmpl_pepbs_ebs); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pelts , plcrProfileReg.fmpl_pelts); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pects , plcrProfileReg.fmpl_pects); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepts_ets,plcrProfileReg.fmpl_pepts_ets); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc , plcrProfileReg.fmpl_pegpc); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc , plcrProfileReg.fmpl_peypc); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc , plcrProfileReg.fmpl_perpc); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc , plcrProfileReg.fmpl_perypc); ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc , plcrProfileReg.fmpl_perrpc); ++ ++ tmpReg32 = FmPcdPlcrBuildWritePlcrActionRegs(absoluteProfileId); ++ WritePar(p_FmPcd, tmpReg32); ++ ++ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ ++ if (!p_ProfileParams->modify) ++ FmPcdPlcrValidateProfileSw(p_FmPcd,absoluteProfileId); ++ else ++ PlcrProfileFlagUnlock(p_Profile); ++ ++ return (t_Handle)p_Profile; ++} ++ ++t_Error FM_PCD_PlcrProfileDelete(t_Handle h_Profile) ++{ ++ t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile; ++ t_FmPcd *p_FmPcd; ++ uint16_t profileIndx; ++ uint32_t tmpReg32, intFlags; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE); ++ p_FmPcd = p_Profile->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ profileIndx = p_Profile->absoluteProfileId; ++ ++ UpdateRequiredActionFlag(p_FmPcd, profileIndx, FALSE); ++ ++ FmPcdPlcrInvalidateProfileSw(p_FmPcd,profileIndx); ++ ++ if (p_FmPcd->h_Hc) ++ { ++ err = FmHcPcdPlcrDeleteProfile(p_FmPcd->h_Hc, h_Profile); ++ if (p_Profile->p_Lock) ++ /* release allocated Profile lock */ ++ FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock); ++ ++ return err; ++ } ++ ++ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr); ++ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->profileRegs.fmpl_pemode, ~FM_PCD_PLCR_PEMODE_PI); ++ ++ tmpReg32 = FmPcdPlcrBuildWritePlcrActionRegs(profileIndx); ++ WritePar(p_FmPcd, tmpReg32); ++ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ ++ ++ if (p_Profile->p_Lock) ++ /* release allocated Profile lock */ ++ FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock); ++ ++ /* we do not memset profile as all its fields are being re-initialized at "set", ++ * plus its allocation information is still valid. */ ++ return E_OK; ++} ++ ++/***************************************************/ ++/*............Policer Profile Counter..............*/ ++/***************************************************/ ++uint32_t FM_PCD_PlcrProfileGetCounter(t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter) ++{ ++ t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile; ++ t_FmPcd *p_FmPcd; ++ uint16_t profileIndx; ++ uint32_t intFlags, counterVal = 0; ++ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE); ++ p_FmPcd = p_Profile->h_FmPcd; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ ++ if (p_FmPcd->h_Hc) ++ return FmHcPcdPlcrGetProfileCounter(p_FmPcd->h_Hc, h_Profile, counter); ++ ++ p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ SANITY_CHECK_RETURN_VALUE(p_FmPcdPlcrRegs, E_INVALID_HANDLE, 0); ++ ++ profileIndx = p_Profile->absoluteProfileId; ++ ++ if (profileIndx >= FM_PCD_PLCR_NUM_ENTRIES) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big ")); ++ return 0; ++ } ++ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr); ++ WritePar(p_FmPcd, FmPcdPlcrBuildReadPlcrActionReg(profileIndx)); ++ ++ switch (counter) ++ { ++ case e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER: ++ counterVal = (GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc)); ++ break; ++ case e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER: ++ counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc); ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER: ++ counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc); ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER: ++ counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc); ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER: ++ counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc); ++ break; ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ break; ++ } ++ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ ++ return counterVal; ++} ++ ++t_Error FM_PCD_PlcrProfileSetCounter(t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter, uint32_t value) ++{ ++ t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile; ++ t_FmPcd *p_FmPcd; ++ uint16_t profileIndx; ++ uint32_t tmpReg32, intFlags; ++ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE); ++ ++ p_FmPcd = p_Profile->h_FmPcd; ++ profileIndx = p_Profile->absoluteProfileId; ++ ++ if (p_FmPcd->h_Hc) ++ return FmHcPcdPlcrSetProfileCounter(p_FmPcd->h_Hc, h_Profile, counter, value); ++ ++ p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ SANITY_CHECK_RETURN_ERROR(p_FmPcdPlcrRegs, E_INVALID_HANDLE); ++ ++ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr); ++ switch (counter) ++ { ++ case e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER: ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc, value); ++ break; ++ case e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER: ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc, value); ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER: ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc, value); ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER: ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc ,value); ++ break; ++ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER: ++ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc ,value); ++ break; ++ default: ++ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ /* Activate the atomic write action by writing FMPL_PAR with: GO=1, RW=1, PSI=0, PNUM = ++ * Profile Number, PWSEL=0xFFFF (select all words). ++ */ ++ tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx); ++ tmpReg32 |= FmPcdPlcrBuildCounterProfileReg(counter); ++ WritePar(p_FmPcd, tmpReg32); ++ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags); ++ ++ return E_OK; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_plcr.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_plcr.h +new file mode 100644 +index 0000000..2bb8b96 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_plcr.h +@@ -0,0 +1,165 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_plcr.h ++ ++ @Description FM Policer private header ++*//***************************************************************************/ ++#ifndef __FM_PLCR_H ++#define __FM_PLCR_H ++ ++#include "std_ext.h" ++ ++ ++/***********************************************************************/ ++/* Policer defines */ ++/***********************************************************************/ ++ ++#define FM_PCD_PLCR_PAR_GO 0x80000000 ++#define FM_PCD_PLCR_PAR_PWSEL_MASK 0x0000FFFF ++#define FM_PCD_PLCR_PAR_R 0x40000000 ++ ++/* shifts */ ++#define FM_PCD_PLCR_PAR_PNUM_SHIFT 16 ++ ++/* masks */ ++#define FM_PCD_PLCR_PEMODE_PI 0x80000000 ++#define FM_PCD_PLCR_PEMODE_CBLND 0x40000000 ++#define FM_PCD_PLCR_PEMODE_ALG_MASK 0x30000000 ++#define FM_PCD_PLCR_PEMODE_ALG_RFC2698 0x10000000 ++#define FM_PCD_PLCR_PEMODE_ALG_RFC4115 0x20000000 ++#define FM_PCD_PLCR_PEMODE_DEFC_MASK 0x0C000000 ++#define FM_PCD_PLCR_PEMODE_DEFC_Y 0x04000000 ++#define FM_PCD_PLCR_PEMODE_DEFC_R 0x08000000 ++#define FM_PCD_PLCR_PEMODE_DEFC_OVERRIDE 0x0C000000 ++#define FM_PCD_PLCR_PEMODE_OVCLR_MASK 0x03000000 ++#define FM_PCD_PLCR_PEMODE_OVCLR_Y 0x01000000 ++#define FM_PCD_PLCR_PEMODE_OVCLR_R 0x02000000 ++#define FM_PCD_PLCR_PEMODE_OVCLR_G_NC 0x03000000 ++#define FM_PCD_PLCR_PEMODE_PKT 0x00800000 ++#define FM_PCD_PLCR_PEMODE_FPP_MASK 0x001F0000 ++#define FM_PCD_PLCR_PEMODE_FPP_SHIFT 16 ++#define FM_PCD_PLCR_PEMODE_FLS_MASK 0x0000F000 ++#define FM_PCD_PLCR_PEMODE_FLS_L2 0x00003000 ++#define FM_PCD_PLCR_PEMODE_FLS_L3 0x0000B000 ++#define FM_PCD_PLCR_PEMODE_FLS_L4 0x0000E000 ++#define FM_PCD_PLCR_PEMODE_FLS_FULL 0x0000F000 ++#define FM_PCD_PLCR_PEMODE_RBFLS 0x00000800 ++#define FM_PCD_PLCR_PEMODE_TRA 0x00000004 ++#define FM_PCD_PLCR_PEMODE_TRB 0x00000002 ++#define FM_PCD_PLCR_PEMODE_TRC 0x00000001 ++#define FM_PCD_PLCR_DOUBLE_ECC 0x80000000 ++#define FM_PCD_PLCR_INIT_ENTRY_ERROR 0x40000000 ++#define FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE 0x80000000 ++#define FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE 0x40000000 ++ ++#define FM_PCD_PLCR_NIA_VALID 0x80000000 ++ ++#define FM_PCD_PLCR_GCR_EN 0x80000000 ++#define FM_PCD_PLCR_GCR_STEN 0x40000000 ++#define FM_PCD_PLCR_GCR_DAR 0x20000000 ++#define FM_PCD_PLCR_GCR_DEFNIA 0x00FFFFFF ++#define FM_PCD_PLCR_NIA_ABS 0x00000100 ++ ++#define FM_PCD_PLCR_GSR_BSY 0x80000000 ++#define FM_PCD_PLCR_GSR_DQS 0x60000000 ++#define FM_PCD_PLCR_GSR_RPB 0x20000000 ++#define FM_PCD_PLCR_GSR_FQS 0x0C000000 ++#define FM_PCD_PLCR_GSR_LPALG 0x0000C000 ++#define FM_PCD_PLCR_GSR_LPCA 0x00003000 ++#define FM_PCD_PLCR_GSR_LPNUM 0x000000FF ++ ++#define FM_PCD_PLCR_EVR_PSIC 0x80000000 ++#define FM_PCD_PLCR_EVR_AAC 0x40000000 ++ ++#define FM_PCD_PLCR_PAR_PSI 0x20000000 ++#define FM_PCD_PLCR_PAR_PNUM 0x00FF0000 ++/* PWSEL Selctive select options */ ++#define FM_PCD_PLCR_PAR_PWSEL_PEMODE 0x00008000 /* 0 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PEGNIA 0x00004000 /* 1 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PEYNIA 0x00002000 /* 2 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PERNIA 0x00001000 /* 3 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PECIR 0x00000800 /* 4 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PECBS 0x00000400 /* 5 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PEPIR_EIR 0x00000200 /* 6 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PEPBS_EBS 0x00000100 /* 7 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PELTS 0x00000080 /* 8 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PECTS 0x00000040 /* 9 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PEPTS_ETS 0x00000020 /* 10 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PEGPC 0x00000010 /* 11 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PEYPC 0x00000008 /* 12 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PERPC 0x00000004 /* 13 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PERYPC 0x00000002 /* 14 */ ++#define FM_PCD_PLCR_PAR_PWSEL_PERRPC 0x00000001 /* 15 */ ++ ++#define FM_PCD_PLCR_PAR_PMR_BRN_1TO1 0x0000 /* - Full bit replacement. {PBNUM[0:N-1] ++ 1-> 2^N specific locations. */ ++#define FM_PCD_PLCR_PAR_PMR_BRN_2TO2 0x1 /* - {PBNUM[0:N-2],PNUM[N-1]}. ++ 2-> 2^(N-1) base locations. */ ++#define FM_PCD_PLCR_PAR_PMR_BRN_4TO4 0x2 /* - {PBNUM[0:N-3],PNUM[N-2:N-1]}. ++ 4-> 2^(N-2) base locations. */ ++#define FM_PCD_PLCR_PAR_PMR_BRN_8TO8 0x3 /* - {PBNUM[0:N-4],PNUM[N-3:N-1]}. ++ 8->2^(N-3) base locations. */ ++#define FM_PCD_PLCR_PAR_PMR_BRN_16TO16 0x4 /* - {PBNUM[0:N-5],PNUM[N-4:N-1]}. ++ 16-> 2^(N-4) base locations. */ ++#define FM_PCD_PLCR_PAR_PMR_BRN_32TO32 0x5 /* {PBNUM[0:N-6],PNUM[N-5:N-1]}. ++ 32-> 2^(N-5) base locations. */ ++#define FM_PCD_PLCR_PAR_PMR_BRN_64TO64 0x6 /* {PBNUM[0:N-7],PNUM[N-6:N-1]}. ++ 64-> 2^(N-6) base locations. */ ++#define FM_PCD_PLCR_PAR_PMR_BRN_128TO128 0x7 /* {PBNUM[0:N-8],PNUM[N-7:N-1]}. ++ 128-> 2^(N-7) base locations. */ ++#define FM_PCD_PLCR_PAR_PMR_BRN_256TO256 0x8 /* - No bit replacement for N=8. {PNUM[N-8:N-1]}. ++ When N=8 this option maps all 256 profiles by the DISPATCH bus into one group. */ ++ ++#define FM_PCD_PLCR_PMR_V 0x80000000 ++#define PLCR_ERR_ECC_CAP 0x80000000 ++#define PLCR_ERR_ECC_TYPE_DOUBLE 0x40000000 ++#define PLCR_ERR_ECC_PNUM_MASK 0x00000FF0 ++#define PLCR_ERR_ECC_OFFSET_MASK 0x0000000F ++ ++#define PLCR_ERR_UNINIT_CAP 0x80000000 ++#define PLCR_ERR_UNINIT_NUM_MASK 0x000000FF ++#define PLCR_ERR_UNINIT_PID_MASK 0x003f0000 ++#define PLCR_ERR_UNINIT_ABSOLUTE_MASK 0x00008000 ++ ++/* shifts */ ++#define PLCR_ERR_ECC_PNUM_SHIFT 4 ++#define PLCR_ERR_UNINIT_PID_SHIFT 16 ++ ++#define FM_PCD_PLCR_PMR_BRN_SHIFT 16 ++ ++#define PLCR_PORT_WINDOW_SIZE(hardwarePortId) ++ ++ ++#endif /* __FM_PLCR_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_prs.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_prs.c +new file mode 100644 +index 0000000..da2fccf +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_prs.c +@@ -0,0 +1,420 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_pcd.c ++ ++ @Description FM PCD ... ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "debug_ext.h" ++#include "net_ext.h" ++ ++#include "fm_common.h" ++#include "fm_pcd.h" ++#include "fm_pcd_ipc.h" ++#include "fm_prs.h" ++#include "fsl_fman_prs.h" ++ ++ ++static void PcdPrsErrorException(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint32_t event, ev_mask; ++ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; ++ ++ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); ++ ev_mask = fman_prs_get_err_ev_mask(PrsRegs); ++ ++ event = fman_prs_get_err_event(PrsRegs, ev_mask); ++ ++ fman_prs_ack_err_event(PrsRegs, event); ++ ++ DBG(TRACE, ("parser error - 0x%08x\n",event)); ++ ++ if(event & FM_PCD_PRS_DOUBLE_ECC) ++ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC); ++} ++ ++static void PcdPrsException(t_Handle h_FmPcd) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ uint32_t event, ev_mask; ++ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; ++ ++ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); ++ ev_mask = fman_prs_get_expt_ev_mask(PrsRegs); ++ event = fman_prs_get_expt_event(PrsRegs, ev_mask); ++ ++ ASSERT_COND(event & FM_PCD_PRS_SINGLE_ECC); ++ ++ DBG(TRACE, ("parser event - 0x%08x\n",event)); ++ ++ fman_prs_ack_expt_event(PrsRegs, event); ++ ++ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC); ++} ++ ++t_Handle PrsConfig(t_FmPcd *p_FmPcd,t_FmPcdParams *p_FmPcdParams) ++{ ++ t_FmPcdPrs *p_FmPcdPrs; ++ uintptr_t baseAddr; ++ ++ UNUSED(p_FmPcd); ++ UNUSED(p_FmPcdParams); ++ ++ p_FmPcdPrs = (t_FmPcdPrs *) XX_Malloc(sizeof(t_FmPcdPrs)); ++ if (!p_FmPcdPrs) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Parser structure allocation FAILED")); ++ return NULL; ++ } ++ memset(p_FmPcdPrs, 0, sizeof(t_FmPcdPrs)); ++ fman_prs_defconfig(&p_FmPcd->p_FmPcdDriverParam->dfltCfg); ++ ++ if (p_FmPcd->guestId == NCSW_MASTER_ID) ++ { ++ baseAddr = FmGetPcdPrsBaseAddr(p_FmPcdParams->h_Fm); ++ p_FmPcdPrs->p_SwPrsCode = (uint32_t *)UINT_TO_PTR(baseAddr); ++ p_FmPcdPrs->p_FmPcdPrsRegs = (struct fman_prs_regs *)UINT_TO_PTR(baseAddr + PRS_REGS_OFFSET); ++ } ++ ++ p_FmPcdPrs->fmPcdPrsPortIdStatistics = p_FmPcd->p_FmPcdDriverParam->dfltCfg.port_id_stat; ++ p_FmPcd->p_FmPcdDriverParam->prsMaxParseCycleLimit = p_FmPcd->p_FmPcdDriverParam->dfltCfg.max_prs_cyc_lim; ++ p_FmPcd->exceptions |= p_FmPcd->p_FmPcdDriverParam->dfltCfg.prs_exceptions; ++ ++ return p_FmPcdPrs; ++} ++ ++#if ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++ static uint8_t swPrsPatch[] = SW_PRS_UDP_LITE_PATCH; ++#else ++ static uint8_t swPrsPatch[] = SW_PRS_OFFLOAD_PATCH; ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++t_Error PrsInit(t_FmPcd *p_FmPcd) ++{ ++ t_FmPcdDriverParam *p_Param = p_FmPcd->p_FmPcdDriverParam; ++ uint32_t *p_TmpCode; ++ uint32_t *p_LoadTarget = (uint32_t *)PTR_MOVE(p_FmPcd->p_FmPcdPrs->p_SwPrsCode, ++ FM_PCD_SW_PRS_SIZE-FM_PCD_PRS_SW_PATCHES_SIZE); ++ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; ++ uint32_t i; ++ ++ ASSERT_COND(sizeof(swPrsPatch) <= (FM_PCD_PRS_SW_PATCHES_SIZE-FM_PCD_PRS_SW_TAIL_SIZE)); ++ ++ /* nothing to do in guest-partition */ ++ if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ return E_OK; ++ ++ p_TmpCode = (uint32_t *)XX_MallocSmart(ROUND_UP(sizeof(swPrsPatch),4), 0, sizeof(uint32_t)); ++ if (!p_TmpCode) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Tmp Sw-Parser code allocation FAILED")); ++ memset((uint8_t *)p_TmpCode, 0, ROUND_UP(sizeof(swPrsPatch),4)); ++ memcpy((uint8_t *)p_TmpCode, (uint8_t *)swPrsPatch, sizeof(swPrsPatch)); ++ ++ fman_prs_init(PrsRegs, &p_Param->dfltCfg); ++ ++ /* register even if no interrupts enabled, to allow future enablement */ ++ FmRegisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_ERR, PcdPrsErrorException, p_FmPcd); ++ ++ /* register even if no interrupts enabled, to allow future enablement */ ++ FmRegisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_NORMAL, PcdPrsException, p_FmPcd); ++ ++ if(p_FmPcd->exceptions & FM_PCD_EX_PRS_SINGLE_ECC) ++ FmEnableRamsEcc(p_FmPcd->h_Fm); ++ ++ if(p_FmPcd->exceptions & FM_PCD_EX_PRS_DOUBLE_ECC) ++ FmEnableRamsEcc(p_FmPcd->h_Fm); ++ ++ /* load sw parser Ip-Frag patch */ ++ for (i=0; iguestId == NCSW_MASTER_ID); ++ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_ERR); ++ /* register even if no interrupts enabled, to allow future enablement */ ++ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_NORMAL); ++} ++ ++void PrsEnable(t_FmPcd *p_FmPcd) ++{ ++ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; ++ ++ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); ++ fman_prs_enable(PrsRegs); ++} ++ ++void PrsDisable(t_FmPcd *p_FmPcd) ++{ ++ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; ++ ++ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); ++ fman_prs_disable(PrsRegs); ++} ++ ++int PrsIsEnabled(t_FmPcd *p_FmPcd) ++{ ++ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; ++ ++ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID); ++ return fman_prs_is_enabled(PrsRegs); ++} ++ ++t_Error PrsIncludePortInStatistics(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, bool include) ++{ ++ struct fman_prs_regs *PrsRegs; ++ uint32_t bitMask = 0; ++ uint8_t prsPortId; ++ ++ SANITY_CHECK_RETURN_ERROR((hardwarePortId >=1 && hardwarePortId <= 16), E_INVALID_VALUE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE); ++ ++ PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; ++ ++ GET_FM_PCD_PRS_PORT_ID(prsPortId, hardwarePortId); ++ GET_FM_PCD_INDEX_FLAG(bitMask, prsPortId); ++ ++ if (include) ++ p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics |= bitMask; ++ else ++ p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics &= ~bitMask; ++ ++ fman_prs_set_stst_port_msk(PrsRegs, ++ p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics); ++ ++ return E_OK; ++} ++ ++t_Error FmPcdPrsIncludePortInStatistics(t_Handle h_FmPcd, uint8_t hardwarePortId, bool include) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR((hardwarePortId >=1 && hardwarePortId <= 16), E_INVALID_VALUE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE); ++ ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ p_FmPcd->h_IpcSession) ++ { ++ t_FmPcdIpcPrsIncludePort prsIncludePortParams; ++ t_FmPcdIpcMsg msg; ++ ++ prsIncludePortParams.hardwarePortId = hardwarePortId; ++ prsIncludePortParams.include = include; ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_PCD_PRS_INC_PORT_STATS; ++ memcpy(msg.msgBody, &prsIncludePortParams, sizeof(prsIncludePortParams)); ++ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) +sizeof(prsIncludePortParams), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ return E_OK; ++ } ++ else if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++ ++ return PrsIncludePortInStatistics(p_FmPcd, hardwarePortId, include); ++} ++ ++uint32_t FmPcdGetSwPrsOffset(t_Handle h_FmPcd, e_NetHeaderType hdr, uint8_t indexPerHdr) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd; ++ t_FmPcdPrsLabelParams *p_Label; ++ int i; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE, 0); ++ ++ if ((p_FmPcd->guestId != NCSW_MASTER_ID) && ++ p_FmPcd->h_IpcSession) ++ { ++ t_Error err = E_OK; ++ t_FmPcdIpcSwPrsLable labelParams; ++ t_FmPcdIpcMsg msg; ++ uint32_t prsOffset = 0; ++ t_FmPcdIpcReply reply; ++ uint32_t replyLength; ++ ++ memset(&reply, 0, sizeof(reply)); ++ memset(&msg, 0, sizeof(msg)); ++ labelParams.enumHdr = (uint32_t)hdr; ++ labelParams.indexPerHdr = indexPerHdr; ++ msg.msgId = FM_PCD_GET_SW_PRS_OFFSET; ++ memcpy(msg.msgBody, &labelParams, sizeof(labelParams)); ++ replyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession, ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) +sizeof(labelParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t) + sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ ++ memcpy((uint8_t*)&prsOffset, reply.replyBody, sizeof(uint32_t)); ++ return prsOffset; ++ } ++ else if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++ ++ ASSERT_COND(p_FmPcd->p_FmPcdPrs->currLabel < FM_PCD_PRS_NUM_OF_LABELS); ++ ++ for (i=0; ip_FmPcdPrs->currLabel; i++) ++ { ++ p_Label = &p_FmPcd->p_FmPcdPrs->labelsTable[i]; ++ ++ if ((hdr == p_Label->hdr) && (indexPerHdr == p_Label->indexPerHdr)) ++ return p_Label->instructionOffset; ++ } ++ ++ REPORT_ERROR(MAJOR, E_NOT_FOUND, ("Sw Parser attachment Not found")); ++ return (uint32_t)ILLEGAL_BASE; ++} ++ ++void FM_PCD_SetPrsStatistics(t_Handle h_FmPcd, bool enable) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ struct fman_prs_regs *PrsRegs; ++ ++ SANITY_CHECK_RETURN(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE); ++ ++ PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs; ++ ++ ++ if(p_FmPcd->guestId != NCSW_MASTER_ID) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_SetPrsStatistics - guest mode!")); ++ return; ++ } ++ ++ fman_prs_set_stst(PrsRegs, enable); ++} ++ ++t_Error FM_PCD_PrsLoadSw(t_Handle h_FmPcd, t_FmPcdPrsSwParams *p_SwPrs) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ uint32_t *p_LoadTarget; ++ uint32_t *p_TmpCode; ++ int i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_SwPrs, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->enabled, E_INVALID_HANDLE); ++ ++ if (p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM in guest-mode!")); ++ ++ if (!p_SwPrs->override) ++ { ++ if(p_FmPcd->p_FmPcdPrs->p_CurrSwPrs > p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SW parser base must be larger than current loaded code")); ++ } ++ else ++ p_FmPcd->p_FmPcdPrs->currLabel = 0; ++ ++ if (p_SwPrs->size > FM_PCD_SW_PRS_SIZE - FM_PCD_PRS_SW_TAIL_SIZE - p_SwPrs->base*2) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_SwPrs->size may not be larger than MAX_SW_PRS_CODE_SIZE")); ++ ++ if (p_FmPcd->p_FmPcdPrs->currLabel + p_SwPrs->numOfLabels > FM_PCD_PRS_NUM_OF_LABELS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceeded number of labels allowed ")); ++ ++ p_TmpCode = (uint32_t *)XX_MallocSmart(ROUND_UP(p_SwPrs->size,4), 0, sizeof(uint32_t)); ++ if (!p_TmpCode) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Tmp Sw-Parser code allocation FAILED")); ++ memset((uint8_t *)p_TmpCode, 0, ROUND_UP(p_SwPrs->size,4)); ++ memcpy((uint8_t *)p_TmpCode, p_SwPrs->p_Code, p_SwPrs->size); ++ ++ /* save sw parser labels */ ++ memcpy(&p_FmPcd->p_FmPcdPrs->labelsTable[p_FmPcd->p_FmPcdPrs->currLabel], ++ p_SwPrs->labelsTable, ++ p_SwPrs->numOfLabels*sizeof(t_FmPcdPrsLabelParams)); ++ p_FmPcd->p_FmPcdPrs->currLabel += p_SwPrs->numOfLabels; ++ ++ /* load sw parser code */ ++ p_LoadTarget = p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4; ++ for(i=0; isize,4); i++) ++ WRITE_UINT32(p_LoadTarget[i], p_TmpCode[i]); ++ p_FmPcd->p_FmPcdPrs->p_CurrSwPrs = ++ p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4 + ROUND_UP(p_SwPrs->size,4); ++ ++ /* copy data parameters */ ++ for (i=0;ip_FmPcdPrs->p_SwPrsCode+PRS_SW_DATA/4+i), p_SwPrs->swPrsDataParams[i]); ++ ++ /* Clear last 4 bytes */ ++ WRITE_UINT32(*(p_FmPcd->p_FmPcdPrs->p_SwPrsCode+(PRS_SW_DATA-FM_PCD_PRS_SW_TAIL_SIZE)/4), 0); ++ ++ XX_FreeSmart(p_TmpCode); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_ConfigPrsMaxCycleLimit(t_Handle h_FmPcd,uint16_t value) ++{ ++ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE); ++ ++ if(p_FmPcd->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ConfigPrsMaxCycleLimit - guest mode!")); ++ ++ p_FmPcd->p_FmPcdDriverParam->prsMaxParseCycleLimit = value; ++ ++ return E_OK; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_prs.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_prs.h +new file mode 100644 +index 0000000..056f225 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_prs.h +@@ -0,0 +1,316 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_prs.h ++ ++ @Description FM Parser private header ++ *//***************************************************************************/ ++#ifndef __FM_PRS_H ++#define __FM_PRS_H ++ ++#include "std_ext.h" ++ ++/***********************************************************************/ ++/* SW parser IP_FRAG patch */ ++/***********************************************************************/ ++ ++#if ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++#define SW_PRS_UDP_LITE_PATCH \ ++{\ ++ 0x31,0x52,0x00,0xDA,0xFC,0x00,0x00,0x00,0x00,0x00, \ ++ 0x00,0x00,0x50,0x2C,0x40,0x00,0x31,0x92,0x50,0x2C, \ ++ 0x00,0x88,0x18,0x2F,0x00,0x01,0x1B,0xFE,0x18,0x71, \ ++ 0x02,0x1F,0x00,0x08,0x00,0x83,0x02,0x1F,0x00,0x20, \ ++ 0x28,0x1B,0x00,0x05,0x29,0x1F,0x30,0xD0,0x60,0x4F, \ ++ 0x00,0x07,0x00,0x05,0x00,0x00,0xC3,0x8F,0x00,0x52, \ ++ 0x00,0x01,0x07,0x01,0x60,0x3B,0x00,0x00,0x30,0xD0, \ ++ 0x00,0xDA,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00, \ ++ 0x40,0x4C,0x00,0x00,0x02,0x8F,0x00,0x00,0x30,0xF2, \ ++ 0x00,0x06,0x18,0x5D,0x00,0x00,0x9F,0xFF,0x30,0xF2, \ ++ 0x00,0x06,0x29,0x1E,0x07,0x08,0x30,0xD0,0x00,0x52, \ ++ 0x00,0x08,0x28,0x1A,0x60,0x37,0x00,0x00,0x30,0xF2, \ ++ 0x18,0x5D,0x06,0x00,0x29,0x1E,0x30,0xF2,0x2F,0x0E, \ ++ 0x30,0x72,0x00,0x00,0x9B,0x8F,0x00,0x06,0x2F,0x0E, \ ++ 0x32,0xF1,0x32,0xB0,0x00,0x4F,0x00,0x57,0x00,0x28, \ ++ 0x00,0x00,0x97,0x9E,0x00,0x4E,0x30,0x72,0x00,0x06, \ ++ 0x2F,0x0E,0x32,0xC1,0x32,0xF0,0x00,0x4A,0x00,0x80, \ ++ 0x00,0x02,0x00,0x00,0x97,0x9E,0x40,0x7E,0x00,0x08, \ ++ 0x08,0x16,0x00,0x54,0x00,0x01,0x1B,0xFE,0x00,0x00, \ ++ 0x9F,0x9E,0x40,0xB3,0x00,0x00,0x02,0x1F,0x00,0x08, \ ++ 0x28,0x1B,0x30,0x73,0x29,0x1F,0x30,0xD0,0x60,0x9F, \ ++ 0x00,0x07,0x00,0x05,0x00,0x00,0xC3,0x8F,0x00,0x52, \ ++ 0x00,0x01,0x07,0x01,0x60,0x8B,0x00,0x00,0x30,0xD0, \ ++ 0x00,0xDA,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00, \ ++ 0x40,0x9C,0x00,0x00,0x02,0x8F,0x00,0x00,0x30,0xF2, \ ++ 0x00,0x06,0x18,0xAD,0x00,0x00,0x9F,0xFF,0x30,0xF2, \ ++ 0x00,0x06,0x29,0x1E,0x07,0x08,0x30,0xD0,0x00,0x52, \ ++ 0x00,0x08,0x28,0x1A,0x60,0x87,0x00,0x00,0x30,0xF2, \ ++ 0x18,0xAD,0x06,0x00,0x29,0x1E,0x30,0xF2,0x50,0xB3, \ ++ 0xFF,0xFF,0x18,0xB8,0x08,0x16,0x00,0x54,0x00,0x01, \ ++ 0x1B,0xFE,0x18,0xC5,0x32,0xF1,0x28,0x5D,0x32,0xF1, \ ++ 0x00,0x55,0x00,0x08,0x28,0x5F,0x00,0x00,0x8F,0x9F, \ ++ 0x29,0x33,0x08,0x16,0x00,0x49,0x00,0x01,0x1B,0xFF, \ ++ 0x00,0x01,0x1B,0xFF \ ++} ++#endif /* ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) */ ++ ++#if (DPAA_VERSION == 10) ++/* Version: 106.1.9 */ ++#define SW_PRS_OFFLOAD_PATCH \ ++{ \ ++ 0x31,0x52,0x00,0xDA,0x0A,0x00,0x00,0x00,0x00,0x00, \ ++ 0x00,0x00,0x43,0x0A,0x00,0x00,0x00,0x01,0x1B,0xFE, \ ++ 0x00,0x00,0x99,0x00,0x53,0x13,0x00,0x00,0x00,0x00, \ ++ 0x9F,0x98,0x53,0x13,0x00,0x00,0x1B,0x23,0x33,0xF1, \ ++ 0x00,0xF9,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00, \ ++ 0x28,0x7F,0x00,0x03,0x00,0x02,0x00,0x00,0x00,0x01, \ ++ 0x32,0xC1,0x32,0xF0,0x00,0x4A,0x00,0x80,0x1F,0xFF, \ ++ 0x00,0x01,0x1B,0xFE,0x31,0x52,0x00,0xDA,0x06,0x00, \ ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x2F,0x00,0x00, \ ++ 0x00,0x01,0x1B,0xFE,0x31,0x52,0x00,0xDA,0x00,0x40, \ ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x95,0x00,0x00, \ ++ 0x00,0x00,0x9B,0x8F,0x2F,0x0F,0x32,0xC1,0x00,0x55, \ ++ 0x00,0x28,0x28,0x43,0x30,0x7E,0x43,0x45,0x00,0x00, \ ++ 0x30,0x7E,0x43,0x45,0x00,0x3C,0x1B,0x5D,0x32,0x11, \ ++ 0x32,0xC0,0x00,0x4F,0x00,0x81,0x00,0x00,0x83,0x8F, \ ++ 0x2F,0x0F,0x06,0x00,0x32,0x11,0x32,0xC0,0x00,0x4F, \ ++ 0x00,0x55,0x00,0x01,0x00,0x81,0x32,0x11,0x00,0x00, \ ++ 0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04,0x00,0x4D, \ ++ 0x28,0x43,0x06,0x00,0x1B,0x3E,0x30,0x7E,0x53,0x79, \ ++ 0x00,0x2B,0x32,0x11,0x32,0xC0,0x00,0x4F,0x00,0x81, \ ++ 0x00,0x00,0x87,0x8F,0x28,0x23,0x06,0x00,0x32,0x11, \ ++ 0x32,0xC0,0x00,0x4F,0x00,0x55,0x00,0x01,0x00,0x81, \ ++ 0x32,0x11,0x00,0x00,0x83,0x8E,0x00,0x50,0x00,0x01, \ ++ 0x01,0x04,0x00,0x4D,0x28,0x43,0x06,0x00,0x00,0x01, \ ++ 0x1B,0xFE,0x00,0x00,0x9B,0x8E,0x53,0x90,0x00,0x00, \ ++ 0x06,0x29,0x00,0x00,0x83,0x8F,0x28,0x23,0x06,0x00, \ ++ 0x06,0x29,0x32,0xC1,0x00,0x55,0x00,0x28,0x00,0x00, \ ++ 0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04,0x00,0x4D, \ ++ 0x28,0x43,0x06,0x00,0x00,0x01,0x1B,0xFE,0x32,0xC1, \ ++ 0x00,0x55,0x00,0x28,0x28,0x43,0x1B,0xCF,0x00,0x00, \ ++ 0x9B,0x8F,0x2F,0x0F,0x32,0xC1,0x00,0x55,0x00,0x28, \ ++ 0x28,0x43,0x30,0x7E,0x43,0xBF,0x00,0x2C,0x32,0x11, \ ++ 0x32,0xC0,0x00,0x4F,0x00,0x81,0x00,0x00,0x87,0x8F, \ ++ 0x28,0x23,0x06,0x00,0x32,0x11,0x32,0xC0,0x00,0x4F, \ ++ 0x00,0x81,0x00,0x00,0x83,0x8F,0x2F,0x0F,0x06,0x00, \ ++ 0x32,0x11,0x32,0xC0,0x00,0x4F,0x00,0x55,0x00,0x01, \ ++ 0x00,0x81,0x32,0x11,0x00,0x00,0x83,0x8E,0x00,0x50, \ ++ 0x00,0x01,0x01,0x04,0x00,0x4D,0x28,0x43,0x06,0x00, \ ++ 0x1B,0x9C,0x33,0xF1,0x00,0xF9,0x00,0x01,0x00,0x00, \ ++ 0x00,0x00,0x00,0x00,0x28,0x7F,0x00,0x03,0x00,0x02, \ ++ 0x00,0x00,0x00,0x01,0x32,0xC1,0x32,0xF0,0x00,0x4A, \ ++ 0x00,0x80,0x1F,0xFF,0x00,0x01,0x1B,0xFE, \ ++} ++ ++#else ++#define SW_PRS_OFFLOAD_PATCH \ ++{ \ ++ 0x31,0x52,0x00,0xDA,0x0E,0x4F,0x00,0x00,0x00,0x00, \ ++ 0x00,0x00,0x51,0x16,0x08,0x4B,0x31,0x53,0x00,0xFB, \ ++ 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x2B, \ ++ 0x33,0xF1,0x00,0xFB,0x00,0xDF,0x00,0x00,0x00,0x00, \ ++ 0x00,0x00,0x28,0x7F,0x31,0x52,0x00,0xDA,0x0A,0x00, \ ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x20,0x00,0x00, \ ++ 0x00,0x01,0x1B,0xFE,0x00,0x00,0x99,0x00,0x51,0x29, \ ++ 0x00,0x00,0x00,0x00,0x9F,0x98,0x51,0x29,0x00,0x00, \ ++ 0x19,0x44,0x09,0x5F,0x00,0x20,0x00,0x00,0x09,0x4F, \ ++ 0x00,0x20,0x00,0x00,0x34,0xB7,0x00,0xF9,0x00,0x00, \ ++ 0x01,0x00,0x00,0x00,0x00,0x00,0x2B,0x97,0x31,0xB3, \ ++ 0x29,0x8F,0x33,0xF1,0x00,0xF9,0x00,0x01,0x00,0x00, \ ++ 0x00,0x00,0x00,0x00,0x28,0x7F,0x00,0x03,0x00,0x02, \ ++ 0x00,0x00,0x00,0x01,0x1B,0xFE,0x00,0x01,0x1B,0xFE, \ ++ 0x31,0x52,0x00,0xDA,0xFC,0x00,0x00,0x00,0x00,0x00, \ ++ 0x00,0x00,0x51,0x52,0x40,0x00,0x31,0x92,0x51,0x52, \ ++ 0x00,0x88,0x19,0x55,0x08,0x05,0x00,0x00,0x19,0x99, \ ++ 0x02,0x1F,0x00,0x08,0x00,0x83,0x02,0x1F,0x00,0x20, \ ++ 0x28,0x1B,0x00,0x05,0x29,0x1F,0x30,0xD0,0x61,0x75, \ ++ 0x00,0x07,0x00,0x05,0x00,0x00,0xC3,0x8F,0x00,0x52, \ ++ 0x00,0x01,0x07,0x01,0x61,0x61,0x00,0x00,0x30,0xD0, \ ++ 0x00,0xDA,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00, \ ++ 0x41,0x72,0x00,0x00,0x02,0x8F,0x00,0x00,0x30,0xF2, \ ++ 0x00,0x06,0x19,0x83,0x00,0x00,0x9F,0xFF,0x30,0xF2, \ ++ 0x00,0x06,0x29,0x1E,0x07,0x08,0x30,0xD0,0x00,0x52, \ ++ 0x00,0x08,0x28,0x1A,0x61,0x5D,0x00,0x00,0x30,0xF2, \ ++ 0x19,0x83,0x06,0x00,0x29,0x1E,0x30,0xF2,0x29,0x0E, \ ++ 0x30,0x72,0x00,0x00,0x9B,0x8F,0x00,0x06,0x29,0x0E, \ ++ 0x32,0xF1,0x32,0xB0,0x00,0x4F,0x00,0x57,0x00,0x28, \ ++ 0x00,0x00,0x97,0x9E,0x00,0x4E,0x30,0x72,0x00,0x06, \ ++ 0x29,0x0E,0x08,0x05,0x00,0x01,0x31,0x52,0x00,0xDA, \ ++ 0x0E,0x4F,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0xAF, \ ++ 0x04,0x4B,0x31,0x53,0x00,0xFB,0xFF,0xF0,0x00,0x00, \ ++ 0x00,0x00,0x00,0x00,0x29,0x2B,0x33,0xF1,0x00,0xFB, \ ++ 0x00,0xDF,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x7F, \ ++ 0x31,0x52,0x00,0xDA,0x06,0x00,0x00,0x00,0x00,0x00, \ ++ 0x00,0x00,0x41,0xB9,0x00,0x00,0x00,0x01,0x1B,0xFE, \ ++ 0x31,0x52,0x00,0xDA,0x00,0x40,0x00,0x00,0x00,0x00, \ ++ 0x00,0x00,0x42,0x06,0x00,0x00,0x00,0x00,0x9B,0x8F, \ ++ 0x28,0x01,0x32,0xC1,0x00,0x55,0x00,0x28,0x28,0x43, \ ++ 0x30,0x00,0x41,0xEB,0x00,0x2C,0x32,0x11,0x32,0xC0, \ ++ 0x00,0x4F,0x00,0x81,0x00,0x00,0x87,0x8F,0x28,0x23, \ ++ 0x06,0x00,0x32,0x11,0x32,0xC0,0x00,0x4F,0x00,0x81, \ ++ 0x00,0x00,0x83,0x8F,0x28,0x01,0x06,0x00,0x32,0x11, \ ++ 0x32,0xC0,0x00,0x4F,0x00,0x55,0x00,0x01,0x00,0x81, \ ++ 0x32,0x11,0x00,0x00,0x83,0x8E,0x00,0x50,0x00,0x01, \ ++ 0x01,0x04,0x00,0x4D,0x28,0x43,0x06,0x00,0x19,0xC8, \ ++ 0x09,0x5F,0x00,0x20,0x00,0x00,0x09,0x4F,0x00,0x20, \ ++ 0x00,0x00,0x34,0xB7,0x00,0xF9,0x00,0x00,0x01,0x00, \ ++ 0x00,0x00,0x00,0x00,0x2B,0x97,0x31,0xB3,0x29,0x8F, \ ++ 0x33,0xF1,0x00,0xF9,0x00,0x01,0x00,0x00,0x00,0x00, \ ++ 0x00,0x00,0x28,0x7F,0x00,0x03,0x00,0x02,0x00,0x00, \ ++ 0x00,0x01,0x1B,0xFE,0x30,0x50,0x52,0x0B,0x00,0x00, \ ++ 0x00,0x01,0x1B,0xFE,0x32,0xF1,0x32,0xC0,0x00,0x4F, \ ++ 0x00,0x81,0x00,0x02,0x00,0x00,0x97,0x9E,0x42,0x18, \ ++ 0x00,0x08,0x08,0x16,0x00,0x54,0x00,0x01,0x1B,0xFE, \ ++ 0x00,0x00,0x9F,0x9E,0x42,0x4D,0x00,0x00,0x02,0x1F, \ ++ 0x00,0x08,0x28,0x1B,0x30,0x73,0x29,0x1F,0x30,0xD0, \ ++ 0x62,0x39,0x00,0x07,0x00,0x05,0x00,0x00,0xC3,0x8F, \ ++ 0x00,0x52,0x00,0x01,0x07,0x01,0x62,0x25,0x00,0x00, \ ++ 0x30,0xD0,0x00,0xDA,0x00,0x01,0x00,0x00,0x00,0x00, \ ++ 0x00,0x00,0x42,0x36,0x00,0x00,0x02,0x8F,0x00,0x00, \ ++ 0x30,0xF2,0x00,0x06,0x1A,0x47,0x00,0x00,0x9F,0xFF, \ ++ 0x30,0xF2,0x00,0x06,0x29,0x1E,0x07,0x08,0x30,0xD0, \ ++ 0x00,0x52,0x00,0x08,0x28,0x1A,0x62,0x21,0x00,0x00, \ ++ 0x30,0xF2,0x1A,0x47,0x06,0x00,0x29,0x1E,0x30,0xF2, \ ++ 0x52,0x4D,0xFF,0xFF,0x1A,0x52,0x08,0x16,0x00,0x54, \ ++ 0x00,0x01,0x1B,0xFE,0x1A,0x5F,0x32,0xF1,0x28,0x5D, \ ++ 0x32,0xF1,0x00,0x55,0x00,0x08,0x28,0x5F,0x00,0x00, \ ++ 0x8F,0x9F,0x29,0x33,0x08,0x16,0x00,0x49,0x00,0x01, \ ++ 0x1B,0xFF,0x00,0x01,0x1B,0xFF,0x31,0x52,0x00,0xDA, \ ++ 0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x6D, \ ++ 0x40,0x00,0x31,0x92,0x52,0x6D,0x00,0x88,0x1A,0x70, \ ++ 0x08,0x05,0x00,0x00,0x1A,0xB4,0x02,0x1F,0x00,0x08, \ ++ 0x00,0x83,0x02,0x1F,0x00,0x20,0x28,0x1B,0x00,0x05, \ ++ 0x29,0x1F,0x30,0xD0,0x62,0x90,0x00,0x07,0x00,0x05, \ ++ 0x00,0x00,0xC3,0x8F,0x00,0x52,0x00,0x01,0x07,0x01, \ ++ 0x62,0x7C,0x00,0x00,0x30,0xD0,0x00,0xDA,0x00,0x01, \ ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x8D,0x00,0x00, \ ++ 0x02,0x8F,0x00,0x00,0x30,0xF2,0x00,0x06,0x1A,0x9E, \ ++ 0x00,0x00,0x9F,0xFF,0x30,0xF2,0x00,0x06,0x29,0x1E, \ ++ 0x07,0x08,0x30,0xD0,0x00,0x52,0x00,0x08,0x28,0x1A, \ ++ 0x62,0x78,0x00,0x00,0x30,0xF2,0x1A,0x9E,0x06,0x00, \ ++ 0x29,0x1E,0x30,0xF2,0x29,0x0E,0x30,0x72,0x00,0x00, \ ++ 0x9B,0x8F,0x00,0x06,0x29,0x0E,0x32,0xF1,0x32,0xB0, \ ++ 0x00,0x4F,0x00,0x57,0x00,0x28,0x00,0x00,0x97,0x9E, \ ++ 0x00,0x4E,0x30,0x72,0x00,0x06,0x29,0x0E,0x08,0x05, \ ++ 0x00,0x01,0x31,0x52,0x00,0xDA,0x0E,0x4F,0x00,0x00, \ ++ 0x00,0x00,0x00,0x00,0x52,0xCA,0x04,0x4B,0x31,0x53, \ ++ 0x00,0xFB,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00, \ ++ 0x29,0x2B,0x33,0xF1,0x00,0xFB,0x00,0xDF,0x00,0x00, \ ++ 0x00,0x00,0x00,0x00,0x28,0x7F,0x31,0x52,0x00,0xDA, \ ++ 0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0xD4, \ ++ 0x00,0x00,0x00,0x01,0x1B,0xFE,0x31,0x52,0x00,0xDA, \ ++ 0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x37, \ ++ 0x00,0x00,0x00,0x00,0x9B,0x8F,0x28,0x01,0x32,0xC1, \ ++ 0x00,0x55,0x00,0x28,0x28,0x43,0x30,0x00,0x42,0xEA, \ ++ 0x00,0x00,0x30,0x00,0x42,0xEA,0x00,0x3C,0x1B,0x02, \ ++ 0x32,0x11,0x32,0xC0,0x00,0x4F,0x00,0x81,0x00,0x00, \ ++ 0x83,0x8F,0x28,0x01,0x06,0x00,0x32,0x11,0x32,0xC0, \ ++ 0x00,0x4F,0x00,0x55,0x00,0x01,0x00,0x81,0x32,0x11, \ ++ 0x00,0x00,0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04, \ ++ 0x00,0x4D,0x28,0x43,0x06,0x00,0x1A,0xE3,0x30,0x00, \ ++ 0x43,0x20,0x00,0x2B,0x00,0x00,0x9B,0x8E,0x43,0x0E, \ ++ 0x00,0x00,0x32,0xC1,0x00,0x55,0x00,0x28,0x28,0x43, \ ++ 0x1B,0x1F,0x06,0x29,0x00,0x00,0x83,0x8F,0x28,0x23, \ ++ 0x06,0x00,0x06,0x29,0x32,0xC1,0x00,0x55,0x00,0x28, \ ++ 0x00,0x00,0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04, \ ++ 0x00,0x4D,0x28,0x43,0x06,0x00,0x1B,0x37,0x32,0x11, \ ++ 0x32,0xC0,0x00,0x4F,0x00,0x81,0x00,0x00,0x87,0x8F, \ ++ 0x28,0x23,0x06,0x00,0x32,0x11,0x32,0xC0,0x00,0x4F, \ ++ 0x00,0x55,0x00,0x01,0x00,0x81,0x32,0x11,0x00,0x00, \ ++ 0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04,0x00,0x4D, \ ++ 0x28,0x43,0x06,0x00,0x30,0x50,0x53,0x3C,0x00,0x00, \ ++ 0x00,0x01,0x1B,0xFE,0x32,0xF1,0x32,0xC0,0x00,0x4F, \ ++ 0x00,0x81,0x00,0x02,0x00,0x00,0x97,0x9E,0x43,0x49, \ ++ 0x00,0x08,0x08,0x16,0x00,0x54,0x00,0x01,0x1B,0xFE, \ ++ 0x00,0x00,0x9F,0x9E,0x43,0x7E,0x00,0x00,0x02,0x1F, \ ++ 0x00,0x08,0x28,0x1B,0x30,0x73,0x29,0x1F,0x30,0xD0, \ ++ 0x63,0x6A,0x00,0x07,0x00,0x05,0x00,0x00,0xC3,0x8F, \ ++ 0x00,0x52,0x00,0x01,0x07,0x01,0x63,0x56,0x00,0x00, \ ++ 0x30,0xD0,0x00,0xDA,0x00,0x01,0x00,0x00,0x00,0x00, \ ++ 0x00,0x00,0x43,0x67,0x00,0x00,0x02,0x8F,0x00,0x00, \ ++ 0x30,0xF2,0x00,0x06,0x1B,0x78,0x00,0x00,0x9F,0xFF, \ ++ 0x30,0xF2,0x00,0x06,0x29,0x1E,0x07,0x08,0x30,0xD0, \ ++ 0x00,0x52,0x00,0x08,0x28,0x1A,0x63,0x52,0x00,0x00, \ ++ 0x30,0xF2,0x1B,0x78,0x06,0x00,0x29,0x1E,0x30,0xF2, \ ++ 0x53,0x7E,0xFF,0xFF,0x1B,0x83,0x08,0x16,0x00,0x54, \ ++ 0x00,0x01,0x1B,0xFE,0x1B,0x90,0x32,0xF1,0x28,0x5D, \ ++ 0x32,0xF1,0x00,0x55,0x00,0x08,0x28,0x5F,0x00,0x00, \ ++ 0x8F,0x9F,0x29,0x33,0x08,0x16,0x00,0x49,0x00,0x01, \ ++ 0x1B,0xFF,0x00,0x01,0x1B,0xFF,0x08,0x07,0x00,0x02, \ ++ 0x00,0x00,0x8D,0x80,0x53,0x9C,0x00,0x01,0x30,0x71, \ ++ 0x00,0x55,0x00,0x01,0x28,0x0F,0x00,0x00,0x8D,0x00, \ ++ 0x53,0xA4,0x00,0x01,0x30,0x71,0x00,0x55,0x00,0x01, \ ++ 0x28,0x0F,0x00,0x00,0x83,0x8E,0x53,0xB9,0x00,0x00, \ ++ 0x00,0x00,0x86,0x08,0x30,0x71,0x00,0x7B,0x03,0xB9, \ ++ 0x33,0xB4,0x00,0xDA,0xFF,0xFF,0x00,0x0F,0x00,0x00, \ ++ 0x00,0x00,0x00,0x00,0x86,0x09,0x01,0x03,0x00,0x7D, \ ++ 0x03,0xB9,0x1B,0xC8,0x33,0xD1,0x00,0xF9,0x00,0x10, \ ++ 0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x7B,0x09,0x5F, \ ++ 0x00,0x1A,0x00,0x00,0x09,0x4F,0x00,0x1A,0x00,0x00, \ ++ 0x00,0x01,0x1B,0xFF,0x00,0x00,0x8C,0x00,0x53,0xF0, \ ++ 0x00,0x01,0x34,0xF5,0x00,0xFB,0xFF,0xFF,0x00,0x7F, \ ++ 0x00,0x00,0x00,0x00,0x2A,0x9F,0x00,0x00,0x93,0x8F, \ ++ 0x28,0x49,0x00,0x00,0x97,0x8F,0x28,0x4B,0x34,0x61, \ ++ 0x28,0x4D,0x34,0x71,0x28,0x4F,0x34,0xB7,0x00,0xF9, \ ++ 0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x2B,0x97, \ ++ 0x33,0xF1,0x00,0xF9,0x00,0x01,0x00,0x00,0x00,0x00, \ ++ 0x00,0x00,0x28,0x7F,0x00,0x03,0x00,0x02,0x00,0x00, \ ++ 0x00,0x01,0x1B,0xFF,0x00,0x01,0x1B,0xFF, \ ++} ++#endif /* (DPAA_VERSION == 10) */ ++ ++/****************************/ ++/* Parser defines */ ++/****************************/ ++#define FM_PCD_PRS_SW_TAIL_SIZE 4 /**< Number of bytes that must be cleared at ++ the end of the SW parser area */ ++ ++/* masks */ ++#define PRS_ERR_CAP 0x80000000 ++#define PRS_ERR_TYPE_DOUBLE 0x40000000 ++#define PRS_ERR_SINGLE_ECC_CNT_MASK 0x00FF0000 ++#define PRS_ERR_ADDR_MASK 0x000001FF ++ ++/* others */ ++#define PRS_MAX_CYCLE_LIMIT 8191 ++#define PRS_SW_DATA 0x00000800 ++#define PRS_REGS_OFFSET 0x00000840 ++ ++#define GET_FM_PCD_PRS_PORT_ID(prsPortId,hardwarePortId) \ ++ prsPortId = (uint8_t)(hardwarePortId & 0x0f) ++ ++#define GET_FM_PCD_INDEX_FLAG(bitMask, prsPortId) \ ++ bitMask = 0x80000000>>prsPortId ++ ++#endif /* __FM_PRS_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_replic.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_replic.c +new file mode 100644 +index 0000000..ee82f73 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_replic.c +@@ -0,0 +1,984 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_replic.c ++ ++ @Description FM frame replicator ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "debug_ext.h" ++#include "fm_pcd_ext.h" ++#include "fm_muram_ext.h" ++#include "fm_common.h" ++#include "fm_hc.h" ++#include "fm_replic.h" ++#include "fm_cc.h" ++#include "list_ext.h" ++ ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++static uint8_t GetMemberPosition(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ uint32_t memberIndex, ++ bool isAddOperation) ++{ ++ uint8_t memberPosition; ++ uint32_t lastMemberIndex; ++ ++ ASSERT_COND(p_ReplicGroup); ++ ++ /* the last member index is different between add and remove operation - ++ in case of remove - this is exactly the last member index ++ in case of add - this is the last member index + 1 - e.g. ++ if we have 4 members, the index of the actual last member is 3(because the ++ index starts from 0) therefore in order to add a new member as the last ++ member we shall use memberIndex = 4 and not 3 ++ */ ++ if (isAddOperation) ++ lastMemberIndex = p_ReplicGroup->numOfEntries; ++ else ++ lastMemberIndex = p_ReplicGroup->numOfEntries-1; ++ ++ /* last */ ++ if (memberIndex == lastMemberIndex) ++ memberPosition = FRM_REPLIC_LAST_MEMBER_INDEX; ++ else ++ { ++ /* first */ ++ if (memberIndex == 0) ++ memberPosition = FRM_REPLIC_FIRST_MEMBER_INDEX; ++ else ++ { ++ /* middle */ ++ ASSERT_COND(memberIndex < lastMemberIndex); ++ memberPosition = FRM_REPLIC_MIDDLE_MEMBER_INDEX; ++ } ++ } ++ return memberPosition; ++} ++ ++static t_Error MemberCheckParams(t_Handle h_FmPcd, ++ t_FmPcdCcNextEngineParams *p_MemberParams) ++{ ++ t_Error err; ++ ++ ++ if ((p_MemberParams->nextEngine != e_FM_PCD_DONE) && ++ (p_MemberParams->nextEngine != e_FM_PCD_KG) && ++ (p_MemberParams->nextEngine != e_FM_PCD_PLCR)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Next engine of a member should be MatchTable(cc) or Done or Policer")); ++ ++ /* check the regular parameters of the next engine */ ++ err = ValidateNextEngineParams(h_FmPcd, p_MemberParams, e_FM_PCD_CC_STATS_MODE_NONE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("member next engine parameters")); ++ ++ return E_OK; ++} ++ ++static t_Error CheckParams(t_Handle h_FmPcd, ++ t_FmPcdFrmReplicGroupParams *p_ReplicGroupParam) ++{ ++ int i; ++ t_Error err; ++ ++ /* check that max num of entries is at least 2 */ ++ if (!IN_RANGE(2, p_ReplicGroupParam->maxNumOfEntries, FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES)) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("maxNumOfEntries in the frame replicator parameters should be 2-%d",FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES)); ++ ++ /* check that number of entries is greater than zero */ ++ if (!p_ReplicGroupParam->numOfEntries) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOFEntries in the frame replicator group should be greater than zero")); ++ ++ /* check that max num of entries is equal or greater than number of entries */ ++ if (p_ReplicGroupParam->maxNumOfEntries < p_ReplicGroupParam->numOfEntries) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxNumOfEntries should be equal or greater than numOfEntries")); ++ ++ for (i=0; inumOfEntries; i++) ++ { ++ err = MemberCheckParams(h_FmPcd, &p_ReplicGroupParam->nextEngineParams[i]); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("member check parameters")); ++ } ++ return E_OK; ++} ++ ++static t_FmPcdFrmReplicMember *GetAvailableMember(t_FmPcdFrmReplicGroup *p_ReplicGroup) ++{ ++ t_FmPcdFrmReplicMember *p_ReplicMember = NULL; ++ t_List *p_Next; ++ ++ if (!LIST_IsEmpty(&p_ReplicGroup->availableMembersList)) ++ { ++ p_Next = LIST_FIRST(&p_ReplicGroup->availableMembersList); ++ p_ReplicMember = LIST_OBJECT(p_Next, t_FmPcdFrmReplicMember, node); ++ ASSERT_COND(p_ReplicMember); ++ LIST_DelAndInit(p_Next); ++ } ++ return p_ReplicMember; ++} ++ ++static void PutAvailableMember(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ t_FmPcdFrmReplicMember *p_ReplicMember) ++{ ++ LIST_AddToTail(&p_ReplicMember->node, &p_ReplicGroup->availableMembersList); ++} ++ ++static void AddMemberToList(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ t_FmPcdFrmReplicMember *p_CurrentMember, ++ t_List *p_ListHead) ++{ ++ LIST_Add(&p_CurrentMember->node, p_ListHead); ++ ++ p_ReplicGroup->numOfEntries++; ++} ++ ++static void RemoveMemberFromList(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ t_FmPcdFrmReplicMember *p_CurrentMember) ++{ ++ ASSERT_COND(p_ReplicGroup->numOfEntries); ++ LIST_DelAndInit(&p_CurrentMember->node); ++ p_ReplicGroup->numOfEntries--; ++} ++ ++static void LinkSourceToMember(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ t_AdOfTypeContLookup *p_SourceTd, ++ t_FmPcdFrmReplicMember *p_ReplicMember) ++{ ++ t_FmPcd *p_FmPcd; ++ ++ ASSERT_COND(p_SourceTd); ++ ASSERT_COND(p_ReplicMember); ++ ASSERT_COND(p_ReplicGroup); ++ ASSERT_COND(p_ReplicGroup->h_FmPcd); ++ ++ /* Link the first member in the group to the source TD */ ++ p_FmPcd = p_ReplicGroup->h_FmPcd; ++ ++ WRITE_UINT32(p_SourceTd->matchTblPtr, ++ (uint32_t)(XX_VirtToPhys(p_ReplicMember->p_MemberAd) - ++ p_FmPcd->physicalMuramBase)); ++} ++ ++static void LinkMemberToMember(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ t_FmPcdFrmReplicMember *p_CurrentMember, ++ t_FmPcdFrmReplicMember *p_NextMember) ++{ ++ t_AdOfTypeResult *p_CurrReplicAd = (t_AdOfTypeResult*)p_CurrentMember->p_MemberAd; ++ t_AdOfTypeResult *p_NextReplicAd = NULL; ++ t_FmPcd *p_FmPcd; ++ uint32_t offset = 0; ++ ++ /* Check if the next member exists or it's NULL (- means that this is the last member) */ ++ if (p_NextMember) ++ { ++ p_NextReplicAd = (t_AdOfTypeResult*)p_NextMember->p_MemberAd; ++ p_FmPcd = p_ReplicGroup->h_FmPcd; ++ offset = (XX_VirtToPhys(p_NextReplicAd) - (p_FmPcd->physicalMuramBase)); ++ offset = ((offset>>NEXT_FRM_REPLIC_ADDR_SHIFT)<< NEXT_FRM_REPLIC_MEMBER_INDEX_SHIFT); ++ } ++ ++ /* link the current AD to point to the AD of the next member */ ++ WRITE_UINT32(p_CurrReplicAd->res, offset); ++} ++ ++static t_Error ModifyDescriptor(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ void *p_OldDescriptor, ++ void *p_NewDescriptor) ++{ ++ t_Handle h_Hc; ++ t_Error err; ++ t_FmPcd *p_FmPcd; ++ ++ ASSERT_COND(p_ReplicGroup); ++ ASSERT_COND(p_ReplicGroup->h_FmPcd); ++ ASSERT_COND(p_OldDescriptor); ++ ASSERT_COND(p_NewDescriptor); ++ ++ p_FmPcd = p_ReplicGroup->h_FmPcd; ++ h_Hc = FmPcdGetHcHandle(p_FmPcd); ++ if (!h_Hc) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("Host command")); ++ ++ err = FmHcPcdCcDoDynamicChange(h_Hc, ++ (uint32_t)(XX_VirtToPhys(p_OldDescriptor) - p_FmPcd->physicalMuramBase), ++ (uint32_t)(XX_VirtToPhys(p_NewDescriptor) - p_FmPcd->physicalMuramBase)); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("Dynamic change host command")); ++ ++ return E_OK; ++} ++ ++static void FillReplicAdOfTypeResult(void *p_ReplicAd, bool last) ++{ ++ t_AdOfTypeResult *p_CurrReplicAd = (t_AdOfTypeResult*)p_ReplicAd; ++ uint32_t tmp; ++ ++ tmp = GET_UINT32(p_CurrReplicAd->plcrProfile); ++ if (last) ++ /* clear the NL bit in case it's the last member in the group*/ ++ WRITE_UINT32(p_CurrReplicAd->plcrProfile,(tmp & ~FRM_REPLIC_NL_BIT)); ++ else ++ /* set the NL bit in case it's not the last member in the group */ ++ WRITE_UINT32(p_CurrReplicAd->plcrProfile, (tmp |FRM_REPLIC_NL_BIT)); ++ ++ /* set FR bit in the action descriptor */ ++ tmp = GET_UINT32(p_CurrReplicAd->nia); ++ WRITE_UINT32(p_CurrReplicAd->nia, ++ (tmp | FRM_REPLIC_FR_BIT | FM_PCD_AD_RESULT_EXTENDED_MODE )); ++} ++ ++static void BuildSourceTd(void *p_Ad) ++{ ++ t_AdOfTypeContLookup *p_SourceTd; ++ ++ ASSERT_COND(p_Ad); ++ ++ p_SourceTd = (t_AdOfTypeContLookup *)p_Ad; ++ ++ IOMemSet32((uint8_t*)p_SourceTd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* initialize the source table descriptor */ ++ WRITE_UINT32(p_SourceTd->ccAdBase, FM_PCD_AD_CONT_LOOKUP_TYPE); ++ WRITE_UINT32(p_SourceTd->pcAndOffsets, FRM_REPLIC_SOURCE_TD_OPCODE); ++} ++ ++static t_Error BuildShadowAndModifyDescriptor(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ t_FmPcdFrmReplicMember *p_NextMember, ++ t_FmPcdFrmReplicMember *p_CurrentMember, ++ bool sourceDescriptor, ++ bool last) ++{ ++ t_FmPcd *p_FmPcd; ++ t_FmPcdFrmReplicMember shadowMember; ++ t_Error err; ++ ++ ASSERT_COND(p_ReplicGroup); ++ ASSERT_COND(p_ReplicGroup->h_FmPcd); ++ ++ p_FmPcd = p_ReplicGroup->h_FmPcd; ++ ASSERT_COND(p_FmPcd->p_CcShadow); ++ ++ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock)) ++ return ERROR_CODE(E_BUSY); ++ ++ if (sourceDescriptor) ++ { ++ BuildSourceTd(p_FmPcd->p_CcShadow); ++ LinkSourceToMember(p_ReplicGroup, p_FmPcd->p_CcShadow, p_NextMember); ++ ++ /* Modify the source table descriptor according to the prepared shadow descriptor */ ++ err = ModifyDescriptor(p_ReplicGroup, ++ p_ReplicGroup->p_SourceTd, ++ p_FmPcd->p_CcShadow/* new prepared source td */); ++ ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("Modify source Descriptor in BuildShadowAndModifyDescriptor")); ++ ++ } ++ else ++ { ++ IO2IOCpy32(p_FmPcd->p_CcShadow, ++ p_CurrentMember->p_MemberAd, ++ FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* update the last bit in the shadow ad */ ++ FillReplicAdOfTypeResult(p_FmPcd->p_CcShadow, last); ++ ++ shadowMember.p_MemberAd = p_FmPcd->p_CcShadow; ++ ++ /* update the next FR member index */ ++ LinkMemberToMember(p_ReplicGroup, &shadowMember, p_NextMember); ++ ++ /* Modify the next member according to the prepared shadow descriptor */ ++ err = ModifyDescriptor(p_ReplicGroup, ++ p_CurrentMember->p_MemberAd, ++ p_FmPcd->p_CcShadow); ++ ++ RELEASE_LOCK(p_FmPcd->shadowLock); ++ if (err) ++ RETURN_ERROR(MAJOR, err, ("Modify Descriptor in BuildShadowAndModifyDescriptor")); ++ } ++ ++ ++ return E_OK; ++} ++ ++static t_FmPcdFrmReplicMember* GetMemberByIndex(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ uint16_t memberIndex) ++{ ++ int i=0; ++ t_List *p_Pos; ++ t_FmPcdFrmReplicMember *p_Member = NULL; ++ ++ LIST_FOR_EACH(p_Pos, &p_ReplicGroup->membersList) ++ { ++ if (i == memberIndex) ++ { ++ p_Member = LIST_OBJECT(p_Pos, t_FmPcdFrmReplicMember, node); ++ return p_Member; ++ } ++ i++; ++ } ++ return p_Member; ++} ++ ++static t_Error AllocMember(t_FmPcdFrmReplicGroup *p_ReplicGroup) ++{ ++ t_FmPcdFrmReplicMember *p_CurrentMember; ++ t_Handle h_Muram; ++ ++ ASSERT_COND(p_ReplicGroup); ++ ++ h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd); ++ ASSERT_COND(h_Muram); ++ ++ /* Initialize an internal structure of a member to add to the available members list */ ++ p_CurrentMember = (t_FmPcdFrmReplicMember *)XX_Malloc(sizeof(t_FmPcdFrmReplicMember)); ++ if (!p_CurrentMember) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Frame replicator member")); ++ ++ memset(p_CurrentMember, 0 ,sizeof(t_FmPcdFrmReplicMember)); ++ ++ /* Allocate the member AD */ ++ p_CurrentMember->p_MemberAd = ++ (t_AdOfTypeResult*)FM_MURAM_AllocMem(h_Muram, ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_CurrentMember->p_MemberAd) ++ { ++ XX_Free(p_CurrentMember); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("member AD table")); ++ } ++ IOMemSet32((uint8_t*)p_CurrentMember->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ /* Add the new member to the available members list */ ++ LIST_AddToTail(&p_CurrentMember->node, &(p_ReplicGroup->availableMembersList)); ++ ++ return E_OK; ++} ++ ++static t_FmPcdFrmReplicMember* InitMember(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ t_FmPcdCcNextEngineParams *p_MemberParams, ++ bool last) ++{ ++ t_FmPcdFrmReplicMember *p_CurrentMember = NULL; ++ ++ ASSERT_COND(p_ReplicGroup); ++ ++ /* Get an available member from the internal members list */ ++ p_CurrentMember = GetAvailableMember(p_ReplicGroup); ++ if (!p_CurrentMember) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_FOUND, ("Available member")); ++ return NULL; ++ } ++ p_CurrentMember->h_Manip = NULL; ++ ++ /* clear the Ad of the new member */ ++ IOMemSet32((uint8_t*)p_CurrentMember->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ INIT_LIST(&p_CurrentMember->node); ++ ++ /* Initialize the Ad of the member */ ++ NextStepAd(p_CurrentMember->p_MemberAd, ++ NULL, ++ p_MemberParams, ++ p_ReplicGroup->h_FmPcd); ++ ++ /* save Manip handle (for free needs) */ ++ if (p_MemberParams->h_Manip) ++ p_CurrentMember->h_Manip = p_MemberParams->h_Manip; ++ ++ /* Initialize the relevant frame replicator fields in the AD */ ++ FillReplicAdOfTypeResult(p_CurrentMember->p_MemberAd, last); ++ ++ return p_CurrentMember; ++} ++ ++static void FreeMember(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ t_FmPcdFrmReplicMember *p_Member) ++{ ++ /* Note: Can't free the member AD just returns the member to the available ++ member list - therefore only memset the AD */ ++ ++ /* zero the AD */ ++ IOMemSet32(p_Member->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ ++ ++ /* return the member to the available members list */ ++ PutAvailableMember(p_ReplicGroup, p_Member); ++} ++ ++static t_Error RemoveMember(t_FmPcdFrmReplicGroup *p_ReplicGroup, ++ uint16_t memberIndex) ++{ ++ t_FmPcd *p_FmPcd = NULL; ++ t_FmPcdFrmReplicMember *p_CurrentMember = NULL, *p_PreviousMember = NULL, *p_NextMember = NULL; ++ t_Error err; ++ uint8_t memberPosition; ++ ++ p_FmPcd = p_ReplicGroup->h_FmPcd; ++ ASSERT_COND(p_FmPcd); ++ UNUSED(p_FmPcd); ++ ++ p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex); ++ ASSERT_COND(p_CurrentMember); ++ ++ /* determine the member position in the group */ ++ memberPosition = GetMemberPosition(p_ReplicGroup, ++ memberIndex, ++ FALSE/*remove operation*/); ++ ++ switch (memberPosition) ++ { ++ case FRM_REPLIC_FIRST_MEMBER_INDEX: ++ p_NextMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex+1)); ++ ASSERT_COND(p_NextMember); ++ ++ /* update the source td itself by using a host command */ ++ err = BuildShadowAndModifyDescriptor(p_ReplicGroup, ++ p_NextMember, ++ NULL, ++ TRUE/*sourceDescriptor*/, ++ FALSE/*last*/); ++ break; ++ ++ case FRM_REPLIC_MIDDLE_MEMBER_INDEX: ++ p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1)); ++ ASSERT_COND(p_PreviousMember); ++ ++ p_NextMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex+1)); ++ ASSERT_COND(p_NextMember); ++ ++ err = BuildShadowAndModifyDescriptor(p_ReplicGroup, ++ p_NextMember, ++ p_PreviousMember, ++ FALSE/*sourceDescriptor*/, ++ FALSE/*last*/); ++ ++ break; ++ ++ case FRM_REPLIC_LAST_MEMBER_INDEX: ++ p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1)); ++ ASSERT_COND(p_PreviousMember); ++ ++ err = BuildShadowAndModifyDescriptor(p_ReplicGroup, ++ NULL, ++ p_PreviousMember, ++ FALSE/*sourceDescriptor*/, ++ TRUE/*last*/); ++ break; ++ ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member position in remove member")); ++ } ++ ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (p_CurrentMember->h_Manip) ++ { ++ FmPcdManipUpdateOwner(p_CurrentMember->h_Manip, FALSE); ++ p_CurrentMember->h_Manip = NULL; ++ } ++ ++ /* remove the member from the driver internal members list */ ++ RemoveMemberFromList(p_ReplicGroup, p_CurrentMember); ++ ++ /* return the member to the available members list */ ++ FreeMember(p_ReplicGroup, p_CurrentMember); ++ ++ return E_OK; ++} ++ ++static void DeleteGroup(t_FmPcdFrmReplicGroup *p_ReplicGroup) ++{ ++ int i, j; ++ t_Handle h_Muram; ++ t_FmPcdFrmReplicMember *p_Member, *p_CurrentMember; ++ ++ if (p_ReplicGroup) ++ { ++ ASSERT_COND(p_ReplicGroup->h_FmPcd); ++ h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd); ++ ASSERT_COND(h_Muram); ++ ++ /* free the source table descriptor */ ++ if (p_ReplicGroup->p_SourceTd) ++ { ++ FM_MURAM_FreeMem(h_Muram, p_ReplicGroup->p_SourceTd); ++ p_ReplicGroup->p_SourceTd = NULL; ++ } ++ ++ /* Remove all members from the members linked list (hw and sw) and ++ return the members to the available members list */ ++ if (p_ReplicGroup->numOfEntries) ++ { ++ j = p_ReplicGroup->numOfEntries-1; ++ ++ /* manually removal of the member because there are no owners of ++ this group */ ++ for (i=j; i>=0; i--) ++ { ++ p_CurrentMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)i/*memberIndex*/); ++ ASSERT_COND(p_CurrentMember); ++ ++ if (p_CurrentMember->h_Manip) ++ { ++ FmPcdManipUpdateOwner(p_CurrentMember->h_Manip, FALSE); ++ p_CurrentMember->h_Manip = NULL; ++ } ++ ++ /* remove the member from the internal driver members list */ ++ RemoveMemberFromList(p_ReplicGroup, p_CurrentMember); ++ ++ /* return the member to the available members list */ ++ FreeMember(p_ReplicGroup, p_CurrentMember); ++ } ++ } ++ ++ /* Free members AD */ ++ for (i=0; imaxNumOfEntries; i++) ++ { ++ p_Member = GetAvailableMember(p_ReplicGroup); ++ ASSERT_COND(p_Member); ++ if (p_Member->p_MemberAd) ++ { ++ FM_MURAM_FreeMem(h_Muram, p_Member->p_MemberAd); ++ p_Member->p_MemberAd = NULL; ++ } ++ XX_Free(p_Member); ++ } ++ ++ /* release the group lock */ ++ if (p_ReplicGroup->p_Lock) ++ FmPcdReleaseLock(p_ReplicGroup->h_FmPcd, p_ReplicGroup->p_Lock); ++ ++ /* free the replicator group */ ++ XX_Free(p_ReplicGroup); ++ } ++} ++ ++ ++/*****************************************************************************/ ++/* Inter-module API routines */ ++/*****************************************************************************/ ++ ++/* NOTE: the inter-module routines are locked by cc in case of using them */ ++void * FrmReplicGroupGetSourceTableDescriptor(t_Handle h_ReplicGroup) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup; ++ ASSERT_COND(p_ReplicGroup); ++ ++ return (p_ReplicGroup->p_SourceTd); ++} ++ ++void FrmReplicGroupUpdateAd(t_Handle h_ReplicGroup, ++ void *p_Ad, ++ t_Handle *h_AdNew) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup; ++ t_AdOfTypeResult *p_AdResult = (t_AdOfTypeResult*)p_Ad; ++ t_FmPcd *p_FmPcd; ++ ++ ASSERT_COND(p_ReplicGroup); ++ p_FmPcd = p_ReplicGroup->h_FmPcd; ++ ++ /* build a bypass ad */ ++ WRITE_UINT32(p_AdResult->fqid, FM_PCD_AD_BYPASS_TYPE | ++ (uint32_t)((XX_VirtToPhys(p_ReplicGroup->p_SourceTd)) - p_FmPcd->physicalMuramBase)); ++ ++ *h_AdNew = NULL; ++} ++ ++void FrmReplicGroupUpdateOwner(t_Handle h_ReplicGroup, ++ bool add) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup; ++ ASSERT_COND(p_ReplicGroup); ++ ++ /* update the group owner counter */ ++ if (add) ++ p_ReplicGroup->owners++; ++ else ++ { ++ ASSERT_COND(p_ReplicGroup->owners); ++ p_ReplicGroup->owners--; ++ } ++} ++ ++t_Error FrmReplicGroupTryLock(t_Handle h_ReplicGroup) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup; ++ ++ ASSERT_COND(h_ReplicGroup); ++ ++ if (FmPcdLockTryLock(p_ReplicGroup->p_Lock)) ++ return E_OK; ++ ++ return ERROR_CODE(E_BUSY); ++} ++ ++void FrmReplicGroupUnlock(t_Handle h_ReplicGroup) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup; ++ ++ ASSERT_COND(h_ReplicGroup); ++ ++ FmPcdLockUnlock(p_ReplicGroup->p_Lock); ++} ++/*********************** End of inter-module routines ************************/ ++ ++ ++/****************************************/ ++/* API Init unit functions */ ++/****************************************/ ++t_Handle FM_PCD_FrmReplicSetGroup(t_Handle h_FmPcd, ++ t_FmPcdFrmReplicGroupParams *p_ReplicGroupParam) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup; ++ t_FmPcdFrmReplicMember *p_CurrentMember, *p_NextMember = NULL; ++ int i; ++ t_Error err; ++ bool last = FALSE; ++ t_Handle h_Muram; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_ReplicGroupParam, E_INVALID_HANDLE, NULL); ++ ++ if (!FmPcdIsAdvancedOffloadSupported(h_FmPcd)) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Advanced-offload must be enabled")); ++ return NULL; ++ } ++ ++ err = CheckParams(h_FmPcd, p_ReplicGroupParam); ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, err, (NO_MSG)); ++ return NULL; ++ } ++ ++ p_ReplicGroup = (t_FmPcdFrmReplicGroup*)XX_Malloc(sizeof(t_FmPcdFrmReplicGroup)); ++ if (!p_ReplicGroup) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory")); ++ return NULL; ++ } ++ memset(p_ReplicGroup, 0, sizeof(t_FmPcdFrmReplicGroup)); ++ ++ /* initialize lists for internal driver use */ ++ INIT_LIST(&p_ReplicGroup->availableMembersList); ++ INIT_LIST(&p_ReplicGroup->membersList); ++ ++ p_ReplicGroup->h_FmPcd = h_FmPcd; ++ ++ h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd); ++ ASSERT_COND(h_Muram); ++ ++ /* initialize the group lock */ ++ p_ReplicGroup->p_Lock = FmPcdAcquireLock(p_ReplicGroup->h_FmPcd); ++ if (!p_ReplicGroup->p_Lock) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Replic group lock")); ++ DeleteGroup(p_ReplicGroup); ++ return NULL; ++ } ++ ++ /* Allocate the frame replicator source table descriptor */ ++ p_ReplicGroup->p_SourceTd = ++ (t_Handle)FM_MURAM_AllocMem(h_Muram, ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (!p_ReplicGroup->p_SourceTd) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("frame replicator source table descriptor")); ++ DeleteGroup(p_ReplicGroup); ++ return NULL; ++ } ++ ++ /* update the shadow size - required for the host commands */ ++ err = FmPcdUpdateCcShadow(p_ReplicGroup->h_FmPcd, ++ FM_PCD_CC_AD_ENTRY_SIZE, ++ FM_PCD_CC_AD_TABLE_ALIGN); ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, err, ("Update CC shadow")); ++ DeleteGroup(p_ReplicGroup); ++ return NULL; ++ } ++ ++ p_ReplicGroup->maxNumOfEntries = p_ReplicGroupParam->maxNumOfEntries; ++ ++ /* Allocate the maximal number of members ADs and Statistics AD for the group ++ It prevents allocation of Muram in run-time */ ++ for (i=0; imaxNumOfEntries; i++) ++ { ++ err = AllocMember(p_ReplicGroup); ++ if (err) ++ { ++ REPORT_ERROR(MAJOR, err, ("allocate a new member")); ++ DeleteGroup(p_ReplicGroup); ++ return NULL; ++ } ++ } ++ ++ /* Initialize the members linked lists: ++ (hw - the one that is used by the FMan controller and ++ sw - the one that is managed by the driver internally) */ ++ for (i=(p_ReplicGroupParam->numOfEntries-1); i>=0; i--) ++ { ++ /* check if this is the last member in the group */ ++ if (i == (p_ReplicGroupParam->numOfEntries-1)) ++ last = TRUE; ++ else ++ last = FALSE; ++ ++ /* Initialize a new member */ ++ p_CurrentMember = InitMember(p_ReplicGroup, ++ &(p_ReplicGroupParam->nextEngineParams[i]), ++ last); ++ if (!p_CurrentMember) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("No available member")); ++ DeleteGroup(p_ReplicGroup); ++ return NULL; ++ } ++ ++ /* Build the members group - link two consecutive members in the hw linked list */ ++ LinkMemberToMember(p_ReplicGroup, p_CurrentMember, p_NextMember); ++ ++ /* update the driver internal members list to be compatible to the hw members linked list */ ++ AddMemberToList(p_ReplicGroup, p_CurrentMember, &p_ReplicGroup->membersList); ++ ++ p_NextMember = p_CurrentMember; ++ } ++ ++ /* initialize the source table descriptor */ ++ BuildSourceTd(p_ReplicGroup->p_SourceTd); ++ ++ /* link the source table descriptor to point to the first member in the group */ ++ LinkSourceToMember(p_ReplicGroup, p_ReplicGroup->p_SourceTd, p_NextMember); ++ ++ return p_ReplicGroup; ++} ++ ++t_Error FM_PCD_FrmReplicDeleteGroup(t_Handle h_ReplicGroup) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup; ++ ++ SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE); ++ ++ if (p_ReplicGroup->owners) ++ RETURN_ERROR(MAJOR, ++ E_INVALID_STATE, ++ ("the group has owners and can't be deleted")); ++ ++ DeleteGroup(p_ReplicGroup); ++ ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* API Run-time Frame replicator Control unit functions */ ++/*****************************************************************************/ ++t_Error FM_PCD_FrmReplicAddMember(t_Handle h_ReplicGroup, ++ uint16_t memberIndex, ++ t_FmPcdCcNextEngineParams *p_MemberParams) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup*) h_ReplicGroup; ++ t_FmPcdFrmReplicMember *p_NewMember, *p_CurrentMember = NULL, *p_PreviousMember = NULL; ++ t_Error err; ++ uint8_t memberPosition; ++ ++ SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_MemberParams, E_INVALID_HANDLE); ++ ++ /* group lock */ ++ err = FrmReplicGroupTryLock(p_ReplicGroup); ++ if (GET_ERROR_TYPE(err) == E_BUSY) ++ return ERROR_CODE(E_BUSY); ++ ++ if (memberIndex > p_ReplicGroup->numOfEntries) ++ { ++ /* unlock */ ++ FrmReplicGroupUnlock(p_ReplicGroup); ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ++ ("memberIndex is greater than the members in the list")); ++ } ++ ++ if (memberIndex >= p_ReplicGroup->maxNumOfEntries) ++ { ++ /* unlock */ ++ FrmReplicGroupUnlock(p_ReplicGroup); ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("memberIndex is greater than the allowed number of members in the group")); ++ } ++ ++ if ((p_ReplicGroup->numOfEntries + 1) > FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES) ++ { ++ /* unlock */ ++ FrmReplicGroupUnlock(p_ReplicGroup); ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("numOfEntries with new entry can not be larger than %d\n", ++ FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES)); ++ } ++ ++ err = MemberCheckParams(p_ReplicGroup->h_FmPcd, p_MemberParams); ++ if (err) ++ { ++ /* unlock */ ++ FrmReplicGroupUnlock(p_ReplicGroup); ++ RETURN_ERROR(MAJOR, err, ("member check parameters in add operation")); ++ } ++ /* determine the member position in the group */ ++ memberPosition = GetMemberPosition(p_ReplicGroup, ++ memberIndex, ++ TRUE/* add operation */); ++ ++ /* Initialize a new member */ ++ p_NewMember = InitMember(p_ReplicGroup, ++ p_MemberParams, ++ (memberPosition == FRM_REPLIC_LAST_MEMBER_INDEX ? TRUE : FALSE)); ++ if (!p_NewMember) ++ { ++ /* unlock */ ++ FrmReplicGroupUnlock(p_ReplicGroup); ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("No available member")); ++ } ++ ++ switch (memberPosition) ++ { ++ case FRM_REPLIC_FIRST_MEMBER_INDEX: ++ p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex); ++ ASSERT_COND(p_CurrentMember); ++ ++ LinkMemberToMember(p_ReplicGroup, p_NewMember, p_CurrentMember); ++ ++ /* update the internal group source TD */ ++ LinkSourceToMember(p_ReplicGroup, ++ p_ReplicGroup->p_SourceTd, ++ p_NewMember); ++ ++ /* add member to the internal sw member list */ ++ AddMemberToList(p_ReplicGroup, ++ p_NewMember, ++ &p_ReplicGroup->membersList); ++ break; ++ ++ case FRM_REPLIC_MIDDLE_MEMBER_INDEX: ++ p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex); ++ ASSERT_COND(p_CurrentMember); ++ ++ p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1)); ++ ASSERT_COND(p_PreviousMember); ++ ++ LinkMemberToMember(p_ReplicGroup, p_NewMember, p_CurrentMember); ++ LinkMemberToMember(p_ReplicGroup, p_PreviousMember, p_NewMember); ++ ++ AddMemberToList(p_ReplicGroup, p_NewMember, &p_PreviousMember->node); ++ break; ++ ++ case FRM_REPLIC_LAST_MEMBER_INDEX: ++ p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1)); ++ ASSERT_COND(p_PreviousMember); ++ ++ LinkMemberToMember(p_ReplicGroup, p_PreviousMember, p_NewMember); ++ FillReplicAdOfTypeResult(p_PreviousMember->p_MemberAd, FALSE/*last*/); ++ ++ /* add the new member to the internal sw member list */ ++ AddMemberToList(p_ReplicGroup, p_NewMember, &p_PreviousMember->node); ++ break; ++ ++ default: ++ /* unlock */ ++ FrmReplicGroupUnlock(p_ReplicGroup); ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member position in add member")); ++ ++ } ++ ++ /* unlock */ ++ FrmReplicGroupUnlock(p_ReplicGroup); ++ ++ return E_OK; ++} ++ ++t_Error FM_PCD_FrmReplicRemoveMember(t_Handle h_ReplicGroup, ++ uint16_t memberIndex) ++{ ++ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup*) h_ReplicGroup; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE); ++ ++ /* lock */ ++ err = FrmReplicGroupTryLock(p_ReplicGroup); ++ if (GET_ERROR_TYPE(err) == E_BUSY) ++ return ERROR_CODE(E_BUSY); ++ ++ if (memberIndex >= p_ReplicGroup->numOfEntries) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member index to remove")); ++ ++ /* Design decision: group must contain at least one member ++ No possibility to remove the last member from the group */ ++ if (p_ReplicGroup->numOfEntries == 1) ++ RETURN_ERROR(MAJOR, E_CONFLICT, ("Can't remove the last member. At least one member should be related to a group.")); ++ ++ err = RemoveMember(p_ReplicGroup, memberIndex); ++ ++ /* unlock */ ++ FrmReplicGroupUnlock(p_ReplicGroup); ++ ++ switch (GET_ERROR_TYPE(err)) ++ { ++ case E_OK: ++ return E_OK; ++ ++ case E_BUSY: ++ DBG(TRACE, ("E_BUSY error")); ++ return ERROR_CODE(E_BUSY); ++ ++ default: ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++} ++ ++/*********************** End of API routines ************************/ ++ ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_replic.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_replic.h +new file mode 100644 +index 0000000..0e8e8bc +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_replic.h +@@ -0,0 +1,101 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_replic.h ++ ++ @Description FM frame replicator ++*//***************************************************************************/ ++#ifndef __FM_REPLIC_H ++#define __FM_REPLIC_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++ ++ ++#define FRM_REPLIC_SOURCE_TD_OPCODE 0x75 ++#define NEXT_FRM_REPLIC_ADDR_SHIFT 4 ++#define NEXT_FRM_REPLIC_MEMBER_INDEX_SHIFT 16 ++#define FRM_REPLIC_FR_BIT 0x08000000 ++#define FRM_REPLIC_NL_BIT 0x10000000 ++#define FRM_REPLIC_INVALID_MEMBER_INDEX 0xffff ++#define FRM_REPLIC_FIRST_MEMBER_INDEX 0 ++ ++#define FRM_REPLIC_MIDDLE_MEMBER_INDEX 1 ++#define FRM_REPLIC_LAST_MEMBER_INDEX 2 ++ ++#define SOURCE_TD_ITSELF_OPTION 0x01 ++#define SOURCE_TD_COPY_OPTION 0x02 ++#define SOURCE_TD_ITSELF_AND_COPY_OPTION SOURCE_TD_ITSELF_OPTION | SOURCE_TD_COPY_OPTION ++#define SOURCE_TD_NONE 0x04 ++ ++/*typedef enum e_SourceTdOption ++{ ++ e_SOURCE_TD_NONE = 0, ++ e_SOURCE_TD_ITSELF_OPTION = 1, ++ e_SOURCE_TD_COPY_OPTION = 2, ++ e_SOURCE_TD_ITSELF_AND_COPY_OPTION = e_SOURCE_TD_ITSELF_OPTION | e_SOURCE_TD_COPY_OPTION ++} e_SourceTdOption; ++*/ ++ ++typedef struct ++{ ++ volatile uint32_t type; ++ volatile uint32_t frGroupPointer; ++ volatile uint32_t operationCode; ++ volatile uint32_t reserved; ++} t_FrmReplicGroupSourceAd; ++ ++typedef struct t_FmPcdFrmReplicMember ++{ ++ void *p_MemberAd; /**< pointer to the member AD */ ++ void *p_StatisticsAd;/**< pointer to the statistics AD of the member */ ++ t_Handle h_Manip; /**< manip handle - need for free routines */ ++ t_List node; ++} t_FmPcdFrmReplicMember; ++ ++typedef struct t_FmPcdFrmReplicGroup ++{ ++ t_Handle h_FmPcd; ++ ++ uint8_t maxNumOfEntries;/**< maximal number of members in the group */ ++ uint8_t numOfEntries; /**< actual number of members in the group */ ++ uint16_t owners; /**< how many keys share this frame replicator group */ ++ void *p_SourceTd; /**< pointer to the frame replicator source table descriptor */ ++ t_List membersList; /**< the members list - should reflect the order of the members as in the hw linked list*/ ++ t_List availableMembersList;/**< list of all the available members in the group */ ++ t_FmPcdLock *p_Lock; ++} t_FmPcdFrmReplicGroup; ++ ++ ++#endif /* __FM_REPLIC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fman_kg.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fman_kg.c +new file mode 100644 +index 0000000..49b86e8 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fman_kg.c +@@ -0,0 +1,888 @@ ++/* ++ * Copyright 2008-2012 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 "fsl_fman_kg.h" ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++ ++ ++static uint32_t build_ar_bind_scheme(uint8_t hwport_id, bool write) ++{ ++ uint32_t rw; ++ ++ rw = write ? (uint32_t)FM_KG_KGAR_WRITE : (uint32_t)FM_KG_KGAR_READ; ++ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ rw | ++ FM_PCD_KG_KGAR_SEL_PORT_ENTRY | ++ hwport_id | ++ FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP); ++} ++ ++static void clear_pe_all_scheme(struct fman_kg_regs *regs, uint8_t hwport_id) ++{ ++ uint32_t ar; ++ ++ fman_kg_write_sp(regs, 0xffffffff, 0); ++ ++ ar = build_ar_bind_scheme(hwport_id, TRUE); ++ fman_kg_write_ar_wait(regs, ar); ++} ++ ++static uint32_t build_ar_bind_cls_plan(uint8_t hwport_id, bool write) ++{ ++ uint32_t rw; ++ ++ rw = write ? (uint32_t)FM_KG_KGAR_WRITE : (uint32_t)FM_KG_KGAR_READ; ++ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ rw | ++ FM_PCD_KG_KGAR_SEL_PORT_ENTRY | ++ hwport_id | ++ FM_PCD_KG_KGAR_SEL_PORT_WSEL_CPP); ++} ++ ++static void clear_pe_all_cls_plan(struct fman_kg_regs *regs, uint8_t hwport_id) ++{ ++ uint32_t ar; ++ ++ fman_kg_write_cpp(regs, 0); ++ ++ ar = build_ar_bind_cls_plan(hwport_id, TRUE); ++ fman_kg_write_ar_wait(regs, ar); ++} ++ ++static uint8_t get_gen_ht_code(enum fman_kg_gen_extract_src src, ++ bool no_validation, ++ uint8_t *offset) ++{ ++ int code; ++ ++ switch (src) { ++ case E_FMAN_KG_GEN_EXTRACT_ETH: ++ code = no_validation ? 0x73 : 0x3; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_ETYPE: ++ code = no_validation ? 0x77 : 0x7; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_SNAP: ++ code = no_validation ? 0x74 : 0x4; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_1: ++ code = no_validation ? 0x75 : 0x5; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_N: ++ code = no_validation ? 0x76 : 0x6; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_PPPoE: ++ code = no_validation ? 0x78 : 0x8; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_MPLS_1: ++ code = no_validation ? 0x79 : 0x9; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_MPLS_2: ++ code = no_validation ? FM_KG_SCH_GEN_HT_INVALID : 0x19; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_MPLS_3: ++ code = no_validation ? FM_KG_SCH_GEN_HT_INVALID : 0x29; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_MPLS_N: ++ code = no_validation ? 0x7a : 0xa; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_IPv4_1: ++ code = no_validation ? 0x7b : 0xb; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_IPv6_1: ++ code = no_validation ? 0x7b : 0x1b; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_IPv4_2: ++ code = no_validation ? 0x7c : 0xc; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_IPv6_2: ++ code = no_validation ? 0x7c : 0x1c; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_MINENCAP: ++ code = no_validation ? 0x7c : 0x2c; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_IP_PID: ++ code = no_validation ? 0x72 : 0x2; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_GRE: ++ code = no_validation ? 0x7d : 0xd; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_TCP: ++ code = no_validation ? 0x7e : 0xe; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_UDP: ++ code = no_validation ? 0x7e : 0x1e; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_SCTP: ++ code = no_validation ? 0x7e : 0x3e; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_DCCP: ++ code = no_validation ? 0x7e : 0x4e; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_IPSEC_AH: ++ code = no_validation ? 0x7e : 0x2e; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_IPSEC_ESP: ++ code = no_validation ? 0x7e : 0x6e; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_SHIM_1: ++ code = 0x70; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_SHIM_2: ++ code = 0x71; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_FROM_DFLT: ++ code = 0x10; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_FROM_FRAME_START: ++ code = 0x40; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_FROM_PARSE_RESULT: ++ code = 0x20; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_FROM_END_OF_PARSE: ++ code = 0x7f; ++ break; ++ ++ case E_FMAN_KG_GEN_EXTRACT_FROM_FQID: ++ code = 0x20; ++ *offset += 0x20; ++ break; ++ ++ default: ++ code = FM_KG_SCH_GEN_HT_INVALID; ++ } ++ ++ return (uint8_t)code; ++} ++ ++static uint32_t build_ar_scheme(uint8_t scheme, ++ uint8_t hwport_id, ++ bool update_counter, ++ bool write) ++{ ++ uint32_t rw; ++ ++ rw = (uint32_t)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ); ++ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ rw | ++ FM_KG_KGAR_SEL_SCHEME_ENTRY | ++ hwport_id | ++ ((uint32_t)scheme << FM_KG_KGAR_NUM_SHIFT) | ++ (update_counter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT : 0)); ++} ++ ++static uint32_t build_ar_cls_plan(uint8_t grp, ++ uint8_t entries_mask, ++ uint8_t hwport_id, ++ bool write) ++{ ++ uint32_t rw; ++ ++ rw = (uint32_t)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ); ++ ++ return (uint32_t)(FM_KG_KGAR_GO | ++ rw | ++ FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY | ++ hwport_id | ++ ((uint32_t)grp << FM_KG_KGAR_NUM_SHIFT) | ++ ((uint32_t)entries_mask << FM_KG_KGAR_WSEL_SHIFT)); ++} ++ ++int fman_kg_write_ar_wait(struct fman_kg_regs *regs, uint32_t fmkg_ar) ++{ ++ iowrite32be(fmkg_ar, ®s->fmkg_ar); ++ /* Wait for GO to be idle and read error */ ++ while ((fmkg_ar = ioread32be(®s->fmkg_ar)) & FM_KG_KGAR_GO) ; ++ if (fmkg_ar & FM_PCD_KG_KGAR_ERR) ++ return -EINVAL; ++ return 0; ++} ++ ++void fman_kg_write_sp(struct fman_kg_regs *regs, uint32_t sp, bool add) ++{ ++ ++ struct fman_kg_pe_regs *kgpe_regs; ++ uint32_t tmp; ++ ++ kgpe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]); ++ tmp = ioread32be(&kgpe_regs->fmkg_pe_sp); ++ ++ if (add) ++ tmp |= sp; ++ else /* clear */ ++ tmp &= ~sp; ++ ++ iowrite32be(tmp, &kgpe_regs->fmkg_pe_sp); ++ ++} ++ ++void fman_kg_write_cpp(struct fman_kg_regs *regs, uint32_t cpp) ++{ ++ struct fman_kg_pe_regs *kgpe_regs; ++ ++ kgpe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]); ++ ++ iowrite32be(cpp, &kgpe_regs->fmkg_pe_cpp); ++} ++ ++void fman_kg_get_event(struct fman_kg_regs *regs, ++ uint32_t *event, ++ uint32_t *scheme_idx) ++{ ++ uint32_t mask, force; ++ ++ *event = ioread32be(®s->fmkg_eer); ++ mask = ioread32be(®s->fmkg_eeer); ++ *scheme_idx = ioread32be(®s->fmkg_seer); ++ *scheme_idx &= ioread32be(®s->fmkg_seeer); ++ ++ *event &= mask; ++ ++ /* clear the forced events */ ++ force = ioread32be(®s->fmkg_feer); ++ if (force & *event) ++ iowrite32be(force & ~*event ,®s->fmkg_feer); ++ ++ iowrite32be(*event, ®s->fmkg_eer); ++ iowrite32be(*scheme_idx, ®s->fmkg_seer); ++} ++ ++ ++void fman_kg_init(struct fman_kg_regs *regs, ++ uint32_t exceptions, ++ uint32_t dflt_nia) ++{ ++ uint32_t tmp; ++ int i; ++ ++ iowrite32be(FM_EX_KG_DOUBLE_ECC | FM_EX_KG_KEYSIZE_OVERFLOW, ++ ®s->fmkg_eer); ++ ++ tmp = 0; ++ if (exceptions & FM_EX_KG_DOUBLE_ECC) ++ tmp |= FM_EX_KG_DOUBLE_ECC; ++ ++ if (exceptions & FM_EX_KG_KEYSIZE_OVERFLOW) ++ tmp |= FM_EX_KG_KEYSIZE_OVERFLOW; ++ ++ iowrite32be(tmp, ®s->fmkg_eeer); ++ iowrite32be(0, ®s->fmkg_fdor); ++ iowrite32be(0, ®s->fmkg_gdv0r); ++ iowrite32be(0, ®s->fmkg_gdv1r); ++ iowrite32be(dflt_nia, ®s->fmkg_gcr); ++ ++ /* Clear binding between ports to schemes and classification plans ++ * so that all ports are not bound to any scheme/classification plan */ ++ for (i = 0; i < FMAN_MAX_NUM_OF_HW_PORTS; i++) { ++ clear_pe_all_scheme(regs, (uint8_t)i); ++ clear_pe_all_cls_plan(regs, (uint8_t)i); ++ } ++} ++ ++void fman_kg_enable_scheme_interrupts(struct fman_kg_regs *regs) ++{ ++ /* enable and enable all scheme interrupts */ ++ iowrite32be(0xFFFFFFFF, ®s->fmkg_seer); ++ iowrite32be(0xFFFFFFFF, ®s->fmkg_seeer); ++} ++ ++void fman_kg_enable(struct fman_kg_regs *regs) ++{ ++ iowrite32be(ioread32be(®s->fmkg_gcr) | FM_KG_KGGCR_EN, ++ ®s->fmkg_gcr); ++} ++ ++void fman_kg_disable(struct fman_kg_regs *regs) ++{ ++ iowrite32be(ioread32be(®s->fmkg_gcr) & ~FM_KG_KGGCR_EN, ++ ®s->fmkg_gcr); ++} ++ ++void fman_kg_set_data_after_prs(struct fman_kg_regs *regs, uint8_t offset) ++{ ++ iowrite32be(offset, ®s->fmkg_fdor); ++} ++ ++void fman_kg_set_dflt_val(struct fman_kg_regs *regs, ++ uint8_t def_id, ++ uint32_t val) ++{ ++ if(def_id == 0) ++ iowrite32be(val, ®s->fmkg_gdv0r); ++ else ++ iowrite32be(val, ®s->fmkg_gdv1r); ++} ++ ++ ++void fman_kg_set_exception(struct fman_kg_regs *regs, ++ uint32_t exception, ++ bool enable) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->fmkg_eeer); ++ ++ if (enable) { ++ tmp |= exception; ++ } else { ++ tmp &= ~exception; ++ } ++ ++ iowrite32be(tmp, ®s->fmkg_eeer); ++} ++ ++void fman_kg_get_exception(struct fman_kg_regs *regs, ++ uint32_t *events, ++ uint32_t *scheme_ids, ++ bool clear) ++{ ++ uint32_t mask; ++ ++ *events = ioread32be(®s->fmkg_eer); ++ mask = ioread32be(®s->fmkg_eeer); ++ *events &= mask; ++ ++ *scheme_ids = 0; ++ ++ if (*events & FM_EX_KG_KEYSIZE_OVERFLOW) { ++ *scheme_ids = ioread32be(®s->fmkg_seer); ++ mask = ioread32be(®s->fmkg_seeer); ++ *scheme_ids &= mask; ++ } ++ ++ if (clear) { ++ iowrite32be(*scheme_ids, ®s->fmkg_seer); ++ iowrite32be(*events, ®s->fmkg_eer); ++ } ++} ++ ++void fman_kg_get_capture(struct fman_kg_regs *regs, ++ struct fman_kg_ex_ecc_attr *ecc_attr, ++ bool clear) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->fmkg_serc); ++ ++ if (tmp & KG_FMKG_SERC_CAP) { ++ /* Captured data is valid */ ++ ecc_attr->valid = TRUE; ++ ecc_attr->double_ecc = ++ (bool)((tmp & KG_FMKG_SERC_CET) ? TRUE : FALSE); ++ ecc_attr->single_ecc_count = ++ (uint8_t)((tmp & KG_FMKG_SERC_CNT_MSK) >> ++ KG_FMKG_SERC_CNT_SHIFT); ++ ecc_attr->addr = (uint16_t)(tmp & KG_FMKG_SERC_ADDR_MSK); ++ ++ if (clear) ++ iowrite32be(KG_FMKG_SERC_CAP, ®s->fmkg_serc); ++ } else { ++ /* No ECC error is captured */ ++ ecc_attr->valid = FALSE; ++ } ++} ++ ++int fman_kg_build_scheme(struct fman_kg_scheme_params *params, ++ struct fman_kg_scheme_regs *scheme_regs) ++{ ++ struct fman_kg_extract_params *extract_params; ++ struct fman_kg_gen_extract_params *gen_params; ++ uint32_t tmp_reg, i, select, mask, fqb; ++ uint8_t offset, shift, ht; ++ ++ /* Zero out all registers so no need to care about unused ones */ ++ memset(scheme_regs, 0, sizeof(struct fman_kg_scheme_regs)); ++ ++ /* Mode register */ ++ tmp_reg = fm_kg_build_nia(params->next_engine, ++ params->next_engine_action); ++ if (tmp_reg == KG_NIA_INVALID) { ++ return -EINVAL; ++ } ++ ++ if (params->next_engine == E_FMAN_PCD_PLCR) { ++ tmp_reg |= FMAN_KG_SCH_MODE_NIA_PLCR; ++ } ++ else if (params->next_engine == E_FMAN_PCD_CC) { ++ tmp_reg |= (uint32_t)params->cc_params.base_offset << ++ FMAN_KG_SCH_MODE_CCOBASE_SHIFT; ++ } ++ ++ tmp_reg |= FMAN_KG_SCH_MODE_EN; ++ scheme_regs->kgse_mode = tmp_reg; ++ ++ /* Match vector */ ++ scheme_regs->kgse_mv = params->match_vector; ++ ++ extract_params = ¶ms->extract_params; ++ ++ /* Scheme default values registers */ ++ scheme_regs->kgse_dv0 = extract_params->def_scheme_0; ++ scheme_regs->kgse_dv1 = extract_params->def_scheme_1; ++ ++ /* Extract Known Fields Command register */ ++ scheme_regs->kgse_ekfc = extract_params->known_fields; ++ ++ /* Entry Extract Known Default Value register */ ++ tmp_reg = 0; ++ tmp_reg |= extract_params->known_fields_def.mac_addr << ++ FMAN_KG_SCH_DEF_MAC_ADDR_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.vlan_tci << ++ FMAN_KG_SCH_DEF_VLAN_TCI_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.etype << ++ FMAN_KG_SCH_DEF_ETYPE_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.ppp_sid << ++ FMAN_KG_SCH_DEF_PPP_SID_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.ppp_pid << ++ FMAN_KG_SCH_DEF_PPP_PID_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.mpls << ++ FMAN_KG_SCH_DEF_MPLS_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.ip_addr << ++ FMAN_KG_SCH_DEF_IP_ADDR_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.ptype << ++ FMAN_KG_SCH_DEF_PTYPE_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.ip_tos_tc << ++ FMAN_KG_SCH_DEF_IP_TOS_TC_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.ipv6_fl << ++ FMAN_KG_SCH_DEF_IPv6_FL_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.ipsec_spi << ++ FMAN_KG_SCH_DEF_IPSEC_SPI_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.l4_port << ++ FMAN_KG_SCH_DEF_L4_PORT_SHIFT; ++ tmp_reg |= extract_params->known_fields_def.tcp_flg << ++ FMAN_KG_SCH_DEF_TCP_FLG_SHIFT; ++ ++ scheme_regs->kgse_ekdv = tmp_reg; ++ ++ /* Generic extract registers */ ++ if (extract_params->gen_extract_num > FM_KG_NUM_OF_GENERIC_REGS) { ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < extract_params->gen_extract_num; i++) { ++ gen_params = extract_params->gen_extract + i; ++ ++ tmp_reg = FMAN_KG_SCH_GEN_VALID; ++ tmp_reg |= (uint32_t)gen_params->def_val << ++ FMAN_KG_SCH_GEN_DEF_SHIFT; ++ ++ if (gen_params->type == E_FMAN_KG_HASH_EXTRACT) { ++ if ((gen_params->extract > FMAN_KG_SCH_GEN_SIZE_MAX) || ++ (gen_params->extract == 0)) { ++ return -EINVAL; ++ } ++ } else { ++ tmp_reg |= FMAN_KG_SCH_GEN_OR; ++ } ++ ++ tmp_reg |= (uint32_t)gen_params->extract << ++ FMAN_KG_SCH_GEN_SIZE_SHIFT; ++ tmp_reg |= (uint32_t)gen_params->mask << ++ FMAN_KG_SCH_GEN_MASK_SHIFT; ++ ++ offset = gen_params->offset; ++ ht = get_gen_ht_code(gen_params->src, ++ gen_params->no_validation, ++ &offset); ++ tmp_reg |= (uint32_t)ht << FMAN_KG_SCH_GEN_HT_SHIFT; ++ tmp_reg |= offset; ++ ++ scheme_regs->kgse_gec[i] = tmp_reg; ++ } ++ ++ /* Masks registers */ ++ if (extract_params->masks_num > FM_KG_EXTRACT_MASKS_NUM) { ++ return -EINVAL; ++ } ++ ++ select = 0; ++ mask = 0; ++ fqb = 0; ++ for (i = 0; i < extract_params->masks_num; i++) { ++ /* MCSx fields */ ++ KG_GET_MASK_SEL_SHIFT(shift, i); ++ if (extract_params->masks[i].is_known) { ++ /* Mask known field */ ++ select |= extract_params->masks[i].field_or_gen_idx << ++ shift; ++ } else { ++ /* Mask generic extract */ ++ select |= (extract_params->masks[i].field_or_gen_idx + ++ FM_KG_MASK_SEL_GEN_BASE) << shift; ++ } ++ ++ /* MOx fields - spread between se_bmch and se_fqb registers */ ++ KG_GET_MASK_OFFSET_SHIFT(shift, i); ++ if (i < 2) { ++ select |= (uint32_t)extract_params->masks[i].offset << ++ shift; ++ } else { ++ fqb |= (uint32_t)extract_params->masks[i].offset << ++ shift; ++ } ++ ++ /* BMx fields */ ++ KG_GET_MASK_SHIFT(shift, i); ++ mask |= (uint32_t)extract_params->masks[i].mask << shift; ++ } ++ ++ /* Finish with rest of BMx fileds - ++ * don't mask bits for unused masks by setting ++ * corresponding BMx field = 0xFF */ ++ for (i = extract_params->masks_num; i < FM_KG_EXTRACT_MASKS_NUM; i++) { ++ KG_GET_MASK_SHIFT(shift, i); ++ mask |= 0xFF << shift; ++ } ++ ++ scheme_regs->kgse_bmch = select; ++ scheme_regs->kgse_bmcl = mask; ++ ++ /* Finish with FQB register initialization. ++ * Check fqid is 24-bit value. */ ++ if (params->base_fqid & ~0x00FFFFFF) { ++ return -EINVAL; ++ } ++ ++ fqb |= params->base_fqid; ++ scheme_regs->kgse_fqb = fqb; ++ ++ /* Hash Configuration register */ ++ tmp_reg = 0; ++ if (params->hash_params.use_hash) { ++ /* Check hash mask is 24-bit value */ ++ if (params->hash_params.mask & ~0x00FFFFFF) { ++ return -EINVAL; ++ } ++ ++ /* Hash function produces 64-bit value, 24 bits of that ++ * are used to generate fq_id and policer profile. ++ * Thus, maximal shift is 40 bits to allow 24 bits out of 64. ++ */ ++ if (params->hash_params.shift_r > FMAN_KG_SCH_HASH_HSHIFT_MAX) { ++ return -EINVAL; ++ } ++ ++ tmp_reg |= params->hash_params.mask; ++ tmp_reg |= (uint32_t)params->hash_params.shift_r << ++ FMAN_KG_SCH_HASH_HSHIFT_SHIFT; ++ ++ if (params->hash_params.sym) { ++ tmp_reg |= FMAN_KG_SCH_HASH_SYM; ++ } ++ ++ } ++ ++ if (params->bypass_fqid_gen) { ++ tmp_reg |= FMAN_KG_SCH_HASH_NO_FQID_GEN; ++ } ++ ++ scheme_regs->kgse_hc = tmp_reg; ++ ++ /* Policer Profile register */ ++ if (params->policer_params.bypass_pp_gen) { ++ tmp_reg = 0; ++ } else { ++ /* Lower 8 bits of 24-bits extracted from hash result ++ * are used for policer profile generation. ++ * That leaves maximum shift value = 23. */ ++ if (params->policer_params.shift > FMAN_KG_SCH_PP_SHIFT_MAX) { ++ return -EINVAL; ++ } ++ ++ tmp_reg = params->policer_params.base; ++ tmp_reg |= ((uint32_t)params->policer_params.shift << ++ FMAN_KG_SCH_PP_SH_SHIFT) & ++ FMAN_KG_SCH_PP_SH_MASK; ++ tmp_reg |= ((uint32_t)params->policer_params.shift << ++ FMAN_KG_SCH_PP_SL_SHIFT) & ++ FMAN_KG_SCH_PP_SL_MASK; ++ tmp_reg |= (uint32_t)params->policer_params.mask << ++ FMAN_KG_SCH_PP_MASK_SHIFT; ++ } ++ ++ scheme_regs->kgse_ppc = tmp_reg; ++ ++ /* Coarse Classification Bit Select register */ ++ if (params->next_engine == E_FMAN_PCD_CC) { ++ scheme_regs->kgse_ccbs = params->cc_params.qlcv_bits_sel; ++ } ++ ++ /* Packets Counter register */ ++ if (params->update_counter) { ++ scheme_regs->kgse_spc = params->counter_value; ++ } ++ ++ return 0; ++} ++ ++int fman_kg_write_scheme(struct fman_kg_regs *regs, ++ uint8_t scheme_id, ++ uint8_t hwport_id, ++ struct fman_kg_scheme_regs *scheme_regs, ++ bool update_counter) ++{ ++ struct fman_kg_scheme_regs *kgse_regs; ++ uint32_t tmp_reg; ++ int err, i; ++ ++ /* Write indirect scheme registers */ ++ kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]); ++ ++ iowrite32be(scheme_regs->kgse_mode, &kgse_regs->kgse_mode); ++ iowrite32be(scheme_regs->kgse_ekfc, &kgse_regs->kgse_ekfc); ++ iowrite32be(scheme_regs->kgse_ekdv, &kgse_regs->kgse_ekdv); ++ iowrite32be(scheme_regs->kgse_bmch, &kgse_regs->kgse_bmch); ++ iowrite32be(scheme_regs->kgse_bmcl, &kgse_regs->kgse_bmcl); ++ iowrite32be(scheme_regs->kgse_fqb, &kgse_regs->kgse_fqb); ++ iowrite32be(scheme_regs->kgse_hc, &kgse_regs->kgse_hc); ++ iowrite32be(scheme_regs->kgse_ppc, &kgse_regs->kgse_ppc); ++ iowrite32be(scheme_regs->kgse_spc, &kgse_regs->kgse_spc); ++ iowrite32be(scheme_regs->kgse_dv0, &kgse_regs->kgse_dv0); ++ iowrite32be(scheme_regs->kgse_dv1, &kgse_regs->kgse_dv1); ++ iowrite32be(scheme_regs->kgse_ccbs, &kgse_regs->kgse_ccbs); ++ iowrite32be(scheme_regs->kgse_mv, &kgse_regs->kgse_mv); ++ ++ for (i = 0 ; i < FM_KG_NUM_OF_GENERIC_REGS ; i++) ++ iowrite32be(scheme_regs->kgse_gec[i], &kgse_regs->kgse_gec[i]); ++ ++ /* Write AR (Action register) */ ++ tmp_reg = build_ar_scheme(scheme_id, hwport_id, update_counter, TRUE); ++ err = fman_kg_write_ar_wait(regs, tmp_reg); ++ return err; ++} ++ ++int fman_kg_delete_scheme(struct fman_kg_regs *regs, ++ uint8_t scheme_id, ++ uint8_t hwport_id) ++{ ++ struct fman_kg_scheme_regs *kgse_regs; ++ uint32_t tmp_reg; ++ int err, i; ++ ++ kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]); ++ ++ /* Clear all registers including enable bit in mode register */ ++ for (i = 0; i < (sizeof(struct fman_kg_scheme_regs)) / 4; ++i) { ++ iowrite32be(0, ((uint32_t *)kgse_regs + i)); ++ } ++ ++ /* Write AR (Action register) */ ++ tmp_reg = build_ar_scheme(scheme_id, hwport_id, FALSE, TRUE); ++ err = fman_kg_write_ar_wait(regs, tmp_reg); ++ return err; ++} ++ ++int fman_kg_get_scheme_counter(struct fman_kg_regs *regs, ++ uint8_t scheme_id, ++ uint8_t hwport_id, ++ uint32_t *counter) ++{ ++ struct fman_kg_scheme_regs *kgse_regs; ++ uint32_t tmp_reg; ++ int err; ++ ++ kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]); ++ ++ tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, FALSE); ++ err = fman_kg_write_ar_wait(regs, tmp_reg); ++ ++ if (err != 0) ++ return err; ++ ++ *counter = ioread32be(&kgse_regs->kgse_spc); ++ ++ return 0; ++} ++ ++int fman_kg_set_scheme_counter(struct fman_kg_regs *regs, ++ uint8_t scheme_id, ++ uint8_t hwport_id, ++ uint32_t counter) ++{ ++ struct fman_kg_scheme_regs *kgse_regs; ++ uint32_t tmp_reg; ++ int err; ++ ++ kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]); ++ ++ tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, FALSE); ++ ++ err = fman_kg_write_ar_wait(regs, tmp_reg); ++ if (err != 0) ++ return err; ++ ++ /* Keygen indirect access memory contains all scheme_id registers ++ * by now. Change only counter value. */ ++ iowrite32be(counter, &kgse_regs->kgse_spc); ++ ++ /* Write back scheme registers */ ++ tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, TRUE); ++ err = fman_kg_write_ar_wait(regs, tmp_reg); ++ ++ return err; ++} ++ ++uint32_t fman_kg_get_schemes_total_counter(struct fman_kg_regs *regs) ++{ ++ return ioread32be(®s->fmkg_tpc); ++} ++ ++int fman_kg_build_cls_plan(struct fman_kg_cls_plan_params *params, ++ struct fman_kg_cp_regs *cls_plan_regs) ++{ ++ uint8_t entries_set, entry_bit; ++ int i; ++ ++ /* Zero out all group's register */ ++ memset(cls_plan_regs, 0, sizeof(struct fman_kg_cp_regs)); ++ ++ /* Go over all classification entries in params->entries_mask and ++ * configure the corresponding cpe register */ ++ entries_set = params->entries_mask; ++ for (i = 0; entries_set; i++) { ++ entry_bit = (uint8_t)(0x80 >> i); ++ if ((entry_bit & entries_set) == 0) ++ continue; ++ entries_set ^= entry_bit; ++ cls_plan_regs->kgcpe[i] = params->mask_vector[i]; ++ } ++ ++ return 0; ++} ++ ++int fman_kg_write_cls_plan(struct fman_kg_regs *regs, ++ uint8_t grp_id, ++ uint8_t entries_mask, ++ uint8_t hwport_id, ++ struct fman_kg_cp_regs *cls_plan_regs) ++{ ++ struct fman_kg_cp_regs *kgcpe_regs; ++ uint32_t tmp_reg; ++ int i, err; ++ ++ /* Check group index is valid and the group isn't empty */ ++ if (grp_id >= FM_KG_CLS_PLAN_GRPS_NUM) ++ return -EINVAL; ++ ++ /* Write indirect classification plan registers */ ++ kgcpe_regs = (struct fman_kg_cp_regs *)&(regs->fmkg_indirect[0]); ++ ++ for (i = 0; i < FM_KG_NUM_CLS_PLAN_ENTR; i++) { ++ iowrite32be(cls_plan_regs->kgcpe[i], &kgcpe_regs->kgcpe[i]); ++ } ++ ++ tmp_reg = build_ar_cls_plan(grp_id, entries_mask, hwport_id, TRUE); ++ err = fman_kg_write_ar_wait(regs, tmp_reg); ++ return err; ++} ++ ++int fman_kg_write_bind_schemes(struct fman_kg_regs *regs, ++ uint8_t hwport_id, ++ uint32_t schemes) ++{ ++ struct fman_kg_pe_regs *kg_pe_regs; ++ uint32_t tmp_reg; ++ int err; ++ ++ kg_pe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]); ++ ++ iowrite32be(schemes, &kg_pe_regs->fmkg_pe_sp); ++ ++ tmp_reg = build_ar_bind_scheme(hwport_id, TRUE); ++ err = fman_kg_write_ar_wait(regs, tmp_reg); ++ return err; ++} ++ ++int fman_kg_build_bind_cls_plans(uint8_t grp_base, ++ uint8_t grp_mask, ++ uint32_t *bind_cls_plans) ++{ ++ /* Check grp_base and grp_mask are 5-bits values */ ++ if ((grp_base & ~0x0000001F) || (grp_mask & ~0x0000001F)) ++ return -EINVAL; ++ ++ *bind_cls_plans = (uint32_t) ((grp_mask << FMAN_KG_PE_CPP_MASK_SHIFT) | grp_base); ++ return 0; ++} ++ ++ ++int fman_kg_write_bind_cls_plans(struct fman_kg_regs *regs, ++ uint8_t hwport_id, ++ uint32_t bind_cls_plans) ++{ ++ struct fman_kg_pe_regs *kg_pe_regs; ++ uint32_t tmp_reg; ++ int err; ++ ++ kg_pe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]); ++ ++ iowrite32be(bind_cls_plans, &kg_pe_regs->fmkg_pe_cpp); ++ ++ tmp_reg = build_ar_bind_cls_plan(hwport_id, TRUE); ++ err = fman_kg_write_ar_wait(regs, tmp_reg); ++ return err; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fman_prs.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fman_prs.c +new file mode 100644 +index 0000000..108779d +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fman_prs.c +@@ -0,0 +1,129 @@ ++/* ++ * Copyright 2012 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 "fsl_fman_prs.h" ++ ++uint32_t fman_prs_get_err_event(struct fman_prs_regs *regs, uint32_t ev_mask) ++{ ++ return ioread32be(®s->fmpr_perr) & ev_mask; ++} ++ ++uint32_t fman_prs_get_err_ev_mask(struct fman_prs_regs *regs) ++{ ++ return ioread32be(®s->fmpr_perer); ++} ++ ++void fman_prs_ack_err_event(struct fman_prs_regs *regs, uint32_t event) ++{ ++ iowrite32be(event, ®s->fmpr_perr); ++} ++ ++uint32_t fman_prs_get_expt_event(struct fman_prs_regs *regs, uint32_t ev_mask) ++{ ++ return ioread32be(®s->fmpr_pevr) & ev_mask; ++} ++ ++uint32_t fman_prs_get_expt_ev_mask(struct fman_prs_regs *regs) ++{ ++ return ioread32be(®s->fmpr_pever); ++} ++ ++void fman_prs_ack_expt_event(struct fman_prs_regs *regs, uint32_t event) ++{ ++ iowrite32be(event, ®s->fmpr_pevr); ++} ++ ++void fman_prs_defconfig(struct fman_prs_cfg *cfg) ++{ ++ cfg->port_id_stat = 0; ++ cfg->max_prs_cyc_lim = DEFAULT_MAX_PRS_CYC_LIM; ++ cfg->prs_exceptions = 0x03000000; ++} ++ ++int fman_prs_init(struct fman_prs_regs *regs, struct fman_prs_cfg *cfg) ++{ ++ uint32_t tmp; ++ ++ iowrite32be(cfg->max_prs_cyc_lim, ®s->fmpr_rpclim); ++ iowrite32be((FM_PCD_PRS_SINGLE_ECC | FM_PCD_PRS_PORT_IDLE_STS), ++ ®s->fmpr_pevr); ++ ++ if (cfg->prs_exceptions & FM_PCD_EX_PRS_SINGLE_ECC) ++ iowrite32be(FM_PCD_PRS_SINGLE_ECC, ®s->fmpr_pever); ++ else ++ iowrite32be(0, ®s->fmpr_pever); ++ ++ iowrite32be(FM_PCD_PRS_DOUBLE_ECC, ®s->fmpr_perr); ++ ++ tmp = 0; ++ if (cfg->prs_exceptions & FM_PCD_EX_PRS_DOUBLE_ECC) ++ tmp |= FM_PCD_PRS_DOUBLE_ECC; ++ iowrite32be(tmp, ®s->fmpr_perer); ++ ++ iowrite32be(cfg->port_id_stat, ®s->fmpr_ppsc); ++ ++ return 0; ++} ++ ++void fman_prs_enable(struct fman_prs_regs *regs) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->fmpr_rpimac) | FM_PCD_PRS_RPIMAC_EN; ++ iowrite32be(tmp, ®s->fmpr_rpimac); ++} ++ ++void fman_prs_disable(struct fman_prs_regs *regs) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(®s->fmpr_rpimac) & ~FM_PCD_PRS_RPIMAC_EN; ++ iowrite32be(tmp, ®s->fmpr_rpimac); ++} ++ ++int fman_prs_is_enabled(struct fman_prs_regs *regs) ++{ ++ return ioread32be(®s->fmpr_rpimac) & FM_PCD_PRS_RPIMAC_EN; ++} ++ ++void fman_prs_set_stst_port_msk(struct fman_prs_regs *regs, uint32_t pid_msk) ++{ ++ iowrite32be(pid_msk, ®s->fmpr_ppsc); ++} ++ ++void fman_prs_set_stst(struct fman_prs_regs *regs, bool enable) ++{ ++ if (enable) ++ iowrite32be(FM_PCD_PRS_PPSC_ALL_PORTS, ®s->fmpr_ppsc); ++ else ++ iowrite32be(0, ®s->fmpr_ppsc); ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/Makefile b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/Makefile +new file mode 100644 +index 0000000..7d928e0 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/Makefile +@@ -0,0 +1,15 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++ccflags-y += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk ++ ++NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc ++ ++ccflags-y += -I$(NCSW_FM_INC) ++ ++obj-y += fsl-ncsw-Pcd.o ++ ++fsl-ncsw-Pcd-objs := fm_port.o fm_port_im.o fman_port.o +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fm_port.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fm_port.c +new file mode 100644 +index 0000000..ec6e0ed +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fm_port.c +@@ -0,0 +1,6436 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_port.c ++ ++ @Description FM driver routines implementation. ++ *//***************************************************************************/ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "string_ext.h" ++#include "sprint_ext.h" ++#include "debug_ext.h" ++#include "fm_muram_ext.h" ++ ++#include "fman_common.h" ++#include "fm_port.h" ++#include "fm_port_dsar.h" ++#include "common/general.h" ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++static t_Error FmPortConfigAutoResForDeepSleepSupport1(t_FmPort *p_FmPort); ++ ++static t_Error CheckInitParameters(t_FmPort *p_FmPort) ++{ ++ t_FmPortDriverParam *p_Params = p_FmPort->p_FmPortDriverParam; ++ struct fman_port_cfg *p_DfltConfig = &p_Params->dfltCfg; ++ t_Error ans = E_OK; ++ uint32_t unusedMask; ++ ++ if (p_FmPort->imEn) ++ { ++ if (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ++ if (p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth ++ > 2) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("fifoDeqPipelineDepth for IM 10G can't be larger than 2")); ++ ++ if ((ans = FmPortImCheckInitParameters(p_FmPort)) != E_OK) ++ return ERROR_CODE(ans); ++ } ++ else ++ { ++ /****************************************/ ++ /* Rx only */ ++ /****************************************/ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ /* external buffer pools */ ++ if (!p_Params->extBufPools.numOfPoolsUsed) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("extBufPools.numOfPoolsUsed=0. At least one buffer pool must be defined")); ++ ++ if (FmSpCheckBufPoolsParams(&p_Params->extBufPools, ++ p_Params->p_BackupBmPools, ++ &p_Params->bufPoolDepletion) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ ++ /* Check that part of IC that needs copying is small enough to enter start margin */ ++ if (p_Params->intContext.size ++ && (p_Params->intContext.size ++ + p_Params->intContext.extBufOffset ++ > p_Params->bufMargins.startMargins)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("intContext.size is larger than start margins")); ++ ++ if ((p_Params->liodnOffset != (uint16_t)DPAA_LIODN_DONT_OVERRIDE) ++ && (p_Params->liodnOffset & ~FM_LIODN_OFFSET_MASK)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("liodnOffset is larger than %d", FM_LIODN_OFFSET_MASK+1)); ++ ++#ifdef FM_NO_BACKUP_POOLS ++ if ((p_FmPort->fmRevInfo.majorRev != 4) && (p_FmPort->fmRevInfo.majorRev < 6)) ++ if (p_FmPort->p_FmPortDriverParam->p_BackupBmPools) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("BackupBmPools")); ++#endif /* FM_NO_BACKUP_POOLS */ ++ } ++ ++ /****************************************/ ++ /* Non Rx ports */ ++ /****************************************/ ++ else ++ { ++ if (p_Params->deqSubPortal >= FM_MAX_NUM_OF_SUB_PORTALS) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ (" deqSubPortal has to be in the range of 0 - %d", FM_MAX_NUM_OF_SUB_PORTALS)); ++ ++ /* to protect HW internal-context from overwrite */ ++ if ((p_Params->intContext.size) ++ && (p_Params->intContext.intContextOffset ++ < MIN_TX_INT_OFFSET)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("non-Rx intContext.intContextOffset can't be smaller than %d", MIN_TX_INT_OFFSET)); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) ++ /* in O/H DEFAULT_notSupported indicates that it is not supported and should not be checked */ ++ || (p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth ++ != DEFAULT_notSupported)) ++ { ++ /* Check that not larger than 8 */ ++ if ((!p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth) ++ || (p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth ++ > MAX_FIFO_PIPELINE_DEPTH)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("fifoDeqPipelineDepth can't be larger than %d", MAX_FIFO_PIPELINE_DEPTH)); ++ } ++ } ++ ++ /****************************************/ ++ /* Rx Or Offline Parsing */ ++ /****************************************/ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ { ++ if (!p_Params->dfltFqid) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("dfltFqid must be between 1 and 2^24-1")); ++#if defined(FM_CAPWAP_SUPPORT) && defined(FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004) ++ if (p_FmPort->p_FmPortDriverParam->bufferPrefixContent.manipExtraSpace % 16) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufferPrefixContent.manipExtraSpace has to be devidable by 16")); ++#endif /* defined(FM_CAPWAP_SUPPORT) && ... */ ++ } ++ ++ /****************************************/ ++ /* All ports */ ++ /****************************************/ ++ /* common BMI registers values */ ++ /* Check that Queue Id is not larger than 2^24, and is not 0 */ ++ if ((p_Params->errFqid & ~0x00FFFFFF) || !p_Params->errFqid) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("errFqid must be between 1 and 2^24-1")); ++ if (p_Params->dfltFqid & ~0x00FFFFFF) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("dfltFqid must be between 1 and 2^24-1")); ++ } ++ ++ /****************************************/ ++ /* Rx only */ ++ /****************************************/ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ if (p_DfltConfig->rx_pri_elevation % BMI_FIFO_UNITS) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("rxFifoPriElevationLevel has to be divisible by %d", BMI_FIFO_UNITS)); ++ if ((p_DfltConfig->rx_pri_elevation < BMI_FIFO_UNITS) ++ || (p_DfltConfig->rx_pri_elevation > MAX_PORT_FIFO_SIZE)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("rxFifoPriElevationLevel has to be in the range of 256 - %d", MAX_PORT_FIFO_SIZE)); ++ if (p_DfltConfig->rx_fifo_thr % BMI_FIFO_UNITS) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("rxFifoThreshold has to be divisible by %d", BMI_FIFO_UNITS)); ++ if ((p_DfltConfig->rx_fifo_thr < BMI_FIFO_UNITS) ++ || (p_DfltConfig->rx_fifo_thr > MAX_PORT_FIFO_SIZE)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("rxFifoThreshold has to be in the range of 256 - %d", MAX_PORT_FIFO_SIZE)); ++ ++ /* Check that not larger than 16 */ ++ if (p_DfltConfig->rx_cut_end_bytes > FRAME_END_DATA_SIZE) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("cutBytesFromEnd can't be larger than %d", FRAME_END_DATA_SIZE)); ++ ++ if (FmSpCheckBufMargins(&p_Params->bufMargins) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ ++ /* extra FIFO size (allowed only to Rx ports) */ ++ if (p_Params->setSizeOfFifo ++ && (p_FmPort->fifoBufs.extra % BMI_FIFO_UNITS)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("fifoBufs.extra has to be divisible by %d", BMI_FIFO_UNITS)); ++ ++ if (p_Params->bufPoolDepletion.poolsGrpModeEnable ++ && !p_Params->bufPoolDepletion.numOfPools) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("bufPoolDepletion.numOfPools can not be 0 when poolsGrpModeEnable=TRUE")); ++#ifdef FM_CSI_CFED_LIMIT ++ if (p_FmPort->fmRevInfo.majorRev == 4) ++ { ++ /* Check that not larger than 16 */ ++ if (p_DfltConfig->rx_cut_end_bytes + p_DfltConfig->checksum_bytes_ignore > FRAME_END_DATA_SIZE) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("cheksumLastBytesIgnore + cutBytesFromEnd can't be larger than %d", FRAME_END_DATA_SIZE)); ++ } ++#endif /* FM_CSI_CFED_LIMIT */ ++ } ++ ++ /****************************************/ ++ /* Non Rx ports */ ++ /****************************************/ ++ /* extra FIFO size (allowed only to Rx ports) */ ++ else ++ if (p_FmPort->fifoBufs.extra) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ (" No fifoBufs.extra for non Rx ports")); ++ ++ /****************************************/ ++ /* Tx only */ ++ /****************************************/ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G)) ++ { ++ if (p_DfltConfig->tx_fifo_min_level % BMI_FIFO_UNITS) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("txFifoMinFillLevel has to be divisible by %d", BMI_FIFO_UNITS)); ++ if (p_DfltConfig->tx_fifo_min_level > (MAX_PORT_FIFO_SIZE - 256)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("txFifoMinFillLevel has to be in the range of 0 - %d", (MAX_PORT_FIFO_SIZE - 256))); ++ if (p_DfltConfig->tx_fifo_low_comf_level % BMI_FIFO_UNITS) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("txFifoLowComfLevel has to be divisible by %d", BMI_FIFO_UNITS)); ++ if ((p_DfltConfig->tx_fifo_low_comf_level < BMI_FIFO_UNITS) ++ || (p_DfltConfig->tx_fifo_low_comf_level > MAX_PORT_FIFO_SIZE)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("txFifoLowComfLevel has to be in the range of 256 - %d", MAX_PORT_FIFO_SIZE)); ++ ++ if (p_FmPort->portType == e_FM_PORT_TYPE_TX) ++ if (p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth ++ > 2) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("fifoDeqPipelineDepth for 1G can't be larger than 2")); ++ } ++ ++ /****************************************/ ++ /* Non Tx Ports */ ++ /****************************************/ ++ /* If discard override was selected , no frames may be discarded. */ ++ else ++ if (p_DfltConfig->discard_override && p_Params->errorsToDiscard) ++ RETURN_ERROR( ++ MAJOR, ++ E_CONFLICT, ++ ("errorsToDiscard is not empty, but frmDiscardOverride selected (all discarded frames to be enqueued to error queue).")); ++ ++ /****************************************/ ++ /* Rx and Offline parsing */ ++ /****************************************/ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ { ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ unusedMask = BMI_STATUS_OP_MASK_UNUSED; ++ else ++ unusedMask = BMI_STATUS_RX_MASK_UNUSED; ++ ++ /* Check that no common bits with BMI_STATUS_MASK_UNUSED */ ++ if (p_Params->errorsToDiscard & unusedMask) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ++ ("errorsToDiscard contains undefined bits")); ++ } ++ ++ /****************************************/ ++ /* Offline Ports */ ++ /****************************************/ ++#ifdef FM_OP_OPEN_DMA_MIN_LIMIT ++ if ((p_FmPort->fmRevInfo.majorRev >= 6) ++ && (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ && p_Params->setNumOfOpenDmas ++ && (p_FmPort->openDmas.num < MIN_NUM_OF_OP_DMAS)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("For Offline port, openDmas.num can't be smaller than %d", MIN_NUM_OF_OP_DMAS)); ++#endif /* FM_OP_OPEN_DMA_MIN_LIMIT */ ++ ++ /****************************************/ ++ /* Offline & HC Ports */ ++ /****************************************/ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)) ++ { ++#ifndef FM_FRAME_END_PARAMS_FOR_OP ++ if ((p_FmPort->fmRevInfo.majorRev < 6) && ++ (p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore != DEFAULT_notSupported)) ++ /* this is an indication that user called config for this mode which is not supported in this integration */ ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("cheksumLastBytesIgnore is available for Rx & Tx ports only")); ++#endif /* !FM_FRAME_END_PARAMS_FOR_OP */ ++ ++#ifndef FM_DEQ_PIPELINE_PARAMS_FOR_OP ++ if ((!((p_FmPort->fmRevInfo.majorRev == 4) || ++ (p_FmPort->fmRevInfo.majorRev >= 6))) && ++ (p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth != DEFAULT_notSupported)) ++ /* this is an indication that user called config for this mode which is not supported in this integration */ ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("fifoDeqPipelineDepth is available for Tx ports only")); ++#endif /* !FM_DEQ_PIPELINE_PARAMS_FOR_OP */ ++ } ++ ++ /****************************************/ ++ /* All ports */ ++ /****************************************/ ++ /* Check that not larger than 16 */ ++ if ((p_Params->cheksumLastBytesIgnore > FRAME_END_DATA_SIZE) ++ && ((p_Params->cheksumLastBytesIgnore != DEFAULT_notSupported))) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("cheksumLastBytesIgnore can't be larger than %d", FRAME_END_DATA_SIZE)); ++ ++ if (FmSpCheckIntContextParams(&p_Params->intContext) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ ++ /* common BMI registers values */ ++ if (p_Params->setNumOfTasks ++ && ((!p_FmPort->tasks.num) ++ || (p_FmPort->tasks.num > MAX_NUM_OF_TASKS))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("tasks.num can't be larger than %d", MAX_NUM_OF_TASKS)); ++ if (p_Params->setNumOfTasks ++ && (p_FmPort->tasks.extra > MAX_NUM_OF_EXTRA_TASKS)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("tasks.extra can't be larger than %d", MAX_NUM_OF_EXTRA_TASKS)); ++ if (p_Params->setNumOfOpenDmas ++ && ((!p_FmPort->openDmas.num) ++ || (p_FmPort->openDmas.num > MAX_NUM_OF_DMAS))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("openDmas.num can't be larger than %d", MAX_NUM_OF_DMAS)); ++ if (p_Params->setNumOfOpenDmas ++ && (p_FmPort->openDmas.extra > MAX_NUM_OF_EXTRA_DMAS)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("openDmas.extra can't be larger than %d", MAX_NUM_OF_EXTRA_DMAS)); ++ if (p_Params->setSizeOfFifo ++ && (!p_FmPort->fifoBufs.num ++ || (p_FmPort->fifoBufs.num > MAX_PORT_FIFO_SIZE))) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("fifoBufs.num has to be in the range of 256 - %d", MAX_PORT_FIFO_SIZE)); ++ if (p_Params->setSizeOfFifo && (p_FmPort->fifoBufs.num % BMI_FIFO_UNITS)) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("fifoBufs.num has to be divisible by %d", BMI_FIFO_UNITS)); ++ ++#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT ++ if (p_FmPort->fmRevInfo.majorRev == 4) ++ if (p_FmPort->p_FmPortDriverParam->deqPrefetchOption != DEFAULT_notSupported) ++ /* this is an indication that user called config for this mode which is not supported in this integration */ ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("deqPrefetchOption")); ++#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ ++ ++ return E_OK; ++} ++ ++static t_Error VerifySizeOfFifo(t_FmPort *p_FmPort) ++{ ++ uint32_t minFifoSizeRequired = 0, optFifoSizeForB2B = 0; ++ ++ /*************************/ ++ /* TX PORTS */ ++ /*************************/ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G)) ++ { ++ minFifoSizeRequired = ++ (uint32_t)(ROUND_UP(p_FmPort->maxFrameLength, BMI_FIFO_UNITS) ++ + (3 * BMI_FIFO_UNITS)); ++ if (!p_FmPort->imEn) ++ minFifoSizeRequired += ++ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth ++ * BMI_FIFO_UNITS; ++ ++ optFifoSizeForB2B = minFifoSizeRequired; ++ ++ /* Add some margin for back-to-back capability to improve performance, ++ allows the hardware to pipeline new frame dma while the previous ++ frame not yet transmitted. */ ++ if (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) ++ optFifoSizeForB2B += 3 * BMI_FIFO_UNITS; ++ else ++ optFifoSizeForB2B += 2 * BMI_FIFO_UNITS; ++ } ++ ++ /*************************/ ++ /* RX IM PORTS */ ++ /*************************/ ++ else ++ if (((p_FmPort->portType == e_FM_PORT_TYPE_RX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ && p_FmPort->imEn) ++ { ++ optFifoSizeForB2B = ++ minFifoSizeRequired = ++ (uint32_t)(ROUND_UP(p_FmPort->maxFrameLength, BMI_FIFO_UNITS) ++ + (4 * BMI_FIFO_UNITS)); ++ } ++ ++ /*************************/ ++ /* RX non-IM PORTS */ ++ /*************************/ ++ else ++ if (((p_FmPort->portType == e_FM_PORT_TYPE_RX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ && !p_FmPort->imEn) ++ { ++ if (p_FmPort->fmRevInfo.majorRev == 4) ++ { ++ if (p_FmPort->rxPoolsParams.numOfPools == 1) ++ minFifoSizeRequired = 8 * BMI_FIFO_UNITS; ++ else ++ minFifoSizeRequired = ++ (uint32_t)(ROUND_UP(p_FmPort->rxPoolsParams.secondLargestBufSize, BMI_FIFO_UNITS) ++ + (7 * BMI_FIFO_UNITS)); ++ } ++ else ++ { ++#if (DPAA_VERSION >= 11) ++ minFifoSizeRequired = ++ (uint32_t)(ROUND_UP(p_FmPort->maxFrameLength, BMI_FIFO_UNITS) ++ + (5 * BMI_FIFO_UNITS)); ++ /* 4 according to spec + 1 for FOF>0 */ ++#else ++ minFifoSizeRequired = (uint32_t) ++ (ROUND_UP(MIN(p_FmPort->maxFrameLength, p_FmPort->rxPoolsParams.largestBufSize), BMI_FIFO_UNITS) ++ + (7*BMI_FIFO_UNITS)); ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ optFifoSizeForB2B = minFifoSizeRequired; ++ ++ /* Add some margin for back-to-back capability to improve performance, ++ allows the hardware to pipeline new frame dma while the previous ++ frame not yet transmitted. */ ++ if (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ++ optFifoSizeForB2B += 8 * BMI_FIFO_UNITS; ++ else ++ optFifoSizeForB2B += 3 * BMI_FIFO_UNITS; ++ } ++ ++ /* For O/H ports, check fifo size and update if necessary */ ++ else ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)) ++ { ++#if (DPAA_VERSION >= 11) ++ optFifoSizeForB2B = ++ minFifoSizeRequired = ++ (uint32_t)(ROUND_UP(p_FmPort->maxFrameLength, BMI_FIFO_UNITS) ++ + ((p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth ++ + 5) * BMI_FIFO_UNITS)); ++ /* 4 according to spec + 1 for FOF>0 */ ++#else ++ optFifoSizeForB2B = minFifoSizeRequired = (uint32_t)((p_FmPort->tasks.num + 2) * BMI_FIFO_UNITS); ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ ASSERT_COND(minFifoSizeRequired > 0); ++ ASSERT_COND(optFifoSizeForB2B >= minFifoSizeRequired); ++ ++ /* Verify the size */ ++ if (p_FmPort->fifoBufs.num < minFifoSizeRequired) ++ DBG(INFO, ++ ("FIFO size is %d and should be enlarged to %d bytes",p_FmPort->fifoBufs.num, minFifoSizeRequired)); ++ else if (p_FmPort->fifoBufs.num < optFifoSizeForB2B) ++ DBG(INFO, ++ ("For back-to-back frames processing, FIFO size is %d and needs to enlarge to %d bytes", p_FmPort->fifoBufs.num, optFifoSizeForB2B)); ++ ++ return E_OK; ++} ++ ++static void FmPortDriverParamFree(t_FmPort *p_FmPort) ++{ ++ if (p_FmPort->p_FmPortDriverParam) ++ { ++ XX_Free(p_FmPort->p_FmPortDriverParam); ++ p_FmPort->p_FmPortDriverParam = NULL; ++ } ++} ++ ++static t_Error SetExtBufferPools(t_FmPort *p_FmPort) ++{ ++ t_FmExtPools *p_ExtBufPools = &p_FmPort->p_FmPortDriverParam->extBufPools; ++ t_FmBufPoolDepletion *p_BufPoolDepletion = ++ &p_FmPort->p_FmPortDriverParam->bufPoolDepletion; ++ uint8_t orderedArray[FM_PORT_MAX_NUM_OF_EXT_POOLS]; ++ uint16_t sizesArray[BM_MAX_NUM_OF_POOLS]; ++ int i = 0, j = 0, err; ++ struct fman_port_bpools bpools; ++ ++ memset(&orderedArray, 0, sizeof(uint8_t) * FM_PORT_MAX_NUM_OF_EXT_POOLS); ++ memset(&sizesArray, 0, sizeof(uint16_t) * BM_MAX_NUM_OF_POOLS); ++ memcpy(&p_FmPort->extBufPools, p_ExtBufPools, sizeof(t_FmExtPools)); ++ ++ FmSpSetBufPoolsInAscOrderOfBufSizes(p_ExtBufPools, orderedArray, ++ sizesArray); ++ ++ /* Prepare flibs bpools structure */ ++ memset(&bpools, 0, sizeof(struct fman_port_bpools)); ++ bpools.count = p_ExtBufPools->numOfPoolsUsed; ++ bpools.counters_enable = TRUE; ++ for (i = 0; i < p_ExtBufPools->numOfPoolsUsed; i++) ++ { ++ bpools.bpool[i].bpid = orderedArray[i]; ++ bpools.bpool[i].size = sizesArray[orderedArray[i]]; ++ /* functionality available only for some derivatives (limited by config) */ ++ if (p_FmPort->p_FmPortDriverParam->p_BackupBmPools) ++ for (j = 0; ++ j ++ < p_FmPort->p_FmPortDriverParam->p_BackupBmPools->numOfBackupPools; ++ j++) ++ if (orderedArray[i] ++ == p_FmPort->p_FmPortDriverParam->p_BackupBmPools->poolIds[j]) ++ { ++ bpools.bpool[i].is_backup = TRUE; ++ break; ++ } ++ } ++ ++ /* save pools parameters for later use */ ++ p_FmPort->rxPoolsParams.numOfPools = p_ExtBufPools->numOfPoolsUsed; ++ p_FmPort->rxPoolsParams.largestBufSize = ++ sizesArray[orderedArray[p_ExtBufPools->numOfPoolsUsed - 1]]; ++ p_FmPort->rxPoolsParams.secondLargestBufSize = ++ sizesArray[orderedArray[p_ExtBufPools->numOfPoolsUsed - 2]]; ++ ++ /* FMBM_RMPD reg. - pool depletion */ ++ if (p_BufPoolDepletion->poolsGrpModeEnable) ++ { ++ bpools.grp_bp_depleted_num = p_BufPoolDepletion->numOfPools; ++ for (i = 0; i < BM_MAX_NUM_OF_POOLS; i++) ++ { ++ if (p_BufPoolDepletion->poolsToConsider[i]) ++ { ++ for (j = 0; j < p_ExtBufPools->numOfPoolsUsed; j++) ++ { ++ if (i == orderedArray[j]) ++ { ++ bpools.bpool[j].grp_bp_depleted = TRUE; ++ break; ++ } ++ } ++ } ++ } ++ } ++ ++ if (p_BufPoolDepletion->singlePoolModeEnable) ++ { ++ for (i = 0; i < BM_MAX_NUM_OF_POOLS; i++) ++ { ++ if (p_BufPoolDepletion->poolsToConsiderForSingleMode[i]) ++ { ++ for (j = 0; j < p_ExtBufPools->numOfPoolsUsed; j++) ++ { ++ if (i == orderedArray[j]) ++ { ++ bpools.bpool[j].single_bp_depleted = TRUE; ++ break; ++ } ++ } ++ } ++ } ++ } ++ ++#if (DPAA_VERSION >= 11) ++ /* fill QbbPEV */ ++ if (p_BufPoolDepletion->poolsGrpModeEnable ++ || p_BufPoolDepletion->singlePoolModeEnable) ++ { ++ for (i = 0; i < FM_MAX_NUM_OF_PFC_PRIORITIES; i++) ++ { ++ if (p_BufPoolDepletion->pfcPrioritiesEn[i] == TRUE) ++ { ++ bpools.bpool[i].pfc_priorities_en = TRUE; ++ } ++ } ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ /* Issue flibs function */ ++ err = fman_port_set_bpools(&p_FmPort->port, &bpools); ++ if (err != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_bpools")); ++ ++ if (p_FmPort->p_FmPortDriverParam->p_BackupBmPools) ++ XX_Free(p_FmPort->p_FmPortDriverParam->p_BackupBmPools); ++ ++ return E_OK; ++} ++ ++static t_Error ClearPerfCnts(t_FmPort *p_FmPort) ++{ ++ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_QUEUE_UTIL, 0); ++ FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL, 0); ++ FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL, 0); ++ FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL, 0); ++ return E_OK; ++} ++ ++static t_Error InitLowLevelDriver(t_FmPort *p_FmPort) ++{ ++ t_FmPortDriverParam *p_DriverParams = p_FmPort->p_FmPortDriverParam; ++ struct fman_port_params portParams; ++ uint32_t tmpVal; ++ t_Error err; ++ ++ /* Set up flibs parameters and issue init function */ ++ ++ memset(&portParams, 0, sizeof(struct fman_port_params)); ++ portParams.discard_mask = p_DriverParams->errorsToDiscard; ++ portParams.dflt_fqid = p_DriverParams->dfltFqid; ++ portParams.err_fqid = p_DriverParams->errFqid; ++ portParams.deq_sp = p_DriverParams->deqSubPortal; ++ portParams.dont_release_buf = p_DriverParams->dontReleaseBuf; ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ portParams.err_mask = (RX_ERRS_TO_ENQ & ~portParams.discard_mask); ++ if (!p_FmPort->imEn) ++ { ++ if (p_DriverParams->forwardReuseIntContext) ++ p_DriverParams->dfltCfg.rx_fd_bits = ++ (uint8_t)(BMI_PORT_RFNE_FRWD_RPD >> 24); ++ } ++ break; ++ ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ portParams.err_mask = (OP_ERRS_TO_ENQ & ~portParams.discard_mask); ++ break; ++ break; ++ ++ default: ++ break; ++ } ++ ++ tmpVal = ++ (uint32_t)( ++ (p_FmPort->internalBufferOffset % OFFSET_UNITS) ? (p_FmPort->internalBufferOffset ++ / OFFSET_UNITS + 1) : ++ (p_FmPort->internalBufferOffset / OFFSET_UNITS)); ++ p_FmPort->internalBufferOffset = (uint8_t)(tmpVal * OFFSET_UNITS); ++ p_DriverParams->dfltCfg.int_buf_start_margin = ++ p_FmPort->internalBufferOffset; ++ ++ p_DriverParams->dfltCfg.ext_buf_start_margin = ++ p_DriverParams->bufMargins.startMargins; ++ p_DriverParams->dfltCfg.ext_buf_end_margin = ++ p_DriverParams->bufMargins.endMargins; ++ ++ p_DriverParams->dfltCfg.ic_ext_offset = ++ p_DriverParams->intContext.extBufOffset; ++ p_DriverParams->dfltCfg.ic_int_offset = ++ p_DriverParams->intContext.intContextOffset; ++ p_DriverParams->dfltCfg.ic_size = p_DriverParams->intContext.size; ++ ++ p_DriverParams->dfltCfg.stats_counters_enable = TRUE; ++ p_DriverParams->dfltCfg.perf_counters_enable = TRUE; ++ p_DriverParams->dfltCfg.queue_counters_enable = TRUE; ++ ++ p_DriverParams->dfltCfg.perf_cnt_params.task_val = ++ (uint8_t)p_FmPort->tasks.num; ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING || ++ p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)p_DriverParams->dfltCfg.perf_cnt_params.queue_val = 0; ++ else ++ p_DriverParams->dfltCfg.perf_cnt_params.queue_val = 1; ++ p_DriverParams->dfltCfg.perf_cnt_params.dma_val = ++ (uint8_t)p_FmPort->openDmas.num; ++ p_DriverParams->dfltCfg.perf_cnt_params.fifo_val = p_FmPort->fifoBufs.num; ++ ++ if (0 ++ != fman_port_init(&p_FmPort->port, &p_DriverParams->dfltCfg, ++ &portParams)) ++ RETURN_ERROR(MAJOR, E_NO_DEVICE, ("fman_port_init")); ++ ++ if (p_FmPort->imEn && ((err = FmPortImInit(p_FmPort)) != E_OK)) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ else ++ { ++ // from QMIInit ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ { ++ if (p_DriverParams->deqPrefetchOption == e_FM_PORT_DEQ_NO_PREFETCH) ++ FmSetPortPreFetchConfiguration(p_FmPort->h_Fm, p_FmPort->portId, ++ FALSE); ++ else ++ FmSetPortPreFetchConfiguration(p_FmPort->h_Fm, p_FmPort->portId, ++ TRUE); ++ } ++ } ++ /* The code bellow is a trick so the FM will not release the buffer ++ to BM nor will try to enqueue the frame to QM */ ++ if (((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_TX)) && (!p_FmPort->imEn)) ++ { ++ if (!p_DriverParams->dfltFqid && p_DriverParams->dontReleaseBuf) ++ { ++ /* override fmbm_tcfqid 0 with a false non-0 value. This will force FM to ++ * act according to tfene. Otherwise, if fmbm_tcfqid is 0 the FM will release ++ * buffers to BM regardless of fmbm_tfene ++ */ ++ WRITE_UINT32(p_FmPort->port.bmi_regs->tx.fmbm_tcfqid, 0xFFFFFF); ++ WRITE_UINT32(p_FmPort->port.bmi_regs->tx.fmbm_tfene, ++ NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE); ++ } ++ } ++ ++ return E_OK; ++} ++ ++static bool CheckRxBmiCounter(t_FmPort *p_FmPort, e_FmPortCounters counter) ++{ ++ UNUSED(p_FmPort); ++ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_CYCLE): ++ case (e_FM_PORT_COUNTERS_TASK_UTIL): ++ case (e_FM_PORT_COUNTERS_QUEUE_UTIL): ++ case (e_FM_PORT_COUNTERS_DMA_UTIL): ++ case (e_FM_PORT_COUNTERS_FIFO_UTIL): ++ case (e_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION): ++ case (e_FM_PORT_COUNTERS_FRAME): ++ case (e_FM_PORT_COUNTERS_DISCARD_FRAME): ++ case (e_FM_PORT_COUNTERS_RX_BAD_FRAME): ++ case (e_FM_PORT_COUNTERS_RX_LARGE_FRAME): ++ case (e_FM_PORT_COUNTERS_RX_FILTER_FRAME): ++ case (e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR): ++ case (e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD): ++ case (e_FM_PORT_COUNTERS_DEALLOC_BUF): ++ case (e_FM_PORT_COUNTERS_PREPARE_TO_ENQUEUE_COUNTER): ++ return TRUE; ++ default: ++ return FALSE; ++ } ++} ++ ++static bool CheckTxBmiCounter(t_FmPort *p_FmPort, e_FmPortCounters counter) ++{ ++ UNUSED(p_FmPort); ++ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_CYCLE): ++ case (e_FM_PORT_COUNTERS_TASK_UTIL): ++ case (e_FM_PORT_COUNTERS_QUEUE_UTIL): ++ case (e_FM_PORT_COUNTERS_DMA_UTIL): ++ case (e_FM_PORT_COUNTERS_FIFO_UTIL): ++ case (e_FM_PORT_COUNTERS_FRAME): ++ case (e_FM_PORT_COUNTERS_DISCARD_FRAME): ++ case (e_FM_PORT_COUNTERS_LENGTH_ERR): ++ case (e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT): ++ case (e_FM_PORT_COUNTERS_DEALLOC_BUF): ++ return TRUE; ++ default: ++ return FALSE; ++ } ++} ++ ++static bool CheckOhBmiCounter(t_FmPort *p_FmPort, e_FmPortCounters counter) ++{ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_CYCLE): ++ case (e_FM_PORT_COUNTERS_TASK_UTIL): ++ case (e_FM_PORT_COUNTERS_DMA_UTIL): ++ case (e_FM_PORT_COUNTERS_FIFO_UTIL): ++ case (e_FM_PORT_COUNTERS_FRAME): ++ case (e_FM_PORT_COUNTERS_DISCARD_FRAME): ++ case (e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR): ++ case (e_FM_PORT_COUNTERS_WRED_DISCARD): ++ case (e_FM_PORT_COUNTERS_LENGTH_ERR): ++ case (e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT): ++ case (e_FM_PORT_COUNTERS_DEALLOC_BUF): ++ return TRUE; ++ case (e_FM_PORT_COUNTERS_RX_FILTER_FRAME): ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) ++ return FALSE; ++ else ++ return TRUE; ++ default: ++ return FALSE; ++ } ++} ++ ++static t_Error BmiPortCheckAndGetCounterType( ++ t_FmPort *p_FmPort, e_FmPortCounters counter, ++ enum fman_port_stats_counters *p_StatsType, ++ enum fman_port_perf_counters *p_PerfType, bool *p_IsStats) ++{ ++ volatile uint32_t *p_Reg; ++ bool isValid; ++ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_Reg = &p_FmPort->port.bmi_regs->rx.fmbm_rstc; ++ isValid = CheckRxBmiCounter(p_FmPort, counter); ++ break; ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_TX): ++ p_Reg = &p_FmPort->port.bmi_regs->tx.fmbm_tstc; ++ isValid = CheckTxBmiCounter(p_FmPort, counter); ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ p_Reg = &p_FmPort->port.bmi_regs->oh.fmbm_ostc; ++ isValid = CheckOhBmiCounter(p_FmPort, counter); ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported port type")); ++ } ++ ++ if (!isValid) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ++ ("Requested counter is not available for this port type")); ++ ++ /* check that counters are enabled */ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_CYCLE): ++ case (e_FM_PORT_COUNTERS_TASK_UTIL): ++ case (e_FM_PORT_COUNTERS_QUEUE_UTIL): ++ case (e_FM_PORT_COUNTERS_DMA_UTIL): ++ case (e_FM_PORT_COUNTERS_FIFO_UTIL): ++ case (e_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION): ++ /* performance counters - may be read when disabled */ ++ *p_IsStats = FALSE; ++ break; ++ case (e_FM_PORT_COUNTERS_FRAME): ++ case (e_FM_PORT_COUNTERS_DISCARD_FRAME): ++ case (e_FM_PORT_COUNTERS_DEALLOC_BUF): ++ case (e_FM_PORT_COUNTERS_RX_BAD_FRAME): ++ case (e_FM_PORT_COUNTERS_RX_LARGE_FRAME): ++ case (e_FM_PORT_COUNTERS_RX_FILTER_FRAME): ++ case (e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR): ++ case (e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD): ++ case (e_FM_PORT_COUNTERS_LENGTH_ERR): ++ case (e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT): ++ case (e_FM_PORT_COUNTERS_WRED_DISCARD): ++ *p_IsStats = TRUE; ++ if (!(GET_UINT32(*p_Reg) & BMI_COUNTERS_EN)) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ++ ("Requested counter was not enabled")); ++ break; ++ default: ++ break; ++ } ++ ++ /* Set counter */ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_CYCLE): ++ *p_PerfType = E_FMAN_PORT_PERF_CNT_CYCLE; ++ break; ++ case (e_FM_PORT_COUNTERS_TASK_UTIL): ++ *p_PerfType = E_FMAN_PORT_PERF_CNT_TASK_UTIL; ++ break; ++ case (e_FM_PORT_COUNTERS_QUEUE_UTIL): ++ *p_PerfType = E_FMAN_PORT_PERF_CNT_QUEUE_UTIL; ++ break; ++ case (e_FM_PORT_COUNTERS_DMA_UTIL): ++ *p_PerfType = E_FMAN_PORT_PERF_CNT_DMA_UTIL; ++ break; ++ case (e_FM_PORT_COUNTERS_FIFO_UTIL): ++ *p_PerfType = E_FMAN_PORT_PERF_CNT_FIFO_UTIL; ++ break; ++ case (e_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION): ++ *p_PerfType = E_FMAN_PORT_PERF_CNT_RX_PAUSE; ++ break; ++ case (e_FM_PORT_COUNTERS_FRAME): ++ *p_StatsType = E_FMAN_PORT_STATS_CNT_FRAME; ++ break; ++ case (e_FM_PORT_COUNTERS_DISCARD_FRAME): ++ *p_StatsType = E_FMAN_PORT_STATS_CNT_DISCARD; ++ break; ++ case (e_FM_PORT_COUNTERS_DEALLOC_BUF): ++ *p_StatsType = E_FMAN_PORT_STATS_CNT_DEALLOC_BUF; ++ break; ++ case (e_FM_PORT_COUNTERS_RX_BAD_FRAME): ++ *p_StatsType = E_FMAN_PORT_STATS_CNT_RX_BAD_FRAME; ++ break; ++ case (e_FM_PORT_COUNTERS_RX_LARGE_FRAME): ++ *p_StatsType = E_FMAN_PORT_STATS_CNT_RX_LARGE_FRAME; ++ break; ++ case (e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD): ++ *p_StatsType = E_FMAN_PORT_STATS_CNT_RX_OUT_OF_BUF; ++ break; ++ case (e_FM_PORT_COUNTERS_RX_FILTER_FRAME): ++ *p_StatsType = E_FMAN_PORT_STATS_CNT_FILTERED_FRAME; ++ break; ++ case (e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR): ++ *p_StatsType = E_FMAN_PORT_STATS_CNT_DMA_ERR; ++ break; ++ case (e_FM_PORT_COUNTERS_WRED_DISCARD): ++ *p_StatsType = E_FMAN_PORT_STATS_CNT_WRED_DISCARD; ++ break; ++ case (e_FM_PORT_COUNTERS_LENGTH_ERR): ++ *p_StatsType = E_FMAN_PORT_STATS_CNT_LEN_ERR; ++ break; ++ case (e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT): ++ *p_StatsType = E_FMAN_PORT_STATS_CNT_UNSUPPORTED_FORMAT; ++ break; ++ default: ++ break; ++ } ++ ++ return E_OK; ++} ++ ++static t_Error AdditionalPrsParams(t_FmPort *p_FmPort, ++ t_FmPcdPrsAdditionalHdrParams *p_HdrParams, ++ uint32_t *p_SoftSeqAttachReg) ++{ ++ uint8_t hdrNum, Ipv4HdrNum; ++ u_FmPcdHdrPrsOpts *p_prsOpts; ++ uint32_t tmpReg = *p_SoftSeqAttachReg, tmpPrsOffset; ++ ++ if (IS_PRIVATE_HEADER(p_HdrParams->hdr) ++ || IS_SPECIAL_HEADER(p_HdrParams->hdr)) ++ RETURN_ERROR( ++ MAJOR, E_NOT_SUPPORTED, ++ ("No additional parameters for private or special headers.")); ++ ++ if (p_HdrParams->errDisable) ++ tmpReg |= PRS_HDR_ERROR_DIS; ++ ++ /* Set parser options */ ++ if (p_HdrParams->usePrsOpts) ++ { ++ p_prsOpts = &p_HdrParams->prsOpts; ++ switch (p_HdrParams->hdr) ++ { ++ case (HEADER_TYPE_MPLS): ++ if (p_prsOpts->mplsPrsOptions.labelInterpretationEnable) ++ tmpReg |= PRS_HDR_MPLS_LBL_INTER_EN; ++ hdrNum = GetPrsHdrNum(p_prsOpts->mplsPrsOptions.nextParse); ++ if (hdrNum == ILLEGAL_HDR_NUM) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ Ipv4HdrNum = GetPrsHdrNum(HEADER_TYPE_IPv4); ++ if (hdrNum < Ipv4HdrNum) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("Header must be equal or higher than IPv4")); ++ tmpReg |= ((uint32_t)hdrNum * PRS_HDR_ENTRY_SIZE) ++ << PRS_HDR_MPLS_NEXT_HDR_SHIFT; ++ break; ++ case (HEADER_TYPE_PPPoE): ++ if (p_prsOpts->pppoePrsOptions.enableMTUCheck) ++ tmpReg |= PRS_HDR_PPPOE_MTU_CHECK_EN; ++ break; ++ case (HEADER_TYPE_IPv6): ++ if (p_prsOpts->ipv6PrsOptions.routingHdrEnable) ++ tmpReg |= PRS_HDR_IPV6_ROUTE_HDR_EN; ++ break; ++ case (HEADER_TYPE_TCP): ++ if (p_prsOpts->tcpPrsOptions.padIgnoreChecksum) ++ tmpReg |= PRS_HDR_TCP_PAD_REMOVAL; ++ else ++ tmpReg &= ~PRS_HDR_TCP_PAD_REMOVAL; ++ break; ++ case (HEADER_TYPE_UDP): ++ if (p_prsOpts->udpPrsOptions.padIgnoreChecksum) ++ tmpReg |= PRS_HDR_UDP_PAD_REMOVAL; ++ else ++ tmpReg &= ~PRS_HDR_UDP_PAD_REMOVAL; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid header")); ++ } ++ } ++ ++ /* set software parsing (address is divided in 2 since parser uses 2 byte access. */ ++ if (p_HdrParams->swPrsEnable) ++ { ++ tmpPrsOffset = FmPcdGetSwPrsOffset(p_FmPort->h_FmPcd, p_HdrParams->hdr, ++ p_HdrParams->indexPerHdr); ++ if (tmpPrsOffset == ILLEGAL_BASE) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ tmpReg |= (PRS_HDR_SW_PRS_EN | tmpPrsOffset); ++ } ++ *p_SoftSeqAttachReg = tmpReg; ++ ++ return E_OK; ++} ++ ++static uint32_t GetPortSchemeBindParams( ++ t_Handle h_FmPort, t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint32_t walking1Mask = 0x80000000, tmp; ++ uint8_t idx = 0; ++ ++ p_SchemeBind->netEnvId = p_FmPort->netEnvId; ++ p_SchemeBind->hardwarePortId = p_FmPort->hardwarePortId; ++ p_SchemeBind->useClsPlan = p_FmPort->useClsPlan; ++ p_SchemeBind->numOfSchemes = 0; ++ tmp = p_FmPort->schemesPerPortVector; ++ if (tmp) ++ { ++ while (tmp) ++ { ++ if (tmp & walking1Mask) ++ { ++ p_SchemeBind->schemesIds[p_SchemeBind->numOfSchemes] = idx; ++ p_SchemeBind->numOfSchemes++; ++ tmp &= ~walking1Mask; ++ } ++ walking1Mask >>= 1; ++ idx++; ++ } ++ } ++ ++ return tmp; ++} ++ ++static void FmPortCheckNApplyMacsec(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ volatile uint32_t *p_BmiCfgReg = NULL; ++ uint32_t macsecEn = BMI_PORT_CFG_EN_MACSEC; ++ uint32_t lcv, walking1Mask = 0x80000000; ++ uint8_t cnt = 0; ++ ++ ASSERT_COND(p_FmPort); ++ ASSERT_COND(p_FmPort->h_FmPcd); ++ ASSERT_COND(!p_FmPort->p_FmPortDriverParam); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ return; ++ ++ p_BmiCfgReg = &p_FmPort->port.bmi_regs->rx.fmbm_rcfg; ++ /* get LCV for MACSEC */ ++ if ((lcv = FmPcdGetMacsecLcv(p_FmPort->h_FmPcd, p_FmPort->netEnvId)) ++ != 0) ++ { ++ while (!(lcv & walking1Mask)) ++ { ++ cnt++; ++ walking1Mask >>= 1; ++ } ++ ++ macsecEn |= (uint32_t)cnt << BMI_PORT_CFG_MS_SEL_SHIFT; ++ WRITE_UINT32(*p_BmiCfgReg, GET_UINT32(*p_BmiCfgReg) | macsecEn); ++ } ++} ++ ++static t_Error SetPcd(t_FmPort *p_FmPort, t_FmPortPcdParams *p_PcdParams) ++{ ++ t_Error err = E_OK; ++ uint32_t tmpReg; ++ volatile uint32_t *p_BmiNia = NULL; ++ volatile uint32_t *p_BmiPrsNia = NULL; ++ volatile uint32_t *p_BmiPrsStartOffset = NULL; ++ volatile uint32_t *p_BmiInitPrsResult = NULL; ++ volatile uint32_t *p_BmiCcBase = NULL; ++ uint16_t hdrNum, L3HdrNum, greHdrNum; ++ int i; ++ bool isEmptyClsPlanGrp; ++ uint32_t tmpHxs[FM_PCD_PRS_NUM_OF_HDRS]; ++ uint16_t absoluteProfileId; ++ uint8_t physicalSchemeId; ++ uint32_t ccTreePhysOffset; ++ t_FmPcdKgInterModuleBindPortToSchemes schemeBind; ++ uint32_t initialSwPrs = 0; ++ ++ ASSERT_COND(p_FmPort); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPort->imEn) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for non-independant mode ports only")); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for Rx and offline parsing ports only")); ++ ++ p_FmPort->netEnvId = FmPcdGetNetEnvId(p_PcdParams->h_NetEnv); ++ ++ p_FmPort->pcdEngines = 0; ++ ++ /* initialize p_FmPort->pcdEngines field in port's structure */ ++ switch (p_PcdParams->pcdSupport) ++ { ++ case (e_FM_PORT_PCD_SUPPORT_NONE): ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("No PCD configuration required if e_FM_PORT_PCD_SUPPORT_NONE selected")); ++ case (e_FM_PORT_PCD_SUPPORT_PRS_ONLY): ++ p_FmPort->pcdEngines |= FM_PCD_PRS; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PLCR_ONLY): ++ p_FmPort->pcdEngines |= FM_PCD_PLCR; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR): ++ p_FmPort->pcdEngines |= FM_PCD_PRS; ++ p_FmPort->pcdEngines |= FM_PCD_PLCR; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG): ++ p_FmPort->pcdEngines |= FM_PCD_PRS; ++ p_FmPort->pcdEngines |= FM_PCD_KG; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC): ++ p_FmPort->pcdEngines |= FM_PCD_PRS; ++ p_FmPort->pcdEngines |= FM_PCD_CC; ++ p_FmPort->pcdEngines |= FM_PCD_KG; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR): ++ p_FmPort->pcdEngines |= FM_PCD_PRS; ++ p_FmPort->pcdEngines |= FM_PCD_KG; ++ p_FmPort->pcdEngines |= FM_PCD_CC; ++ p_FmPort->pcdEngines |= FM_PCD_PLCR; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_CC): ++ p_FmPort->pcdEngines |= FM_PCD_PRS; ++ p_FmPort->pcdEngines |= FM_PCD_CC; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_CC_AND_PLCR): ++ p_FmPort->pcdEngines |= FM_PCD_PRS; ++ p_FmPort->pcdEngines |= FM_PCD_CC; ++ p_FmPort->pcdEngines |= FM_PCD_PLCR; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR): ++ p_FmPort->pcdEngines |= FM_PCD_PRS; ++ p_FmPort->pcdEngines |= FM_PCD_KG; ++ p_FmPort->pcdEngines |= FM_PCD_PLCR; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_CC_ONLY): ++ p_FmPort->pcdEngines |= FM_PCD_CC; ++ break; ++#ifdef FM_CAPWAP_SUPPORT ++ case (e_FM_PORT_PCD_SUPPORT_CC_AND_KG): ++ p_FmPort->pcdEngines |= FM_PCD_CC; ++ p_FmPort->pcdEngines |= FM_PCD_KG; ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR): ++ p_FmPort->pcdEngines |= FM_PCD_CC; ++ p_FmPort->pcdEngines |= FM_PCD_KG; ++ p_FmPort->pcdEngines |= FM_PCD_PLCR; ++ break; ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid pcdSupport")); ++ } ++ ++ if ((p_FmPort->pcdEngines & FM_PCD_PRS) ++ && (p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams ++ > FM_PCD_PRS_NUM_OF_HDRS)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("Port parser numOfHdrsWithAdditionalParams may not exceed %d", FM_PCD_PRS_NUM_OF_HDRS)); ++ ++ /* check that parameters exist for each and only each defined engine */ ++ if ((!!(p_FmPort->pcdEngines & FM_PCD_PRS) != !!p_PcdParams->p_PrsParams) ++ || (!!(p_FmPort->pcdEngines & FM_PCD_KG) ++ != !!p_PcdParams->p_KgParams) ++ || (!!(p_FmPort->pcdEngines & FM_PCD_CC) ++ != !!p_PcdParams->p_CcParams)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("PCD initialization structure is not consistent with pcdSupport")); ++ ++ /* get PCD registers pointers */ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiNia = &p_FmPort->port.bmi_regs->rx.fmbm_rfne; ++ p_BmiPrsNia = &p_FmPort->port.bmi_regs->rx.fmbm_rfpne; ++ p_BmiPrsStartOffset = &p_FmPort->port.bmi_regs->rx.fmbm_rpso; ++ p_BmiInitPrsResult = &p_FmPort->port.bmi_regs->rx.fmbm_rprai[0]; ++ p_BmiCcBase = &p_FmPort->port.bmi_regs->rx.fmbm_rccb; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiNia = &p_FmPort->port.bmi_regs->oh.fmbm_ofne; ++ p_BmiPrsNia = &p_FmPort->port.bmi_regs->oh.fmbm_ofpne; ++ p_BmiPrsStartOffset = &p_FmPort->port.bmi_regs->oh.fmbm_opso; ++ p_BmiInitPrsResult = &p_FmPort->port.bmi_regs->oh.fmbm_oprai[0]; ++ p_BmiCcBase = &p_FmPort->port.bmi_regs->oh.fmbm_occb; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ ++ /* set PCD port parameter */ ++ if (p_FmPort->pcdEngines & FM_PCD_CC) ++ { ++ err = FmPcdCcBindTree(p_FmPort->h_FmPcd, p_PcdParams, ++ p_PcdParams->p_CcParams->h_CcTree, ++ &ccTreePhysOffset, p_FmPort); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ WRITE_UINT32(*p_BmiCcBase, ccTreePhysOffset); ++ p_FmPort->ccTreeId = p_PcdParams->p_CcParams->h_CcTree; ++ } ++ ++ if (p_FmPort->pcdEngines & FM_PCD_KG) ++ { ++ if (p_PcdParams->p_KgParams->numOfSchemes == 0) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("For ports using Keygen, at least one scheme must be bound. ")); ++ ++ err = FmPcdKgSetOrBindToClsPlanGrp(p_FmPort->h_FmPcd, ++ p_FmPort->hardwarePortId, ++ p_FmPort->netEnvId, ++ p_FmPort->optArray, ++ &p_FmPort->clsPlanGrpId, ++ &isEmptyClsPlanGrp); ++ if (err) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("FmPcdKgSetOrBindToClsPlanGrp failed. ")); ++ ++ p_FmPort->useClsPlan = !isEmptyClsPlanGrp; ++ ++ schemeBind.netEnvId = p_FmPort->netEnvId; ++ schemeBind.hardwarePortId = p_FmPort->hardwarePortId; ++ schemeBind.numOfSchemes = p_PcdParams->p_KgParams->numOfSchemes; ++ schemeBind.useClsPlan = p_FmPort->useClsPlan; ++ ++ /* for each scheme */ ++ for (i = 0; i < p_PcdParams->p_KgParams->numOfSchemes; i++) ++ { ++ ASSERT_COND(p_PcdParams->p_KgParams->h_Schemes[i]); ++ physicalSchemeId = FmPcdKgGetSchemeId( ++ p_PcdParams->p_KgParams->h_Schemes[i]); ++ schemeBind.schemesIds[i] = physicalSchemeId; ++ /* build vector */ ++ p_FmPort->schemesPerPortVector |= 1 ++ << (31 - (uint32_t)physicalSchemeId); ++#if (DPAA_VERSION >= 11) ++ /*because of the state that VSPE is defined per port - all PCD path should be according to this requirement ++ if !VSPE - in port, for relevant scheme VSPE can not be set*/ ++ if (!p_FmPort->vspe ++ && FmPcdKgGetVspe((p_PcdParams->p_KgParams->h_Schemes[i]))) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("VSPE is not at port level")); ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ err = FmPcdKgBindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ /***************************/ ++ /* configure NIA after BMI */ ++ /***************************/ ++ /* rfne may contain FDCS bits, so first we read them. */ ++ p_FmPort->savedBmiNia = GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK; ++ ++ /* If policer is used directly after BMI or PRS */ ++ if ((p_FmPort->pcdEngines & FM_PCD_PLCR) ++ && ((p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PLCR_ONLY) ++ || (p_PcdParams->pcdSupport ++ == e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR))) ++ { ++ if (!p_PcdParams->p_PlcrParams->h_Profile) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("Profile should be initialized")); ++ ++ absoluteProfileId = (uint16_t)FmPcdPlcrProfileGetAbsoluteId( ++ p_PcdParams->p_PlcrParams->h_Profile); ++ ++ if (!FmPcdPlcrIsProfileValid(p_FmPort->h_FmPcd, absoluteProfileId)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("Private port profile not valid.")); ++ ++ tmpReg = (uint32_t)(absoluteProfileId | NIA_PLCR_ABSOLUTE); ++ ++ if (p_FmPort->pcdEngines & FM_PCD_PRS) /* e_FM_PCD_SUPPORT_PRS_AND_PLCR */ ++ /* update BMI HPNIA */ ++ WRITE_UINT32(*p_BmiPrsNia, (uint32_t)(NIA_ENG_PLCR | tmpReg)); ++ else ++ /* e_FM_PCD_SUPPORT_PLCR_ONLY */ ++ /* update BMI NIA */ ++ p_FmPort->savedBmiNia |= (uint32_t)(NIA_ENG_PLCR); ++ } ++ ++ /* if CC is used directly after BMI */ ++ if ((p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_CC_ONLY) ++#ifdef FM_CAPWAP_SUPPORT ++ || (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_CC_AND_KG) ++ || (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR) ++#endif /* FM_CAPWAP_SUPPORT */ ++ ) ++ { ++ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_OPERATION, ++ ("e_FM_PORT_PCD_SUPPORT_CC_xx available for offline parsing ports only")); ++ p_FmPort->savedBmiNia |= (uint32_t)(NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC); ++ /* check that prs start offset == RIM[FOF] */ ++ } ++ ++ if (p_FmPort->pcdEngines & FM_PCD_PRS) ++ { ++ ASSERT_COND(p_PcdParams->p_PrsParams); ++#if (DPAA_VERSION >= 11) ++ if (p_PcdParams->p_PrsParams->firstPrsHdr == HEADER_TYPE_CAPWAP) ++ hdrNum = OFFLOAD_SW_PATCH_CAPWAP_LABEL; ++ else ++ { ++#endif /* (DPAA_VERSION >= 11) */ ++ /* if PRS is used it is always first */ ++ hdrNum = GetPrsHdrNum(p_PcdParams->p_PrsParams->firstPrsHdr); ++ if (hdrNum == ILLEGAL_HDR_NUM) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unsupported header.")); ++#if (DPAA_VERSION >= 11) ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ p_FmPort->savedBmiNia |= (uint32_t)(NIA_ENG_PRS | (uint32_t)(hdrNum)); ++ /* set after parser NIA */ ++ tmpReg = 0; ++ switch (p_PcdParams->pcdSupport) ++ { ++ case (e_FM_PORT_PCD_SUPPORT_PRS_ONLY): ++ WRITE_UINT32(*p_BmiPrsNia, ++ GET_NIA_BMI_AC_ENQ_FRAME(p_FmPort->h_FmPcd)); ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC): ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR): ++ tmpReg = NIA_KG_CC_EN; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG): ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR): ++ if (p_PcdParams->p_KgParams->directScheme) ++ { ++ physicalSchemeId = FmPcdKgGetSchemeId( ++ p_PcdParams->p_KgParams->h_DirectScheme); ++ /* check that this scheme was bound to this port */ ++ for (i = 0; i < p_PcdParams->p_KgParams->numOfSchemes; i++) ++ if (p_PcdParams->p_KgParams->h_DirectScheme ++ == p_PcdParams->p_KgParams->h_Schemes[i]) ++ break; ++ if (i == p_PcdParams->p_KgParams->numOfSchemes) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("Direct scheme is not one of the port selected schemes.")); ++ tmpReg |= (uint32_t)(NIA_KG_DIRECT | physicalSchemeId); ++ } ++ WRITE_UINT32(*p_BmiPrsNia, NIA_ENG_KG | tmpReg); ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_CC): ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_CC_AND_PLCR): ++ WRITE_UINT32(*p_BmiPrsNia, ++ (uint32_t)(NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC)); ++ break; ++ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR): ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid PCD support")); ++ } ++ ++ /* set start parsing offset */ ++ WRITE_UINT32(*p_BmiPrsStartOffset, ++ p_PcdParams->p_PrsParams->parsingOffset); ++ ++ /************************************/ ++ /* Parser port parameters */ ++ /************************************/ ++ /* stop before configuring */ ++ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pcac, PRS_CAC_STOP); ++ /* wait for parser to be in idle state */ ++ while (GET_UINT32(p_FmPort->p_FmPortPrsRegs->pcac) & PRS_CAC_ACTIVE) ++ ; ++ ++ /* set soft seq attachment register */ ++ memset(tmpHxs, 0, FM_PCD_PRS_NUM_OF_HDRS * sizeof(uint32_t)); ++ ++ /* set protocol options */ ++ for (i = 0; p_FmPort->optArray[i]; i++) ++ switch (p_FmPort->optArray[i]) ++ { ++ case (ETH_BROADCAST): ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_ETH); ++ tmpHxs[hdrNum] |= (i + 1) << PRS_HDR_ETH_BC_SHIFT; ++ break; ++ case (ETH_MULTICAST): ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_ETH); ++ tmpHxs[hdrNum] |= (i + 1) << PRS_HDR_ETH_MC_SHIFT; ++ break; ++ case (VLAN_STACKED): ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_VLAN); ++ tmpHxs[hdrNum] |= (i + 1) << PRS_HDR_VLAN_STACKED_SHIFT; ++ break; ++ case (MPLS_STACKED): ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_MPLS); ++ tmpHxs[hdrNum] |= (i + 1) << PRS_HDR_MPLS_STACKED_SHIFT; ++ break; ++ case (IPV4_BROADCAST_1): ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_IPv4); ++ tmpHxs[hdrNum] |= (i + 1) << PRS_HDR_IPV4_1_BC_SHIFT; ++ break; ++ case (IPV4_MULTICAST_1): ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_IPv4); ++ tmpHxs[hdrNum] |= (i + 1) << PRS_HDR_IPV4_1_MC_SHIFT; ++ break; ++ case (IPV4_UNICAST_2): ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_IPv4); ++ tmpHxs[hdrNum] |= (i + 1) << PRS_HDR_IPV4_2_UC_SHIFT; ++ break; ++ case (IPV4_MULTICAST_BROADCAST_2): ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_IPv4); ++ tmpHxs[hdrNum] |= (i + 1) << PRS_HDR_IPV4_2_MC_BC_SHIFT; ++ break; ++ case (IPV6_MULTICAST_1): ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_IPv6); ++ tmpHxs[hdrNum] |= (i + 1) << PRS_HDR_IPV6_1_MC_SHIFT; ++ break; ++ case (IPV6_UNICAST_2): ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_IPv6); ++ tmpHxs[hdrNum] |= (i + 1) << PRS_HDR_IPV6_2_UC_SHIFT; ++ break; ++ case (IPV6_MULTICAST_2): ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_IPv6); ++ tmpHxs[hdrNum] |= (i + 1) << PRS_HDR_IPV6_2_MC_SHIFT; ++ break; ++ } ++ ++ if (FmPcdNetEnvIsHdrExist(p_FmPort->h_FmPcd, p_FmPort->netEnvId, ++ HEADER_TYPE_UDP_ENCAP_ESP)) ++ { ++ if (p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams == FM_PCD_PRS_NUM_OF_HDRS) ++ RETURN_ERROR( ++ MINOR, E_INVALID_VALUE, ++ ("If HEADER_TYPE_UDP_ENCAP_ESP is used, numOfHdrsWithAdditionalParams may be up to FM_PCD_PRS_NUM_OF_HDRS - 1")); ++ ++ p_PcdParams->p_PrsParams->additionalParams[p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams].hdr = ++ HEADER_TYPE_UDP; ++ p_PcdParams->p_PrsParams->additionalParams[p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams].swPrsEnable = ++ TRUE; ++ p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams++; ++ } ++ ++ /* set MPLS default next header - HW reset workaround */ ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_MPLS); ++ tmpHxs[hdrNum] |= PRS_HDR_MPLS_LBL_INTER_EN; ++ L3HdrNum = GetPrsHdrNum(HEADER_TYPE_USER_DEFINED_L3); ++ tmpHxs[hdrNum] |= (uint32_t)L3HdrNum << PRS_HDR_MPLS_NEXT_HDR_SHIFT; ++ ++ /* for GRE, disable errors */ ++ greHdrNum = GetPrsHdrNum(HEADER_TYPE_GRE); ++ tmpHxs[greHdrNum] |= PRS_HDR_ERROR_DIS; ++ ++ /* For UDP remove PAD from L4 checksum calculation */ ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_UDP); ++ tmpHxs[hdrNum] |= PRS_HDR_UDP_PAD_REMOVAL; ++ /* For TCP remove PAD from L4 checksum calculation */ ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_TCP); ++ tmpHxs[hdrNum] |= PRS_HDR_TCP_PAD_REMOVAL; ++ ++ /* config additional params for specific headers */ ++ for (i = 0; i < p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams; ++ i++) ++ { ++ /* case for using sw parser as the initial NIA address, before ++ * HW parsing ++ */ ++ if ((p_PcdParams->p_PrsParams->additionalParams[i].hdr == HEADER_TYPE_NONE) && ++ p_PcdParams->p_PrsParams->additionalParams[i].swPrsEnable) ++ { ++ initialSwPrs = FmPcdGetSwPrsOffset(p_FmPort->h_FmPcd, HEADER_TYPE_NONE, ++ p_PcdParams->p_PrsParams->additionalParams[i].indexPerHdr); ++ if (initialSwPrs == ILLEGAL_BASE) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ ++ /* clear parser first HXS */ ++ p_FmPort->savedBmiNia &= ~BMI_RFNE_HXS_MASK; /* 0x000000FF */ ++ /* rewrite with soft parser start */ ++ p_FmPort->savedBmiNia |= initialSwPrs; ++ continue; ++ } ++ ++ hdrNum = ++ GetPrsHdrNum(p_PcdParams->p_PrsParams->additionalParams[i].hdr); ++ if (hdrNum == ILLEGAL_HDR_NUM) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ if (hdrNum == NO_HDR_NUM) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("Private headers may not use additional parameters")); ++ ++ err = AdditionalPrsParams( ++ p_FmPort, &p_PcdParams->p_PrsParams->additionalParams[i], ++ &tmpHxs[hdrNum]); ++ if (err) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ } ++ ++ /* Check if ip-reassembly port - need to link sw-parser code */ ++ if (p_FmPort->h_IpReassemblyManip) ++ { ++ /* link to sw parser code for IP Frag - only if no other code is applied. */ ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_IPv4); ++ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN)) ++ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | OFFLOAD_SW_PATCH_IPv4_IPR_LABEL); ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_IPv6); ++ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN)) ++ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | OFFLOAD_SW_PATCH_IPv6_IPR_LABEL); ++ } else { ++ if (FmPcdNetEnvIsHdrExist(p_FmPort->h_FmPcd, p_FmPort->netEnvId, HEADER_TYPE_UDP_LITE)) ++ { ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_IPv6); ++ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN)) ++ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | OFFLOAD_SW_PATCH_IPv6_IPF_LABEL); ++ } else if ((FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd) ++ && (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING))) ++ { ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_IPv6); ++ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN)) ++ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | OFFLOAD_SW_PATCH_IPv6_IPF_LABEL); ++ } ++ } ++ ++#if ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++ if (FmPcdNetEnvIsHdrExist(p_FmPort->h_FmPcd, p_FmPort->netEnvId, ++ HEADER_TYPE_UDP_LITE)) ++ { ++ /* link to sw parser code for udp lite - only if no other code is applied. */ ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_IPv6); ++ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN)) ++ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | UDP_LITE_SW_PATCH_LABEL); ++ } ++#endif /* ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) */ ++ for (i = 0; i < FM_PCD_PRS_NUM_OF_HDRS; i++) ++ { ++ /* For all header set LCV as taken from netEnv*/ ++ WRITE_UINT32( ++ p_FmPort->p_FmPortPrsRegs->hdrs[i].lcv, ++ FmPcdGetLcv(p_FmPort->h_FmPcd, p_FmPort->netEnvId, (uint8_t)i)); ++ /* set HXS register according to default+Additional params+protocol options */ ++ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->hdrs[i].softSeqAttach, ++ tmpHxs[i]); ++ } ++ ++ /* set tpid. */ ++ tmpReg = PRS_TPID_DFLT; ++ if (p_PcdParams->p_PrsParams->setVlanTpid1) ++ { ++ tmpReg &= PRS_TPID2_MASK; ++ tmpReg |= (uint32_t)p_PcdParams->p_PrsParams->vlanTpid1 ++ << PRS_PCTPID_SHIFT; ++ } ++ if (p_PcdParams->p_PrsParams->setVlanTpid2) ++ { ++ tmpReg &= PRS_TPID1_MASK; ++ tmpReg |= (uint32_t)p_PcdParams->p_PrsParams->vlanTpid2; ++ }WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pctpid, tmpReg); ++ ++ /* enable parser */ ++ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pcac, 0); ++ ++ if (p_PcdParams->p_PrsParams->prsResultPrivateInfo) ++ p_FmPort->privateInfo = ++ p_PcdParams->p_PrsParams->prsResultPrivateInfo; ++ ++ } /* end parser */ ++ else { ++ if (FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd) ++ && (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ { ++ hdrNum = GetPrsHdrNum(HEADER_TYPE_IPv6); ++ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->hdrs[hdrNum].softSeqAttach, ++ (PRS_HDR_SW_PRS_EN | OFFLOAD_SW_PATCH_IPv6_IPF_LABEL)); ++ } ++ ++ WRITE_UINT32(*p_BmiPrsStartOffset, 0); ++ ++ p_FmPort->privateInfo = 0; ++ } ++ ++ FmPortCheckNApplyMacsec(p_FmPort); ++ ++ WRITE_UINT32( ++ *p_BmiPrsStartOffset, ++ GET_UINT32(*p_BmiPrsStartOffset) + p_FmPort->internalBufferOffset); ++ ++ /* set initial parser result - used for all engines */ ++ for (i = 0; i < FM_PORT_PRS_RESULT_NUM_OF_WORDS; i++) ++ { ++ if (!i) ++ WRITE_UINT32( ++ *(p_BmiInitPrsResult), ++ (uint32_t)(((uint32_t)p_FmPort->privateInfo << BMI_PR_PORTID_SHIFT) | BMI_PRS_RESULT_HIGH)); ++ else ++ { ++ if (i < FM_PORT_PRS_RESULT_NUM_OF_WORDS / 2) ++ WRITE_UINT32(*(p_BmiInitPrsResult+i), BMI_PRS_RESULT_HIGH); ++ else ++ WRITE_UINT32(*(p_BmiInitPrsResult+i), BMI_PRS_RESULT_LOW); ++ } ++ } ++ ++ return E_OK; ++} ++ ++static t_Error DeletePcd(t_FmPort *p_FmPort) ++{ ++ t_Error err = E_OK; ++ volatile uint32_t *p_BmiNia = NULL; ++ volatile uint32_t *p_BmiPrsStartOffset = NULL; ++ ++ ASSERT_COND(p_FmPort); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPort->imEn) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for non-independant mode ports only")); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ RETURN_ERROR( MAJOR, E_INVALID_OPERATION, ++ ("available for Rx and offline parsing ports only")); ++ ++ if (!p_FmPort->pcdEngines) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("called for non PCD port")); ++ ++ /* get PCD registers pointers */ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiNia = &p_FmPort->port.bmi_regs->rx.fmbm_rfne; ++ p_BmiPrsStartOffset = &p_FmPort->port.bmi_regs->rx.fmbm_rpso; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiNia = &p_FmPort->port.bmi_regs->oh.fmbm_ofne; ++ p_BmiPrsStartOffset = &p_FmPort->port.bmi_regs->oh.fmbm_opso; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ ++ if ((GET_UINT32(*p_BmiNia) & GET_NO_PCD_NIA_BMI_AC_ENQ_FRAME()) ++ != GET_NO_PCD_NIA_BMI_AC_ENQ_FRAME()) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("port has to be detached previousely")); ++ ++ WRITE_UINT32(*p_BmiPrsStartOffset, 0); ++ ++ /* "cut" PCD out of the port's flow - go to BMI */ ++ /* WRITE_UINT32(*p_BmiNia, (p_FmPort->savedBmiNia & BMI_RFNE_FDCS_MASK) | (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)); */ ++ ++ if (p_FmPort->pcdEngines & FM_PCD_PRS) ++ { ++ /* stop parser */ ++ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pcac, PRS_CAC_STOP); ++ /* wait for parser to be in idle state */ ++ while (GET_UINT32(p_FmPort->p_FmPortPrsRegs->pcac) & PRS_CAC_ACTIVE) ++ ; ++ } ++ ++ if (p_FmPort->pcdEngines & FM_PCD_KG) ++ { ++ t_FmPcdKgInterModuleBindPortToSchemes schemeBind; ++ ++ /* unbind all schemes */ ++ p_FmPort->schemesPerPortVector = GetPortSchemeBindParams(p_FmPort, ++ &schemeBind); ++ ++ err = FmPcdKgUnbindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ err = FmPcdKgDeleteOrUnbindPortToClsPlanGrp(p_FmPort->h_FmPcd, ++ p_FmPort->hardwarePortId, ++ p_FmPort->clsPlanGrpId); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ p_FmPort->useClsPlan = FALSE; ++ } ++ ++ if (p_FmPort->pcdEngines & FM_PCD_CC) ++ { ++ /* unbind - we need to get the treeId too */ ++ err = FmPcdCcUnbindTree(p_FmPort->h_FmPcd, p_FmPort->ccTreeId); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ p_FmPort->pcdEngines = 0; ++ ++ return E_OK; ++} ++ ++static t_Error AttachPCD(t_FmPort *p_FmPort) ++{ ++ volatile uint32_t *p_BmiNia = NULL; ++ ++ ASSERT_COND(p_FmPort); ++ ++ /* get PCD registers pointers */ ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ p_BmiNia = &p_FmPort->port.bmi_regs->oh.fmbm_ofne; ++ else ++ p_BmiNia = &p_FmPort->port.bmi_regs->rx.fmbm_rfne; ++ ++ /* check that current NIA is BMI to BMI */ ++ if ((GET_UINT32(*p_BmiNia) & ~BMI_RFNE_FDCS_MASK) ++ != GET_NO_PCD_NIA_BMI_AC_ENQ_FRAME()) ++ RETURN_ERROR( MAJOR, E_INVALID_OPERATION, ++ ("may be called only for ports in BMI-to-BMI state.")); ++ ++ if (p_FmPort->requiredAction & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY) ++ if (FmSetNumOfRiscsPerPort(p_FmPort->h_Fm, p_FmPort->hardwarePortId, 1, ++ p_FmPort->orFmanCtrl) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ if (p_FmPort->requiredAction & UPDATE_NIA_CMNE) ++ { ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ WRITE_UINT32(p_FmPort->port.bmi_regs->oh.fmbm_ocmne, ++ p_FmPort->savedBmiCmne); ++ else ++ WRITE_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rcmne, ++ p_FmPort->savedBmiCmne); ++ } ++ ++ if (p_FmPort->requiredAction & UPDATE_NIA_PNEN) ++ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, ++ p_FmPort->savedQmiPnen); ++ ++ if (p_FmPort->requiredAction & UPDATE_NIA_FENE) ++ { ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ WRITE_UINT32(p_FmPort->port.bmi_regs->oh.fmbm_ofene, ++ p_FmPort->savedBmiFene); ++ else ++ WRITE_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rfene, ++ p_FmPort->savedBmiFene); ++ } ++ ++ if (p_FmPort->requiredAction & UPDATE_NIA_FPNE) ++ { ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ WRITE_UINT32(p_FmPort->port.bmi_regs->oh.fmbm_ofpne, ++ p_FmPort->savedBmiFpne); ++ else ++ WRITE_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rfpne, ++ p_FmPort->savedBmiFpne); ++ } ++ ++ if (p_FmPort->requiredAction & UPDATE_OFP_DPTE) ++ { ++ ASSERT_COND(p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING); ++ ++ WRITE_UINT32(p_FmPort->port.bmi_regs->oh.fmbm_ofp, ++ p_FmPort->savedBmiOfp); ++ } ++ ++ WRITE_UINT32(*p_BmiNia, p_FmPort->savedBmiNia); ++ ++ if (p_FmPort->requiredAction & UPDATE_NIA_PNDN) ++ { ++ p_FmPort->origNonRxQmiRegsPndn = ++ GET_UINT32(p_FmPort->port.qmi_regs->fmqm_pndn); ++ WRITE_UINT32(p_FmPort->port.qmi_regs->fmqm_pndn, ++ p_FmPort->savedNonRxQmiRegsPndn); ++ } ++ ++ return E_OK; ++} ++ ++static t_Error DetachPCD(t_FmPort *p_FmPort) ++{ ++ volatile uint32_t *p_BmiNia = NULL; ++ ++ ASSERT_COND(p_FmPort); ++ ++ /* get PCD registers pointers */ ++ if (p_FmPort->requiredAction & UPDATE_NIA_PNDN) ++ WRITE_UINT32(p_FmPort->port.qmi_regs->fmqm_pndn, ++ p_FmPort->origNonRxQmiRegsPndn); ++ ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ p_BmiNia = &p_FmPort->port.bmi_regs->oh.fmbm_ofne; ++ else ++ p_BmiNia = &p_FmPort->port.bmi_regs->rx.fmbm_rfne; ++ ++ WRITE_UINT32( ++ *p_BmiNia, ++ (p_FmPort->savedBmiNia & BMI_RFNE_FDCS_MASK) | GET_NO_PCD_NIA_BMI_AC_ENQ_FRAME()); ++ ++ if (FmPcdGetHcHandle(p_FmPort->h_FmPcd)) ++ FmPcdHcSync(p_FmPort->h_FmPcd); ++ ++ if (p_FmPort->requiredAction & UPDATE_NIA_FENE) ++ { ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ WRITE_UINT32(p_FmPort->port.bmi_regs->oh.fmbm_ofene, ++ NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR); ++ else ++ WRITE_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rfene, ++ NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR); ++ } ++ ++ if (p_FmPort->requiredAction & UPDATE_NIA_PNEN) ++ WRITE_UINT32(p_FmPort->port.qmi_regs->fmqm_pnen, ++ NIA_ENG_BMI | NIA_BMI_AC_RELEASE); ++ ++ if (p_FmPort->requiredAction & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY) ++ if (FmSetNumOfRiscsPerPort(p_FmPort->h_Fm, p_FmPort->hardwarePortId, 2, ++ p_FmPort->orFmanCtrl) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ p_FmPort->requiredAction = 0; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++/* Inter-module API routines */ ++/*****************************************************************************/ ++void FmPortSetMacsecCmd(t_Handle h_FmPort, uint8_t dfltSci) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ volatile uint32_t *p_BmiCfgReg = NULL; ++ uint32_t tmpReg; ++ ++ SANITY_CHECK_RETURN(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_TX)) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_OPERATION, ("The routine is relevant for Tx ports only")); ++ return; ++ } ++ ++ p_BmiCfgReg = &p_FmPort->port.bmi_regs->tx.fmbm_tfca; ++ tmpReg = GET_UINT32(*p_BmiCfgReg) & ~BMI_CMD_ATTR_MACCMD_MASK; ++ tmpReg |= BMI_CMD_ATTR_MACCMD_SECURED; ++ tmpReg |= (((uint32_t)dfltSci << BMI_CMD_ATTR_MACCMD_SC_SHIFT) ++ & BMI_CMD_ATTR_MACCMD_SC_MASK); ++ ++ WRITE_UINT32(*p_BmiCfgReg, tmpReg); ++} ++ ++uint8_t FmPortGetNetEnvId(t_Handle h_FmPort) ++{ ++ return ((t_FmPort*)h_FmPort)->netEnvId; ++} ++ ++uint8_t FmPortGetHardwarePortId(t_Handle h_FmPort) ++{ ++ return ((t_FmPort*)h_FmPort)->hardwarePortId; ++} ++ ++uint32_t FmPortGetPcdEngines(t_Handle h_FmPort) ++{ ++ return ((t_FmPort*)h_FmPort)->pcdEngines; ++} ++ ++#if (DPAA_VERSION >= 11) ++t_Error FmPortSetGprFunc(t_Handle h_FmPort, e_FmPortGprFuncType gprFunc, ++ void **p_Value) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint32_t muramPageOffset; ++ ++ ASSERT_COND(p_FmPort); ++ ASSERT_COND(p_Value); ++ ++ if (p_FmPort->gprFunc != e_FM_PORT_GPR_EMPTY) ++ { ++ if (p_FmPort->gprFunc != gprFunc) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("gpr was assigned with different func")); ++ } ++ else ++ { ++ switch (gprFunc) ++ { ++ case (e_FM_PORT_GPR_MURAM_PAGE): ++ p_FmPort->p_ParamsPage = FM_MURAM_AllocMem(p_FmPort->h_FmMuram, ++ 256, 8); ++ if (!p_FmPort->p_ParamsPage) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for page")); ++ ++ IOMemSet32(p_FmPort->p_ParamsPage, 0, 256); ++ muramPageOffset = ++ (uint32_t)(XX_VirtToPhys(p_FmPort->p_ParamsPage) ++ - p_FmPort->fmMuramPhysBaseAddr); ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ WRITE_UINT32( ++ p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr, ++ muramPageOffset); ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ WRITE_UINT32( ++ p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ogpr, ++ muramPageOffset); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("Invalid port type")); ++ } ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ p_FmPort->gprFunc = gprFunc; ++ } ++ ++ switch (p_FmPort->gprFunc) ++ { ++ case (e_FM_PORT_GPR_MURAM_PAGE): ++ *p_Value = p_FmPort->p_ParamsPage; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ return E_OK; ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++t_Error FmPortGetSetCcParams(t_Handle h_FmPort, ++ t_FmPortGetSetCcParams *p_CcParams) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ int tmpInt; ++ volatile uint32_t *p_BmiPrsStartOffset = NULL; ++ ++ /* this function called from Cc for pass and receive parameters port params between CC and PORT*/ ++ ++ if ((p_CcParams->getCcParams.type & OFFSET_OF_PR) ++ && (p_FmPort->bufferOffsets.prsResultOffset != ILLEGAL_BASE)) ++ { ++ p_CcParams->getCcParams.prOffset = ++ (uint8_t)p_FmPort->bufferOffsets.prsResultOffset; ++ p_CcParams->getCcParams.type &= ~OFFSET_OF_PR; ++ } ++ if (p_CcParams->getCcParams.type & HW_PORT_ID) ++ { ++ p_CcParams->getCcParams.hardwarePortId = ++ (uint8_t)p_FmPort->hardwarePortId; ++ p_CcParams->getCcParams.type &= ~HW_PORT_ID; ++ } ++ if ((p_CcParams->getCcParams.type & OFFSET_OF_DATA) ++ && (p_FmPort->bufferOffsets.dataOffset != ILLEGAL_BASE)) ++ { ++ p_CcParams->getCcParams.dataOffset = ++ (uint16_t)p_FmPort->bufferOffsets.dataOffset; ++ p_CcParams->getCcParams.type &= ~OFFSET_OF_DATA; ++ } ++ if (p_CcParams->getCcParams.type & NUM_OF_TASKS) ++ { ++ p_CcParams->getCcParams.numOfTasks = (uint8_t)p_FmPort->tasks.num; ++ p_CcParams->getCcParams.type &= ~NUM_OF_TASKS; ++ } ++ if (p_CcParams->getCcParams.type & NUM_OF_EXTRA_TASKS) ++ { ++ p_CcParams->getCcParams.numOfExtraTasks = ++ (uint8_t)p_FmPort->tasks.extra; ++ p_CcParams->getCcParams.type &= ~NUM_OF_EXTRA_TASKS; ++ } ++ if (p_CcParams->getCcParams.type & FM_REV) ++ { ++ p_CcParams->getCcParams.revInfo.majorRev = p_FmPort->fmRevInfo.majorRev; ++ p_CcParams->getCcParams.revInfo.minorRev = p_FmPort->fmRevInfo.minorRev; ++ p_CcParams->getCcParams.type &= ~FM_REV; ++ } ++ if (p_CcParams->getCcParams.type & DISCARD_MASK) ++ { ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ p_CcParams->getCcParams.discardMask = ++ GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsdm); ++ else ++ p_CcParams->getCcParams.discardMask = ++ GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfsdm); ++ p_CcParams->getCcParams.type &= ~DISCARD_MASK; ++ } ++ if (p_CcParams->getCcParams.type & MANIP_EXTRA_SPACE) ++ { ++ p_CcParams->getCcParams.internalBufferOffset = ++ p_FmPort->internalBufferOffset; ++ p_CcParams->getCcParams.type &= ~MANIP_EXTRA_SPACE; ++ } ++ if (p_CcParams->getCcParams.type & GET_NIA_FPNE) ++ { ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ p_CcParams->getCcParams.nia = ++ GET_UINT32(p_FmPort->port.bmi_regs->oh.fmbm_ofpne); ++ else ++ p_CcParams->getCcParams.nia = ++ GET_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rfpne); ++ p_CcParams->getCcParams.type &= ~GET_NIA_FPNE; ++ } ++ if (p_CcParams->getCcParams.type & GET_NIA_PNDN) ++ { ++ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ p_CcParams->getCcParams.nia = ++ GET_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn); ++ p_CcParams->getCcParams.type &= ~GET_NIA_PNDN; ++ } ++ ++ if ((p_CcParams->setCcParams.type & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY) ++ && !(p_FmPort->requiredAction & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY)) ++ { ++ p_FmPort->requiredAction |= UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY; ++ p_FmPort->orFmanCtrl = p_CcParams->setCcParams.orFmanCtrl; ++ } ++ ++ if ((p_CcParams->setCcParams.type & UPDATE_NIA_PNEN) ++ && !(p_FmPort->requiredAction & UPDATE_NIA_PNEN)) ++ { ++ p_FmPort->savedQmiPnen = p_CcParams->setCcParams.nia; ++ p_FmPort->requiredAction |= UPDATE_NIA_PNEN; ++ } ++ else ++ if (p_CcParams->setCcParams.type & UPDATE_NIA_PNEN) ++ { ++ if (p_FmPort->savedQmiPnen != p_CcParams->setCcParams.nia) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("PNEN was defined previously different")); ++ } ++ ++ if ((p_CcParams->setCcParams.type & UPDATE_NIA_PNDN) ++ && !(p_FmPort->requiredAction & UPDATE_NIA_PNDN)) ++ { ++ p_FmPort->savedNonRxQmiRegsPndn = p_CcParams->setCcParams.nia; ++ p_FmPort->requiredAction |= UPDATE_NIA_PNDN; ++ } ++ else ++ if (p_CcParams->setCcParams.type & UPDATE_NIA_PNDN) ++ { ++ if (p_FmPort->savedNonRxQmiRegsPndn != p_CcParams->setCcParams.nia) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("PNDN was defined previously different")); ++ } ++ ++ if ((p_CcParams->setCcParams.type & UPDATE_NIA_FENE) ++ && (p_CcParams->setCcParams.overwrite ++ || !(p_FmPort->requiredAction & UPDATE_NIA_FENE))) ++ { ++ p_FmPort->savedBmiFene = p_CcParams->setCcParams.nia; ++ p_FmPort->requiredAction |= UPDATE_NIA_FENE; ++ } ++ else ++ if (p_CcParams->setCcParams.type & UPDATE_NIA_FENE) ++ { ++ if (p_FmPort->savedBmiFene != p_CcParams->setCcParams.nia) ++ RETURN_ERROR( MAJOR, E_INVALID_STATE, ++ ("xFENE was defined previously different")); ++ } ++ ++ if ((p_CcParams->setCcParams.type & UPDATE_NIA_FPNE) ++ && !(p_FmPort->requiredAction & UPDATE_NIA_FPNE)) ++ { ++ p_FmPort->savedBmiFpne = p_CcParams->setCcParams.nia; ++ p_FmPort->requiredAction |= UPDATE_NIA_FPNE; ++ } ++ else ++ if (p_CcParams->setCcParams.type & UPDATE_NIA_FPNE) ++ { ++ if (p_FmPort->savedBmiFpne != p_CcParams->setCcParams.nia) ++ RETURN_ERROR( MAJOR, E_INVALID_STATE, ++ ("xFPNE was defined previously different")); ++ } ++ ++ if ((p_CcParams->setCcParams.type & UPDATE_NIA_CMNE) ++ && !(p_FmPort->requiredAction & UPDATE_NIA_CMNE)) ++ { ++ p_FmPort->savedBmiCmne = p_CcParams->setCcParams.nia; ++ p_FmPort->requiredAction |= UPDATE_NIA_CMNE; ++ } ++ else ++ if (p_CcParams->setCcParams.type & UPDATE_NIA_CMNE) ++ { ++ if (p_FmPort->savedBmiCmne != p_CcParams->setCcParams.nia) ++ RETURN_ERROR( MAJOR, E_INVALID_STATE, ++ ("xCMNE was defined previously different")); ++ } ++ ++ if ((p_CcParams->setCcParams.type & UPDATE_PSO) ++ && !(p_FmPort->requiredAction & UPDATE_PSO)) ++ { ++ /* get PCD registers pointers */ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiPrsStartOffset = &p_FmPort->port.bmi_regs->rx.fmbm_rpso; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiPrsStartOffset = &p_FmPort->port.bmi_regs->oh.fmbm_opso; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ ++ /* set start parsing offset */ ++ tmpInt = (int)GET_UINT32(*p_BmiPrsStartOffset) ++ + p_CcParams->setCcParams.psoSize; ++ if (tmpInt > 0) ++ WRITE_UINT32(*p_BmiPrsStartOffset, (uint32_t)tmpInt); ++ ++ p_FmPort->requiredAction |= UPDATE_PSO; ++ p_FmPort->savedPrsStartOffset = p_CcParams->setCcParams.psoSize; ++ } ++ else ++ if (p_CcParams->setCcParams.type & UPDATE_PSO) ++ { ++ if (p_FmPort->savedPrsStartOffset ++ != p_CcParams->setCcParams.psoSize) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("parser start offset was defoned previousley different")); ++ } ++ ++ if ((p_CcParams->setCcParams.type & UPDATE_OFP_DPTE) ++ && !(p_FmPort->requiredAction & UPDATE_OFP_DPTE)) ++ { ++ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ p_FmPort->savedBmiOfp = GET_UINT32(p_FmPort->port.bmi_regs->oh.fmbm_ofp); ++ p_FmPort->savedBmiOfp &= ~BMI_FIFO_PIPELINE_DEPTH_MASK; ++ p_FmPort->savedBmiOfp |= p_CcParams->setCcParams.ofpDpde ++ << BMI_FIFO_PIPELINE_DEPTH_SHIFT; ++ p_FmPort->requiredAction |= UPDATE_OFP_DPTE; ++ } ++ ++ return E_OK; ++} ++/*********************** End of inter-module routines ************************/ ++ ++/****************************************/ ++/* API Init unit functions */ ++/****************************************/ ++ ++t_Handle FM_PORT_Config(t_FmPortParams *p_FmPortParams) ++{ ++ t_FmPort *p_FmPort; ++ uintptr_t baseAddr = p_FmPortParams->baseAddr; ++ uint32_t tmpReg; ++ ++ /* Allocate FM structure */ ++ p_FmPort = (t_FmPort *)XX_Malloc(sizeof(t_FmPort)); ++ if (!p_FmPort) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Port driver structure")); ++ return NULL; ++ } ++ memset(p_FmPort, 0, sizeof(t_FmPort)); ++ ++ /* Allocate the FM driver's parameters structure */ ++ p_FmPort->p_FmPortDriverParam = (t_FmPortDriverParam *)XX_Malloc( ++ sizeof(t_FmPortDriverParam)); ++ if (!p_FmPort->p_FmPortDriverParam) ++ { ++ XX_Free(p_FmPort); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Port driver parameters")); ++ return NULL; ++ } ++ memset(p_FmPort->p_FmPortDriverParam, 0, sizeof(t_FmPortDriverParam)); ++ ++ /* Initialize FM port parameters which will be kept by the driver */ ++ p_FmPort->portType = p_FmPortParams->portType; ++ p_FmPort->portId = p_FmPortParams->portId; ++ p_FmPort->pcdEngines = FM_PCD_NONE; ++ p_FmPort->f_Exception = p_FmPortParams->f_Exception; ++ p_FmPort->h_App = p_FmPortParams->h_App; ++ p_FmPort->h_Fm = p_FmPortParams->h_Fm; ++ ++ /* get FM revision */ ++ FM_GetRevision(p_FmPort->h_Fm, &p_FmPort->fmRevInfo); ++ ++ /* calculate global portId number */ ++ p_FmPort->hardwarePortId = SwPortIdToHwPortId(p_FmPort->portType, ++ p_FmPortParams->portId, ++ p_FmPort->fmRevInfo.majorRev, ++ p_FmPort->fmRevInfo.minorRev); ++ ++ if (p_FmPort->fmRevInfo.majorRev >= 6) ++ { ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) ++ && (p_FmPortParams->portId != FM_OH_PORT_ID)) ++ DBG(WARNING, ++ ("Port ID %d is recommended for HC port. Overwriting HW defaults to be suitable for HC.", ++ FM_OH_PORT_ID)); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ && (p_FmPortParams->portId == FM_OH_PORT_ID)) ++ DBG(WARNING, ("Use non-zero portId for OP port due to insufficient resources on portId 0.")); ++ } ++ ++ /* Set up FM port parameters for initialization phase only */ ++ ++ /* First, fill in flibs struct */ ++ fman_port_defconfig(&p_FmPort->p_FmPortDriverParam->dfltCfg, ++ (enum fman_port_type)p_FmPort->portType); ++ /* Overwrite some integration specific parameters */ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.rx_pri_elevation = ++ DEFAULT_PORT_rxFifoPriElevationLevel; ++ p_FmPort->p_FmPortDriverParam->dfltCfg.rx_fifo_thr = ++ DEFAULT_PORT_rxFifoThreshold; ++ ++#if defined(FM_OP_NO_VSP_NO_RELEASE_ERRATA_FMAN_A006675) || defined(FM_ERROR_VSP_NO_MATCH_SW006) ++ p_FmPort->p_FmPortDriverParam->dfltCfg.errata_A006675 = TRUE; ++#else ++ p_FmPort->p_FmPortDriverParam->dfltCfg.errata_A006675 = FALSE; ++#endif ++ if ((p_FmPort->fmRevInfo.majorRev == 6) ++ && (p_FmPort->fmRevInfo.minorRev == 0)) ++ p_FmPort->p_FmPortDriverParam->dfltCfg.errata_A006320 = TRUE; ++ else ++ p_FmPort->p_FmPortDriverParam->dfltCfg.errata_A006320 = FALSE; ++ ++ /* Excessive Threshold register - exists for pre-FMv3 chips only */ ++ if (p_FmPort->fmRevInfo.majorRev < 6) ++ { ++#ifdef FM_NO_RESTRICT_ON_ACCESS_RSRC ++ p_FmPort->p_FmPortDriverParam->dfltCfg.excessive_threshold_register = ++ TRUE; ++#endif ++ p_FmPort->p_FmPortDriverParam->dfltCfg.fmbm_rebm_has_sgd = FALSE; ++ p_FmPort->p_FmPortDriverParam->dfltCfg.fmbm_tfne_has_features = FALSE; ++ } ++ else ++ { ++ p_FmPort->p_FmPortDriverParam->dfltCfg.excessive_threshold_register = ++ FALSE; ++ p_FmPort->p_FmPortDriverParam->dfltCfg.fmbm_rebm_has_sgd = TRUE; ++ p_FmPort->p_FmPortDriverParam->dfltCfg.fmbm_tfne_has_features = TRUE; ++ } ++ if (p_FmPort->fmRevInfo.majorRev == 4) ++ p_FmPort->p_FmPortDriverParam->dfltCfg.qmi_deq_options_support = FALSE; ++ else ++ p_FmPort->p_FmPortDriverParam->dfltCfg.qmi_deq_options_support = TRUE; ++ ++ /* Continue with other parameters */ ++ p_FmPort->p_FmPortDriverParam->baseAddr = baseAddr; ++ /* set memory map pointers */ ++ p_FmPort->p_FmPortQmiRegs = ++ (t_FmPortQmiRegs *)UINT_TO_PTR(baseAddr + QMI_PORT_REGS_OFFSET); ++ p_FmPort->p_FmPortBmiRegs = ++ (u_FmPortBmiRegs *)UINT_TO_PTR(baseAddr + BMI_PORT_REGS_OFFSET); ++ p_FmPort->p_FmPortPrsRegs = ++ (t_FmPortPrsRegs *)UINT_TO_PTR(baseAddr + PRS_PORT_REGS_OFFSET); ++ ++ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.privDataSize = ++ DEFAULT_PORT_bufferPrefixContent_privDataSize; ++ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passPrsResult = ++ DEFAULT_PORT_bufferPrefixContent_passPrsResult; ++ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passTimeStamp = ++ DEFAULT_PORT_bufferPrefixContent_passTimeStamp; ++ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passAllOtherPCDInfo = ++ DEFAULT_PORT_bufferPrefixContent_passTimeStamp; ++ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign = ++ DEFAULT_PORT_bufferPrefixContent_dataAlign; ++ /* p_FmPort->p_FmPortDriverParam->dmaSwapData = (e_FmDmaSwapOption)DEFAULT_PORT_dmaSwapData; ++ p_FmPort->p_FmPortDriverParam->dmaIntContextCacheAttr = (e_FmDmaCacheOption)DEFAULT_PORT_dmaIntContextCacheAttr; ++ p_FmPort->p_FmPortDriverParam->dmaHeaderCacheAttr = (e_FmDmaCacheOption)DEFAULT_PORT_dmaHeaderCacheAttr; ++ p_FmPort->p_FmPortDriverParam->dmaScatterGatherCacheAttr = (e_FmDmaCacheOption)DEFAULT_PORT_dmaScatterGatherCacheAttr; ++ p_FmPort->p_FmPortDriverParam->dmaWriteOptimize = DEFAULT_PORT_dmaWriteOptimize; ++ */ ++ p_FmPort->p_FmPortDriverParam->liodnBase = p_FmPortParams->liodnBase; ++ p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore = ++ DEFAULT_PORT_cheksumLastBytesIgnore; ++ ++ p_FmPort->maxFrameLength = DEFAULT_PORT_maxFrameLength; ++ /* resource distribution. */ ++ p_FmPort->fifoBufs.num = DEFAULT_PORT_numOfFifoBufs(p_FmPort->portType) ++ * BMI_FIFO_UNITS; ++ p_FmPort->fifoBufs.extra = DEFAULT_PORT_extraNumOfFifoBufs ++ * BMI_FIFO_UNITS; ++ p_FmPort->openDmas.num = DEFAULT_PORT_numOfOpenDmas(p_FmPort->portType); ++ p_FmPort->openDmas.extra = ++ DEFAULT_PORT_extraNumOfOpenDmas(p_FmPort->portType); ++ p_FmPort->tasks.num = DEFAULT_PORT_numOfTasks(p_FmPort->portType); ++ p_FmPort->tasks.extra = DEFAULT_PORT_extraNumOfTasks(p_FmPort->portType); ++ ++ ++#ifdef FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981 ++ if ((p_FmPort->fmRevInfo.majorRev == 6) ++ && (p_FmPort->fmRevInfo.minorRev == 0) ++ && ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_TX))) ++ { ++ p_FmPort->openDmas.num = 16; ++ p_FmPort->openDmas.extra = 0; ++ } ++#endif /* FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981 */ ++ ++ /* Port type specific initialization: */ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX): ++ case (e_FM_PORT_TYPE_RX_10G): ++ /* Initialize FM port parameters for initialization phase only */ ++ p_FmPort->p_FmPortDriverParam->cutBytesFromEnd = ++ DEFAULT_PORT_cutBytesFromEnd; ++ p_FmPort->p_FmPortDriverParam->enBufPoolDepletion = FALSE; ++ p_FmPort->p_FmPortDriverParam->frmDiscardOverride = ++ DEFAULT_PORT_frmDiscardOverride; ++ ++ tmpReg = ++ GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfp); ++ p_FmPort->p_FmPortDriverParam->rxFifoPriElevationLevel = ++ (((tmpReg & BMI_RX_FIFO_PRI_ELEVATION_MASK) ++ >> BMI_RX_FIFO_PRI_ELEVATION_SHIFT) + 1) ++ * BMI_FIFO_UNITS; ++ p_FmPort->p_FmPortDriverParam->rxFifoThreshold = (((tmpReg ++ & BMI_RX_FIFO_THRESHOLD_MASK) ++ >> BMI_RX_FIFO_THRESHOLD_SHIFT) + 1) * BMI_FIFO_UNITS; ++ ++ p_FmPort->p_FmPortDriverParam->bufMargins.endMargins = ++ DEFAULT_PORT_BufMargins_endMargins; ++ p_FmPort->p_FmPortDriverParam->errorsToDiscard = ++ DEFAULT_PORT_errorsToDiscard; ++ p_FmPort->p_FmPortDriverParam->forwardReuseIntContext = ++ DEFAULT_PORT_forwardIntContextReuse; ++#if (DPAA_VERSION >= 11) ++ p_FmPort->p_FmPortDriverParam->noScatherGather = ++ DEFAULT_PORT_noScatherGather; ++#endif /* (DPAA_VERSION >= 11) */ ++ break; ++ ++ case (e_FM_PORT_TYPE_TX): ++ p_FmPort->p_FmPortDriverParam->dontReleaseBuf = FALSE; ++#ifdef FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 ++ tmpReg = 0x00001013; ++ WRITE_UINT32( p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tfp, ++ tmpReg); ++#endif /* FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 */ ++ case (e_FM_PORT_TYPE_TX_10G): ++ tmpReg = ++ GET_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tfp); ++ p_FmPort->p_FmPortDriverParam->txFifoMinFillLevel = ((tmpReg ++ & BMI_TX_FIFO_MIN_FILL_MASK) ++ >> BMI_TX_FIFO_MIN_FILL_SHIFT) * BMI_FIFO_UNITS; ++ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth = ++ (uint8_t)(((tmpReg & BMI_FIFO_PIPELINE_DEPTH_MASK) ++ >> BMI_FIFO_PIPELINE_DEPTH_SHIFT) + 1); ++ p_FmPort->p_FmPortDriverParam->txFifoLowComfLevel = (((tmpReg ++ & BMI_TX_LOW_COMF_MASK) >> BMI_TX_LOW_COMF_SHIFT) + 1) ++ * BMI_FIFO_UNITS; ++ ++ p_FmPort->p_FmPortDriverParam->deqType = DEFAULT_PORT_deqType; ++ p_FmPort->p_FmPortDriverParam->deqPrefetchOption = ++ DEFAULT_PORT_deqPrefetchOption; ++ p_FmPort->p_FmPortDriverParam->deqHighPriority = ++ (bool)((p_FmPort->portType == e_FM_PORT_TYPE_TX) ? DEFAULT_PORT_deqHighPriority_1G : ++ DEFAULT_PORT_deqHighPriority_10G); ++ p_FmPort->p_FmPortDriverParam->deqByteCnt = ++ (uint16_t)( ++ (p_FmPort->portType == e_FM_PORT_TYPE_TX) ? DEFAULT_PORT_deqByteCnt_1G : ++ DEFAULT_PORT_deqByteCnt_10G); ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_FmPort->p_FmPortDriverParam->errorsToDiscard = ++ DEFAULT_PORT_errorsToDiscard; ++#if (DPAA_VERSION >= 11) ++ p_FmPort->p_FmPortDriverParam->noScatherGather = ++ DEFAULT_PORT_noScatherGather; ++#endif /* (DPAA_VERSION >= 11) */ ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ p_FmPort->p_FmPortDriverParam->deqPrefetchOption = ++ DEFAULT_PORT_deqPrefetchOption_HC; ++ p_FmPort->p_FmPortDriverParam->deqHighPriority = ++ DEFAULT_PORT_deqHighPriority_1G; ++ p_FmPort->p_FmPortDriverParam->deqType = DEFAULT_PORT_deqType; ++ p_FmPort->p_FmPortDriverParam->deqByteCnt = ++ DEFAULT_PORT_deqByteCnt_1G; ++ ++ tmpReg = ++ GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofp); ++ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth = ++ (uint8_t)(((tmpReg & BMI_FIFO_PIPELINE_DEPTH_MASK) ++ >> BMI_FIFO_PIPELINE_DEPTH_SHIFT) + 1); ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) ++ && (p_FmPortParams->portId != FM_OH_PORT_ID)) ++ { ++ /* Overwrite HC defaults */ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth = ++ DEFAULT_PORT_fifoDeqPipelineDepth_OH; ++ } ++ ++#ifndef FM_FRAME_END_PARAMS_FOR_OP ++ if (p_FmPort->fmRevInfo.majorRev < 6) ++ p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore = DEFAULT_notSupported; ++#endif /* !FM_FRAME_END_PARAMS_FOR_OP */ ++ ++#ifndef FM_DEQ_PIPELINE_PARAMS_FOR_OP ++ if (!((p_FmPort->fmRevInfo.majorRev == 4) || ++ (p_FmPort->fmRevInfo.majorRev >= 6))) ++ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth = DEFAULT_notSupported; ++#endif /* !FM_DEQ_PIPELINE_PARAMS_FOR_OP */ ++ break; ++ ++ default: ++ XX_Free(p_FmPort->p_FmPortDriverParam); ++ XX_Free(p_FmPort); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ return NULL; ++ } ++#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT ++ if (p_FmPort->fmRevInfo.majorRev == 4) ++ p_FmPort->p_FmPortDriverParam->deqPrefetchOption = (e_FmPortDeqPrefetchOption)DEFAULT_notSupported; ++#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ ++ ++ p_FmPort->imEn = p_FmPortParams->independentModeEnable; ++ ++ if (p_FmPort->imEn) ++ { ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G)) ++ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth = ++ DEFAULT_PORT_fifoDeqPipelineDepth_IM; ++ FmPortConfigIM(p_FmPort, p_FmPortParams); ++ } ++ else ++ { ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX): ++ case (e_FM_PORT_TYPE_RX_10G): ++ /* Initialize FM port parameters for initialization phase only */ ++ memcpy(&p_FmPort->p_FmPortDriverParam->extBufPools, ++ &p_FmPortParams->specificParams.rxParams.extBufPools, ++ sizeof(t_FmExtPools)); ++ p_FmPort->p_FmPortDriverParam->errFqid = ++ p_FmPortParams->specificParams.rxParams.errFqid; ++ p_FmPort->p_FmPortDriverParam->dfltFqid = ++ p_FmPortParams->specificParams.rxParams.dfltFqid; ++ p_FmPort->p_FmPortDriverParam->liodnOffset = ++ p_FmPortParams->specificParams.rxParams.liodnOffset; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ case (e_FM_PORT_TYPE_TX): ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ p_FmPort->p_FmPortDriverParam->errFqid = ++ p_FmPortParams->specificParams.nonRxParams.errFqid; ++ p_FmPort->p_FmPortDriverParam->deqSubPortal = ++ (uint8_t)(p_FmPortParams->specificParams.nonRxParams.qmChannel ++ & QMI_DEQ_CFG_SUBPORTAL_MASK); ++ p_FmPort->p_FmPortDriverParam->dfltFqid = ++ p_FmPortParams->specificParams.nonRxParams.dfltFqid; ++ break; ++ default: ++ XX_Free(p_FmPort->p_FmPortDriverParam); ++ XX_Free(p_FmPort); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ return NULL; ++ } ++ } ++ ++ memset(p_FmPort->name, 0, (sizeof(char)) * MODULE_NAME_SIZE); ++ if (Sprint( ++ p_FmPort->name, ++ "FM-%d-port-%s-%d", ++ FmGetId(p_FmPort->h_Fm), ++ ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING ++ || (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)) ? "OH" : ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX ? "1g-RX" : ++ (p_FmPort->portType == e_FM_PORT_TYPE_TX ? "1g-TX" : ++ (p_FmPort->portType ++ == e_FM_PORT_TYPE_RX_10G ? "10g-RX" : ++ "10g-TX")))), ++ p_FmPort->portId) == 0) ++ { ++ XX_Free(p_FmPort->p_FmPortDriverParam); ++ XX_Free(p_FmPort); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ return NULL; ++ } ++ ++ p_FmPort->h_Spinlock = XX_InitSpinlock(); ++ if (!p_FmPort->h_Spinlock) ++ { ++ XX_Free(p_FmPort->p_FmPortDriverParam); ++ XX_Free(p_FmPort); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ return NULL; ++ } ++ ++ return p_FmPort; ++} ++ ++t_FmPort *rx_port = 0; ++t_FmPort *tx_port = 0; ++ ++/**************************************************************************//** ++ @Function FM_PORT_Init ++ ++ @Description Initializes the FM module ++ ++ @Param[in] h_FmPort - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++ *//***************************************************************************/ ++t_Error FM_PORT_Init(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_FmPortDriverParam *p_DriverParams; ++ t_Error errCode; ++ t_FmInterModulePortInitParams fmParams; ++ t_FmRevisionInfo revInfo; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ errCode = FmSpBuildBufferStructure( ++ &p_FmPort->p_FmPortDriverParam->intContext, ++ &p_FmPort->p_FmPortDriverParam->bufferPrefixContent, ++ &p_FmPort->p_FmPortDriverParam->bufMargins, ++ &p_FmPort->bufferOffsets, &p_FmPort->internalBufferOffset); ++ if (errCode != E_OK) ++ RETURN_ERROR(MAJOR, errCode, NO_MSG); ++#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 ++ if ((p_FmPort->p_FmPortDriverParam->bcbWorkaround) && ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX)) ++ { ++ p_FmPort->p_FmPortDriverParam->errorsToDiscard |= FM_PORT_FRM_ERR_PHYSICAL; ++ if (!p_FmPort->fifoBufs.num) ++ p_FmPort->fifoBufs.num = DEFAULT_PORT_numOfFifoBufs(p_FmPort->portType)*BMI_FIFO_UNITS; ++ p_FmPort->fifoBufs.num += 4*KILOBYTE; ++ } ++#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */ ++ ++ CHECK_INIT_PARAMETERS(p_FmPort, CheckInitParameters); ++ ++ p_DriverParams = p_FmPort->p_FmPortDriverParam; ++ ++ /* Set up flibs port structure */ ++ memset(&p_FmPort->port, 0, sizeof(struct fman_port)); ++ p_FmPort->port.type = (enum fman_port_type)p_FmPort->portType; ++ FM_GetRevision(p_FmPort->h_Fm, &revInfo); ++ p_FmPort->port.fm_rev_maj = revInfo.majorRev; ++ p_FmPort->port.fm_rev_min = revInfo.minorRev; ++ p_FmPort->port.bmi_regs = ++ (union fman_port_bmi_regs *)UINT_TO_PTR(p_DriverParams->baseAddr + BMI_PORT_REGS_OFFSET); ++ p_FmPort->port.qmi_regs = ++ (struct fman_port_qmi_regs *)UINT_TO_PTR(p_DriverParams->baseAddr + QMI_PORT_REGS_OFFSET); ++ p_FmPort->port.ext_pools_num = (uint8_t)((revInfo.majorRev == 4) ? 4 : 8); ++ p_FmPort->port.im_en = p_FmPort->imEn; ++ p_FmPort->p_FmPortPrsRegs = ++ (t_FmPortPrsRegs *)UINT_TO_PTR(p_DriverParams->baseAddr + PRS_PORT_REGS_OFFSET); ++ ++ if (((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX)) && !p_FmPort->imEn) ++ { ++ /* Call the external Buffer routine which also checks fifo ++ size and updates it if necessary */ ++ /* define external buffer pools and pool depletion*/ ++ errCode = SetExtBufferPools(p_FmPort); ++ if (errCode) ++ RETURN_ERROR(MAJOR, errCode, NO_MSG); ++ /* check if the largest external buffer pool is large enough */ ++ if (p_DriverParams->bufMargins.startMargins + MIN_EXT_BUF_SIZE ++ + p_DriverParams->bufMargins.endMargins ++ > p_FmPort->rxPoolsParams.largestBufSize) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("bufMargins.startMargins (%d) + minimum buf size (64) + bufMargins.endMargins (%d) is larger than maximum external buffer size (%d)", p_DriverParams->bufMargins.startMargins, p_DriverParams->bufMargins.endMargins, p_FmPort->rxPoolsParams.largestBufSize)); ++ } ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ { ++ { ++#ifdef FM_NO_OP_OBSERVED_POOLS ++ t_FmRevisionInfo revInfo; ++ ++ FM_GetRevision(p_FmPort->h_Fm, &revInfo); ++ if ((revInfo.majorRev == 4) && (p_DriverParams->enBufPoolDepletion)) ++#endif /* FM_NO_OP_OBSERVED_POOLS */ ++ { ++ /* define external buffer pools */ ++ errCode = SetExtBufferPools(p_FmPort); ++ if (errCode) ++ RETURN_ERROR(MAJOR, errCode, NO_MSG); ++ } ++ } ++ } ++ ++ /************************************************************/ ++ /* Call FM module routine for communicating parameters */ ++ /************************************************************/ ++ memset(&fmParams, 0, sizeof(fmParams)); ++ fmParams.hardwarePortId = p_FmPort->hardwarePortId; ++ fmParams.portType = (e_FmPortType)p_FmPort->portType; ++ fmParams.numOfTasks = (uint8_t)p_FmPort->tasks.num; ++ fmParams.numOfExtraTasks = (uint8_t)p_FmPort->tasks.extra; ++ fmParams.numOfOpenDmas = (uint8_t)p_FmPort->openDmas.num; ++ fmParams.numOfExtraOpenDmas = (uint8_t)p_FmPort->openDmas.extra; ++ ++ if (p_FmPort->fifoBufs.num) ++ { ++ errCode = VerifySizeOfFifo(p_FmPort); ++ if (errCode != E_OK) ++ RETURN_ERROR(MAJOR, errCode, NO_MSG); ++ } ++ fmParams.sizeOfFifo = p_FmPort->fifoBufs.num; ++ fmParams.extraSizeOfFifo = p_FmPort->fifoBufs.extra; ++ fmParams.independentMode = p_FmPort->imEn; ++ fmParams.liodnOffset = p_DriverParams->liodnOffset; ++ fmParams.liodnBase = p_DriverParams->liodnBase; ++ fmParams.deqPipelineDepth = ++ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth; ++ fmParams.maxFrameLength = p_FmPort->maxFrameLength; ++#ifndef FM_DEQ_PIPELINE_PARAMS_FOR_OP ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)) ++ { ++ if (!((p_FmPort->fmRevInfo.majorRev == 4) || ++ (p_FmPort->fmRevInfo.majorRev >= 6))) ++ /* HC ports do not have fifoDeqPipelineDepth, but it is needed only ++ * for deq threshold calculation. ++ */ ++ fmParams.deqPipelineDepth = 2; ++ } ++#endif /* !FM_DEQ_PIPELINE_PARAMS_FOR_OP */ ++ ++ errCode = FmGetSetPortParams(p_FmPort->h_Fm, &fmParams); ++ if (errCode) ++ RETURN_ERROR(MAJOR, errCode, NO_MSG); ++ ++ /* get params for use in init */ ++ p_FmPort->fmMuramPhysBaseAddr = ++ (uint64_t)((uint64_t)(fmParams.fmMuramPhysBaseAddr.low) ++ | ((uint64_t)(fmParams.fmMuramPhysBaseAddr.high) << 32)); ++ p_FmPort->h_FmMuram = FmGetMuramHandle(p_FmPort->h_Fm); ++ ++ errCode = InitLowLevelDriver(p_FmPort); ++ if (errCode != E_OK) ++ RETURN_ERROR(MAJOR, errCode, NO_MSG); ++ ++ FmPortDriverParamFree(p_FmPort); ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ { ++ t_FmPcdCtrlParamsPage *p_ParamsPage; ++ ++ FmPortSetGprFunc(p_FmPort, e_FM_PORT_GPR_MURAM_PAGE, ++ (void**)&p_ParamsPage); ++ ASSERT_COND(p_ParamsPage); ++ ++ WRITE_UINT32(p_ParamsPage->misc, FM_CTL_PARAMS_PAGE_ALWAYS_ON); ++#ifdef FM_OP_NO_VSP_NO_RELEASE_ERRATA_FMAN_A006675 ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ { ++ WRITE_UINT32( ++ p_ParamsPage->misc, ++ (GET_UINT32(p_ParamsPage->misc) | FM_CTL_PARAMS_PAGE_OP_FIX_EN)); ++ WRITE_UINT32( ++ p_ParamsPage->discardMask, ++ GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsdm)); ++ } ++#endif /* FM_OP_NO_VSP_NO_RELEASE_ERRATA_FMAN_A006675 */ ++#ifdef FM_ERROR_VSP_NO_MATCH_SW006 ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ WRITE_UINT32( ++ p_ParamsPage->errorsDiscardMask, ++ (GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsdm) | GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsem))); ++ else ++ WRITE_UINT32( ++ p_ParamsPage->errorsDiscardMask, ++ (GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfsdm) | GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfsem))); ++#endif /* FM_ERROR_VSP_NO_MATCH_SW006 */ ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (p_FmPort->deepSleepVars.autoResMaxSizes) ++ FmPortConfigAutoResForDeepSleepSupport1(p_FmPort); ++ return E_OK; ++} ++ ++/**************************************************************************//** ++ @Function FM_PORT_Free ++ ++ @Description Frees all resources that were assigned to FM module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmPort - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++ *//***************************************************************************/ ++t_Error FM_PORT_Free(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_FmInterModulePortFreeParams fmParams; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ ++ if (p_FmPort->pcdEngines) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("Trying to free a port with PCD. FM_PORT_DeletePCD must be called first.")); ++ ++ if (p_FmPort->enabled) ++ { ++ if (FM_PORT_Disable(p_FmPort) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM_PORT_Disable FAILED")); ++ } ++ ++ if (p_FmPort->imEn) ++ FmPortImFree(p_FmPort); ++ ++ FmPortDriverParamFree(p_FmPort); ++ ++ memset(&fmParams, 0, sizeof(fmParams)); ++ fmParams.hardwarePortId = p_FmPort->hardwarePortId; ++ fmParams.portType = (e_FmPortType)p_FmPort->portType; ++ fmParams.deqPipelineDepth = ++ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth; ++ ++ FmFreePortParams(p_FmPort->h_Fm, &fmParams); ++ ++#if (DPAA_VERSION >= 11) ++ if (FmVSPFreeForPort(p_FmPort->h_Fm, p_FmPort->portType, p_FmPort->portId) ++ != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("VSP free of port FAILED")); ++ ++ if (p_FmPort->p_ParamsPage) ++ FM_MURAM_FreeMem(p_FmPort->h_FmMuram, p_FmPort->p_ParamsPage); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (p_FmPort->h_Spinlock) ++ XX_FreeSpinlock(p_FmPort->h_Spinlock); ++ ++ XX_Free(p_FmPort); ++ ++ return E_OK; ++} ++ ++/*************************************************/ ++/* API Advanced Init unit functions */ ++/*************************************************/ ++ ++t_Error FM_PORT_ConfigNumOfOpenDmas(t_Handle h_FmPort, t_FmPortRsrc *p_OpenDmas) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->setNumOfOpenDmas = TRUE; ++ memcpy(&p_FmPort->openDmas, p_OpenDmas, sizeof(t_FmPortRsrc)); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigNumOfTasks(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfTasks) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ memcpy(&p_FmPort->tasks, p_NumOfTasks, sizeof(t_FmPortRsrc)); ++ p_FmPort->p_FmPortDriverParam->setNumOfTasks = TRUE; ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigSizeOfFifo(t_Handle h_FmPort, t_FmPortRsrc *p_SizeOfFifo) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->setSizeOfFifo = TRUE; ++ memcpy(&p_FmPort->fifoBufs, p_SizeOfFifo, sizeof(t_FmPortRsrc)); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDeqHighPriority(t_Handle h_FmPort, bool highPri) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("not available for Rx ports")); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.deq_high_pri = highPri; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDeqType(t_Handle h_FmPort, e_FmPortDeqType deqType) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("not available for Rx ports")); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.deq_type = ++ (enum fman_port_deq_type)deqType; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDeqPrefetchOption( ++ t_Handle h_FmPort, e_FmPortDeqPrefetchOption deqPrefetchOption) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("not available for Rx ports")); ++ p_FmPort->p_FmPortDriverParam->dfltCfg.deq_prefetch_opt = ++ (enum fman_port_deq_prefetch)deqPrefetchOption; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigBackupPools(t_Handle h_FmPort, ++ t_FmBackupBmPools *p_BackupBmPools) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for Rx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->p_BackupBmPools = ++ (t_FmBackupBmPools *)XX_Malloc(sizeof(t_FmBackupBmPools)); ++ if (!p_FmPort->p_FmPortDriverParam->p_BackupBmPools) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_BackupBmPools allocation failed")); ++ memcpy(p_FmPort->p_FmPortDriverParam->p_BackupBmPools, p_BackupBmPools, ++ sizeof(t_FmBackupBmPools)); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDeqByteCnt(t_Handle h_FmPort, uint16_t deqByteCnt) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("not available for Rx ports")); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.deq_byte_cnt = deqByteCnt; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigBufferPrefixContent( ++ t_Handle h_FmPort, t_FmBufferPrefixContent *p_FmBufferPrefixContent) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ memcpy(&p_FmPort->p_FmPortDriverParam->bufferPrefixContent, ++ p_FmBufferPrefixContent, sizeof(t_FmBufferPrefixContent)); ++ /* if dataAlign was not initialized by user, we return to driver's default */ ++ if (!p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign) ++ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign = ++ DEFAULT_PORT_bufferPrefixContent_dataAlign; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigCheksumLastBytesIgnore(t_Handle h_FmPort, ++ uint8_t checksumLastBytesIgnore) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.checksum_bytes_ignore = ++ checksumLastBytesIgnore; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigCutBytesFromEnd(t_Handle h_FmPort, ++ uint8_t cutBytesFromEnd) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for Rx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.rx_cut_end_bytes = cutBytesFromEnd; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigPoolDepletion(t_Handle h_FmPort, ++ t_FmBufPoolDepletion *p_BufPoolDepletion) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for Rx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->enBufPoolDepletion = TRUE; ++ memcpy(&p_FmPort->p_FmPortDriverParam->bufPoolDepletion, p_BufPoolDepletion, ++ sizeof(t_FmBufPoolDepletion)); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigObservedPoolDepletion( ++ t_Handle h_FmPort, ++ t_FmPortObservedBufPoolDepletion *p_FmPortObservedBufPoolDepletion) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for OP ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->enBufPoolDepletion = TRUE; ++ memcpy(&p_FmPort->p_FmPortDriverParam->bufPoolDepletion, ++ &p_FmPortObservedBufPoolDepletion->poolDepletionParams, ++ sizeof(t_FmBufPoolDepletion)); ++ memcpy(&p_FmPort->p_FmPortDriverParam->extBufPools, ++ &p_FmPortObservedBufPoolDepletion->poolsParams, ++ sizeof(t_FmExtPools)); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigExtBufPools(t_Handle h_FmPort, t_FmExtPools *p_FmExtPools) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for OP ports only")); ++ ++ memcpy(&p_FmPort->p_FmPortDriverParam->extBufPools, p_FmExtPools, ++ sizeof(t_FmExtPools)); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDontReleaseTxBufToBM(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_TX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for Tx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->dontReleaseBuf = TRUE; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDfltColor(t_Handle h_FmPort, e_FmPortColor color) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ p_FmPort->p_FmPortDriverParam->dfltCfg.color = (enum fman_port_color)color; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigSyncReq(t_Handle h_FmPort, bool syncReq) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_TX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("Not available for Tx ports")); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.sync_req = syncReq; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigFrmDiscardOverride(t_Handle h_FmPort, bool override) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_TX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("Not available for Tx ports")); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.discard_override = override; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigErrorsToDiscard(t_Handle h_FmPort, ++ fmPortFrameErrSelect_t errs) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ RETURN_ERROR( MAJOR, E_INVALID_OPERATION, ++ ("available for Rx and offline parsing ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->errorsToDiscard = errs; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDmaSwapData(t_Handle h_FmPort, e_FmDmaSwapOption swapData) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.dma_swap_data = ++ (enum fman_port_dma_swap)swapData; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDmaIcCacheAttr(t_Handle h_FmPort, ++ e_FmDmaCacheOption intContextCacheAttr) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.dma_ic_stash_on = ++ (bool)(intContextCacheAttr == e_FM_DMA_STASH); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDmaHdrAttr(t_Handle h_FmPort, ++ e_FmDmaCacheOption headerCacheAttr) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.dma_header_stash_on = ++ (bool)(headerCacheAttr == e_FM_DMA_STASH); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDmaScatterGatherAttr( ++ t_Handle h_FmPort, e_FmDmaCacheOption scatterGatherCacheAttr) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.dma_sg_stash_on = ++ (bool)(scatterGatherCacheAttr == e_FM_DMA_STASH); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigDmaWriteOptimize(t_Handle h_FmPort, bool optimize) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_TX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("Not available for Tx ports")); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.dma_write_optimize = optimize; ++ ++ return E_OK; ++} ++ ++#if (DPAA_VERSION >= 11) ++t_Error FM_PORT_ConfigNoScatherGather(t_Handle h_FmPort, bool noScatherGather) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ UNUSED(noScatherGather); ++ UNUSED(p_FmPort); ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->noScatherGather = noScatherGather; ++ ++ return E_OK; ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++t_Error FM_PORT_ConfigForwardReuseIntContext(t_Handle h_FmPort, ++ bool forwardReuse) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for Rx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->forwardReuseIntContext = forwardReuse; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigMaxFrameLength(t_Handle h_FmPort, uint16_t length) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->maxFrameLength = length; ++ ++ return E_OK; ++} ++ ++#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 ++t_Error FM_PORT_ConfigBCBWorkaround(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->p_FmPortDriverParam->bcbWorkaround = TRUE; ++ ++ return E_OK; ++} ++#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */ ++ ++/****************************************************/ ++/* Hidden-DEBUG Only API */ ++/****************************************************/ ++ ++t_Error FM_PORT_ConfigTxFifoMinFillLevel(t_Handle h_FmPort, ++ uint32_t minFillLevel) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_TX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for Tx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_min_level = minFillLevel; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigFifoDeqPipelineDepth(t_Handle h_FmPort, ++ uint8_t deqPipelineDepth) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("Not available for Rx ports")); ++ ++ if (p_FmPort->imEn) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("Not available for IM ports!")); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth = ++ deqPipelineDepth; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigTxFifoLowComfLevel(t_Handle h_FmPort, ++ uint32_t fifoLowComfLevel) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_TX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for Tx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_low_comf_level = ++ fifoLowComfLevel; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigRxFifoThreshold(t_Handle h_FmPort, uint32_t fifoThreshold) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for Rx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.rx_fifo_thr = fifoThreshold; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigRxFifoPriElevationLevel(t_Handle h_FmPort, ++ uint32_t priElevationLevel) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for Rx ports only")); ++ ++ p_FmPort->p_FmPortDriverParam->dfltCfg.rx_pri_elevation = priElevationLevel; ++ ++ return E_OK; ++} ++/****************************************************/ ++/* API Run-time Control unit functions */ ++/****************************************************/ ++ ++t_Error FM_PORT_SetNumOfOpenDmas(t_Handle h_FmPort, ++ t_FmPortRsrc *p_NumOfOpenDmas) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if ((!p_NumOfOpenDmas->num) || (p_NumOfOpenDmas->num > MAX_NUM_OF_DMAS)) ++ RETURN_ERROR( MAJOR, E_INVALID_VALUE, ++ ("openDmas-num can't be larger than %d", MAX_NUM_OF_DMAS)); ++ if (p_NumOfOpenDmas->extra > MAX_NUM_OF_EXTRA_DMAS) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("openDmas-extra can't be larger than %d", MAX_NUM_OF_EXTRA_DMAS)); ++ err = FmSetNumOfOpenDmas(p_FmPort->h_Fm, p_FmPort->hardwarePortId, ++ (uint8_t*)&p_NumOfOpenDmas->num, ++ (uint8_t*)&p_NumOfOpenDmas->extra, FALSE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ memcpy(&p_FmPort->openDmas, p_NumOfOpenDmas, sizeof(t_FmPortRsrc)); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetNumOfTasks(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfTasks) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ /* only driver uses host command port, so ASSERT rather than RETURN_ERROR */ ++ ASSERT_COND(p_FmPort->portType != e_FM_PORT_TYPE_OH_HOST_COMMAND); ++ ++ if ((!p_NumOfTasks->num) || (p_NumOfTasks->num > MAX_NUM_OF_TASKS)) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("NumOfTasks-num can't be larger than %d", MAX_NUM_OF_TASKS)); ++ if (p_NumOfTasks->extra > MAX_NUM_OF_EXTRA_TASKS) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("NumOfTasks-extra can't be larger than %d", MAX_NUM_OF_EXTRA_TASKS)); ++ ++ err = FmSetNumOfTasks(p_FmPort->h_Fm, p_FmPort->hardwarePortId, ++ (uint8_t*)&p_NumOfTasks->num, ++ (uint8_t*)&p_NumOfTasks->extra, FALSE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ /* update driver's struct */ ++ memcpy(&p_FmPort->tasks, p_NumOfTasks, sizeof(t_FmPortRsrc)); ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetSizeOfFifo(t_Handle h_FmPort, t_FmPortRsrc *p_SizeOfFifo) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if (!p_SizeOfFifo->num || (p_SizeOfFifo->num > MAX_PORT_FIFO_SIZE)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("SizeOfFifo-num has to be in the range of 256 - %d", MAX_PORT_FIFO_SIZE)); ++ if (p_SizeOfFifo->num % BMI_FIFO_UNITS) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("SizeOfFifo-num has to be divisible by %d", BMI_FIFO_UNITS)); ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ /* extra FIFO size (allowed only to Rx ports) */ ++ if (p_SizeOfFifo->extra % BMI_FIFO_UNITS) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("SizeOfFifo-extra has to be divisible by %d", BMI_FIFO_UNITS)); ++ } ++ else ++ if (p_SizeOfFifo->extra) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ (" No SizeOfFifo-extra for non Rx ports")); ++ ++ memcpy(&p_FmPort->fifoBufs, p_SizeOfFifo, sizeof(t_FmPortRsrc)); ++ ++ /* we do not change user's parameter */ ++ err = VerifySizeOfFifo(p_FmPort); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ err = FmSetSizeOfFifo(p_FmPort->h_Fm, p_FmPort->hardwarePortId, ++ &p_SizeOfFifo->num, &p_SizeOfFifo->extra, FALSE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++uint32_t FM_PORT_GetBufferDataOffset(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, ++ 0); ++ ++ return p_FmPort->bufferOffsets.dataOffset; ++} ++ ++uint8_t * FM_PORT_GetBufferICInfo(t_Handle h_FmPort, char *p_Data) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, ++ NULL); ++ ++ if (p_FmPort->bufferOffsets.pcdInfoOffset == ILLEGAL_BASE) ++ return NULL; ++ ++ return (uint8_t *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.pcdInfoOffset); ++} ++ ++t_FmPrsResult * FM_PORT_GetBufferPrsResult(t_Handle h_FmPort, char *p_Data) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, ++ NULL); ++ ++ if (p_FmPort->bufferOffsets.prsResultOffset == ILLEGAL_BASE) ++ return NULL; ++ ++ return (t_FmPrsResult *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.prsResultOffset); ++} ++ ++uint64_t * FM_PORT_GetBufferTimeStamp(t_Handle h_FmPort, char *p_Data) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, ++ NULL); ++ ++ if (p_FmPort->bufferOffsets.timeStampOffset == ILLEGAL_BASE) ++ return NULL; ++ ++ return (uint64_t *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.timeStampOffset); ++} ++ ++uint8_t * FM_PORT_GetBufferHashResult(t_Handle h_FmPort, char *p_Data) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, ++ NULL); ++ ++ if (p_FmPort->bufferOffsets.hashResultOffset == ILLEGAL_BASE) ++ return NULL; ++ ++ return (uint8_t *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.hashResultOffset); ++} ++ ++t_Error FM_PORT_Disable(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ int err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPort->imEn) ++ FmPortImDisable(p_FmPort); ++ ++ err = fman_port_disable(&p_FmPort->port); ++ if (err == -EBUSY) ++ { ++ DBG(WARNING, ("%s: BMI or QMI is Busy. Port forced down", ++ p_FmPort->name)); ++ } ++ else ++ if (err != 0) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_disable")); ++ } ++ ++ p_FmPort->enabled = FALSE; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_Enable(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ int err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ /* Used by FM_PORT_Free routine as indication ++ if to disable port. Thus set it to TRUE prior ++ to enabling itself. This way if part of enable ++ process fails there will be still things ++ to disable during Free. For example, if BMI ++ enable succeeded but QMI failed, still BMI ++ needs to be disabled by Free. */ ++ p_FmPort->enabled = TRUE; ++ ++ if (p_FmPort->imEn) ++ FmPortImEnable(p_FmPort); ++ ++ err = fman_port_enable(&p_FmPort->port); ++ if (err != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_enable")); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetRateLimit(t_Handle h_FmPort, t_FmPortRateLimit *p_RateLimit) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint8_t factor, countUnitBit; ++ uint16_t baseGran; ++ struct fman_port_rate_limiter params; ++ int err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_TX): ++ baseGran = BMI_RATE_LIMIT_GRAN_TX; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ baseGran = BMI_RATE_LIMIT_GRAN_OP; ++ break; ++ default: ++ RETURN_ERROR( MAJOR, E_INVALID_OPERATION, ++ ("available for Tx and Offline parsing ports only")); ++ } ++ ++ countUnitBit = (uint8_t)FmGetTimeStampScale(p_FmPort->h_Fm); /* TimeStamp per nano seconds units */ ++ /* normally, we use 1 usec as the reference count */ ++ factor = 1; ++ /* if ratelimit is too small for a 1usec factor, multiply the factor */ ++ while (p_RateLimit->rateLimit < baseGran / factor) ++ { ++ if (countUnitBit == 31) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Rate limit is too small")); ++ ++ countUnitBit++; ++ factor <<= 1; ++ } ++ /* if ratelimit is too large for a 1usec factor, it is also larger than max rate*/ ++ if (p_RateLimit->rateLimit ++ > ((uint32_t)baseGran * (1 << 10) * (uint32_t)factor)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Rate limit is too large")); ++ ++ if (!p_RateLimit->maxBurstSize ++ || (p_RateLimit->maxBurstSize > BMI_RATE_LIMIT_MAX_BURST_SIZE)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("maxBurstSize must be between 1K and %dk", BMI_RATE_LIMIT_MAX_BURST_SIZE)); ++ ++ params.count_1micro_bit = (uint8_t)FmGetTimeStampScale(p_FmPort->h_Fm); ++ params.high_burst_size_gran = FALSE; ++ params.burst_size = p_RateLimit->maxBurstSize; ++ params.rate = p_RateLimit->rateLimit; ++ params.rate_factor = E_FMAN_PORT_RATE_DOWN_NONE; ++ ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ { ++#ifndef FM_NO_ADVANCED_RATE_LIMITER ++ ++ if ((p_FmPort->fmRevInfo.majorRev == 4) ++ || (p_FmPort->fmRevInfo.majorRev >= 6)) ++ { ++ params.high_burst_size_gran = TRUE; ++ } ++ else ++#endif /* ! FM_NO_ADVANCED_RATE_LIMITER */ ++ { ++ if (p_RateLimit->rateLimitDivider ++ != e_FM_PORT_DUAL_RATE_LIMITER_NONE) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("FM_PORT_ConfigDualRateLimitScaleDown")); ++ ++ if (p_RateLimit->maxBurstSize % 1000) ++ { ++ p_RateLimit->maxBurstSize = ++ (uint16_t)((p_RateLimit->maxBurstSize / 1000) + 1); ++ DBG(WARNING, ("rateLimit.maxBurstSize rounded up to %d", (p_RateLimit->maxBurstSize/1000+1)*1000)); ++ } ++ else ++ p_RateLimit->maxBurstSize = (uint16_t)(p_RateLimit->maxBurstSize ++ / 1000); ++ } ++ params.rate_factor = ++ (enum fman_port_rate_limiter_scale_down)p_RateLimit->rateLimitDivider; ++ params.burst_size = p_RateLimit->maxBurstSize; ++ } ++ ++ err = fman_port_set_rate_limiter(&p_FmPort->port, ¶ms); ++ if (err != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_rate_limiter")); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_DeleteRateLimit(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ int err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)) ++ RETURN_ERROR( MAJOR, E_INVALID_OPERATION, ++ ("available for Tx and Offline parsing ports only")); ++ ++ err = fman_port_delete_rate_limiter(&p_FmPort->port); ++ if (err != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_rate_limiter")); ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetPfcPrioritiesMappingToQmanWQ(t_Handle h_FmPort, uint8_t prio, ++ uint8_t wq) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint32_t tmpReg; ++ uint32_t wqTmpReg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_TX_10G)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("PFC mapping is available for Tx ports only")); ++ ++ if (prio > 7) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ++ ("PFC priority (%d) is out of range (0-7)", prio)); ++ if (wq > 7) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ++ ("WQ (%d) is out of range (0-7)", wq)); ++ ++ tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tpfcm[0]); ++ tmpReg &= ~(0xf << ((7 - prio) * 4)); ++ wqTmpReg = ((uint32_t)wq << ((7 - prio) * 4)); ++ tmpReg |= wqTmpReg; ++ ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tpfcm[0], ++ tmpReg); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetFrameQueueCounters(t_Handle h_FmPort, bool enable) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ fman_port_set_queue_cnt_mode(&p_FmPort->port, enable); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetPerformanceCounters(t_Handle h_FmPort, bool enable) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ int err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ err = fman_port_set_perf_cnt_mode(&p_FmPort->port, enable); ++ if (err != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_perf_cnt_mode")); ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetPerformanceCountersParams( ++ t_Handle h_FmPort, t_FmPortPerformanceCnt *p_FmPortPerformanceCnt) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ struct fman_port_perf_cnt_params params; ++ int err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ ++ /* check parameters */ ++ if (!p_FmPortPerformanceCnt->taskCompVal ++ || (p_FmPortPerformanceCnt->taskCompVal > p_FmPort->tasks.num)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("taskCompVal (%d) has to be in the range of 1 - %d (current value)!", p_FmPortPerformanceCnt->taskCompVal, p_FmPort->tasks.num)); ++ if (!p_FmPortPerformanceCnt->dmaCompVal ++ || (p_FmPortPerformanceCnt->dmaCompVal > p_FmPort->openDmas.num)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("dmaCompVal (%d) has to be in the range of 1 - %d (current value)!", p_FmPortPerformanceCnt->dmaCompVal, p_FmPort->openDmas.num)); ++ if (!p_FmPortPerformanceCnt->fifoCompVal ++ || (p_FmPortPerformanceCnt->fifoCompVal > p_FmPort->fifoBufs.num)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("fifoCompVal (%d) has to be in the range of 256 - %d (current value)!", p_FmPortPerformanceCnt->fifoCompVal, p_FmPort->fifoBufs.num)); ++ if (p_FmPortPerformanceCnt->fifoCompVal % BMI_FIFO_UNITS) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("fifoCompVal (%d) has to be divisible by %d", p_FmPortPerformanceCnt->fifoCompVal, BMI_FIFO_UNITS)); ++ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ if (!p_FmPortPerformanceCnt->queueCompVal ++ || (p_FmPortPerformanceCnt->queueCompVal ++ > MAX_PERFORMANCE_RX_QUEUE_COMP)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("performanceCnt.queueCompVal for Rx has to be in the range of 1 - %d", MAX_PERFORMANCE_RX_QUEUE_COMP)); ++ break; ++ case (e_FM_PORT_TYPE_TX_10G): ++ case (e_FM_PORT_TYPE_TX): ++ if (!p_FmPortPerformanceCnt->queueCompVal ++ || (p_FmPortPerformanceCnt->queueCompVal ++ > MAX_PERFORMANCE_TX_QUEUE_COMP)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("performanceCnt.queueCompVal for Tx has to be in the range of 1 - %d", MAX_PERFORMANCE_TX_QUEUE_COMP)); ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ if (p_FmPortPerformanceCnt->queueCompVal) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("performanceCnt.queueCompVal is not relevant for H/O ports.")); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ ++ params.task_val = p_FmPortPerformanceCnt->taskCompVal; ++ params.queue_val = p_FmPortPerformanceCnt->queueCompVal; ++ params.dma_val = p_FmPortPerformanceCnt->dmaCompVal; ++ params.fifo_val = p_FmPortPerformanceCnt->fifoCompVal; ++ ++ err = fman_port_set_perf_cnt_params(&p_FmPort->port, ¶ms); ++ if (err != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_perf_cnt_params")); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_AnalyzePerformanceParams(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_FmPortPerformanceCnt currParams, savedParams; ++ t_Error err; ++ bool underTest, failed = FALSE; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ ++ XX_Print("Analyzing Performance parameters for port (type %d, id%d)\n", ++ p_FmPort->portType, p_FmPort->portId); ++ ++ currParams.taskCompVal = (uint8_t)p_FmPort->tasks.num; ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)) ++ currParams.queueCompVal = 0; ++ else ++ currParams.queueCompVal = 1; ++ currParams.dmaCompVal = (uint8_t)p_FmPort->openDmas.num; ++ currParams.fifoCompVal = p_FmPort->fifoBufs.num; ++ ++ FM_PORT_SetPerformanceCounters(p_FmPort, FALSE); ++ ClearPerfCnts(p_FmPort); ++ if ((err = FM_PORT_SetPerformanceCountersParams(p_FmPort, &currParams)) ++ != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ FM_PORT_SetPerformanceCounters(p_FmPort, TRUE); ++ XX_UDelay(1000000); ++ FM_PORT_SetPerformanceCounters(p_FmPort, FALSE); ++ if (FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL)) ++ { ++ XX_Print( ++ "Max num of defined port tasks (%d) utilized - Please enlarge\n", ++ p_FmPort->tasks.num); ++ failed = TRUE; ++ } ++ if (FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL)) ++ { ++ XX_Print( ++ "Max num of defined port openDmas (%d) utilized - Please enlarge\n", ++ p_FmPort->openDmas.num); ++ failed = TRUE; ++ } ++ if (FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL)) ++ { ++ XX_Print( ++ "Max size of defined port fifo (%d) utilized - Please enlarge\n", ++ p_FmPort->fifoBufs.num); ++ failed = TRUE; ++ } ++ if (failed) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ memset(&savedParams, 0, sizeof(savedParams)); ++ while (TRUE) ++ { ++ underTest = FALSE; ++ if ((currParams.taskCompVal != 1) && !savedParams.taskCompVal) ++ { ++ currParams.taskCompVal--; ++ underTest = TRUE; ++ } ++ if ((currParams.dmaCompVal != 1) && !savedParams.dmaCompVal) ++ { ++ currParams.dmaCompVal--; ++ underTest = TRUE; ++ } ++ if ((currParams.fifoCompVal != BMI_FIFO_UNITS) ++ && !savedParams.fifoCompVal) ++ { ++ currParams.fifoCompVal -= BMI_FIFO_UNITS; ++ underTest = TRUE; ++ } ++ if (!underTest) ++ break; ++ ++ ClearPerfCnts(p_FmPort); ++ if ((err = FM_PORT_SetPerformanceCountersParams(p_FmPort, &currParams)) ++ != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ FM_PORT_SetPerformanceCounters(p_FmPort, TRUE); ++ XX_UDelay(1000000); ++ FM_PORT_SetPerformanceCounters(p_FmPort, FALSE); ++ ++ if (!savedParams.taskCompVal ++ && FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL)) ++ savedParams.taskCompVal = (uint8_t)(currParams.taskCompVal + 2); ++ if (!savedParams.dmaCompVal ++ && FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL)) ++ savedParams.dmaCompVal = (uint8_t)(currParams.dmaCompVal + 2); ++ if (!savedParams.fifoCompVal ++ && FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL)) ++ savedParams.fifoCompVal = currParams.fifoCompVal ++ + (2 * BMI_FIFO_UNITS); ++ } ++ ++ XX_Print("best vals: tasks %d, dmas %d, fifos %d\n", ++ savedParams.taskCompVal, savedParams.dmaCompVal, ++ savedParams.fifoCompVal); ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetStatisticsCounters(t_Handle h_FmPort, bool enable) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ int err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ err = fman_port_set_stats_cnt_mode(&p_FmPort->port, enable); ++ if (err != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_stats_cnt_mode")); ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetErrorsRoute(t_Handle h_FmPort, fmPortFrameErrSelect_t errs) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ volatile uint32_t *p_ErrDiscard = NULL; ++ int err; ++ ++ UNUSED(p_ErrDiscard); ++ err = fman_port_set_err_mask(&p_FmPort->port, (uint32_t)errs); ++ if (err != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_err_mask")); ++ ++#ifdef FM_ERROR_VSP_NO_MATCH_SW006 ++ if (p_FmPort->fmRevInfo.majorRev >= 6) ++ { ++ t_FmPcdCtrlParamsPage *p_ParamsPage; ++ ++ FmPortSetGprFunc(p_FmPort, e_FM_PORT_GPR_MURAM_PAGE, ++ (void**)&p_ParamsPage); ++ ASSERT_COND(p_ParamsPage); ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_ErrDiscard = ++ &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfsdm; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_ErrDiscard = ++ &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsdm; ++ break; ++ default: ++ RETURN_ERROR( ++ MAJOR, E_INVALID_OPERATION, ++ ("available for Rx and offline parsing ports only")); ++ } ++ WRITE_UINT32(p_ParamsPage->errorsDiscardMask, ++ GET_UINT32(*p_ErrDiscard) | errs); ++ } ++#endif /* FM_ERROR_VSP_NO_MATCH_SW006 */ ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetAllocBufCounter(t_Handle h_FmPort, uint8_t poolId, ++ bool enable) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ int err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(poolIdp_FmPortDriverParam, E_INVALID_STATE); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for Rx ports only")); ++ ++ err = fman_port_set_bpool_cnt_mode(&p_FmPort->port, poolId, enable); ++ if (err != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_bpool_cnt_mode")); ++ return E_OK; ++} ++ ++t_Error FM_PORT_GetBmiCounters(t_Handle h_FmPort, t_FmPortBmiStats *p_BmiStats) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)){ ++ p_BmiStats->cntCycle = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_CYCLE); ++ /* fmbm_rccn */ ++ p_BmiStats->cntTaskUtil = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL); ++ /* fmbm_rtuc */ ++ p_BmiStats->cntQueueUtil = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_QUEUE_UTIL); ++ /* fmbm_rrquc */ ++ p_BmiStats->cntDmaUtil = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL); ++ /* fmbm_rduc */ ++ p_BmiStats->cntFifoUtil = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL); ++ /* fmbm_rfuc */ ++ p_BmiStats->cntRxPauseActivation = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION); ++ /* fmbm_rpac */ ++ p_BmiStats->cntFrame = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_FRAME); ++ /* fmbm_rfrc */ ++ p_BmiStats->cntDiscardFrame = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_DISCARD_FRAME); ++ /* fmbm_rfdc */ ++ p_BmiStats->cntDeallocBuf = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_DEALLOC_BUF); ++ /* fmbm_rbdc */ ++ p_BmiStats->cntRxBadFrame = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_RX_BAD_FRAME); ++ /* fmbm_rfbc */ ++ p_BmiStats->cntRxLargeFrame = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_RX_LARGE_FRAME); ++ /* fmbm_rlfc */ ++ p_BmiStats->cntRxFilterFrame = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_RX_FILTER_FRAME); ++ /* fmbm_rffc */ ++ p_BmiStats->cntRxListDmaErr = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR); ++ /* fmbm_rfldec */ ++ p_BmiStats->cntRxOutOfBuffersDiscard = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD); ++ /* fmbm_rodc */ ++ p_BmiStats->cntWredDiscard = 0; ++ p_BmiStats->cntLengthErr = 0; ++ p_BmiStats->cntUnsupportedFormat = 0; ++ } ++ else if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G)){ ++ p_BmiStats->cntCycle = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_CYCLE); ++ /* fmbm_tccn */ ++ p_BmiStats->cntTaskUtil = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL); ++ /* fmbm_ttuc */ ++ p_BmiStats->cntQueueUtil = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_QUEUE_UTIL); ++ /* fmbm_ttcquc */ ++ p_BmiStats->cntDmaUtil = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL); ++ /* fmbm_tduc */ ++ p_BmiStats->cntFifoUtil = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL); ++ /* fmbm_tfuc */ ++ p_BmiStats->cntRxPauseActivation = 0; ++ p_BmiStats->cntFrame = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_FRAME); ++ /* fmbm_tfrc */ ++ p_BmiStats->cntDiscardFrame = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_DISCARD_FRAME); ++ /* fmbm_tfdc */ ++ p_BmiStats->cntDeallocBuf = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_DEALLOC_BUF); ++ /* fmbm_tbdc */ ++ p_BmiStats->cntRxBadFrame = 0; ++ p_BmiStats->cntRxLargeFrame = 0; ++ p_BmiStats->cntRxFilterFrame = 0; ++ p_BmiStats->cntRxListDmaErr = 0; ++ p_BmiStats->cntRxOutOfBuffersDiscard = 0; ++ p_BmiStats->cntWredDiscard = 0; ++ p_BmiStats->cntLengthErr = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_LENGTH_ERR); ++ /* fmbm_tfledc */ ++ p_BmiStats->cntUnsupportedFormat = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT); ++ /* fmbm_tfufdc */ ++ } ++ else if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) { ++ p_BmiStats->cntCycle = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_CYCLE); ++ /* fmbm_occn */ ++ p_BmiStats->cntTaskUtil = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL); ++ /* fmbm_otuc */ ++ p_BmiStats->cntQueueUtil = 0; ++ p_BmiStats->cntDmaUtil = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL); ++ /* fmbm_oduc */ ++ p_BmiStats->cntFifoUtil = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL); ++ /* fmbm_ofuc*/ ++ p_BmiStats->cntRxPauseActivation = 0; ++ p_BmiStats->cntFrame = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_FRAME); ++ /* fmbm_ofrc */ ++ p_BmiStats->cntDiscardFrame = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_DISCARD_FRAME); ++ /* fmbm_ofdc */ ++ p_BmiStats->cntDeallocBuf = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_DEALLOC_BUF); ++ /* fmbm_obdc*/ ++ p_BmiStats->cntRxBadFrame = 0; ++ p_BmiStats->cntRxLargeFrame = 0; ++ p_BmiStats->cntRxFilterFrame = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_RX_FILTER_FRAME); ++ /* fmbm_offc */ ++ p_BmiStats->cntRxListDmaErr = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR); ++ /* fmbm_ofldec */ ++ p_BmiStats->cntRxOutOfBuffersDiscard = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD); ++ /* fmbm_rodc */ ++ p_BmiStats->cntWredDiscard = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_WRED_DISCARD); ++ /* fmbm_ofwdc */ ++ p_BmiStats->cntLengthErr = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_LENGTH_ERR); ++ /* fmbm_ofledc */ ++ p_BmiStats->cntUnsupportedFormat = ++ FM_PORT_GetCounter(h_FmPort, e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT); ++ /* fmbm_ofufdc */ ++ } ++ return E_OK; ++} ++ ++uint32_t FM_PORT_GetCounter(t_Handle h_FmPort, e_FmPortCounters counter) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ bool bmiCounter = FALSE; ++ enum fman_port_stats_counters statsType; ++ enum fman_port_perf_counters perfType; ++ enum fman_port_qmi_counters queueType; ++ bool isStats; ++ t_Error errCode; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_DEQ_TOTAL): ++ case (e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT): ++ case (e_FM_PORT_COUNTERS_DEQ_CONFIRM): ++ /* check that counter is available for the port type */ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ++ ("Requested counter is not available for Rx ports")); ++ return 0; ++ } ++ bmiCounter = FALSE; ++ break; ++ case (e_FM_PORT_COUNTERS_ENQ_TOTAL): ++ bmiCounter = FALSE; ++ break; ++ default: /* BMI counters (or error - will be checked in BMI routine )*/ ++ bmiCounter = TRUE; ++ break; ++ } ++ ++ if (bmiCounter) ++ { ++ errCode = BmiPortCheckAndGetCounterType(p_FmPort, counter, &statsType, ++ &perfType, &isStats); ++ if (errCode != E_OK) ++ { ++ REPORT_ERROR(MINOR, errCode, NO_MSG); ++ return 0; ++ } ++ if (isStats) ++ return fman_port_get_stats_counter(&p_FmPort->port, statsType); ++ else ++ return fman_port_get_perf_counter(&p_FmPort->port, perfType); ++ } ++ else /* QMI counter */ ++ { ++ /* check that counters are enabled */ ++ if (!(GET_UINT32(p_FmPort->port.qmi_regs->fmqm_pnc) ++ & QMI_PORT_CFG_EN_COUNTERS)) ++ ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled")); ++ return 0; ++ } ++ ++ /* Set counter */ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_ENQ_TOTAL): ++ queueType = E_FMAN_PORT_ENQ_TOTAL; ++ break; ++ case (e_FM_PORT_COUNTERS_DEQ_TOTAL): ++ queueType = E_FMAN_PORT_DEQ_TOTAL; ++ break; ++ case (e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT): ++ queueType = E_FMAN_PORT_DEQ_FROM_DFLT; ++ break; ++ case (e_FM_PORT_COUNTERS_DEQ_CONFIRM): ++ queueType = E_FMAN_PORT_DEQ_CONFIRM; ++ break; ++ default: ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available")); ++ return 0; ++ } ++ ++ return fman_port_get_qmi_counter(&p_FmPort->port, queueType); ++ } ++ ++ return 0; ++} ++ ++t_Error FM_PORT_ModifyCounter(t_Handle h_FmPort, e_FmPortCounters counter, ++ uint32_t value) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ bool bmiCounter = FALSE; ++ enum fman_port_stats_counters statsType; ++ enum fman_port_perf_counters perfType; ++ enum fman_port_qmi_counters queueType; ++ bool isStats; ++ t_Error errCode; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_DEQ_TOTAL): ++ case (e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT): ++ case (e_FM_PORT_COUNTERS_DEQ_CONFIRM): ++ /* check that counter is available for the port type */ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ++ || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ RETURN_ERROR( ++ MINOR, E_INVALID_STATE, ++ ("Requested counter is not available for Rx ports")); ++ case (e_FM_PORT_COUNTERS_ENQ_TOTAL): ++ bmiCounter = FALSE; ++ break; ++ default: /* BMI counters (or error - will be checked in BMI routine )*/ ++ bmiCounter = TRUE; ++ break; ++ } ++ ++ if (bmiCounter) ++ { ++ errCode = BmiPortCheckAndGetCounterType(p_FmPort, counter, &statsType, ++ &perfType, &isStats); ++ if (errCode != E_OK) ++ { ++ RETURN_ERROR(MINOR, errCode, NO_MSG); ++ } ++ if (isStats) ++ fman_port_set_stats_counter(&p_FmPort->port, statsType, value); ++ else ++ fman_port_set_perf_counter(&p_FmPort->port, perfType, value); ++ } ++ else /* QMI counter */ ++ { ++ /* check that counters are enabled */ ++ if (!(GET_UINT32(p_FmPort->port.qmi_regs->fmqm_pnc) ++ & QMI_PORT_CFG_EN_COUNTERS)) ++ { ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ++ ("Requested counter was not enabled")); ++ } ++ ++ /* Set counter */ ++ switch (counter) ++ { ++ case (e_FM_PORT_COUNTERS_ENQ_TOTAL): ++ queueType = E_FMAN_PORT_ENQ_TOTAL; ++ break; ++ case (e_FM_PORT_COUNTERS_DEQ_TOTAL): ++ queueType = E_FMAN_PORT_DEQ_TOTAL; ++ break; ++ case (e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT): ++ queueType = E_FMAN_PORT_DEQ_FROM_DFLT; ++ break; ++ case (e_FM_PORT_COUNTERS_DEQ_CONFIRM): ++ queueType = E_FMAN_PORT_DEQ_CONFIRM; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("Requested counter is not available")); ++ } ++ ++ fman_port_set_qmi_counter(&p_FmPort->port, queueType, value); ++ } ++ ++ return E_OK; ++} ++ ++uint32_t FM_PORT_GetAllocBufCounter(t_Handle h_FmPort, uint8_t poolId) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX) ++ && (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for non-Rx ports")); ++ return 0; ++ } ++ return fman_port_get_bpool_counter(&p_FmPort->port, poolId); ++} ++ ++t_Error FM_PORT_ModifyAllocBufCounter(t_Handle h_FmPort, uint8_t poolId, ++ uint32_t value) ++{ ++ t_FmPort *p_FmPort = (t_FmPort *)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX) ++ && (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ RETURN_ERROR( MINOR, E_INVALID_STATE, ++ ("Requested counter is not available for non-Rx ports")); ++ ++ fman_port_set_bpool_counter(&p_FmPort->port, poolId, value); ++ return E_OK; ++} ++bool FM_PORT_IsStalled(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err; ++ bool isStalled; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, FALSE); ++ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, ++ FALSE); ++ ++ err = FmIsPortStalled(p_FmPort->h_Fm, p_FmPort->hardwarePortId, &isStalled); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return TRUE; ++ } ++ return isStalled; ++} ++ ++t_Error FM_PORT_ReleaseStalled(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ return FmResumeStalledPort(p_FmPort->h_Fm, p_FmPort->hardwarePortId); ++} ++ ++t_Error FM_PORT_SetRxL4ChecksumVerify(t_Handle h_FmPort, bool l4Checksum) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ int err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for Rx ports only")); ++ ++ if (l4Checksum) ++ err = fman_port_modify_rx_fd_bits( ++ &p_FmPort->port, (uint8_t)(BMI_PORT_RFNE_FRWD_DCL4C >> 24), ++ TRUE); ++ else ++ err = fman_port_modify_rx_fd_bits( ++ &p_FmPort->port, (uint8_t)(BMI_PORT_RFNE_FRWD_DCL4C >> 24), ++ FALSE); ++ if (err != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_modify_rx_fd_bits")); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++/* API Run-time PCD Control unit functions */ ++/*****************************************************************************/ ++ ++#if (DPAA_VERSION >= 11) ++t_Error FM_PORT_VSPAlloc(t_Handle h_FmPort, t_FmPortVSPAllocParams *p_VSPParams) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ volatile uint32_t *p_BmiStorageProfileId = NULL, *p_BmiVspe = NULL; ++ uint32_t tmpReg = 0, tmp = 0; ++ uint16_t hwStoragePrflId; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->h_Fm, E_INVALID_HANDLE); ++ /*for numOfProfiles = 0 don't call this function*/ ++ SANITY_CHECK_RETURN_ERROR(p_VSPParams->numOfProfiles, E_INVALID_VALUE); ++ /*dfltRelativeId should be in the range of numOfProfiles*/ ++ SANITY_CHECK_RETURN_ERROR( ++ p_VSPParams->dfltRelativeId < p_VSPParams->numOfProfiles, ++ E_INVALID_VALUE); ++ /*p_FmPort should be from Rx type or OP*/ ++ SANITY_CHECK_RETURN_ERROR( ++ ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)), ++ E_INVALID_VALUE); ++ /*port should be disabled*/ ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->enabled, E_INVALID_STATE); ++ /*if its called for Rx port relevant Tx Port should be passed (initialized) too and it should be disabled*/ ++ SANITY_CHECK_RETURN_ERROR( ++ ((p_VSPParams->h_FmTxPort && !((t_FmPort *)(p_VSPParams->h_FmTxPort))->enabled) || (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)), ++ E_INVALID_VALUE); ++ /*should be called before SetPCD - this port should be without PCD*/ ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->pcdEngines, E_INVALID_STATE); ++ ++ /*alloc window of VSPs for this port*/ ++ err = FmVSPAllocForPort(p_FmPort->h_Fm, p_FmPort->portType, ++ p_FmPort->portId, p_VSPParams->numOfProfiles); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ /*get absolute VSP ID for dfltRelative*/ ++ err = FmVSPGetAbsoluteProfileId(p_FmPort->h_Fm, p_FmPort->portType, ++ p_FmPort->portId, ++ p_VSPParams->dfltRelativeId, ++ &hwStoragePrflId); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ /*fill relevant registers for p_FmPort and relative TxPort in the case p_FmPort from Rx type*/ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiStorageProfileId = ++ &(((t_FmPort *)(p_VSPParams->h_FmTxPort))->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfqid); ++ p_BmiVspe = ++ &(((t_FmPort *)(p_VSPParams->h_FmTxPort))->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tfne); ++ ++ tmpReg = GET_UINT32(*p_BmiStorageProfileId) & ~BMI_SP_ID_MASK; ++ tmpReg |= (uint32_t)hwStoragePrflId << BMI_SP_ID_SHIFT; ++ WRITE_UINT32(*p_BmiStorageProfileId, tmpReg); ++ ++ tmpReg = GET_UINT32(*p_BmiVspe); ++ WRITE_UINT32(*p_BmiVspe, tmpReg | BMI_SP_EN); ++ ++ p_BmiStorageProfileId = ++ &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfqid; ++ p_BmiVspe = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpp; ++ hwStoragePrflId = p_VSPParams->dfltRelativeId; ++ break; ++ ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ tmpReg = NIA_ENG_BMI | NIA_BMI_AC_FETCH_ALL_FRAME; ++ WRITE_UINT32( p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn, ++ tmpReg); ++ ++ p_BmiStorageProfileId = ++ &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofqid; ++ p_BmiVspe = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opp; ++ tmp |= BMI_EBD_EN; ++ break; ++ ++ default: ++ RETURN_ERROR( MAJOR, E_INVALID_OPERATION, ++ ("available for Rx and offline parsing ports only")); ++ } ++ ++ p_FmPort->vspe = TRUE; ++ p_FmPort->dfltRelativeId = p_VSPParams->dfltRelativeId; ++ ++ tmpReg = GET_UINT32(*p_BmiStorageProfileId) & ~BMI_SP_ID_MASK; ++ tmpReg |= (uint32_t)hwStoragePrflId << BMI_SP_ID_SHIFT; ++ WRITE_UINT32(*p_BmiStorageProfileId, tmpReg); ++ ++ tmpReg = GET_UINT32(*p_BmiVspe); ++ WRITE_UINT32(*p_BmiVspe, tmpReg | BMI_SP_EN | tmp); ++ return E_OK; ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++t_Error FM_PORT_PcdPlcrAllocProfiles(t_Handle h_FmPort, uint16_t numOfProfiles) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ ++ p_FmPort->h_FmPcd = FmGetPcdHandle(p_FmPort->h_Fm); ++ ASSERT_COND(p_FmPort->h_FmPcd); ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ if (numOfProfiles) ++ { ++ err = FmPcdPlcrAllocProfiles(p_FmPort->h_FmPcd, ++ p_FmPort->hardwarePortId, numOfProfiles); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ /* set the port handle within the PCD policer, even if no profiles defined */ ++ FmPcdPortRegister(p_FmPort->h_FmPcd, h_FmPort, p_FmPort->hardwarePortId); ++ ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_PcdPlcrFreeProfiles(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdPlcrFreeProfiles(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId); ++ ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_PcdKgModifyInitialScheme(t_Handle h_FmPort, ++ t_FmPcdKgSchemeSelect *p_FmPcdKgScheme) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ volatile uint32_t *p_BmiHpnia = NULL; ++ uint32_t tmpReg; ++ uint8_t relativeSchemeId; ++ uint8_t physicalSchemeId; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_KG, ++ E_INVALID_STATE); ++ ++ tmpReg = (uint32_t)((p_FmPort->pcdEngines & FM_PCD_CC) ? NIA_KG_CC_EN : 0); ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiHpnia = &p_FmPort->port.bmi_regs->rx.fmbm_rfpne; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiHpnia = &p_FmPort->port.bmi_regs->oh.fmbm_ofpne; ++ break; ++ default: ++ RETURN_ERROR( MAJOR, E_INVALID_OPERATION, ++ ("available for Rx and offline parsing ports only")); ++ } ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ /* if we want to change to direct scheme, we need to check that this scheme is valid */ ++ if (p_FmPcdKgScheme->direct) ++ { ++ physicalSchemeId = FmPcdKgGetSchemeId(p_FmPcdKgScheme->h_DirectScheme); ++ /* check that this scheme is bound to this port */ ++ if (!(p_FmPort->schemesPerPortVector ++ & (uint32_t)(1 << (31 - (uint32_t)physicalSchemeId)))) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR( ++ MAJOR, E_INVALID_STATE, ++ ("called with a scheme that is not bound to this port")); ++ } ++ ++ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPort->h_FmPcd, ++ physicalSchemeId); ++ if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ++ ("called with invalid Scheme ")); ++ } ++ ++ if (!FmPcdKgIsSchemeValidSw(p_FmPcdKgScheme->h_DirectScheme)) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("called with uninitialized Scheme ")); ++ } ++ ++ WRITE_UINT32( ++ *p_BmiHpnia, ++ NIA_ENG_KG | tmpReg | NIA_KG_DIRECT | (uint32_t)physicalSchemeId); ++ } ++ else ++ /* change to indirect scheme */ ++ WRITE_UINT32(*p_BmiHpnia, NIA_ENG_KG | tmpReg); ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_PcdPlcrModifyInitialProfile(t_Handle h_FmPort, ++ t_Handle h_Profile) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ volatile uint32_t *p_BmiNia; ++ volatile uint32_t *p_BmiHpnia; ++ uint32_t tmpReg; ++ uint16_t absoluteProfileId = FmPcdPlcrProfileGetAbsoluteId(h_Profile); ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_PLCR, ++ E_INVALID_STATE); ++ ++ /* check relevance of this routine - only when policer is used ++ directly after BMI or Parser */ ++ if ((p_FmPort->pcdEngines & FM_PCD_KG) ++ || (p_FmPort->pcdEngines & FM_PCD_CC)) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("relevant only when PCD support mode is e_FM_PCD_SUPPORT_PLCR_ONLY or e_FM_PCD_SUPPORT_PRS_AND_PLCR")); ++ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiNia = &p_FmPort->port.bmi_regs->rx.fmbm_rfne; ++ p_BmiHpnia = &p_FmPort->port.bmi_regs->rx.fmbm_rfpne; ++ tmpReg = GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiNia = &p_FmPort->port.bmi_regs->oh.fmbm_ofne; ++ p_BmiHpnia = &p_FmPort->port.bmi_regs->oh.fmbm_ofpne; ++ tmpReg = 0; ++ break; ++ default: ++ RETURN_ERROR( MAJOR, E_INVALID_OPERATION, ++ ("available for Rx and offline parsing ports only")); ++ } ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ if (!FmPcdPlcrIsProfileValid(p_FmPort->h_FmPcd, absoluteProfileId)) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Invalid profile")); ++ } ++ ++ tmpReg |= (uint32_t)(NIA_ENG_PLCR | NIA_PLCR_ABSOLUTE | absoluteProfileId); ++ ++ if (p_FmPort->pcdEngines & FM_PCD_PRS) /* e_FM_PCD_SUPPORT_PRS_AND_PLCR */ ++ { ++ /* update BMI HPNIA */ ++ WRITE_UINT32(*p_BmiHpnia, tmpReg); ++ } ++ else /* e_FM_PCD_SUPPORT_PLCR_ONLY */ ++ { ++ /* rfne may contain FDCS bits, so first we read them. */ ++ tmpReg |= (GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK); ++ /* update BMI NIA */ ++ WRITE_UINT32(*p_BmiNia, tmpReg); ++ }RELEASE_LOCK(p_FmPort->lock); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_PcdCcModifyTree(t_Handle h_FmPort, t_Handle h_CcTree) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ volatile uint32_t *p_BmiCcBase = NULL; ++ volatile uint32_t *p_BmiNia = NULL; ++ uint32_t ccTreePhysOffset; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(h_CcTree, E_INVALID_HANDLE); ++ ++ if (p_FmPort->imEn) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for non-independent mode ports only")); ++ ++ /* get PCD registers pointers */ ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiNia = &p_FmPort->port.bmi_regs->rx.fmbm_rfne; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiNia = &p_FmPort->port.bmi_regs->oh.fmbm_ofne; ++ break; ++ default: ++ RETURN_ERROR( MAJOR, E_INVALID_OPERATION, ++ ("available for Rx and offline parsing ports only")); ++ } ++ ++ /* check that current NIA is BMI to BMI */ ++ if ((GET_UINT32(*p_BmiNia) & ~BMI_RFNE_FDCS_MASK) ++ != GET_NIA_BMI_AC_ENQ_FRAME(p_FmPort->h_FmPcd)) ++ RETURN_ERROR( MAJOR, E_INVALID_OPERATION, ++ ("may be called only for ports in BMI-to-BMI state.")); ++ ++ if (p_FmPort->pcdEngines & FM_PCD_CC) ++ { ++ if (p_FmPort->h_IpReassemblyManip) ++ { ++ err = FmPcdCcTreeAddIPR(p_FmPort->h_FmPcd, h_CcTree, NULL, ++ p_FmPort->h_IpReassemblyManip, FALSE); ++ if (err != E_OK) ++ { ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ else ++ if (p_FmPort->h_CapwapReassemblyManip) ++ { ++ err = FmPcdCcTreeAddCPR(p_FmPort->h_FmPcd, h_CcTree, NULL, ++ p_FmPort->h_CapwapReassemblyManip, ++ FALSE); ++ if (err != E_OK) ++ { ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ switch (p_FmPort->portType) ++ { ++ case (e_FM_PORT_TYPE_RX_10G): ++ case (e_FM_PORT_TYPE_RX): ++ p_BmiCcBase = &p_FmPort->port.bmi_regs->rx.fmbm_rccb; ++ break; ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ p_BmiCcBase = &p_FmPort->port.bmi_regs->oh.fmbm_occb; ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type")); ++ } ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ err = FmPcdCcBindTree(p_FmPort->h_FmPcd, NULL, h_CcTree, ++ &ccTreePhysOffset, h_FmPort); ++ if (err) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ }WRITE_UINT32(*p_BmiCcBase, ccTreePhysOffset); ++ ++ p_FmPort->ccTreeId = h_CcTree; ++ RELEASE_LOCK(p_FmPort->lock); ++ } ++ else ++ RETURN_ERROR( MAJOR, E_INVALID_STATE, ++ ("Coarse Classification not defined for this port.")); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_AttachPCD(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPort->imEn) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for non-independent mode ports only")); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ RETURN_ERROR( MAJOR, E_INVALID_OPERATION, ++ ("available for Rx and offline parsing ports only")); ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ if (p_FmPort->h_ReassemblyTree) ++ p_FmPort->pcdEngines |= FM_PCD_CC; ++ ++ err = AttachPCD(h_FmPort); ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return err; ++} ++ ++t_Error FM_PORT_DetachPCD(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPort->imEn) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for non-independent mode ports only")); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ RETURN_ERROR( MAJOR, E_INVALID_OPERATION, ++ ("available for Rx and offline parsing ports only")); ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = DetachPCD(h_FmPort); ++ if (err != E_OK) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ if (p_FmPort->h_ReassemblyTree) ++ p_FmPort->pcdEngines &= ~FM_PCD_CC; ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetPCD(t_Handle h_FmPort, t_FmPortPcdParams *p_PcdParam) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ t_FmPortPcdParams modifiedPcdParams, *p_PcdParams; ++ t_FmPcdCcTreeParams *p_FmPcdCcTreeParams; ++ t_FmPortPcdCcParams fmPortPcdCcParams; ++ t_FmPortGetSetCcParams fmPortGetSetCcParams; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_PcdParam, E_NULL_POINTER); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPort->imEn) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for non-independent mode ports only")); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ RETURN_ERROR( MAJOR, E_INVALID_OPERATION, ++ ("available for Rx and offline parsing ports only")); ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ p_FmPort->h_FmPcd = FmGetPcdHandle(p_FmPort->h_Fm); ++ ASSERT_COND(p_FmPort->h_FmPcd); ++ ++ if (p_PcdParam->p_CcParams && !p_PcdParam->p_CcParams->h_CcTree) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ++ ("Tree handle must be given if CC is required")); ++ ++ memcpy(&modifiedPcdParams, p_PcdParam, sizeof(t_FmPortPcdParams)); ++ p_PcdParams = &modifiedPcdParams; ++ if ((p_PcdParams->h_IpReassemblyManip) ++#if (DPAA_VERSION >= 11) ++ || (p_PcdParams->h_CapwapReassemblyManip) ++#endif /* (DPAA_VERSION >= 11) */ ++ ) ++ { ++ if ((p_PcdParams->pcdSupport != e_FM_PORT_PCD_SUPPORT_PRS_AND_KG) ++ && (p_PcdParams->pcdSupport ++ != e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC) ++ && (p_PcdParams->pcdSupport ++ != e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR) ++ && (p_PcdParams->pcdSupport ++ != e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR)) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR( MAJOR, E_INVALID_STATE, ++ ("pcdSupport must have KG for supporting Reassembly")); ++ } ++ p_FmPort->h_IpReassemblyManip = p_PcdParams->h_IpReassemblyManip; ++#if (DPAA_VERSION >= 11) ++ if ((p_PcdParams->h_IpReassemblyManip) ++ && (p_PcdParams->h_CapwapReassemblyManip)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("Either IP-R or CAPWAP-R is allowed")); ++ if ((p_PcdParams->h_CapwapReassemblyManip) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("CAPWAP-R is allowed only on offline-port")); ++ if (p_PcdParams->h_CapwapReassemblyManip) ++ p_FmPort->h_CapwapReassemblyManip = ++ p_PcdParams->h_CapwapReassemblyManip; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (!p_PcdParams->p_CcParams) ++ { ++ if (!((p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PRS_AND_KG) ++ || (p_PcdParams->pcdSupport ++ == e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR))) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_STATE, ++ ("PCD initialization structure is not consistent with pcdSupport")); ++ } ++ ++ /* No user-tree, need to build internal tree */ ++ p_FmPcdCcTreeParams = (t_FmPcdCcTreeParams*)XX_Malloc( ++ sizeof(t_FmPcdCcTreeParams)); ++ if (!p_FmPcdCcTreeParams) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_FmPcdCcTreeParams")); ++ memset(p_FmPcdCcTreeParams, 0, sizeof(t_FmPcdCcTreeParams)); ++ p_FmPcdCcTreeParams->h_NetEnv = p_PcdParams->h_NetEnv; ++ p_FmPort->h_ReassemblyTree = FM_PCD_CcRootBuild( ++ p_FmPort->h_FmPcd, p_FmPcdCcTreeParams); ++ ++ if (!p_FmPort->h_ReassemblyTree) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ XX_Free(p_FmPcdCcTreeParams); ++ RETURN_ERROR( MAJOR, E_INVALID_HANDLE, ++ ("FM_PCD_CcBuildTree for Reassembly failed")); ++ } ++ if (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PRS_AND_KG) ++ p_PcdParams->pcdSupport = ++ e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC; ++ else ++ p_PcdParams->pcdSupport = ++ e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR; ++ ++ memset(&fmPortPcdCcParams, 0, sizeof(t_FmPortPcdCcParams)); ++ fmPortPcdCcParams.h_CcTree = p_FmPort->h_ReassemblyTree; ++ p_PcdParams->p_CcParams = &fmPortPcdCcParams; ++ XX_Free(p_FmPcdCcTreeParams); ++ } ++ ++ if (p_FmPort->h_IpReassemblyManip) ++ err = FmPcdCcTreeAddIPR(p_FmPort->h_FmPcd, ++ p_PcdParams->p_CcParams->h_CcTree, ++ p_PcdParams->h_NetEnv, ++ p_FmPort->h_IpReassemblyManip, TRUE); ++#if (DPAA_VERSION >= 11) ++ else ++ if (p_FmPort->h_CapwapReassemblyManip) ++ err = FmPcdCcTreeAddCPR(p_FmPort->h_FmPcd, ++ p_PcdParams->p_CcParams->h_CcTree, ++ p_PcdParams->h_NetEnv, ++ p_FmPort->h_CapwapReassemblyManip, ++ TRUE); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (err != E_OK) ++ { ++ if (p_FmPort->h_ReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_ReassemblyTree); ++ p_FmPort->h_ReassemblyTree = NULL; ++ }RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ ++ if (!FmPcdLockTryLockAll(p_FmPort->h_FmPcd)) ++ { ++ if (p_FmPort->h_ReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_ReassemblyTree); ++ p_FmPort->h_ReassemblyTree = NULL; ++ }RELEASE_LOCK(p_FmPort->lock); ++ DBG(TRACE, ("Try LockAll - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = SetPcd(h_FmPort, p_PcdParams); ++ if (err) ++ { ++ if (p_FmPort->h_ReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_ReassemblyTree); ++ p_FmPort->h_ReassemblyTree = NULL; ++ } ++ FmPcdLockUnlockAll(p_FmPort->h_FmPcd); ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ if ((p_FmPort->pcdEngines & FM_PCD_PRS) ++ && (p_PcdParams->p_PrsParams->includeInPrsStatistics)) ++ { ++ err = FmPcdPrsIncludePortInStatistics(p_FmPort->h_FmPcd, ++ p_FmPort->hardwarePortId, TRUE); ++ if (err) ++ { ++ DeletePcd(p_FmPort); ++ if (p_FmPort->h_ReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_ReassemblyTree); ++ p_FmPort->h_ReassemblyTree = NULL; ++ } ++ FmPcdLockUnlockAll(p_FmPort->h_FmPcd); ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ p_FmPort->includeInPrsStatistics = TRUE; ++ } ++ ++ FmPcdIncNetEnvOwners(p_FmPort->h_FmPcd, p_FmPort->netEnvId); ++ ++ if (FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd)) ++ { ++ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams)); ++ ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ { ++#ifdef FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004 ++ if ((p_FmPort->fmRevInfo.majorRev < 6) && ++ (p_FmPort->pcdEngines & FM_PCD_KG)) ++ { ++ int i; ++ for (i = 0; ip_KgParams->numOfSchemes; i++) ++ /* The following function must be locked */ ++ FmPcdKgCcGetSetParams(p_FmPort->h_FmPcd, ++ p_PcdParams->p_KgParams->h_Schemes[i], ++ UPDATE_KG_NIA_CC_WA, ++ 0); ++ } ++#endif /* FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004 */ ++ ++#if (DPAA_VERSION >= 11) ++ { ++ t_FmPcdCtrlParamsPage *p_ParamsPage; ++ ++ FmPortSetGprFunc(p_FmPort, e_FM_PORT_GPR_MURAM_PAGE, ++ (void**)&p_ParamsPage); ++ ASSERT_COND(p_ParamsPage); ++ WRITE_UINT32(p_ParamsPage->postBmiFetchNia, ++ p_FmPort->savedBmiNia); ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ /* Set post-bmi-fetch nia */ ++ p_FmPort->savedBmiNia &= BMI_RFNE_FDCS_MASK; ++ p_FmPort->savedBmiNia |= (NIA_FM_CTL_AC_POST_BMI_FETCH ++ | NIA_ENG_FM_CTL); ++ ++ /* Set pre-bmi-fetch nia */ ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNDN; ++#if (DPAA_VERSION >= 11) ++ fmPortGetSetCcParams.setCcParams.nia = ++ (NIA_FM_CTL_AC_PRE_BMI_FETCH_FULL_FRAME | NIA_ENG_FM_CTL); ++#else ++ fmPortGetSetCcParams.setCcParams.nia = (NIA_FM_CTL_AC_PRE_BMI_FETCH_HEADER | NIA_ENG_FM_CTL); ++#endif /* (DPAA_VERSION >= 11) */ ++ if ((err = FmPortGetSetCcParams(p_FmPort, &fmPortGetSetCcParams)) ++ != E_OK) ++ { ++ DeletePcd(p_FmPort); ++ if (p_FmPort->h_ReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_ReassemblyTree); ++ p_FmPort->h_ReassemblyTree = NULL; ++ } ++ FmPcdLockUnlockAll(p_FmPort->h_FmPcd); ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ ++ FmPcdLockUnlockAll(p_FmPort->h_FmPcd); ++ ++ /* Set pop-to-next-step nia */ ++#if (DPAA_VERSION == 10) ++ if (p_FmPort->fmRevInfo.majorRev < 6) ++ { ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN; ++ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_POP_TO_N_STEP | NIA_ENG_FM_CTL; ++ } ++ else ++ { ++#endif /* (DPAA_VERSION == 10) */ ++ fmPortGetSetCcParams.getCcParams.type = GET_NIA_FPNE; ++#if (DPAA_VERSION == 10) ++ } ++#endif /* (DPAA_VERSION == 10) */ ++ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) ++ != E_OK) ++ { ++ DeletePcd(p_FmPort); ++ if (p_FmPort->h_ReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_ReassemblyTree); ++ p_FmPort->h_ReassemblyTree = NULL; ++ }RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ /* Set post-bmi-prepare-to-enq nia */ ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_FENE; ++ fmPortGetSetCcParams.setCcParams.nia = (NIA_FM_CTL_AC_POST_BMI_ENQ ++ | NIA_ENG_FM_CTL); ++ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) ++ != E_OK) ++ { ++ DeletePcd(p_FmPort); ++ if (p_FmPort->h_ReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_ReassemblyTree); ++ p_FmPort->h_ReassemblyTree = NULL; ++ }RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ if ((p_FmPort->h_IpReassemblyManip) ++ || (p_FmPort->h_CapwapReassemblyManip)) ++ { ++#if (DPAA_VERSION == 10) ++ if (p_FmPort->fmRevInfo.majorRev < 6) ++ { ++ /* Overwrite post-bmi-prepare-to-enq nia */ ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_FENE; ++ fmPortGetSetCcParams.setCcParams.nia = (NIA_FM_CTL_AC_POST_BMI_ENQ_ORR | NIA_ENG_FM_CTL | NIA_ORDER_RESTOR); ++ fmPortGetSetCcParams.setCcParams.overwrite = TRUE; ++ } ++ else ++ { ++#endif /* (DPAA_VERSION == 10) */ ++ /* Set the ORR bit (for order-restoration) */ ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_FPNE; ++ fmPortGetSetCcParams.setCcParams.nia = ++ fmPortGetSetCcParams.getCcParams.nia | NIA_ORDER_RESTOR; ++#if (DPAA_VERSION == 10) ++ } ++#endif /* (DPAA_VERSION == 10) */ ++ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) ++ != E_OK) ++ { ++ DeletePcd(p_FmPort); ++ if (p_FmPort->h_ReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_ReassemblyTree); ++ p_FmPort->h_ReassemblyTree = NULL; ++ }RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ } ++ } ++ else ++ FmPcdLockUnlockAll(p_FmPort->h_FmPcd); ++ ++#if (DPAA_VERSION >= 11) ++ { ++ t_FmPcdCtrlParamsPage *p_ParamsPage; ++ ++ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams)); ++ ++ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_CMNE; ++ if (FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd)) ++ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_POP_TO_N_STEP ++ | NIA_ENG_FM_CTL; ++ else ++ fmPortGetSetCcParams.setCcParams.nia = ++ NIA_FM_CTL_AC_NO_IPACC_POP_TO_N_STEP | NIA_ENG_FM_CTL; ++ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) ++ != E_OK) ++ { ++ DeletePcd(p_FmPort); ++ if (p_FmPort->h_ReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_ReassemblyTree); ++ p_FmPort->h_ReassemblyTree = NULL; ++ }RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ FmPortSetGprFunc(p_FmPort, e_FM_PORT_GPR_MURAM_PAGE, ++ (void**)&p_ParamsPage); ++ ASSERT_COND(p_ParamsPage); ++ ++ if (FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd)) ++ WRITE_UINT32( ++ p_ParamsPage->misc, ++ GET_UINT32(p_ParamsPage->misc) | FM_CTL_PARAMS_PAGE_OFFLOAD_SUPPORT_EN); ++ ++ if ((p_FmPort->h_IpReassemblyManip) ++ || (p_FmPort->h_CapwapReassemblyManip)) ++ { ++ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ WRITE_UINT32( ++ p_ParamsPage->discardMask, ++ GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsdm)); ++ else ++ WRITE_UINT32( ++ p_ParamsPage->discardMask, ++ GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfsdm)); ++ } ++#ifdef FM_ERROR_VSP_NO_MATCH_SW006 ++ if (p_FmPort->vspe) ++ WRITE_UINT32( ++ p_ParamsPage->misc, ++ GET_UINT32(p_ParamsPage->misc) | (p_FmPort->dfltRelativeId & FM_CTL_PARAMS_PAGE_ERROR_VSP_MASK)); ++#endif /* FM_ERROR_VSP_NO_MATCH_SW006 */ ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ err = AttachPCD(h_FmPort); ++ if (err) ++ { ++ DeletePcd(p_FmPort); ++ if (p_FmPort->h_ReassemblyTree) ++ { ++ FM_PCD_CcRootDelete(p_FmPort->h_ReassemblyTree); ++ p_FmPort->h_ReassemblyTree = NULL; ++ }RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return err; ++} ++ ++t_Error FM_PORT_DeletePCD(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ ++ if (p_FmPort->imEn) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ++ ("available for non-independant mode ports only")); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ RETURN_ERROR( MAJOR, E_INVALID_OPERATION, ++ ("available for Rx and offline parsing ports only")); ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = DetachPCD(h_FmPort); ++ if (err) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ FmPcdDecNetEnvOwners(p_FmPort->h_FmPcd, p_FmPort->netEnvId); ++ ++ /* we do it anyway, instead of checking if included */ ++ if ((p_FmPort->pcdEngines & FM_PCD_PRS) && p_FmPort->includeInPrsStatistics) ++ { ++ FmPcdPrsIncludePortInStatistics(p_FmPort->h_FmPcd, ++ p_FmPort->hardwarePortId, FALSE); ++ p_FmPort->includeInPrsStatistics = FALSE; ++ } ++ ++ if (!FmPcdLockTryLockAll(p_FmPort->h_FmPcd)) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ DBG(TRACE, ("Try LockAll - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = DeletePcd(h_FmPort); ++ FmPcdLockUnlockAll(p_FmPort->h_FmPcd); ++ if (err) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ if (p_FmPort->h_ReassemblyTree) ++ { ++ err = FM_PCD_CcRootDelete(p_FmPort->h_ReassemblyTree); ++ if (err) ++ { ++ RELEASE_LOCK(p_FmPort->lock); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ p_FmPort->h_ReassemblyTree = NULL; ++ }RELEASE_LOCK(p_FmPort->lock); ++ ++ return err; ++} ++ ++t_Error FM_PORT_PcdKgBindSchemes(t_Handle h_FmPort, ++ t_FmPcdPortSchemesParams *p_PortScheme) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_FmPcdKgInterModuleBindPortToSchemes schemeBind; ++ t_Error err = E_OK; ++ uint32_t tmpScmVec = 0; ++ int i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_KG, ++ E_INVALID_STATE); ++ ++ schemeBind.netEnvId = p_FmPort->netEnvId; ++ schemeBind.hardwarePortId = p_FmPort->hardwarePortId; ++ schemeBind.numOfSchemes = p_PortScheme->numOfSchemes; ++ schemeBind.useClsPlan = p_FmPort->useClsPlan; ++ for (i = 0; i < schemeBind.numOfSchemes; i++) ++ { ++ schemeBind.schemesIds[i] = FmPcdKgGetSchemeId( ++ p_PortScheme->h_Schemes[i]); ++ /* build vector */ ++ tmpScmVec |= 1 << (31 - (uint32_t)schemeBind.schemesIds[i]); ++ } ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdKgBindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind); ++ if (err == E_OK) ++ p_FmPort->schemesPerPortVector |= tmpScmVec; ++ ++#ifdef FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004 ++ if ((FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd)) && ++ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) && ++ (p_FmPort->fmRevInfo.majorRev < 6)) ++ { ++ for (i=0; inumOfSchemes; i++) ++ FmPcdKgCcGetSetParams(p_FmPort->h_FmPcd, p_PortScheme->h_Schemes[i], UPDATE_KG_NIA_CC_WA, 0); ++ } ++#endif /* FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004 */ ++ ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return err; ++} ++ ++t_Error FM_PORT_PcdKgUnbindSchemes(t_Handle h_FmPort, ++ t_FmPcdPortSchemesParams *p_PortScheme) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_FmPcdKgInterModuleBindPortToSchemes schemeBind; ++ t_Error err = E_OK; ++ uint32_t tmpScmVec = 0; ++ int i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_KG, ++ E_INVALID_STATE); ++ ++ schemeBind.netEnvId = p_FmPort->netEnvId; ++ schemeBind.hardwarePortId = p_FmPort->hardwarePortId; ++ schemeBind.numOfSchemes = p_PortScheme->numOfSchemes; ++ for (i = 0; i < schemeBind.numOfSchemes; i++) ++ { ++ schemeBind.schemesIds[i] = FmPcdKgGetSchemeId( ++ p_PortScheme->h_Schemes[i]); ++ /* build vector */ ++ tmpScmVec |= 1 << (31 - (uint32_t)schemeBind.schemesIds[i]); ++ } ++ ++ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock)) ++ { ++ DBG(TRACE, ("FM Port Try Lock - BUSY")); ++ return ERROR_CODE(E_BUSY); ++ } ++ ++ err = FmPcdKgUnbindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind); ++ if (err == E_OK) ++ p_FmPort->schemesPerPortVector &= ~tmpScmVec; ++ RELEASE_LOCK(p_FmPort->lock); ++ ++ return err; ++} ++ ++t_Error FM_PORT_AddCongestionGrps(t_Handle h_FmPort, ++ t_FmPortCongestionGrps *p_CongestionGrps) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint8_t priorityTmpArray[FM_PORT_NUM_OF_CONGESTION_GRPS]; ++ uint8_t mod, index; ++ uint32_t i, grpsMap[FMAN_PORT_CG_MAP_NUM]; ++ int err; ++#if (DPAA_VERSION >= 11) ++ int j; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ ++ /* un-necessary check of the indexes; probably will be needed in the future when there ++ will be more CGs available .... ++ for (i=0; inumOfCongestionGrpsToConsider; i++) ++ if (p_CongestionGrps->congestionGrpsToConsider[i] >= FM_PORT_NUM_OF_CONGESTION_GRPS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("CG id!")); ++ */ ++ ++#ifdef FM_NO_OP_OBSERVED_CGS ++ if ((p_FmPort->fmRevInfo.majorRev != 4) && ++ (p_FmPort->fmRevInfo.majorRev < 6)) ++ { ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx ports only")); ++ } ++ else ++#endif /* FM_NO_OP_OBSERVED_CGS */ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("Available for Rx & OP ports only")); ++ ++ /* Prepare groups map array */ ++ memset(grpsMap, 0, FMAN_PORT_CG_MAP_NUM * sizeof(uint32_t)); ++ for (i = 0; i < p_CongestionGrps->numOfCongestionGrpsToConsider; i++) ++ { ++ index = (uint8_t)(p_CongestionGrps->congestionGrpsToConsider[i] / 32); ++ mod = (uint8_t)(p_CongestionGrps->congestionGrpsToConsider[i] % 32); ++ if (p_FmPort->fmRevInfo.majorRev != 4) ++ grpsMap[7 - index] |= (uint32_t)(1 << mod); ++ else ++ grpsMap[0] |= (uint32_t)(1 << mod); ++ } ++ ++ memset(&priorityTmpArray, 0, ++ FM_PORT_NUM_OF_CONGESTION_GRPS * sizeof(uint8_t)); ++ ++ for (i = 0; i < p_CongestionGrps->numOfCongestionGrpsToConsider; i++) ++ { ++#if (DPAA_VERSION >= 11) ++ for (j = 0; j < FM_MAX_NUM_OF_PFC_PRIORITIES; j++) ++ if (p_CongestionGrps->pfcPrioritiesEn[i][j]) ++ priorityTmpArray[p_CongestionGrps->congestionGrpsToConsider[i]] |= ++ (0x01 << (FM_MAX_NUM_OF_PFC_PRIORITIES - j - 1)); ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++#if (DPAA_VERSION >= 11) ++ for (i = 0; i < FM_PORT_NUM_OF_CONGESTION_GRPS; i++) ++ { ++ err = FmSetCongestionGroupPFCpriority(p_FmPort->h_Fm, i, ++ priorityTmpArray[i]); ++ if (err) ++ return err; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ err = fman_port_add_congestion_grps(&p_FmPort->port, grpsMap); ++ if (err != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_add_congestion_grps")); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_RemoveCongestionGrps(t_Handle h_FmPort, ++ t_FmPortCongestionGrps *p_CongestionGrps) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint8_t mod, index; ++ uint32_t i, grpsMap[FMAN_PORT_CG_MAP_NUM]; ++ int err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ ++ { ++#ifdef FM_NO_OP_OBSERVED_CGS ++ t_FmRevisionInfo revInfo; ++ ++ FM_GetRevision(p_FmPort->h_Fm, &revInfo); ++ if (revInfo.majorRev != 4) ++ { ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx ports only")); ++ } ++ else ++#endif /* FM_NO_OP_OBSERVED_CGS */ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_RX) ++ && (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("Available for Rx & OP ports only")); ++ } ++ ++ /* Prepare groups map array */ ++ memset(grpsMap, 0, FMAN_PORT_CG_MAP_NUM * sizeof(uint32_t)); ++ for (i = 0; i < p_CongestionGrps->numOfCongestionGrpsToConsider; i++) ++ { ++ index = (uint8_t)(p_CongestionGrps->congestionGrpsToConsider[i] / 32); ++ mod = (uint8_t)(p_CongestionGrps->congestionGrpsToConsider[i] % 32); ++ if (p_FmPort->fmRevInfo.majorRev != 4) ++ grpsMap[7 - index] |= (uint32_t)(1 << mod); ++ else ++ grpsMap[0] |= (uint32_t)(1 << mod); ++ } ++ ++#if (DPAA_VERSION >= 11) ++ for (i = 0; i < p_CongestionGrps->numOfCongestionGrpsToConsider; i++) ++ { ++ t_Error err = FmSetCongestionGroupPFCpriority( ++ p_FmPort->h_Fm, p_CongestionGrps->congestionGrpsToConsider[i], ++ 0); ++ if (err) ++ return err; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ err = fman_port_remove_congestion_grps(&p_FmPort->port, grpsMap); ++ if (err != 0) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("fman_port_remove_congestion_grps")); ++ return E_OK; ++} ++ ++#if (DPAA_VERSION >= 11) ++t_Error FM_PORT_GetIPv4OptionsCount(t_Handle h_FmPort, ++ uint32_t *p_Ipv4OptionsCount) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR( ++ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING), ++ E_INVALID_VALUE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_ParamsPage, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_Ipv4OptionsCount, E_NULL_POINTER); ++ ++ *p_Ipv4OptionsCount = GET_UINT32(p_FmPort->p_ParamsPage->ipfOptionsCounter); ++ ++ return E_OK; ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++t_Error FM_PORT_ConfigDsarSupport(t_Handle h_FmPortRx, ++ t_FmPortDsarTablesSizes *params) ++{ ++ t_FmPort *p_FmPort = (t_FmPort *)h_FmPortRx; ++ p_FmPort->deepSleepVars.autoResMaxSizes = XX_Malloc( ++ sizeof(struct t_FmPortDsarTablesSizes)); ++ memcpy(p_FmPort->deepSleepVars.autoResMaxSizes, params, ++ sizeof(struct t_FmPortDsarTablesSizes)); ++ return E_OK; ++} ++ ++static t_Error FmPortConfigAutoResForDeepSleepSupport1(t_FmPort *p_FmPort) ++{ ++ uint32_t *param_page; ++ t_FmPortDsarTablesSizes *params = p_FmPort->deepSleepVars.autoResMaxSizes; ++ t_ArCommonDesc *ArCommonDescPtr; ++ uint32_t size = sizeof(t_ArCommonDesc); ++ // ARP ++ // should put here if (params->max_num_of_arp_entries)? ++ size = ROUND_UP(size,4); ++ size += sizeof(t_DsarArpDescriptor); ++ size += sizeof(t_DsarArpBindingEntry) * params->maxNumOfArpEntries; ++ size += sizeof(t_DsarArpStatistics); ++ //ICMPV4 ++ size = ROUND_UP(size,4); ++ size += sizeof(t_DsarIcmpV4Descriptor); ++ size += sizeof(t_DsarIcmpV4BindingEntry) * params->maxNumOfEchoIpv4Entries; ++ size += sizeof(t_DsarIcmpV4Statistics); ++ //ICMPV6 ++ size = ROUND_UP(size,4); ++ size += sizeof(t_DsarIcmpV6Descriptor); ++ size += sizeof(t_DsarIcmpV6BindingEntry) * params->maxNumOfEchoIpv6Entries; ++ size += sizeof(t_DsarIcmpV6Statistics); ++ //ND ++ size = ROUND_UP(size,4); ++ size += sizeof(t_DsarNdDescriptor); ++ size += sizeof(t_DsarIcmpV6BindingEntry) * params->maxNumOfNdpEntries; ++ size += sizeof(t_DsarIcmpV6Statistics); ++ //SNMP ++ size = ROUND_UP(size,4); ++ size += sizeof(t_DsarSnmpDescriptor); ++ size += sizeof(t_DsarSnmpIpv4AddrTblEntry) ++ * params->maxNumOfSnmpIPV4Entries; ++ size += sizeof(t_DsarSnmpIpv6AddrTblEntry) ++ * params->maxNumOfSnmpIPV6Entries; ++ size += sizeof(t_OidsTblEntry) * params->maxNumOfSnmpOidEntries; ++ size += params->maxNumOfSnmpOidChar; ++ size += sizeof(t_DsarIcmpV6Statistics); ++ //filters ++ size = ROUND_UP(size,4); ++ size += params->maxNumOfIpProtFiltering; ++ size = ROUND_UP(size,4); ++ size += params->maxNumOfUdpPortFiltering * sizeof(t_PortTblEntry); ++ size = ROUND_UP(size,4); ++ size += params->maxNumOfTcpPortFiltering * sizeof(t_PortTblEntry); ++ ++ // add here for more protocols ++ ++ // statistics ++ size = ROUND_UP(size,4); ++ size += sizeof(t_ArStatistics); ++ ++ ArCommonDescPtr = FM_MURAM_AllocMem(p_FmPort->h_FmMuram, size, 0x10); ++ ++ param_page = ++ XX_PhysToVirt( ++ p_FmPort->fmMuramPhysBaseAddr ++ + GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr)); ++ WRITE_UINT32( ++ *param_page, ++ (uint32_t)(XX_VirtToPhys(ArCommonDescPtr) - p_FmPort->fmMuramPhysBaseAddr)); ++ return E_OK; ++} ++ ++t_FmPortDsarTablesSizes* FM_PORT_GetDsarTablesMaxSizes(t_Handle h_FmPortRx) ++{ ++ t_FmPort *p_FmPort = (t_FmPort *)h_FmPortRx; ++ return p_FmPort->deepSleepVars.autoResMaxSizes; ++} ++ ++struct arOffsets ++{ ++ uint32_t arp; ++ uint32_t nd; ++ uint32_t icmpv4; ++ uint32_t icmpv6; ++ uint32_t snmp; ++ uint32_t stats; ++ uint32_t filtIp; ++ uint32_t filtUdp; ++ uint32_t filtTcp; ++}; ++ ++static uint32_t AR_ComputeOffsets(struct arOffsets* of, ++ struct t_FmPortDsarParams *params, ++ t_FmPort *p_FmPort) ++{ ++ uint32_t size = sizeof(t_ArCommonDesc); ++ // ARP ++ if (params->p_AutoResArpInfo) ++ { ++ size = ROUND_UP(size,4); ++ of->arp = size; ++ size += sizeof(t_DsarArpDescriptor); ++ size += sizeof(t_DsarArpBindingEntry) ++ * params->p_AutoResArpInfo->tableSize; ++ size += sizeof(t_DsarArpStatistics); ++ } ++ // ICMPV4 ++ if (params->p_AutoResEchoIpv4Info) ++ { ++ size = ROUND_UP(size,4); ++ of->icmpv4 = size; ++ size += sizeof(t_DsarIcmpV4Descriptor); ++ size += sizeof(t_DsarIcmpV4BindingEntry) ++ * params->p_AutoResEchoIpv4Info->tableSize; ++ size += sizeof(t_DsarIcmpV4Statistics); ++ } ++ // ICMPV6 ++ if (params->p_AutoResEchoIpv6Info) ++ { ++ size = ROUND_UP(size,4); ++ of->icmpv6 = size; ++ size += sizeof(t_DsarIcmpV6Descriptor); ++ size += sizeof(t_DsarIcmpV6BindingEntry) ++ * params->p_AutoResEchoIpv6Info->tableSize; ++ size += sizeof(t_DsarIcmpV6Statistics); ++ } ++ // ND ++ if (params->p_AutoResNdpInfo) ++ { ++ size = ROUND_UP(size,4); ++ of->nd = size; ++ size += sizeof(t_DsarNdDescriptor); ++ size += sizeof(t_DsarIcmpV6BindingEntry) ++ * (params->p_AutoResNdpInfo->tableSizeAssigned ++ + params->p_AutoResNdpInfo->tableSizeTmp); ++ size += sizeof(t_DsarIcmpV6Statistics); ++ } ++ // SNMP ++ if (params->p_AutoResSnmpInfo) ++ { ++ size = ROUND_UP(size,4); ++ of->snmp = size; ++ size += sizeof(t_DsarSnmpDescriptor); ++ size += sizeof(t_DsarSnmpIpv4AddrTblEntry) ++ * params->p_AutoResSnmpInfo->numOfIpv4Addresses; ++ size += sizeof(t_DsarSnmpIpv6AddrTblEntry) ++ * params->p_AutoResSnmpInfo->numOfIpv6Addresses; ++ size += sizeof(t_OidsTblEntry) * params->p_AutoResSnmpInfo->oidsTblSize; ++ size += p_FmPort->deepSleepVars.autoResMaxSizes->maxNumOfSnmpOidChar; ++ size += sizeof(t_DsarIcmpV6Statistics); ++ } ++ //filters ++ size = ROUND_UP(size,4); ++ if (params->p_AutoResFilteringInfo) ++ { ++ of->filtIp = size; ++ size += params->p_AutoResFilteringInfo->ipProtTableSize; ++ size = ROUND_UP(size,4); ++ of->filtUdp = size; ++ size += params->p_AutoResFilteringInfo->udpPortsTableSize ++ * sizeof(t_PortTblEntry); ++ size = ROUND_UP(size,4); ++ of->filtTcp = size; ++ size += params->p_AutoResFilteringInfo->tcpPortsTableSize ++ * sizeof(t_PortTblEntry); ++ } ++ // add here for more protocols ++ // statistics ++ size = ROUND_UP(size,4); ++ of->stats = size; ++ size += sizeof(t_ArStatistics); ++ return size; ++} ++ ++uint32_t* ARDesc; ++void PrsEnable(t_Handle p_FmPcd); ++void PrsDisable(t_Handle p_FmPcd); ++int PrsIsEnabled(t_Handle p_FmPcd); ++t_Handle FM_PCD_GetHcPort(t_Handle h_FmPcd); ++ ++static t_Error DsarCheckParams(t_FmPortDsarParams *params, ++ t_FmPortDsarTablesSizes *sizes) ++{ ++ bool macInit = FALSE; ++ uint8_t mac[6]; ++ int i = 0; ++ ++ // check table sizes ++ if (params->p_AutoResArpInfo ++ && sizes->maxNumOfArpEntries < params->p_AutoResArpInfo->tableSize) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("DSAR: Arp table size exceeds the configured maximum size.")); ++ if (params->p_AutoResEchoIpv4Info ++ && sizes->maxNumOfEchoIpv4Entries ++ < params->p_AutoResEchoIpv4Info->tableSize) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("DSAR: EchoIpv4 table size exceeds the configured maximum size.")); ++ if (params->p_AutoResNdpInfo ++ && sizes->maxNumOfNdpEntries ++ < params->p_AutoResNdpInfo->tableSizeAssigned ++ + params->p_AutoResNdpInfo->tableSizeTmp) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("DSAR: NDP table size exceeds the configured maximum size.")); ++ if (params->p_AutoResEchoIpv6Info ++ && sizes->maxNumOfEchoIpv6Entries ++ < params->p_AutoResEchoIpv6Info->tableSize) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("DSAR: EchoIpv6 table size exceeds the configured maximum size.")); ++ if (params->p_AutoResSnmpInfo ++ && sizes->maxNumOfSnmpOidEntries ++ < params->p_AutoResSnmpInfo->oidsTblSize) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("DSAR: Snmp Oid table size exceeds the configured maximum size.")); ++ if (params->p_AutoResSnmpInfo ++ && sizes->maxNumOfSnmpIPV4Entries ++ < params->p_AutoResSnmpInfo->numOfIpv4Addresses) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("DSAR: Snmp ipv4 table size exceeds the configured maximum size.")); ++ if (params->p_AutoResSnmpInfo ++ && sizes->maxNumOfSnmpIPV6Entries ++ < params->p_AutoResSnmpInfo->numOfIpv6Addresses) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("DSAR: Snmp ipv6 table size exceeds the configured maximum size.")); ++ if (params->p_AutoResFilteringInfo) ++ { ++ if (sizes->maxNumOfIpProtFiltering ++ < params->p_AutoResFilteringInfo->ipProtTableSize) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("DSAR: ip filter table size exceeds the configured maximum size.")); ++ if (sizes->maxNumOfTcpPortFiltering ++ < params->p_AutoResFilteringInfo->udpPortsTableSize) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("DSAR: udp filter table size exceeds the configured maximum size.")); ++ if (sizes->maxNumOfUdpPortFiltering ++ < params->p_AutoResFilteringInfo->tcpPortsTableSize) ++ RETURN_ERROR( ++ MAJOR, ++ E_INVALID_VALUE, ++ ("DSAR: tcp filter table size exceeds the configured maximum size.")); ++ } ++ /* check only 1 MAC address is configured (this is what ucode currently supports) */ ++ if (params->p_AutoResArpInfo && params->p_AutoResArpInfo->tableSize) ++ { ++ memcpy(mac, params->p_AutoResArpInfo->p_AutoResTable[0].mac, 6); ++ i = 1; ++ macInit = TRUE; ++ ++ for (; i < params->p_AutoResArpInfo->tableSize; i++) ++ if (memcmp(mac, params->p_AutoResArpInfo->p_AutoResTable[i].mac, 6)) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("DSAR: Only 1 mac address is currently supported.")); ++ } ++ if (params->p_AutoResEchoIpv4Info ++ && params->p_AutoResEchoIpv4Info->tableSize) ++ { ++ i = 0; ++ if (!macInit) ++ { ++ memcpy(mac, params->p_AutoResEchoIpv4Info->p_AutoResTable[0].mac, ++ 6); ++ i = 1; ++ macInit = TRUE; ++ } ++ for (; i < params->p_AutoResEchoIpv4Info->tableSize; i++) ++ if (memcmp(mac, ++ params->p_AutoResEchoIpv4Info->p_AutoResTable[i].mac, 6)) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("DSAR: Only 1 mac address is currently supported.")); ++ } ++ if (params->p_AutoResEchoIpv6Info ++ && params->p_AutoResEchoIpv6Info->tableSize) ++ { ++ i = 0; ++ if (!macInit) ++ { ++ memcpy(mac, params->p_AutoResEchoIpv6Info->p_AutoResTable[0].mac, ++ 6); ++ i = 1; ++ macInit = TRUE; ++ } ++ for (; i < params->p_AutoResEchoIpv6Info->tableSize; i++) ++ if (memcmp(mac, ++ params->p_AutoResEchoIpv6Info->p_AutoResTable[i].mac, 6)) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("DSAR: Only 1 mac address is currently supported.")); ++ } ++ if (params->p_AutoResNdpInfo && params->p_AutoResNdpInfo->tableSizeAssigned) ++ { ++ i = 0; ++ if (!macInit) ++ { ++ memcpy(mac, params->p_AutoResNdpInfo->p_AutoResTableAssigned[0].mac, ++ 6); ++ i = 1; ++ macInit = TRUE; ++ } ++ for (; i < params->p_AutoResNdpInfo->tableSizeAssigned; i++) ++ if (memcmp(mac, ++ params->p_AutoResNdpInfo->p_AutoResTableAssigned[i].mac, ++ 6)) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("DSAR: Only 1 mac address is currently supported.")); ++ } ++ if (params->p_AutoResNdpInfo && params->p_AutoResNdpInfo->tableSizeTmp) ++ { ++ i = 0; ++ if (!macInit) ++ { ++ memcpy(mac, params->p_AutoResNdpInfo->p_AutoResTableTmp[0].mac, 6); ++ i = 1; ++ } ++ for (; i < params->p_AutoResNdpInfo->tableSizeTmp; i++) ++ if (memcmp(mac, params->p_AutoResNdpInfo->p_AutoResTableTmp[i].mac, ++ 6)) ++ RETURN_ERROR( ++ MAJOR, E_INVALID_VALUE, ++ ("DSAR: Only 1 mac address is currently supported.")); ++ } ++ return E_OK; ++} ++ ++static int GetBERLen(uint8_t* buf) ++{ ++ if (*buf & 0x80) ++ { ++ if ((*buf & 0x7F) == 1) ++ return buf[1]; ++ else ++ return *(uint16_t*)&buf[1]; // assuming max len is 2 ++ } ++ else ++ return buf[0]; ++} ++#define TOTAL_BER_LEN(len) (len < 128) ? len + 2 : len + 3 ++ ++#define SCFG_FMCLKDPSLPCR_ADDR 0xFFE0FC00C ++#define SCFG_FMCLKDPSLPCR_DS_VAL 0x08402000 ++#define SCFG_FMCLKDPSLPCR_NORMAL_VAL 0x00402000 ++static int fm_soc_suspend(void) ++{ ++ uint32_t *fmclk, tmp32; ++ fmclk = ioremap(SCFG_FMCLKDPSLPCR_ADDR, 4); ++ tmp32 = GET_UINT32(*fmclk); ++ WRITE_UINT32(*fmclk, SCFG_FMCLKDPSLPCR_DS_VAL); ++ tmp32 = GET_UINT32(*fmclk); ++ iounmap(fmclk); ++ return 0; ++} ++ ++void fm_clk_down(void) ++{ ++ uint32_t *fmclk, tmp32; ++ fmclk = ioremap(SCFG_FMCLKDPSLPCR_ADDR, 4); ++ tmp32 = GET_UINT32(*fmclk); ++ WRITE_UINT32(*fmclk, SCFG_FMCLKDPSLPCR_DS_VAL | 0x40000000); ++ tmp32 = GET_UINT32(*fmclk); ++ iounmap(fmclk); ++} ++ ++t_Error FM_PORT_EnterDsar(t_Handle h_FmPortRx, t_FmPortDsarParams *params) ++{ ++ int i, j; ++ t_Error err; ++ uint32_t nia; ++ t_FmPort *p_FmPort = (t_FmPort *)h_FmPortRx; ++ t_FmPort *p_FmPortTx = (t_FmPort *)params->h_FmPortTx; ++ t_DsarArpDescriptor *ArpDescriptor; ++ t_DsarIcmpV4Descriptor* ICMPV4Descriptor; ++ t_DsarIcmpV6Descriptor* ICMPV6Descriptor; ++ t_DsarNdDescriptor* NDDescriptor; ++ ++ uint64_t fmMuramVirtBaseAddr = (uint64_t)PTR_TO_UINT(XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr)); ++ uint32_t *param_page = XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr)); ++ t_ArCommonDesc *ArCommonDescPtr = (t_ArCommonDesc*)(XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(*param_page))); ++ struct arOffsets* of; ++ uint8_t tmp = 0; ++ t_FmGetSetParams fmGetSetParams; ++ memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); ++ fmGetSetParams.setParams.type = UPDATE_FPM_BRKC_SLP; ++ fmGetSetParams.setParams.sleep = 1; ++ ++ err = DsarCheckParams(params, p_FmPort->deepSleepVars.autoResMaxSizes); ++ if (err != E_OK) ++ return err; ++ ++ p_FmPort->deepSleepVars.autoResOffsets = XX_Malloc(sizeof(struct arOffsets)); ++ of = (struct arOffsets *)p_FmPort->deepSleepVars.autoResOffsets; ++ IOMemSet32(ArCommonDescPtr, 0, AR_ComputeOffsets(of, params, p_FmPort)); ++ ++ // common ++ WRITE_UINT8(ArCommonDescPtr->arTxPort, p_FmPortTx->hardwarePortId); ++ nia = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne); // bmi nia ++ if ((nia & 0x007C0000) == 0x00440000) // bmi nia is parser ++ WRITE_UINT32(ArCommonDescPtr->activeHPNIA, GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne)); ++ else ++ WRITE_UINT32(ArCommonDescPtr->activeHPNIA, nia); ++ WRITE_UINT16(ArCommonDescPtr->snmpPort, 161); ++ ++ // ARP ++ if (params->p_AutoResArpInfo) ++ { ++ t_DsarArpBindingEntry* arp_bindings; ++ ArpDescriptor = (t_DsarArpDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->arp); ++ WRITE_UINT32(ArCommonDescPtr->p_ArpDescriptor, PTR_TO_UINT(ArpDescriptor) - fmMuramVirtBaseAddr); ++ arp_bindings = (t_DsarArpBindingEntry*)(PTR_TO_UINT(ArpDescriptor) + sizeof(t_DsarArpDescriptor)); ++ if (params->p_AutoResArpInfo->enableConflictDetection) ++ WRITE_UINT16(ArpDescriptor->control, 1); ++ else ++ WRITE_UINT16(ArpDescriptor->control, 0); ++ if (params->p_AutoResArpInfo->tableSize) ++ { ++ t_FmPortDsarArpEntry* arp_entry = params->p_AutoResArpInfo->p_AutoResTable; ++ WRITE_UINT16(*(uint16_t*)&ArCommonDescPtr->macStationAddr[0], *(uint16_t*)&arp_entry[0].mac[0]); ++ WRITE_UINT32(*(uint32_t*)&ArCommonDescPtr->macStationAddr[2], *(uint32_t*)&arp_entry[0].mac[2]); ++ WRITE_UINT16(ArpDescriptor->numOfBindings, params->p_AutoResArpInfo->tableSize); ++ ++ for (i = 0; i < params->p_AutoResArpInfo->tableSize; i++) ++ { ++ WRITE_UINT32(arp_bindings[i].ipv4Addr, arp_entry[i].ipAddress); ++ if (arp_entry[i].isVlan) ++ WRITE_UINT16(arp_bindings[i].vlanId, arp_entry[i].vid & 0xFFF); ++ } ++ WRITE_UINT32(ArpDescriptor->p_Bindings, PTR_TO_UINT(arp_bindings) - fmMuramVirtBaseAddr); ++ } ++ WRITE_UINT32(ArpDescriptor->p_Statistics, PTR_TO_UINT(arp_bindings) + ++ sizeof(t_DsarArpBindingEntry) * params->p_AutoResArpInfo->tableSize - fmMuramVirtBaseAddr); ++ } ++ ++ // ICMPV4 ++ if (params->p_AutoResEchoIpv4Info) ++ { ++ t_DsarIcmpV4BindingEntry* icmpv4_bindings; ++ ICMPV4Descriptor = (t_DsarIcmpV4Descriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->icmpv4); ++ WRITE_UINT32(ArCommonDescPtr->p_IcmpV4Descriptor, PTR_TO_UINT(ICMPV4Descriptor) - fmMuramVirtBaseAddr); ++ icmpv4_bindings = (t_DsarIcmpV4BindingEntry*)(PTR_TO_UINT(ICMPV4Descriptor) + sizeof(t_DsarIcmpV4Descriptor)); ++ WRITE_UINT16(ICMPV4Descriptor->control, 0); ++ if (params->p_AutoResEchoIpv4Info->tableSize) ++ { ++ t_FmPortDsarArpEntry* arp_entry = params->p_AutoResEchoIpv4Info->p_AutoResTable; ++ WRITE_UINT16(*(uint16_t*)&ArCommonDescPtr->macStationAddr[0], *(uint16_t*)&arp_entry[0].mac[0]); ++ WRITE_UINT32(*(uint32_t*)&ArCommonDescPtr->macStationAddr[2], *(uint32_t*)&arp_entry[0].mac[2]); ++ WRITE_UINT16(ICMPV4Descriptor->numOfBindings, params->p_AutoResEchoIpv4Info->tableSize); ++ ++ for (i = 0; i < params->p_AutoResEchoIpv4Info->tableSize; i++) ++ { ++ WRITE_UINT32(icmpv4_bindings[i].ipv4Addr, arp_entry[i].ipAddress); ++ if (arp_entry[i].isVlan) ++ WRITE_UINT16(icmpv4_bindings[i].vlanId, arp_entry[i].vid & 0xFFF); ++ } ++ WRITE_UINT32(ICMPV4Descriptor->p_Bindings, PTR_TO_UINT(icmpv4_bindings) - fmMuramVirtBaseAddr); ++ } ++ WRITE_UINT32(ICMPV4Descriptor->p_Statistics, PTR_TO_UINT(icmpv4_bindings) + ++ sizeof(t_DsarIcmpV4BindingEntry) * params->p_AutoResEchoIpv4Info->tableSize - fmMuramVirtBaseAddr); ++ } ++ ++ // ICMPV6 ++ if (params->p_AutoResEchoIpv6Info) ++ { ++ t_DsarIcmpV6BindingEntry* icmpv6_bindings; ++ ICMPV6Descriptor = (t_DsarIcmpV6Descriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->icmpv6); ++ WRITE_UINT32(ArCommonDescPtr->p_IcmpV6Descriptor, PTR_TO_UINT(ICMPV6Descriptor) - fmMuramVirtBaseAddr); ++ icmpv6_bindings = (t_DsarIcmpV6BindingEntry*)(PTR_TO_UINT(ICMPV6Descriptor) + sizeof(t_DsarIcmpV6Descriptor)); ++ WRITE_UINT16(ICMPV6Descriptor->control, 0); ++ if (params->p_AutoResEchoIpv6Info->tableSize) ++ { ++ t_FmPortDsarNdpEntry* ndp_entry = params->p_AutoResEchoIpv6Info->p_AutoResTable; ++ WRITE_UINT16(*(uint16_t*)&ArCommonDescPtr->macStationAddr[0], *(uint16_t*)&ndp_entry[0].mac[0]); ++ WRITE_UINT32(*(uint32_t*)&ArCommonDescPtr->macStationAddr[2], *(uint32_t*)&ndp_entry[0].mac[2]); ++ WRITE_UINT16(ICMPV6Descriptor->numOfBindings, params->p_AutoResEchoIpv6Info->tableSize); ++ ++ for (i = 0; i < params->p_AutoResEchoIpv6Info->tableSize; i++) ++ { ++ for (j = 0; j < 4; j++) ++ WRITE_UINT32(icmpv6_bindings[i].ipv6Addr[j], ndp_entry[i].ipAddress[j]); ++ if (ndp_entry[i].isVlan) ++ WRITE_UINT16(*(uint16_t*)&icmpv6_bindings[i].ipv6Addr[4], ndp_entry[i].vid & 0xFFF); // writing vlan ++ } ++ WRITE_UINT32(ICMPV6Descriptor->p_Bindings, PTR_TO_UINT(icmpv6_bindings) - fmMuramVirtBaseAddr); ++ } ++ WRITE_UINT32(ICMPV6Descriptor->p_Statistics, PTR_TO_UINT(icmpv6_bindings) + ++ sizeof(t_DsarIcmpV6BindingEntry) * params->p_AutoResEchoIpv6Info->tableSize - fmMuramVirtBaseAddr); ++ } ++ ++ // ND ++ if (params->p_AutoResNdpInfo) ++ { ++ t_DsarIcmpV6BindingEntry* icmpv6_bindings; ++ NDDescriptor = (t_DsarNdDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->nd); ++ WRITE_UINT32(ArCommonDescPtr->p_NdDescriptor, PTR_TO_UINT(NDDescriptor) - fmMuramVirtBaseAddr); ++ icmpv6_bindings = (t_DsarIcmpV6BindingEntry*)(PTR_TO_UINT(NDDescriptor) + sizeof(t_DsarNdDescriptor)); ++ if (params->p_AutoResNdpInfo->enableConflictDetection) ++ WRITE_UINT16(NDDescriptor->control, 1); ++ else ++ WRITE_UINT16(NDDescriptor->control, 0); ++ if (params->p_AutoResNdpInfo->tableSizeAssigned + params->p_AutoResNdpInfo->tableSizeTmp) ++ { ++ t_FmPortDsarNdpEntry* ndp_entry = params->p_AutoResNdpInfo->p_AutoResTableAssigned; ++ WRITE_UINT16(*(uint16_t*)&ArCommonDescPtr->macStationAddr[0], *(uint16_t*)&ndp_entry[0].mac[0]); ++ WRITE_UINT32(*(uint32_t*)&ArCommonDescPtr->macStationAddr[2], *(uint32_t*)&ndp_entry[0].mac[2]); ++ WRITE_UINT16(NDDescriptor->numOfBindings, params->p_AutoResNdpInfo->tableSizeAssigned ++ + params->p_AutoResNdpInfo->tableSizeTmp); ++ ++ for (i = 0; i < params->p_AutoResNdpInfo->tableSizeAssigned; i++) ++ { ++ for (j = 0; j < 4; j++) ++ WRITE_UINT32(icmpv6_bindings[i].ipv6Addr[j], ndp_entry[i].ipAddress[j]); ++ if (ndp_entry[i].isVlan) ++ WRITE_UINT16(*(uint16_t*)&icmpv6_bindings[i].ipv6Addr[4], ndp_entry[i].vid & 0xFFF); // writing vlan ++ } ++ ndp_entry = params->p_AutoResNdpInfo->p_AutoResTableTmp; ++ for (i = 0; i < params->p_AutoResNdpInfo->tableSizeTmp; i++) ++ { ++ for (j = 0; j < 4; j++) ++ WRITE_UINT32(icmpv6_bindings[i + params->p_AutoResNdpInfo->tableSizeAssigned].ipv6Addr[j], ndp_entry[i].ipAddress[j]); ++ if (ndp_entry[i].isVlan) ++ WRITE_UINT16(*(uint16_t*)&icmpv6_bindings[i + params->p_AutoResNdpInfo->tableSizeAssigned].ipv6Addr[4], ndp_entry[i].vid & 0xFFF); // writing vlan ++ } ++ WRITE_UINT32(NDDescriptor->p_Bindings, PTR_TO_UINT(icmpv6_bindings) - fmMuramVirtBaseAddr); ++ } ++ WRITE_UINT32(NDDescriptor->p_Statistics, PTR_TO_UINT(icmpv6_bindings) + sizeof(t_DsarIcmpV6BindingEntry) ++ * (params->p_AutoResNdpInfo->tableSizeAssigned + params->p_AutoResNdpInfo->tableSizeTmp) ++ - fmMuramVirtBaseAddr); ++ WRITE_UINT32(NDDescriptor->solicitedAddr, 0xFFFFFFFF); ++ } ++ ++ // SNMP ++ if (params->p_AutoResSnmpInfo) ++ { ++ t_FmPortDsarSnmpInfo *snmpSrc = params->p_AutoResSnmpInfo; ++ t_DsarSnmpIpv4AddrTblEntry* snmpIpv4Addr; ++ t_DsarSnmpIpv6AddrTblEntry* snmpIpv6Addr; ++ t_OidsTblEntry* snmpOid; ++ uint8_t *charPointer; ++ int len; ++ t_DsarSnmpDescriptor* SnmpDescriptor = (t_DsarSnmpDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->snmp); ++ WRITE_UINT32(ArCommonDescPtr->p_SnmpDescriptor, PTR_TO_UINT(SnmpDescriptor) - fmMuramVirtBaseAddr); ++ WRITE_UINT16(SnmpDescriptor->control, snmpSrc->control); ++ WRITE_UINT16(SnmpDescriptor->maxSnmpMsgLength, snmpSrc->maxSnmpMsgLength); ++ snmpIpv4Addr = (t_DsarSnmpIpv4AddrTblEntry*)(PTR_TO_UINT(SnmpDescriptor) + sizeof(t_DsarSnmpDescriptor)); ++ if (snmpSrc->numOfIpv4Addresses) ++ { ++ t_FmPortDsarSnmpIpv4AddrTblEntry* snmpIpv4AddrSrc = snmpSrc->p_Ipv4AddrTbl; ++ WRITE_UINT16(SnmpDescriptor->numOfIpv4Addresses, snmpSrc->numOfIpv4Addresses); ++ for (i = 0; i < snmpSrc->numOfIpv4Addresses; i++) ++ { ++ WRITE_UINT32(snmpIpv4Addr[i].ipv4Addr, snmpIpv4AddrSrc[i].ipv4Addr); ++ if (snmpIpv4AddrSrc[i].isVlan) ++ WRITE_UINT16(snmpIpv4Addr[i].vlanId, snmpIpv4AddrSrc[i].vid & 0xFFF); ++ } ++ WRITE_UINT32(SnmpDescriptor->p_Ipv4AddrTbl, PTR_TO_UINT(snmpIpv4Addr) - fmMuramVirtBaseAddr); ++ } ++ snmpIpv6Addr = (t_DsarSnmpIpv6AddrTblEntry*)(PTR_TO_UINT(snmpIpv4Addr) ++ + sizeof(t_DsarSnmpIpv4AddrTblEntry) * snmpSrc->numOfIpv4Addresses); ++ if (snmpSrc->numOfIpv6Addresses) ++ { ++ t_FmPortDsarSnmpIpv6AddrTblEntry* snmpIpv6AddrSrc = snmpSrc->p_Ipv6AddrTbl; ++ WRITE_UINT16(SnmpDescriptor->numOfIpv6Addresses, snmpSrc->numOfIpv6Addresses); ++ for (i = 0; i < snmpSrc->numOfIpv6Addresses; i++) ++ { ++ for (j = 0; j < 4; j++) ++ WRITE_UINT32(snmpIpv6Addr[i].ipv6Addr[j], snmpIpv6AddrSrc[i].ipv6Addr[j]); ++ if (snmpIpv6AddrSrc[i].isVlan) ++ WRITE_UINT16(snmpIpv6Addr[i].vlanId, snmpIpv6AddrSrc[i].vid & 0xFFF); ++ } ++ WRITE_UINT32(SnmpDescriptor->p_Ipv6AddrTbl, PTR_TO_UINT(snmpIpv6Addr) - fmMuramVirtBaseAddr); ++ } ++ snmpOid = (t_OidsTblEntry*)(PTR_TO_UINT(snmpIpv6Addr) ++ + sizeof(t_DsarSnmpIpv6AddrTblEntry) * snmpSrc->numOfIpv6Addresses); ++ charPointer = (uint8_t*)(PTR_TO_UINT(snmpOid) ++ + sizeof(t_OidsTblEntry) * snmpSrc->oidsTblSize); ++ len = TOTAL_BER_LEN(GetBERLen(&snmpSrc->p_RdOnlyCommunityStr[1])); ++ Mem2IOCpy32(charPointer, snmpSrc->p_RdOnlyCommunityStr, len); ++ WRITE_UINT32(SnmpDescriptor->p_RdOnlyCommunityStr, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr); ++ charPointer += len; ++ len = TOTAL_BER_LEN(GetBERLen(&snmpSrc->p_RdWrCommunityStr[1])); ++ Mem2IOCpy32(charPointer, snmpSrc->p_RdWrCommunityStr, len); ++ WRITE_UINT32(SnmpDescriptor->p_RdWrCommunityStr, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr); ++ charPointer += len; ++ WRITE_UINT32(SnmpDescriptor->oidsTblSize, snmpSrc->oidsTblSize); ++ WRITE_UINT32(SnmpDescriptor->p_OidsTbl, PTR_TO_UINT(snmpOid) - fmMuramVirtBaseAddr); ++ for (i = 0; i < snmpSrc->oidsTblSize; i++) ++ { ++ WRITE_UINT16(snmpOid->oidSize, snmpSrc->p_OidsTbl[i].oidSize); ++ WRITE_UINT16(snmpOid->resSize, snmpSrc->p_OidsTbl[i].resSize); ++ Mem2IOCpy32(charPointer, snmpSrc->p_OidsTbl[i].oidVal, snmpSrc->p_OidsTbl[i].oidSize); ++ WRITE_UINT32(snmpOid->p_Oid, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr); ++ charPointer += snmpSrc->p_OidsTbl[i].oidSize; ++ if (snmpSrc->p_OidsTbl[i].resSize <= 4) ++ WRITE_UINT32(snmpOid->resValOrPtr, *snmpSrc->p_OidsTbl[i].resVal); ++ else ++ { ++ Mem2IOCpy32(charPointer, snmpSrc->p_OidsTbl[i].resVal, snmpSrc->p_OidsTbl[i].resSize); ++ WRITE_UINT32(snmpOid->resValOrPtr, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr); ++ charPointer += snmpSrc->p_OidsTbl[i].resSize; ++ } ++ snmpOid++; ++ } ++ charPointer = UINT_TO_PTR(ROUND_UP(PTR_TO_UINT(charPointer),4)); ++ WRITE_UINT32(SnmpDescriptor->p_Statistics, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr); ++ } ++ ++ // filtering ++ if (params->p_AutoResFilteringInfo) ++ { ++ if (params->p_AutoResFilteringInfo->ipProtPassOnHit) ++ tmp |= IP_PROT_TBL_PASS_MASK; ++ if (params->p_AutoResFilteringInfo->udpPortPassOnHit) ++ tmp |= UDP_PORT_TBL_PASS_MASK; ++ if (params->p_AutoResFilteringInfo->tcpPortPassOnHit) ++ tmp |= TCP_PORT_TBL_PASS_MASK; ++ WRITE_UINT8(ArCommonDescPtr->filterControl, tmp); ++ WRITE_UINT16(ArCommonDescPtr->tcpControlPass, params->p_AutoResFilteringInfo->tcpFlagsMask); ++ ++ // ip filtering ++ if (params->p_AutoResFilteringInfo->ipProtTableSize) ++ { ++ uint8_t* ip_tbl = (uint8_t*)(PTR_TO_UINT(ArCommonDescPtr) + of->filtIp); ++ WRITE_UINT8(ArCommonDescPtr->ipProtocolTblSize, params->p_AutoResFilteringInfo->ipProtTableSize); ++ for (i = 0; i < params->p_AutoResFilteringInfo->ipProtTableSize; i++) ++ WRITE_UINT8(ip_tbl[i], params->p_AutoResFilteringInfo->p_IpProtTablePtr[i]); ++ WRITE_UINT32(ArCommonDescPtr->p_IpProtocolFiltTbl, PTR_TO_UINT(ip_tbl) - fmMuramVirtBaseAddr); ++ } ++ ++ // udp filtering ++ if (params->p_AutoResFilteringInfo->udpPortsTableSize) ++ { ++ t_PortTblEntry* udp_tbl = (t_PortTblEntry*)(PTR_TO_UINT(ArCommonDescPtr) + of->filtUdp); ++ WRITE_UINT8(ArCommonDescPtr->udpPortTblSize, params->p_AutoResFilteringInfo->udpPortsTableSize); ++ for (i = 0; i < params->p_AutoResFilteringInfo->udpPortsTableSize; i++) ++ { ++ WRITE_UINT32(udp_tbl[i].Ports, ++ (params->p_AutoResFilteringInfo->p_UdpPortsTablePtr[i].srcPort << 16) + ++ params->p_AutoResFilteringInfo->p_UdpPortsTablePtr[i].dstPort); ++ WRITE_UINT32(udp_tbl[i].PortsMask, ++ (params->p_AutoResFilteringInfo->p_UdpPortsTablePtr[i].srcPortMask << 16) + ++ params->p_AutoResFilteringInfo->p_UdpPortsTablePtr[i].dstPortMask); ++ } ++ WRITE_UINT32(ArCommonDescPtr->p_UdpPortFiltTbl, PTR_TO_UINT(udp_tbl) - fmMuramVirtBaseAddr); ++ } ++ ++ // tcp filtering ++ if (params->p_AutoResFilteringInfo->tcpPortsTableSize) ++ { ++ t_PortTblEntry* tcp_tbl = (t_PortTblEntry*)(PTR_TO_UINT(ArCommonDescPtr) + of->filtTcp); ++ WRITE_UINT8(ArCommonDescPtr->tcpPortTblSize, params->p_AutoResFilteringInfo->tcpPortsTableSize); ++ for (i = 0; i < params->p_AutoResFilteringInfo->tcpPortsTableSize; i++) ++ { ++ WRITE_UINT32(tcp_tbl[i].Ports, ++ (params->p_AutoResFilteringInfo->p_TcpPortsTablePtr[i].srcPort << 16) + ++ params->p_AutoResFilteringInfo->p_TcpPortsTablePtr[i].dstPort); ++ WRITE_UINT32(tcp_tbl[i].PortsMask, ++ (params->p_AutoResFilteringInfo->p_TcpPortsTablePtr[i].srcPortMask << 16) + ++ params->p_AutoResFilteringInfo->p_TcpPortsTablePtr[i].dstPortMask); ++ } ++ WRITE_UINT32(ArCommonDescPtr->p_TcpPortFiltTbl, PTR_TO_UINT(tcp_tbl) - fmMuramVirtBaseAddr); ++ } ++ } ++ // common stats ++ WRITE_UINT32(ArCommonDescPtr->p_ArStats, PTR_TO_UINT(ArCommonDescPtr) + of->stats - fmMuramVirtBaseAddr); ++ ++ // get into Deep Sleep sequence: ++ ++ // Ensures that FMan do not enter the idle state. This is done by programing ++ // FMDPSLPCR[FM_STOP] to one. ++ fm_soc_suspend(); ++ ++ ARDesc = UINT_TO_PTR(XX_VirtToPhys(ArCommonDescPtr)); ++ return E_OK; ++ ++} ++ ++void FM_ChangeClock(t_Handle h_Fm, int hardwarePortId); ++t_Error FM_PORT_EnterDsarFinal(t_Handle h_DsarRxPort, t_Handle h_DsarTxPort) ++{ ++ t_FmGetSetParams fmGetSetParams; ++ t_FmPort *p_FmPort = (t_FmPort *)h_DsarRxPort; ++ t_FmPort *p_FmPortTx = (t_FmPort *)h_DsarTxPort; ++ t_Handle *h_FmPcd = FmGetPcd(p_FmPort->h_Fm); ++ t_FmPort *p_FmPortHc = FM_PCD_GetHcPort(h_FmPcd); ++ memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); ++ fmGetSetParams.setParams.type = UPDATE_FM_CLD; ++ FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); ++ ++ /* Issue graceful stop to HC port */ ++ FM_PORT_Disable(p_FmPortHc); ++ ++ // config tx port ++ p_FmPort->deepSleepVars.fmbm_tcfg = GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg); ++ WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg, GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg) | BMI_PORT_CFG_IM | BMI_PORT_CFG_EN); ++ // ???? ++ p_FmPort->deepSleepVars.fmbm_tcmne = GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcmne); ++ WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcmne, 0xE); ++ // Stage 7:echo ++ p_FmPort->deepSleepVars.fmbm_rfpne = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne); ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne, 0x2E); ++ if (!PrsIsEnabled(h_FmPcd)) ++ { ++ p_FmPort->deepSleepVars.dsarEnabledParser = TRUE; ++ PrsEnable(h_FmPcd); ++ } ++ else ++ p_FmPort->deepSleepVars.dsarEnabledParser = FALSE; ++ ++ p_FmPort->deepSleepVars.fmbm_rfne = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne); ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne, 0x440000); ++ ++ // save rcfg for restoring: accumulate mode is changed by ucode ++ p_FmPort->deepSleepVars.fmbm_rcfg = GET_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rcfg); ++ WRITE_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rcfg, p_FmPort->deepSleepVars.fmbm_rcfg | BMI_PORT_CFG_AM); ++ memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); ++ fmGetSetParams.setParams.type = UPDATE_FPM_BRKC_SLP; ++ fmGetSetParams.setParams.sleep = 1; ++ FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); ++ ++// ***** issue external request sync command ++ memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); ++ fmGetSetParams.setParams.type = UPDATE_FPM_EXTC; ++ FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); ++ // get ++ memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); ++ fmGetSetParams.getParams.type = GET_FMFP_EXTC; ++ FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); ++ if (fmGetSetParams.getParams.fmfp_extc != 0) ++ { ++ // clear ++ memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); ++ fmGetSetParams.setParams.type = UPDATE_FPM_EXTC_CLEAR; ++ FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); ++} ++ ++ memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); ++ fmGetSetParams.getParams.type = GET_FMFP_EXTC | GET_FM_NPI; ++ do ++ { ++ FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); ++ } while (fmGetSetParams.getParams.fmfp_extc != 0 && fmGetSetParams.getParams.fm_npi == 0); ++ if (fmGetSetParams.getParams.fm_npi != 0) ++ XX_Print("FM: Sync did not finish\n"); ++ ++ // check that all stoped ++ memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); ++ fmGetSetParams.getParams.type = GET_FMQM_GS | GET_FM_NPI; ++ FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); ++ while (fmGetSetParams.getParams.fmqm_gs & 0xF0000000) ++ FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); ++ if (fmGetSetParams.getParams.fmqm_gs == 0 && fmGetSetParams.getParams.fm_npi == 0) ++ XX_Print("FM: Sleeping\n"); ++// FM_ChangeClock(p_FmPort->h_Fm, p_FmPort->hardwarePortId); ++ ++ return E_OK; ++} ++ ++EXPORT_SYMBOL(FM_PORT_EnterDsarFinal); ++ ++void FM_PORT_Dsar_DumpRegs() ++{ ++ uint32_t* hh = XX_PhysToVirt(PTR_TO_UINT(ARDesc)); ++ DUMP_MEMORY(hh, 0x220); ++} ++ ++void FM_PORT_ExitDsar(t_Handle h_FmPortRx, t_Handle h_FmPortTx) ++{ ++ t_FmPort *p_FmPort = (t_FmPort *)h_FmPortRx; ++ t_FmPort *p_FmPortTx = (t_FmPort *)h_FmPortTx; ++ t_Handle *h_FmPcd = FmGetPcd(p_FmPort->h_Fm); ++ t_FmPort *p_FmPortHc = FM_PCD_GetHcPort(h_FmPcd); ++ t_FmGetSetParams fmGetSetParams; ++ memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); ++ fmGetSetParams.setParams.type = UPDATE_FPM_BRKC_SLP; ++ fmGetSetParams.setParams.sleep = 0; ++ if (p_FmPort->deepSleepVars.autoResOffsets) ++ { ++ XX_Free(p_FmPort->deepSleepVars.autoResOffsets); ++ p_FmPort->deepSleepVars.autoResOffsets = 0; ++ } ++ ++ if (p_FmPort->deepSleepVars.dsarEnabledParser) ++ PrsDisable(FmGetPcd(p_FmPort->h_Fm)); ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne, p_FmPort->deepSleepVars.fmbm_rfpne); ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne, p_FmPort->deepSleepVars.fmbm_rfne); ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcfg, p_FmPort->deepSleepVars.fmbm_rcfg); ++ FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); ++ WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcmne, p_FmPort->deepSleepVars.fmbm_tcmne); ++ WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg, p_FmPort->deepSleepVars.fmbm_tcfg); ++ FM_PORT_Enable(p_FmPortHc); ++} ++ ++bool FM_PORT_IsInDsar(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort *)h_FmPort; ++ return PTR_TO_UINT(p_FmPort->deepSleepVars.autoResOffsets); ++} ++ ++t_Error FM_PORT_GetDsarStats(t_Handle h_FmPortRx, t_FmPortDsarStats *stats) ++{ ++ t_FmPort *p_FmPort = (t_FmPort *)h_FmPortRx; ++ struct arOffsets *of = (struct arOffsets*)p_FmPort->deepSleepVars.autoResOffsets; ++ uint8_t* fmMuramVirtBaseAddr = XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr); ++ uint32_t *param_page = XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr)); ++ t_ArCommonDesc *ArCommonDescPtr = (t_ArCommonDesc*)(XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(*param_page))); ++ t_DsarArpDescriptor *ArpDescriptor = (t_DsarArpDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->arp); ++ t_DsarArpStatistics* arp_stats = (t_DsarArpStatistics*)(PTR_TO_UINT(ArpDescriptor->p_Statistics) + fmMuramVirtBaseAddr); ++ t_DsarIcmpV4Descriptor* ICMPV4Descriptor = (t_DsarIcmpV4Descriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->icmpv4); ++ t_DsarIcmpV4Statistics* icmpv4_stats = (t_DsarIcmpV4Statistics*)(PTR_TO_UINT(ICMPV4Descriptor->p_Statistics) + fmMuramVirtBaseAddr); ++ t_DsarNdDescriptor* NDDescriptor = (t_DsarNdDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->nd); ++ t_NdStatistics* nd_stats = (t_NdStatistics*)(PTR_TO_UINT(NDDescriptor->p_Statistics) + fmMuramVirtBaseAddr); ++ t_DsarIcmpV6Descriptor* ICMPV6Descriptor = (t_DsarIcmpV6Descriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->icmpv6); ++ t_DsarIcmpV6Statistics* icmpv6_stats = (t_DsarIcmpV6Statistics*)(PTR_TO_UINT(ICMPV6Descriptor->p_Statistics) + fmMuramVirtBaseAddr); ++ t_DsarSnmpDescriptor* SnmpDescriptor = (t_DsarSnmpDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->snmp); ++ t_DsarSnmpStatistics* snmp_stats = (t_DsarSnmpStatistics*)(PTR_TO_UINT(SnmpDescriptor->p_Statistics) + fmMuramVirtBaseAddr); ++ stats->arpArCnt = arp_stats->arCnt; ++ stats->echoIcmpv4ArCnt = icmpv4_stats->arCnt; ++ stats->ndpArCnt = nd_stats->arCnt; ++ stats->echoIcmpv6ArCnt = icmpv6_stats->arCnt; ++ stats->snmpGetCnt = snmp_stats->snmpGetReqCnt; ++ stats->snmpGetNextCnt = snmp_stats->snmpGetNextReqCnt; ++ return E_OK; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fm_port.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fm_port.h +new file mode 100644 +index 0000000..85986f5 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fm_port.h +@@ -0,0 +1,999 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_port.h ++ ++ @Description FM Port internal structures and definitions. ++*//***************************************************************************/ ++#ifndef __FM_PORT_H ++#define __FM_PORT_H ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "fm_port_ext.h" ++ ++#include "fm_common.h" ++#include "fm_sp_common.h" ++#include "fsl_fman_sp.h" ++#include "fm_port_ext.h" ++#include "fsl_fman_port.h" ++ ++#define __ERR_MODULE__ MODULE_FM_PORT ++ ++ ++#define MIN_EXT_BUF_SIZE 64 ++#define DATA_ALIGNMENT 64 ++#define MAX_LIODN_OFFSET 64 ++#define MAX_PORT_FIFO_SIZE MIN(BMI_MAX_FIFO_SIZE, 1024*BMI_FIFO_UNITS) ++ ++/**************************************************************************//** ++ @Description Memory Map defines ++*//***************************************************************************/ ++#define BMI_PORT_REGS_OFFSET 0 ++#define QMI_PORT_REGS_OFFSET 0x400 ++#define PRS_PORT_REGS_OFFSET 0x800 ++ ++/**************************************************************************//** ++ @Description defaults ++*//***************************************************************************/ ++#define DEFAULT_PORT_deqHighPriority_1G FALSE ++#define DEFAULT_PORT_deqHighPriority_10G TRUE ++#define DEFAULT_PORT_deqType e_FM_PORT_DEQ_TYPE1 ++#define DEFAULT_PORT_deqPrefetchOption e_FM_PORT_DEQ_FULL_PREFETCH ++#define DEFAULT_PORT_deqPrefetchOption_HC e_FM_PORT_DEQ_NO_PREFETCH ++#define DEFAULT_PORT_deqByteCnt_10G 0x1400 ++#define DEFAULT_PORT_deqByteCnt_1G 0x400 ++#define DEFAULT_PORT_bufferPrefixContent_privDataSize DEFAULT_FM_SP_bufferPrefixContent_privDataSize ++#define DEFAULT_PORT_bufferPrefixContent_passPrsResult DEFAULT_FM_SP_bufferPrefixContent_passPrsResult ++#define DEFAULT_PORT_bufferPrefixContent_passTimeStamp DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp ++#define DEFAULT_PORT_bufferPrefixContent_allOtherPCDInfo DEFAULT_FM_SP_bufferPrefixContent_allOtherPCDInfo ++#define DEFAULT_PORT_bufferPrefixContent_dataAlign DEFAULT_FM_SP_bufferPrefixContent_dataAlign ++#define DEFAULT_PORT_cheksumLastBytesIgnore 0 ++#define DEFAULT_PORT_cutBytesFromEnd 4 ++#define DEFAULT_PORT_fifoDeqPipelineDepth_IM 2 ++ ++#define DEFAULT_PORT_frmDiscardOverride FALSE ++ ++#define DEFAULT_PORT_dmaSwapData (e_FmDmaSwapOption)DEFAULT_FMAN_SP_DMA_SWAP_DATA ++#define DEFAULT_PORT_dmaIntContextCacheAttr (e_FmDmaCacheOption)DEFAULT_FMAN_SP_DMA_INT_CONTEXT_CACHE_ATTR ++#define DEFAULT_PORT_dmaHeaderCacheAttr (e_FmDmaCacheOption)DEFAULT_FMAN_SP_DMA_HEADER_CACHE_ATTR ++#define DEFAULT_PORT_dmaScatterGatherCacheAttr (e_FmDmaCacheOption)DEFAULT_FMAN_SP_DMA_SCATTER_GATHER_CACHE_ATTR ++#define DEFAULT_PORT_dmaWriteOptimize DEFAULT_FMAN_SP_DMA_WRITE_OPTIMIZE ++ ++#define DEFAULT_PORT_noScatherGather DEFAULT_FMAN_SP_NO_SCATTER_GATHER ++#define DEFAULT_PORT_forwardIntContextReuse FALSE ++#define DEFAULT_PORT_BufMargins_startMargins 32 ++#define DEFAULT_PORT_BufMargins_endMargins 0 ++#define DEFAULT_PORT_syncReq TRUE ++#define DEFAULT_PORT_syncReqForHc FALSE ++#define DEFAULT_PORT_color e_FM_PORT_COLOR_GREEN ++#define DEFAULT_PORT_errorsToDiscard FM_PORT_FRM_ERR_CLS_DISCARD ++/* #define DEFAULT_PORT_dualRateLimitScaleDown e_FM_PORT_DUAL_RATE_LIMITER_NONE */ ++/* #define DEFAULT_PORT_rateLimitBurstSizeHighGranularity FALSE */ ++#define DEFAULT_PORT_exception IM_EV_BSY ++#define DEFAULT_PORT_maxFrameLength 9600 ++ ++#define DEFAULT_notSupported 0xff ++ ++#if (DPAA_VERSION < 11) ++#define DEFAULT_PORT_rxFifoPriElevationLevel MAX_PORT_FIFO_SIZE ++#define DEFAULT_PORT_rxFifoThreshold (MAX_PORT_FIFO_SIZE*3/4) ++ ++#define DEFAULT_PORT_txFifoMinFillLevel 0 ++#define DEFAULT_PORT_txFifoLowComfLevel (5*KILOBYTE) ++#define DEFAULT_PORT_fifoDeqPipelineDepth_1G 1 ++#define DEFAULT_PORT_fifoDeqPipelineDepth_10G 4 ++ ++#define DEFAULT_PORT_fifoDeqPipelineDepth_OH 2 ++ ++/* Host command port MUST NOT be changed to more than 1 !!! */ ++#define DEFAULT_PORT_numOfTasks(type) \ ++ (uint32_t)((((type) == e_FM_PORT_TYPE_RX_10G) || \ ++ ((type) == e_FM_PORT_TYPE_TX_10G)) ? 16 : \ ++ ((((type) == e_FM_PORT_TYPE_RX) || \ ++ ((type) == e_FM_PORT_TYPE_TX) || \ ++ ((type) == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ? 3 : 1)) ++ ++#define DEFAULT_PORT_extraNumOfTasks(type) \ ++ (uint32_t)(((type) == e_FM_PORT_TYPE_RX_10G) ? 8 : \ ++ (((type) == e_FM_PORT_TYPE_RX) ? 2 : 0)) ++ ++#define DEFAULT_PORT_numOfOpenDmas(type) \ ++ (uint32_t)((((type) == e_FM_PORT_TYPE_TX_10G) || \ ++ ((type) == e_FM_PORT_TYPE_RX_10G)) ? 8 : 1 ) ++ ++#define DEFAULT_PORT_extraNumOfOpenDmas(type) \ ++ (uint32_t)(((type) == e_FM_PORT_TYPE_RX_10G) ? 8 : \ ++ (((type) == e_FM_PORT_TYPE_RX) ? 1 : 0)) ++ ++#define DEFAULT_PORT_numOfFifoBufs(type) \ ++ (uint32_t)((((type) == e_FM_PORT_TYPE_RX_10G) || \ ++ ((type) == e_FM_PORT_TYPE_TX_10G)) ? 48 : \ ++ ((type) == e_FM_PORT_TYPE_RX) ? 45 : \ ++ ((type) == e_FM_PORT_TYPE_TX) ? 44 : 8) ++ ++#define DEFAULT_PORT_extraNumOfFifoBufs 0 ++ ++#else /* (DPAA_VERSION < 11) */ ++/* Defaults are registers' reset values */ ++#define DEFAULT_PORT_rxFifoPriElevationLevel MAX_PORT_FIFO_SIZE ++#define DEFAULT_PORT_rxFifoThreshold MAX_PORT_FIFO_SIZE ++ ++#define DEFAULT_PORT_txFifoMinFillLevel 0 ++#define DEFAULT_PORT_txFifoLowComfLevel (5 * KILOBYTE) ++#define DEFAULT_PORT_fifoDeqPipelineDepth_1G 2 ++#define DEFAULT_PORT_fifoDeqPipelineDepth_10G 4 ++ ++#define DEFAULT_PORT_fifoDeqPipelineDepth_OH 2 ++ ++#define DEFAULT_PORT_numOfTasks(type) \ ++ (uint32_t)((((type) == e_FM_PORT_TYPE_RX_10G) || \ ++ ((type) == e_FM_PORT_TYPE_TX_10G)) ? 14 : \ ++ (((type) == e_FM_PORT_TYPE_RX) || \ ++ ((type) == e_FM_PORT_TYPE_TX)) ? 4 : \ ++ ((type) == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ? 6 : 1) ++ ++#define DEFAULT_PORT_extraNumOfTasks(type) 0 ++ ++#define DEFAULT_PORT_numOfOpenDmas(type) \ ++ (uint32_t)(((type) == e_FM_PORT_TYPE_RX_10G) ? 8 : \ ++ ((type) == e_FM_PORT_TYPE_TX_10G) ? 12 : \ ++ ((type) == e_FM_PORT_TYPE_RX) ? 2 : \ ++ ((type) == e_FM_PORT_TYPE_TX) ? 3 : \ ++ ((type) == e_FM_PORT_TYPE_OH_HOST_COMMAND) ? 2 : 4) ++ ++#define DEFAULT_PORT_extraNumOfOpenDmas(type) 0 ++ ++#define DEFAULT_PORT_numOfFifoBufs(type) \ ++ (uint32_t) (((type) == e_FM_PORT_TYPE_RX_10G) ? 96 : \ ++ ((type) == e_FM_PORT_TYPE_TX_10G) ? 64 : \ ++ ((type) == e_FM_PORT_TYPE_OH_HOST_COMMAND) ? 10 : 50) ++ ++#define DEFAULT_PORT_extraNumOfFifoBufs 0 ++ ++#endif /* (DPAA_VERSION < 11) */ ++ ++#define DEFAULT_PORT_txBdRingLength 16 ++#define DEFAULT_PORT_rxBdRingLength 128 ++#define DEFAULT_PORT_ImfwExtStructsMemId 0 ++#define DEFAULT_PORT_ImfwExtStructsMemAttr MEMORY_ATTR_CACHEABLE ++ ++#define FM_PORT_CG_REG_NUM(_cgId) (((FM_PORT_NUM_OF_CONGESTION_GRPS/32)-1)-_cgId/32) ++ ++/**************************************************************************//** ++ @Collection PCD Engines ++*//***************************************************************************/ ++typedef uint32_t fmPcdEngines_t; /**< options as defined below: */ ++ ++#define FM_PCD_NONE 0 /**< No PCD Engine indicated */ ++#define FM_PCD_PRS 0x80000000 /**< Parser indicated */ ++#define FM_PCD_KG 0x40000000 /**< Keygen indicated */ ++#define FM_PCD_CC 0x20000000 /**< Coarse classification indicated */ ++#define FM_PCD_PLCR 0x10000000 /**< Policer indicated */ ++#define FM_PCD_MANIP 0x08000000 /**< Manipulation indicated */ ++/* @} */ ++ ++#define FM_PORT_MAX_NUM_OF_EXT_POOLS_ALL_INTEGRATIONS 8 ++#define FM_PORT_MAX_NUM_OF_CONGESTION_GRPS_ALL_INTEGRATIONS 256 ++#define FM_PORT_CG_REG_NUM(_cgId) (((FM_PORT_NUM_OF_CONGESTION_GRPS/32)-1)-_cgId/32) ++ ++#define FM_OH_PORT_ID 0 ++ ++/***********************************************************************/ ++/* SW parser OFFLOAD labels (offsets) */ ++/***********************************************************************/ ++#if (DPAA_VERSION == 10) ++#define OFFLOAD_SW_PATCH_IPv4_IPR_LABEL 0x300 ++#define OFFLOAD_SW_PATCH_IPv6_IPR_LABEL 0x325 ++#define OFFLOAD_SW_PATCH_IPv6_IPF_LABEL 0x325 ++#else ++#define OFFLOAD_SW_PATCH_IPv4_IPR_LABEL 0x100 ++/* Will be used for: ++ * 1. identify fragments ++ * 2. udp-lite ++ */ ++#define OFFLOAD_SW_PATCH_IPv6_IPR_LABEL 0x146 ++/* Will be used for: ++ * 1. will identify the fragmentable area ++ * 2. udp-lite ++ */ ++#define OFFLOAD_SW_PATCH_IPv6_IPF_LABEL 0x261 ++#define OFFLOAD_SW_PATCH_CAPWAP_LABEL 0x38d ++#endif /* (DPAA_VERSION == 10) */ ++ ++#if ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++#define UDP_LITE_SW_PATCH_LABEL 0x2E0 ++#endif /* ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) */ ++ ++ ++/**************************************************************************//** ++ @Description Memory Mapped Registers ++*//***************************************************************************/ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++typedef struct ++{ ++ volatile uint32_t fmbm_rcfg; /**< Rx Configuration */ ++ volatile uint32_t fmbm_rst; /**< Rx Status */ ++ volatile uint32_t fmbm_rda; /**< Rx DMA attributes*/ ++ volatile uint32_t fmbm_rfp; /**< Rx FIFO Parameters*/ ++ volatile uint32_t fmbm_rfed; /**< Rx Frame End Data*/ ++ volatile uint32_t fmbm_ricp; /**< Rx Internal Context Parameters*/ ++ volatile uint32_t fmbm_rim; /**< Rx Internal Buffer Margins*/ ++ volatile uint32_t fmbm_rebm; /**< Rx External Buffer Margins*/ ++ volatile uint32_t fmbm_rfne; /**< Rx Frame Next Engine*/ ++ volatile uint32_t fmbm_rfca; /**< Rx Frame Command Attributes.*/ ++ volatile uint32_t fmbm_rfpne; /**< Rx Frame Parser Next Engine*/ ++ volatile uint32_t fmbm_rpso; /**< Rx Parse Start Offset*/ ++ volatile uint32_t fmbm_rpp; /**< Rx Policer Profile */ ++ volatile uint32_t fmbm_rccb; /**< Rx Coarse Classification Base */ ++ volatile uint32_t fmbm_reth; /**< Rx Excessive Threshold */ ++ volatile uint32_t reserved1[0x01];/**< (0x03C) */ ++ volatile uint32_t fmbm_rprai[FM_PORT_PRS_RESULT_NUM_OF_WORDS]; ++ /**< Rx Parse Results Array Initialization*/ ++ volatile uint32_t fmbm_rfqid; /**< Rx Frame Queue ID*/ ++ volatile uint32_t fmbm_refqid; /**< Rx Error Frame Queue ID*/ ++ volatile uint32_t fmbm_rfsdm; /**< Rx Frame Status Discard Mask*/ ++ volatile uint32_t fmbm_rfsem; /**< Rx Frame Status Error Mask*/ ++ volatile uint32_t fmbm_rfene; /**< Rx Frame Enqueue Next Engine */ ++ volatile uint32_t reserved2[0x02];/**< (0x074-0x078) */ ++ volatile uint32_t fmbm_rcmne; /**< Rx Frame Continuous Mode Next Engine */ ++ volatile uint32_t reserved3[0x20];/**< (0x080 0x0FF) */ ++ volatile uint32_t fmbm_ebmpi[FM_PORT_MAX_NUM_OF_EXT_POOLS_ALL_INTEGRATIONS]; ++ /**< Buffer Manager pool Information-*/ ++ volatile uint32_t fmbm_acnt[FM_PORT_MAX_NUM_OF_EXT_POOLS_ALL_INTEGRATIONS]; ++ /**< Allocate Counter-*/ ++ volatile uint32_t reserved4[0x08]; ++ /**< 0x130/0x140 - 0x15F reserved -*/ ++ volatile uint32_t fmbm_rcgm[FM_PORT_MAX_NUM_OF_CONGESTION_GRPS_ALL_INTEGRATIONS/32]; ++ /**< Congestion Group Map*/ ++ volatile uint32_t fmbm_rmpd; /**< BM Pool Depletion */ ++ volatile uint32_t reserved5[0x1F];/**< (0x184 0x1FF) */ ++ volatile uint32_t fmbm_rstc; /**< Rx Statistics Counters*/ ++ volatile uint32_t fmbm_rfrc; /**< Rx Frame Counter*/ ++ volatile uint32_t fmbm_rfbc; /**< Rx Bad Frames Counter*/ ++ volatile uint32_t fmbm_rlfc; /**< Rx Large Frames Counter*/ ++ volatile uint32_t fmbm_rffc; /**< Rx Filter Frames Counter*/ ++ volatile uint32_t fmbm_rfcd; /**< Rx Frame Discard Counter*/ ++ volatile uint32_t fmbm_rfldec; /**< Rx Frames List DMA Error Counter*/ ++ volatile uint32_t fmbm_rodc; /**< Rx Out of Buffers Discard Counter-*/ ++ volatile uint32_t fmbm_rbdc; /**< Rx Buffers Deallocate Counter-*/ ++ volatile uint32_t fmbm_rpec; /**< Rx RX Prepare to enqueue Counter-*/ ++ volatile uint32_t reserved6[0x16];/**< (0x228 0x27F) */ ++ volatile uint32_t fmbm_rpc; /**< Rx Performance Counters*/ ++ volatile uint32_t fmbm_rpcp; /**< Rx Performance Count Parameters*/ ++ volatile uint32_t fmbm_rccn; /**< Rx Cycle Counter*/ ++ volatile uint32_t fmbm_rtuc; /**< Rx Tasks Utilization Counter*/ ++ volatile uint32_t fmbm_rrquc; /**< Rx Receive Queue Utilization Counter*/ ++ volatile uint32_t fmbm_rduc; /**< Rx DMA Utilization Counter*/ ++ volatile uint32_t fmbm_rfuc; /**< Rx FIFO Utilization Counter*/ ++ volatile uint32_t fmbm_rpac; /**< Rx Pause Activation Counter*/ ++ volatile uint32_t reserved7[0x18];/**< (0x2A0-0x2FF) */ ++ volatile uint32_t fmbm_rdcfg[0x3];/**< Rx Debug-*/ ++ volatile uint32_t fmbm_rgpr; /**< Rx General Purpose Register. */ ++ volatile uint32_t reserved8[0x3a];/**< (0x310-0x3FF) */ ++} t_FmPortRxBmiRegs; ++ ++typedef struct ++{ ++ volatile uint32_t fmbm_tcfg; /**< Tx Configuration */ ++ volatile uint32_t fmbm_tst; /**< Tx Status */ ++ volatile uint32_t fmbm_tda; /**< Tx DMA attributes */ ++ volatile uint32_t fmbm_tfp; /**< Tx FIFO Parameters */ ++ volatile uint32_t fmbm_tfed; /**< Tx Frame End Data */ ++ volatile uint32_t fmbm_ticp; /**< Tx Internal Context Parameters */ ++ volatile uint32_t fmbm_tfdne; /**< Tx Frame Dequeue Next Engine. */ ++ volatile uint32_t fmbm_tfca; /**< Tx Frame Command attribute. */ ++ volatile uint32_t fmbm_tcfqid; /**< Tx Confirmation Frame Queue ID. */ ++ volatile uint32_t fmbm_tfeqid; /**< Tx Frame Error Queue ID */ ++ volatile uint32_t fmbm_tfene; /**< Tx Frame Enqueue Next Engine */ ++ volatile uint32_t fmbm_trlmts; /**< Tx Rate Limiter Scale */ ++ volatile uint32_t fmbm_trlmt; /**< Tx Rate Limiter */ ++ volatile uint32_t fmbm_tccb; /**< Tx Coarse Classification Base */ ++ volatile uint32_t reserved0[0x0e];/**< (0x038-0x070) */ ++ volatile uint32_t fmbm_tfne; /**< Tx Frame Next Engine */ ++ volatile uint32_t fmbm_tpfcm[0x02];/**< Tx Priority based Flow Control (PFC) Mapping */ ++ volatile uint32_t fmbm_tcmne; /**< Tx Frame Continuous Mode Next Engine */ ++ volatile uint32_t reserved2[0x60];/**< (0x080-0x200) */ ++ volatile uint32_t fmbm_tstc; /**< Tx Statistics Counters */ ++ volatile uint32_t fmbm_tfrc; /**< Tx Frame Counter */ ++ volatile uint32_t fmbm_tfdc; /**< Tx Frames Discard Counter */ ++ volatile uint32_t fmbm_tfledc; /**< Tx Frame Length error discard counter */ ++ volatile uint32_t fmbm_tfufdc; /**< Tx Frame unsupported format discard Counter */ ++ volatile uint32_t fmbm_tbdc; /**< Tx Buffers Deallocate Counter */ ++ volatile uint32_t reserved3[0x1A];/**< (0x218-0x280) */ ++ volatile uint32_t fmbm_tpc; /**< Tx Performance Counters*/ ++ volatile uint32_t fmbm_tpcp; /**< Tx Performance Count Parameters*/ ++ volatile uint32_t fmbm_tccn; /**< Tx Cycle Counter*/ ++ volatile uint32_t fmbm_ttuc; /**< Tx Tasks Utilization Counter*/ ++ volatile uint32_t fmbm_ttcquc; /**< Tx Transmit Confirm Queue Utilization Counter*/ ++ volatile uint32_t fmbm_tduc; /**< Tx DMA Utilization Counter*/ ++ volatile uint32_t fmbm_tfuc; /**< Tx FIFO Utilization Counter*/ ++ volatile uint32_t reserved4[16]; /**< (0x29C-0x2FF) */ ++ volatile uint32_t fmbm_tdcfg[0x3];/**< Tx Debug-*/ ++ volatile uint32_t fmbm_tgpr; /**< O/H General Purpose Register */ ++ volatile uint32_t reserved5[0x3a];/**< (0x310-0x3FF) */ ++} t_FmPortTxBmiRegs; ++ ++typedef struct ++{ ++ volatile uint32_t fmbm_ocfg; /**< O/H Configuration */ ++ volatile uint32_t fmbm_ost; /**< O/H Status */ ++ volatile uint32_t fmbm_oda; /**< O/H DMA attributes */ ++ volatile uint32_t fmbm_oicp; /**< O/H Internal Context Parameters */ ++ volatile uint32_t fmbm_ofdne; /**< O/H Frame Dequeue Next Engine */ ++ volatile uint32_t fmbm_ofne; /**< O/H Frame Next Engine */ ++ volatile uint32_t fmbm_ofca; /**< O/H Frame Command Attributes. */ ++ volatile uint32_t fmbm_ofpne; /**< O/H Frame Parser Next Engine */ ++ volatile uint32_t fmbm_opso; /**< O/H Parse Start Offset */ ++ volatile uint32_t fmbm_opp; /**< O/H Policer Profile */ ++ volatile uint32_t fmbm_occb; /**< O/H Coarse Classification base */ ++ volatile uint32_t fmbm_oim; /**< O/H Internal margins*/ ++ volatile uint32_t fmbm_ofp; /**< O/H Fifo Parameters*/ ++ volatile uint32_t fmbm_ofed; /**< O/H Frame End Data*/ ++ volatile uint32_t reserved0[2]; /**< (0x038 - 0x03F) */ ++ volatile uint32_t fmbm_oprai[FM_PORT_PRS_RESULT_NUM_OF_WORDS]; ++ /**< O/H Parse Results Array Initialization */ ++ volatile uint32_t fmbm_ofqid; /**< O/H Frame Queue ID */ ++ volatile uint32_t fmbm_oefqid; /**< O/H Error Frame Queue ID */ ++ volatile uint32_t fmbm_ofsdm; /**< O/H Frame Status Discard Mask */ ++ volatile uint32_t fmbm_ofsem; /**< O/H Frame Status Error Mask */ ++ volatile uint32_t fmbm_ofene; /**< O/H Frame Enqueue Next Engine */ ++ volatile uint32_t fmbm_orlmts; /**< O/H Rate Limiter Scale */ ++ volatile uint32_t fmbm_orlmt; /**< O/H Rate Limiter */ ++ volatile uint32_t fmbm_ocmne; /**< O/H Continuous Mode Next Engine */ ++ volatile uint32_t reserved1[0x20];/**< (0x080 - 0x0FF) */ ++ volatile uint32_t fmbm_oebmpi[2]; /**< Buffer Manager Observed Pool Information */ ++ volatile uint32_t reserved2[0x16];/**< (0x108 - 0x15F) */ ++ volatile uint32_t fmbm_ocgm; /**< Observed Congestion Group Map */ ++ volatile uint32_t reserved3[0x7]; /**< (0x164 - 0x17F) */ ++ volatile uint32_t fmbm_ompd; /**< Observed BMan Pool Depletion */ ++ volatile uint32_t reserved4[0x1F];/**< (0x184 - 0x1FF) */ ++ volatile uint32_t fmbm_ostc; /**< O/H Statistics Counters */ ++ volatile uint32_t fmbm_ofrc; /**< O/H Frame Counter */ ++ volatile uint32_t fmbm_ofdc; /**< O/H Frames Discard Counter */ ++ volatile uint32_t fmbm_ofledc; /**< O/H Frames Length Error Discard Counter */ ++ volatile uint32_t fmbm_ofufdc; /**< O/H Frames Unsupported Format Discard Counter */ ++ volatile uint32_t fmbm_offc; /**< O/H Filter Frames Counter */ ++ volatile uint32_t fmbm_ofwdc; /**< - Rx Frames WRED Discard Counter */ ++ volatile uint32_t fmbm_ofldec; /**< O/H Frames List DMA Error Counter */ ++ volatile uint32_t fmbm_obdc; /**< O/H Buffers Deallocate Counter */ ++ volatile uint32_t fmbm_oodc; /**< O/H Out of Buffers Discard Counter */ ++ volatile uint32_t fmbm_opec; /**< O/H Prepare to enqueue Counter */ ++ volatile uint32_t reserved5[0x15];/**< ( - 0x27F) */ ++ volatile uint32_t fmbm_opc; /**< O/H Performance Counters */ ++ volatile uint32_t fmbm_opcp; /**< O/H Performance Count Parameters */ ++ volatile uint32_t fmbm_occn; /**< O/H Cycle Counter */ ++ volatile uint32_t fmbm_otuc; /**< O/H Tasks Utilization Counter */ ++ volatile uint32_t fmbm_oduc; /**< O/H DMA Utilization Counter */ ++ volatile uint32_t fmbm_ofuc; /**< O/H FIFO Utilization Counter */ ++ volatile uint32_t reserved6[26]; /**< (0x298-0x2FF) */ ++ volatile uint32_t fmbm_odcfg[0x3];/**< O/H Debug (only 1 in P1023) */ ++ volatile uint32_t fmbm_ogpr; /**< O/H General Purpose Register. */ ++ volatile uint32_t reserved7[0x3a];/**< (0x310 0x3FF) */ ++} t_FmPortOhBmiRegs; ++ ++typedef union ++{ ++ t_FmPortRxBmiRegs rxPortBmiRegs; ++ t_FmPortTxBmiRegs txPortBmiRegs; ++ t_FmPortOhBmiRegs ohPortBmiRegs; ++} u_FmPortBmiRegs; ++ ++typedef struct ++{ ++ volatile uint32_t reserved1[2]; /**< 0xn024 - 0x02B */ ++ volatile uint32_t fmqm_pndn; /**< PortID n Dequeue NIA Register */ ++ volatile uint32_t fmqm_pndc; /**< PortID n Dequeue Config Register */ ++ volatile uint32_t fmqm_pndtfc; /**< PortID n Dequeue Total Frame Counter */ ++ volatile uint32_t fmqm_pndfdc; /**< PortID n Dequeue FQID from Default Counter */ ++ volatile uint32_t fmqm_pndcc; /**< PortID n Dequeue Confirm Counter */ ++} t_FmPortNonRxQmiRegs; ++ ++typedef struct ++{ ++ volatile uint32_t fmqm_pnc; /**< PortID n Configuration Register */ ++ volatile uint32_t fmqm_pns; /**< PortID n Status Register */ ++ volatile uint32_t fmqm_pnts; /**< PortID n Task Status Register */ ++ volatile uint32_t reserved0[4]; /**< 0xn00C - 0xn01B */ ++ volatile uint32_t fmqm_pnen; /**< PortID n Enqueue NIA Register */ ++ volatile uint32_t fmqm_pnetfc; /**< PortID n Enqueue Total Frame Counter */ ++ t_FmPortNonRxQmiRegs nonRxQmiRegs; /**< Registers for Tx Hc & Op ports */ ++} t_FmPortQmiRegs; ++ ++typedef struct ++{ ++ struct ++ { ++ volatile uint32_t softSeqAttach; /**< Soft Sequence Attachment */ ++ volatile uint32_t lcv; /**< Line-up Enable Confirmation Mask */ ++ } hdrs[FM_PCD_PRS_NUM_OF_HDRS]; ++ volatile uint32_t reserved0[0xde]; ++ volatile uint32_t pcac; /**< Parse Internal Memory Configuration Access Control Register */ ++ volatile uint32_t pctpid; /**< Parse Internal Memory Configured TPID Register */ ++} t_FmPortPrsRegs; ++ ++/**************************************************************************//* ++ @Description Basic buffer descriptor (BD) structure ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ volatile uint16_t status; ++ volatile uint16_t length; ++ volatile uint8_t reserved0[0x6]; ++ volatile uint8_t reserved1[0x1]; ++ volatile t_FmPhysAddr buff; ++} _PackedType t_FmImBd; ++ ++typedef _Packed struct ++{ ++ volatile uint16_t gen; /**< tbd */ ++ volatile uint8_t reserved0[0x1]; ++ volatile t_FmPhysAddr bdRingBase; /**< tbd */ ++ volatile uint16_t bdRingSize; /**< tbd */ ++ volatile uint16_t offsetIn; /**< tbd */ ++ volatile uint16_t offsetOut; /**< tbd */ ++ volatile uint8_t reserved1[0x12]; /**< 0x0e - 0x1f */ ++} _PackedType t_FmPortImQd; ++ ++typedef _Packed struct ++{ ++ volatile uint32_t mode; /**< Mode register */ ++ volatile uint32_t rxQdPtr; /**< tbd */ ++ volatile uint32_t txQdPtr; /**< tbd */ ++ volatile uint16_t mrblr; /**< tbd */ ++ volatile uint16_t rxQdBsyCnt; /**< tbd */ ++ volatile uint8_t reserved0[0x10]; /**< 0x10 - 0x1f */ ++ t_FmPortImQd rxQd; ++ t_FmPortImQd txQd; ++ volatile uint8_t reserved1[0xa0]; /**< 0x60 - 0xff */ ++} _PackedType t_FmPortImPram; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/**************************************************************************//** ++ @Description Registers bit fields ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description BMI defines ++*//***************************************************************************/ ++#if (DPAA_VERSION >= 11) ++#define BMI_SP_ID_MASK 0xff000000 ++#define BMI_SP_ID_SHIFT 24 ++#define BMI_SP_EN 0x01000000 ++#endif /* (DPAA_VERSION >= 11) */ ++ ++#define BMI_PORT_CFG_EN 0x80000000 ++#define BMI_PORT_CFG_EN_MACSEC 0x00800000 ++#define BMI_PORT_CFG_FDOVR 0x02000000 ++#define BMI_PORT_CFG_IM 0x01000000 ++#define BMI_PORT_CFG_AM 0x00000040 ++#define BMI_PORT_STATUS_BSY 0x80000000 ++#define BMI_COUNTERS_EN 0x80000000 ++ ++#define BMI_PORT_RFNE_FRWD_DCL4C 0x10000000 ++#define BMI_PORT_RFNE_FRWD_RPD 0x40000000 ++#define BMI_RFNE_FDCS_MASK 0xFF000000 ++#define BMI_RFNE_HXS_MASK 0x000000FF ++ ++#define BMI_CMD_MR_LEAC 0x00200000 ++#define BMI_CMD_MR_SLEAC 0x00100000 ++#define BMI_CMD_MR_MA 0x00080000 ++#define BMI_CMD_MR_DEAS 0x00040000 ++#define BMI_CMD_RX_MR_DEF (BMI_CMD_MR_LEAC | \ ++ BMI_CMD_MR_SLEAC | \ ++ BMI_CMD_MR_MA | \ ++ BMI_CMD_MR_DEAS) ++#define BMI_CMD_ATTR_ORDER 0x80000000 ++#define BMI_CMD_ATTR_SYNC 0x02000000 ++#define BMI_CMD_ATTR_MODE_MISS_ALLIGN_ADDR_EN 0x00080000 ++#define BMI_CMD_ATTR_MACCMD_MASK 0x0000ff00 ++#define BMI_CMD_ATTR_MACCMD_OVERRIDE 0x00008000 ++#define BMI_CMD_ATTR_MACCMD_SECURED 0x00001000 ++#define BMI_CMD_ATTR_MACCMD_SC_MASK 0x00000f00 ++ ++#define BMI_EXT_BUF_POOL_ID_MASK 0x003F0000 ++#define BMI_STATUS_RX_MASK_UNUSED (uint32_t)(~(FM_PORT_FRM_ERR_DMA | \ ++ FM_PORT_FRM_ERR_PHYSICAL | \ ++ FM_PORT_FRM_ERR_SIZE | \ ++ FM_PORT_FRM_ERR_CLS_DISCARD | \ ++ FM_PORT_FRM_ERR_EXTRACTION | \ ++ FM_PORT_FRM_ERR_NO_SCHEME | \ ++ FM_PORT_FRM_ERR_COLOR_RED | \ ++ FM_PORT_FRM_ERR_COLOR_YELLOW | \ ++ FM_PORT_FRM_ERR_ILL_PLCR | \ ++ FM_PORT_FRM_ERR_PLCR_FRAME_LEN | \ ++ FM_PORT_FRM_ERR_PRS_TIMEOUT | \ ++ FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT | \ ++ FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED | \ ++ FM_PORT_FRM_ERR_PRS_HDR_ERR | \ ++ FM_PORT_FRM_ERR_IPRE | \ ++ FM_PORT_FRM_ERR_IPR_NCSP | \ ++ FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW)) ++ ++#define BMI_STATUS_OP_MASK_UNUSED (uint32_t)(BMI_STATUS_RX_MASK_UNUSED & \ ++ ~(FM_PORT_FRM_ERR_LENGTH | \ ++ FM_PORT_FRM_ERR_NON_FM | \ ++ FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT)) ++ ++#define BMI_RATE_LIMIT_EN 0x80000000 ++#define BMI_RATE_LIMIT_BURST_SIZE_GRAN 0x80000000 ++#define BMI_RATE_LIMIT_SCALE_BY_2 0x00000001 ++#define BMI_RATE_LIMIT_SCALE_BY_4 0x00000002 ++#define BMI_RATE_LIMIT_SCALE_BY_8 0x00000003 ++ ++#define BMI_RX_FIFO_THRESHOLD_BC 0x80000000 ++ ++#define BMI_PRS_RESULT_HIGH 0x00000000 ++#define BMI_PRS_RESULT_LOW 0xFFFFFFFF ++ ++ ++#define RX_ERRS_TO_ENQ (FM_PORT_FRM_ERR_DMA | \ ++ FM_PORT_FRM_ERR_PHYSICAL | \ ++ FM_PORT_FRM_ERR_SIZE | \ ++ FM_PORT_FRM_ERR_EXTRACTION | \ ++ FM_PORT_FRM_ERR_NO_SCHEME | \ ++ FM_PORT_FRM_ERR_ILL_PLCR | \ ++ FM_PORT_FRM_ERR_PLCR_FRAME_LEN | \ ++ FM_PORT_FRM_ERR_PRS_TIMEOUT | \ ++ FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT | \ ++ FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED | \ ++ FM_PORT_FRM_ERR_PRS_HDR_ERR | \ ++ FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW | \ ++ FM_PORT_FRM_ERR_IPRE) ++ ++#define OP_ERRS_TO_ENQ (RX_ERRS_TO_ENQ | \ ++ FM_PORT_FRM_ERR_LENGTH | \ ++ FM_PORT_FRM_ERR_NON_FM | \ ++ FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT) ++ ++ ++#define BMI_RX_FIFO_PRI_ELEVATION_MASK 0x03FF0000 ++#define BMI_RX_FIFO_THRESHOLD_MASK 0x000003FF ++#define BMI_TX_FIFO_MIN_FILL_MASK 0x03FF0000 ++#define BMI_FIFO_PIPELINE_DEPTH_MASK 0x0000F000 ++#define BMI_TX_LOW_COMF_MASK 0x000003FF ++ ++/* shifts */ ++#define BMI_PORT_CFG_MS_SEL_SHIFT 16 ++#define BMI_DMA_ATTR_IC_CACHE_SHIFT FMAN_SP_DMA_ATTR_IC_CACHE_SHIFT ++#define BMI_DMA_ATTR_HDR_CACHE_SHIFT FMAN_SP_DMA_ATTR_HDR_CACHE_SHIFT ++#define BMI_DMA_ATTR_SG_CACHE_SHIFT FMAN_SP_DMA_ATTR_SG_CACHE_SHIFT ++ ++#define BMI_IM_FOF_SHIFT 28 ++#define BMI_PR_PORTID_SHIFT 24 ++ ++#define BMI_RX_FIFO_PRI_ELEVATION_SHIFT 16 ++#define BMI_RX_FIFO_THRESHOLD_SHIFT 0 ++ ++#define BMI_RX_FRAME_END_CS_IGNORE_SHIFT 24 ++#define BMI_RX_FRAME_END_CUT_SHIFT 16 ++ ++#define BMI_IC_SIZE_SHIFT FMAN_SP_IC_SIZE_SHIFT ++ ++#define BMI_INT_BUF_MARG_SHIFT 28 ++ ++#define BMI_EXT_BUF_MARG_END_SHIFT FMAN_SP_EXT_BUF_MARG_END_SHIFT ++ ++#define BMI_CMD_ATTR_COLOR_SHIFT 26 ++#define BMI_CMD_ATTR_COM_MODE_SHIFT 16 ++#define BMI_CMD_ATTR_MACCMD_SHIFT 8 ++#define BMI_CMD_ATTR_MACCMD_OVERRIDE_SHIFT 15 ++#define BMI_CMD_ATTR_MACCMD_SECURED_SHIFT 12 ++#define BMI_CMD_ATTR_MACCMD_SC_SHIFT 8 ++ ++#define BMI_POOL_DEP_NUM_OF_POOLS_VECTOR_SHIFT 24 ++ ++#define BMI_TX_FIFO_MIN_FILL_SHIFT 16 ++#define BMI_TX_LOW_COMF_SHIFT 0 ++ ++#define BMI_PERFORMANCE_TASK_COMP_SHIFT 24 ++#define BMI_PERFORMANCE_PORT_COMP_SHIFT 16 ++#define BMI_PERFORMANCE_DMA_COMP_SHIFT 12 ++#define BMI_PERFORMANCE_FIFO_COMP_SHIFT 0 ++ ++#define BMI_MAX_BURST_SHIFT 16 ++#define BMI_COUNT_RATE_UNIT_SHIFT 16 ++ ++/* sizes */ ++#define FRAME_END_DATA_SIZE 16 ++#define FRAME_OFFSET_UNITS 16 ++#define MIN_TX_INT_OFFSET 16 ++#define MAX_FRAME_OFFSET 64 ++#define MAX_FIFO_PIPELINE_DEPTH 8 ++#define MAX_PERFORMANCE_TASK_COMP 64 ++#define MAX_PERFORMANCE_TX_QUEUE_COMP 8 ++#define MAX_PERFORMANCE_RX_QUEUE_COMP 64 ++#define MAX_PERFORMANCE_DMA_COMP 16 ++#define MAX_NUM_OF_TASKS 64 ++#define MAX_NUM_OF_EXTRA_TASKS 8 ++#define MAX_NUM_OF_DMAS 16 ++#define MAX_NUM_OF_EXTRA_DMAS 8 ++#define MAX_BURST_SIZE 1024 ++#define MIN_NUM_OF_OP_DMAS 2 ++ ++ ++/**************************************************************************//** ++ @Description QMI defines ++*//***************************************************************************/ ++/* masks */ ++#define QMI_PORT_CFG_EN 0x80000000 ++#define QMI_PORT_CFG_EN_COUNTERS 0x10000000 ++#define QMI_PORT_STATUS_DEQ_TNUM_BSY 0x80000000 ++#define QMI_PORT_STATUS_DEQ_FD_BSY 0x20000000 ++ ++#define QMI_DEQ_CFG_PREFETCH_NO_TNUM 0x02000000 ++#define QMI_DEQ_CFG_PREFETCH_WAITING_TNUM 0 ++#define QMI_DEQ_CFG_PREFETCH_1_FRAME 0 ++#define QMI_DEQ_CFG_PREFETCH_3_FRAMES 0x01000000 ++ ++#define QMI_DEQ_CFG_PRI 0x80000000 ++#define QMI_DEQ_CFG_TYPE1 0x10000000 ++#define QMI_DEQ_CFG_TYPE2 0x20000000 ++#define QMI_DEQ_CFG_TYPE3 0x30000000 ++ ++#define QMI_DEQ_CFG_SUBPORTAL_MASK 0x1f ++#define QMI_DEQ_CFG_SUBPORTAL_SHIFT 20 ++ ++/**************************************************************************//** ++ @Description PARSER defines ++*//***************************************************************************/ ++/* masks */ ++#define PRS_HDR_ERROR_DIS 0x00000800 ++#define PRS_HDR_SW_PRS_EN 0x00000400 ++#define PRS_CP_OFFSET_MASK 0x0000000F ++#define PRS_TPID1_MASK 0xFFFF0000 ++#define PRS_TPID2_MASK 0x0000FFFF ++#define PRS_TPID_DFLT 0x91009100 ++ ++#define PRS_HDR_MPLS_LBL_INTER_EN 0x00200000 ++#define PRS_HDR_IPV6_ROUTE_HDR_EN 0x00008000 ++#define PRS_HDR_PPPOE_MTU_CHECK_EN 0x80000000 ++#define PRS_HDR_UDP_PAD_REMOVAL 0x80000000 ++#define PRS_HDR_TCP_PAD_REMOVAL 0x80000000 ++#define PRS_CAC_STOP 0x00000001 ++#define PRS_CAC_ACTIVE 0x00000100 ++ ++/* shifts */ ++#define PRS_PCTPID_SHIFT 16 ++#define PRS_HDR_MPLS_NEXT_HDR_SHIFT 22 ++#define PRS_HDR_ETH_BC_SHIFT 28 ++#define PRS_HDR_ETH_MC_SHIFT 24 ++#define PRS_HDR_VLAN_STACKED_SHIFT 16 ++#define PRS_HDR_MPLS_STACKED_SHIFT 16 ++#define PRS_HDR_IPV4_1_BC_SHIFT 28 ++#define PRS_HDR_IPV4_1_MC_SHIFT 24 ++#define PRS_HDR_IPV4_2_UC_SHIFT 20 ++#define PRS_HDR_IPV4_2_MC_BC_SHIFT 16 ++#define PRS_HDR_IPV6_1_MC_SHIFT 24 ++#define PRS_HDR_IPV6_2_UC_SHIFT 20 ++#define PRS_HDR_IPV6_2_MC_SHIFT 16 ++ ++#define PRS_HDR_ETH_BC_MASK 0x0fffffff ++#define PRS_HDR_ETH_MC_MASK 0xf0ffffff ++#define PRS_HDR_VLAN_STACKED_MASK 0xfff0ffff ++#define PRS_HDR_MPLS_STACKED_MASK 0xfff0ffff ++#define PRS_HDR_IPV4_1_BC_MASK 0x0fffffff ++#define PRS_HDR_IPV4_1_MC_MASK 0xf0ffffff ++#define PRS_HDR_IPV4_2_UC_MASK 0xff0fffff ++#define PRS_HDR_IPV4_2_MC_BC_MASK 0xfff0ffff ++#define PRS_HDR_IPV6_1_MC_MASK 0xf0ffffff ++#define PRS_HDR_IPV6_2_UC_MASK 0xff0fffff ++#define PRS_HDR_IPV6_2_MC_MASK 0xfff0ffff ++ ++/* others */ ++#define PRS_HDR_ENTRY_SIZE 8 ++#define DEFAULT_CLS_PLAN_VECTOR 0xFFFFFFFF ++ ++#define IPSEC_SW_PATCH_START 0x20 ++#define SCTP_SW_PATCH_START 0x4D ++#define DCCP_SW_PATCH_START 0x41 ++ ++/**************************************************************************//** ++ @Description IM defines ++*//***************************************************************************/ ++#define BD_R_E 0x80000000 ++#define BD_L 0x08000000 ++ ++#define BD_RX_CRE 0x00080000 ++#define BD_RX_FTL 0x00040000 ++#define BD_RX_FTS 0x00020000 ++#define BD_RX_OV 0x00010000 ++ ++#define BD_RX_ERRORS (BD_RX_CRE | BD_RX_FTL | BD_RX_FTS | BD_RX_OV) ++ ++#define FM_IM_SIZEOF_BD sizeof(t_FmImBd) ++ ++#define BD_STATUS_MASK 0xffff0000 ++#define BD_LENGTH_MASK 0x0000ffff ++ ++#define BD_STATUS_AND_LENGTH_SET(bd, val) WRITE_UINT32(*(volatile uint32_t*)(bd), (val)) ++ ++#define BD_STATUS_AND_LENGTH(bd) GET_UINT32(*(volatile uint32_t*)(bd)) ++ ++#define BD_GET(id) &p_FmPort->im.p_BdRing[id] ++ ++#define IM_ILEGAL_BD_ID 0xffff ++ ++/* others */ ++#define IM_PRAM_ALIGN 0x100 ++ ++/* masks */ ++#define IM_MODE_GBL 0x20000000 ++#define IM_MODE_BO_MASK 0x18000000 ++#define IM_MODE_BO_SHIFT 3 ++#define IM_MODE_GRC_STP 0x00800000 ++ ++#define IM_MODE_SET_BO(val) (uint32_t)((val << (31-IM_MODE_BO_SHIFT)) & IM_MODE_BO_MASK) ++ ++#define IM_RXQD_BSYINTM 0x0008 ++#define IM_RXQD_RXFINTM 0x0010 ++#define IM_RXQD_FPMEVT_SEL_MASK 0x0003 ++ ++#define IM_EV_BSY 0x40000000 ++#define IM_EV_RX 0x80000000 ++ ++ ++/**************************************************************************//** ++ @Description Additional defines ++*//***************************************************************************/ ++ ++typedef struct { ++ t_Handle h_FmMuram; ++ t_FmPortImPram *p_FmPortImPram; ++ uint8_t fwExtStructsMemId; ++ uint32_t fwExtStructsMemAttr; ++ uint16_t bdRingSize; ++ t_FmImBd *p_BdRing; ++ t_Handle *p_BdShadow; ++ uint16_t currBdId; ++ uint16_t firstBdOfFrameId; ++ ++ /* Rx port parameters */ ++ uint8_t dataMemId; /**< Memory partition ID for data buffers */ ++ uint32_t dataMemAttributes; /**< Memory attributes for data buffers */ ++ t_BufferPoolInfo rxPool; ++ uint16_t mrblr; ++ uint16_t rxFrameAccumLength; ++ t_FmPortImRxStoreCallback *f_RxStore; ++ ++ /* Tx port parameters */ ++ uint32_t txFirstBdStatus; ++ t_FmPortImTxConfCallback *f_TxConf; ++} t_FmMacIm; ++ ++ ++typedef struct { ++ struct fman_port_cfg dfltCfg; ++ uint32_t dfltFqid; ++ uint32_t confFqid; ++ uint32_t errFqid; ++ uintptr_t baseAddr; ++ uint8_t deqSubPortal; ++ bool deqHighPriority; ++ e_FmPortDeqType deqType; ++ e_FmPortDeqPrefetchOption deqPrefetchOption; ++ uint16_t deqByteCnt; ++ uint8_t cheksumLastBytesIgnore; ++ uint8_t cutBytesFromEnd; ++ t_FmBufPoolDepletion bufPoolDepletion; ++ uint8_t pipelineDepth; ++ uint16_t fifoLowComfLevel; ++ bool frmDiscardOverride; ++ bool enRateLimit; ++ t_FmPortRateLimit rateLimit; ++ e_FmPortDualRateLimiterScaleDown rateLimitDivider; ++ bool enBufPoolDepletion; ++ uint16_t liodnOffset; ++ uint16_t liodnBase; ++ t_FmExtPools extBufPools; ++ e_FmDmaSwapOption dmaSwapData; ++ e_FmDmaCacheOption dmaIntContextCacheAttr; ++ e_FmDmaCacheOption dmaHeaderCacheAttr; ++ e_FmDmaCacheOption dmaScatterGatherCacheAttr; ++ bool dmaReadOptimize; ++ bool dmaWriteOptimize; ++ uint32_t txFifoMinFillLevel; ++ uint32_t txFifoLowComfLevel; ++ uint32_t rxFifoPriElevationLevel; ++ uint32_t rxFifoThreshold; ++ t_FmSpBufMargins bufMargins; ++ t_FmSpIntContextDataCopy intContext; ++ bool syncReq; ++ e_FmPortColor color; ++ fmPortFrameErrSelect_t errorsToDiscard; ++ fmPortFrameErrSelect_t errorsToEnq; ++ bool forwardReuseIntContext; ++ t_FmBufferPrefixContent bufferPrefixContent; ++ t_FmBackupBmPools *p_BackupBmPools; ++ bool dontReleaseBuf; ++ bool setNumOfTasks; ++ bool setNumOfOpenDmas; ++ bool setSizeOfFifo; ++#if (DPAA_VERSION >= 11) ++ bool noScatherGather; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 ++ bool bcbWorkaround; ++#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */ ++} t_FmPortDriverParam; ++ ++ ++typedef struct t_FmPortRxPoolsParams ++{ ++ uint8_t numOfPools; ++ uint16_t secondLargestBufSize; ++ uint16_t largestBufSize; ++} t_FmPortRxPoolsParams; ++ ++typedef struct t_FmPortDsarVars { ++ t_Handle *autoResOffsets; ++ t_FmPortDsarTablesSizes *autoResMaxSizes; ++ uint32_t fmbm_tcfg; ++ uint32_t fmbm_tcmne; ++ uint32_t fmbm_rfne; ++ uint32_t fmbm_rfpne; ++ uint32_t fmbm_rcfg; ++ bool dsarEnabledParser; ++} t_FmPortDsarVars; ++typedef struct { ++ struct fman_port port; ++ t_Handle h_Fm; ++ t_Handle h_FmPcd; ++ t_Handle h_FmMuram; ++ t_FmRevisionInfo fmRevInfo; ++ uint8_t portId; ++ e_FmPortType portType; ++ int enabled; ++ char name[MODULE_NAME_SIZE]; ++ uint8_t hardwarePortId; ++ uint16_t fmClkFreq; ++ t_FmPortQmiRegs *p_FmPortQmiRegs; ++ u_FmPortBmiRegs *p_FmPortBmiRegs; ++ t_FmPortPrsRegs *p_FmPortPrsRegs; ++ fmPcdEngines_t pcdEngines; ++ uint32_t savedBmiNia; ++ uint8_t netEnvId; ++ uint32_t optArray[FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)]; ++ uint32_t lcvs[FM_PCD_PRS_NUM_OF_HDRS]; ++ uint8_t privateInfo; ++ uint32_t schemesPerPortVector; ++ bool useClsPlan; ++ uint8_t clsPlanGrpId; ++ t_Handle ccTreeId; ++ t_Handle completeArg; ++ void (*f_Complete)(t_Handle arg); ++ t_FmSpBufferOffsets bufferOffsets; ++ /* Independent-Mode parameters support */ ++ bool imEn; ++ t_FmMacIm im; ++ volatile bool lock; ++ t_Handle h_Spinlock; ++ t_FmPortExceptionCallback *f_Exception; ++ t_Handle h_App; ++ uint8_t internalBufferOffset; ++ uint8_t fmanCtrlEventId; ++ uint32_t exceptions; ++ bool polling; ++ t_FmExtPools extBufPools; ++ uint32_t requiredAction; ++ uint32_t savedQmiPnen; ++ uint32_t savedBmiFene; ++ uint32_t savedBmiFpne; ++ uint32_t savedBmiCmne; ++ uint32_t savedBmiOfp; ++ uint32_t savedNonRxQmiRegsPndn; ++ uint32_t origNonRxQmiRegsPndn; ++ int savedPrsStartOffset; ++ bool includeInPrsStatistics; ++ uint16_t maxFrameLength; ++ t_FmFmanCtrl orFmanCtrl; ++ t_FmPortRsrc openDmas; ++ t_FmPortRsrc tasks; ++ t_FmPortRsrc fifoBufs; ++ t_FmPortRxPoolsParams rxPoolsParams; ++// bool explicitUserSizeOfFifo; ++ t_Handle h_IpReassemblyManip; ++ t_Handle h_CapwapReassemblyManip; ++ t_Handle h_ReassemblyTree; ++ uint64_t fmMuramPhysBaseAddr; ++#if (DPAA_VERSION >= 11) ++ bool vspe; ++ uint8_t dfltRelativeId; ++ e_FmPortGprFuncType gprFunc; ++ t_FmPcdCtrlParamsPage *p_ParamsPage; ++#endif /* (DPAA_VERSION >= 11) */ ++ t_FmPortDsarVars deepSleepVars; ++ t_FmPortDriverParam *p_FmPortDriverParam; ++} t_FmPort; ++ ++ ++void FmPortConfigIM (t_FmPort *p_FmPort, t_FmPortParams *p_FmPortParams); ++t_Error FmPortImCheckInitParameters(t_FmPort *p_FmPort); ++ ++t_Error FmPortImInit(t_FmPort *p_FmPort); ++void FmPortImFree(t_FmPort *p_FmPort); ++ ++t_Error FmPortImEnable (t_FmPort *p_FmPort); ++t_Error FmPortImDisable (t_FmPort *p_FmPort); ++t_Error FmPortImRx (t_FmPort *p_FmPort); ++ ++void FmPortSetMacsecLcv(t_Handle h_FmPort); ++void FmPortSetMacsecCmd(t_Handle h_FmPort, uint8_t dfltSci); ++ ++ ++t_Error FM_PORT_SetNumOfOpenDmas(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfOpenDmas); ++t_Error FM_PORT_SetNumOfTasks(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfTasks); ++t_Error FM_PORT_SetSizeOfFifo(t_Handle h_FmPort, t_FmPortRsrc *p_SizeOfFifo); ++ ++static __inline__ uint8_t * BdBufferGet (t_PhysToVirt *f_PhysToVirt, t_FmImBd *p_Bd) ++{ ++ uint64_t physAddr = (uint64_t)((uint64_t)GET_UINT8(p_Bd->buff.high) << 32); ++ physAddr |= GET_UINT32(p_Bd->buff.low); ++ ++ return (uint8_t *)f_PhysToVirt((physAddress_t)(physAddr)); ++} ++ ++static __inline__ void SET_ADDR(volatile t_FmPhysAddr *fmPhysAddr, uint64_t value) ++{ ++ WRITE_UINT8(fmPhysAddr->high,(uint8_t)((value & 0x000000ff00000000LL) >> 32)); ++ WRITE_UINT32(fmPhysAddr->low,(uint32_t)value); ++} ++ ++static __inline__ void BdBufferSet(t_VirtToPhys *f_VirtToPhys, t_FmImBd *p_Bd, uint8_t *p_Buffer) ++{ ++ uint64_t physAddr = (uint64_t)(f_VirtToPhys(p_Buffer)); ++ SET_ADDR(&p_Bd->buff, physAddr); ++} ++ ++static __inline__ uint16_t GetNextBdId(t_FmPort *p_FmPort, uint16_t id) ++{ ++ if (id < p_FmPort->im.bdRingSize-1) ++ return (uint16_t)(id+1); ++ else ++ return 0; ++} ++ ++void FM_PORT_Dsar_DumpRegs(void); ++ ++ ++#endif /* __FM_PORT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fm_port_dsar.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fm_port_dsar.h +new file mode 100755 +index 0000000..95619ef +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fm_port_dsar.h +@@ -0,0 +1,494 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/**************************************************************************//** ++ @File fm_port_dsar.h ++ ++ @Description Deep Sleep Auto Response project - common module header file. ++ ++ Author - Eyal Harari ++ ++ @Cautions See the FMan Controller spec and design document for more information. ++*//***************************************************************************/ ++ ++#ifndef __FM_PORT_DSAR_H_ ++#define __FM_PORT_DSAR_H_ ++ ++#define DSAR_GETSER_MASK 0xFF0000FF ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response VLAN-IPv4 Binding Table (for ARP/ICMPv4) ++ Refer to the FMan Controller spec for more details. ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ uint32_t ipv4Addr; /*!< 32 bit IPv4 Address. */ ++ uint16_t vlanId; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */ ++ /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */ ++ uint16_t reserved; ++} _PackedType t_DsarArpBindingEntry; ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response Address Resolution Protocol Statistics Descriptor ++ Refer to the FMan Controller spec for more details. ++ 0x00 INVAL_CNT Invalid ARP IPv4-Ethernet counter ++ 0x04 ECHO_CNT Echo counter ++ 0x08 CD_CNT Conflict Detection counter ++ 0x0C AR_CNT Auto-Response counter ++ 0x10 RATM_CNT Replies Addressed To Me counter ++ 0x14 UKOP_CNT Unknown Operation counter ++ 0x18 NMTP_CNT Not my TPA counter ++ 0x1C NMVLAN_CNT Not My VLAN counter ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ uint32_t invalCnt; /**< Invalid ARP IPv4-Ethernet counter. */ ++ uint32_t echoCnt; /**< Echo counter. */ ++ uint32_t cdCnt; /**< Conflict Detection counter. */ ++ uint32_t arCnt; /**< Auto-Response counter. */ ++ uint32_t ratmCnt; /**< Replies Addressed To Me counter. */ ++ uint32_t ukopCnt; /**< Unknown Operation counter. */ ++ uint32_t nmtpCnt; /**< Not my TPA counter. */ ++ uint32_t nmVlanCnt; /**< Not My VLAN counter */ ++} _PackedType t_DsarArpStatistics; ++ ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response Address Resolution Protocol Descriptor ++ 0x0 0-15 Control bits [0-15]. Bit 15 = CDEN. ++ 0x2 0-15 NumOfBindings Number of entries in the binding list. ++ 0x4 0-15 BindingsPointer Bindings Pointer. This points to an IPv4-MAC Addresses Bindings list. ++ 0x6 0-15 ++ 0x8 0-15 StatisticsPointer Statistics Pointer. This field points to the ARP Descriptors statistics data structure. ++ 0xA 0-15 ++ 0xC 0-15 Reserved Reserved. Must be cleared. ++ 0xE 015 ++ ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ uint16_t control; /** Control bits [0-15]. Bit 15 = CDEN */ ++ uint16_t numOfBindings; /**< Number of VLAN-IPv4 */ ++ uint32_t p_Bindings; /**< VLAN-IPv4 Bindings table pointer. */ ++ uint32_t p_Statistics; /**< Statistics Data Structure pointer. */ ++ uint32_t reserved1; /**< Reserved. */ ++} _PackedType t_DsarArpDescriptor; ++ ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response VLAN-IPv4 Binding Table (for ARP/ICMPv4) ++ Refer to the FMan Controller spec for more details. ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ uint32_t ipv4Addr; /*!< 32 bit IPv4 Address. */ ++ uint16_t vlanId; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */ ++ /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */ ++ uint16_t reserved; ++} _PackedType t_DsarIcmpV4BindingEntry; ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response ICMPv4 Statistics Descriptor ++ Refer to the FMan Controller spec for more details. ++ 0x00 INVAL_CNT Invalid ICMPv4 header counter ++ 0x04 NMVLAN_CNT Not My VLAN counter ++ 0x08 NMIP_CNT Not My IP counter ++ 0x0C AR_CNT Auto-Response counter ++ 0x10 CSERR_CNT Checksum Error counter ++ 0x14 Reserved Reserved ++ 0x18 Reserved Reserved ++ 0x1C Reserved Reserved ++ ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ uint32_t invalCnt; /**< Invalid ICMPv4 Echo counter. */ ++ uint32_t nmVlanCnt; /**< Not My VLAN counter */ ++ uint32_t nmIpCnt; /**< Not My IP counter */ ++ uint32_t arCnt; /**< Auto-Response counter */ ++ uint32_t cserrCnt; /**< Checksum Error counter */ ++ uint32_t reserved0; /**< Reserved */ ++ uint32_t reserved1; /**< Reserved */ ++ uint32_t reserved2; /**< Reserved */ ++} _PackedType t_DsarIcmpV4Statistics; ++ ++ ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response ICMPv4 Descriptor ++ 0x0 0-15 Control bits [0-15] ++ 0x2 0-15 NumOfBindings Number of entries in the binding list. ++ 0x4 0-15 BindingsPointer Bindings Pointer. This points to an VLAN-IPv4 Addresses Bindings list. ++ 0x6 0-15 ++ 0x8 0-15 StatisticsPointer Statistics Pointer. This field points to the ICMPv4 statistics data structure. ++ 0xA 0-15 ++ 0xC 0-15 Reserved Reserved. Must be cleared. ++ 0xE 015 ++ ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ uint16_t control; /** Control bits [0-15]. */ ++ uint16_t numOfBindings; /**< Number of VLAN-IPv4 */ ++ uint32_t p_Bindings; /**< VLAN-IPv4 Bindings table pointer. */ ++ uint32_t p_Statistics; /**< Statistics Data Structure pointer. */ ++ uint32_t reserved1; /**< Reserved. */ ++} _PackedType t_DsarIcmpV4Descriptor; ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response VLAN-IPv4 Binding Table (for ARP/ICMPv4) ++ The 4 left-most bits (15:12) of the VlanId parameter are control flags. ++ Flags[3:1] (VlanId[15:13]): Reserved, should be cleared. ++ Flags[0] (VlanId[12]): Temporary address. ++ ? 0 - Assigned IP address. ++ ? 1- Temporary (tentative) IP address. ++ Refer to the FMan Controller spec for more details. ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ uint32_t ipv6Addr[4]; /*!< 3 * 32 bit IPv4 Address. */ ++ uint16_t resFlags:4; /*!< reserved flags. should be cleared */ ++ uint16_t vlanId:12; /*!< 12 bits VLAN ID. */ ++ /*!< This field should be 0x000 for an entry with no VLAN tag or a null VLAN ID. */ ++ uint16_t reserved; ++} _PackedType t_DsarIcmpV6BindingEntry; ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response ICMPv4 Statistics Descriptor ++ Refer to the FMan Controller spec for more details. ++ 0x00 INVAL_CNT Invalid ICMPv4 header counter ++ 0x04 NMVLAN_CNT Not My VLAN counter ++ 0x08 NMIP_CNT Not My IP counter ++ 0x0C AR_CNT Auto-Response counter ++ 0x10 CSERR_CNT Checksum Error counter ++ 0x14 MCAST_CNT Multicast counter ++ 0x18 Reserved Reserved ++ 0x1C Reserved Reserved ++ ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ uint32_t invalCnt; /**< Invalid ICMPv4 Echo counter. */ ++ uint32_t nmVlanCnt; /**< Not My VLAN counter */ ++ uint32_t nmIpCnt; /**< Not My IP counter */ ++ uint32_t arCnt; /**< Auto-Response counter */ ++ uint32_t reserved1; /**< Reserved */ ++ uint32_t reserved2; /**< Reserved */ ++ uint32_t reserved3; /**< Reserved */ ++ uint32_t reserved4; /**< Reserved */ ++} _PackedType t_DsarIcmpV6Statistics; ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response Neighbor Discovery Statistics Descriptor ++ 0x00 INVAL_CNT Invalid Neighbor Discovery message counter ++ 0x04 NMVLAN_CNT Not My VLAN counter ++ 0x08 NMIP_CNT Not My IP counter ++ 0x0C AR_CNT Auto-Response counter ++ 0x10 CSERR_CNT Checksum Error counter ++ 0x14 USADVERT_CNT Unsolicited Neighbor Advertisements counter ++ 0x18 NMMCAST_CNT Not My Multicast group counter ++ 0x1C NSLLA_CNT No Source Link-Layer Address counter. Indicates that there was a match on a Target ++ Address of a packet that its source IP address is a unicast address, but the ICMPv6 ++ Source Link-layer Address option is omitted ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ uint32_t invalCnt; /**< Invalid ICMPv4 Echo counter. */ ++ uint32_t nmVlanCnt; /**< Not My VLAN counter */ ++ uint32_t nmIpCnt; /**< Not My IP counter */ ++ uint32_t arCnt; /**< Auto-Response counter */ ++ uint32_t reserved1; /**< Reserved */ ++ uint32_t usadvertCnt; /**< Unsolicited Neighbor Advertisements counter */ ++ uint32_t nmmcastCnt; /**< Not My Multicast group counter */ ++ uint32_t nsllaCnt; /**< No Source Link-Layer Address counter */ ++} _PackedType t_NdStatistics; ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response ICMPv6 Descriptor ++ 0x0 0-15 Control bits [0-15] ++ 0x2 0-15 NumOfBindings Number of entries in the binding list. ++ 0x4 0-15 BindingsPointer Bindings Pointer. This points to an VLAN-IPv4 Addresses Bindings list. ++ 0x6 0-15 ++ 0x8 0-15 StatisticsPointer Statistics Pointer. This field points to the ICMPv4 statistics data structure. ++ 0xA 0-15 ++ 0xC 0-15 Reserved Reserved. Must be cleared. ++ 0xE 015 ++ ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ uint16_t control; /** Control bits [0-15]. */ ++ uint16_t numOfBindings; /**< Number of VLAN-IPv6 */ ++ uint32_t p_Bindings; /**< VLAN-IPv4 Bindings table pointer. */ ++ uint32_t p_Statistics; /**< Statistics Data Structure pointer. */ ++ uint32_t reserved1; /**< Reserved. */ ++} _PackedType t_DsarIcmpV6Descriptor; ++ ++ ++/**************************************************************************//** ++ @Description Internet Control Message Protocol (ICMPv6) Echo message header ++ The fields names are taken from RFC 4443. ++*//***************************************************************************/ ++/* 0 1 2 3 */ ++/* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 */ ++/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ ++/* | Type | Code | Checksum | */ ++/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ ++/* | Identifier | Sequence Number | */ ++/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ ++/* | Data ... */ ++/* +-+-+-+-+- */ ++typedef _Packed struct ++{ ++ uint8_t type; ++ uint8_t code; ++ uint16_t checksum; ++ uint16_t identifier; ++ uint16_t sequenceNumber; ++} _PackedType t_IcmpV6EchoHdr; ++ ++/**************************************************************************//** ++ @Description Internet Control Message Protocol (ICMPv6) ++ Neighbor Solicitation/Advertisement header ++ The fields names are taken from RFC 4861. ++ The R/S/O fields are valid for Neighbor Advertisement only ++*//***************************************************************************/ ++/* 0 1 2 3 ++ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * | Type | Code | Checksum | ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * |R|S|O| Reserved | ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * | | ++ * + + ++ * | | ++ * + Target Address + ++ * | | ++ * + + ++ * | | ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * | Options ... ++ * +-+-+-+-+-+-+-+-+-+-+-+- ++ * ++ * Options Format: ++ * 0 1 2 3 ++ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * | Type | Length | Link-Layer Address ... | ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ * | Link-Layer Address | ++ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++*/ ++typedef _Packed struct ++{ ++ uint8_t type; ++ uint8_t code; ++ uint16_t checksum; ++ uint32_t router:1; ++ uint32_t solicited:1; ++ uint32_t override:1; ++ uint32_t reserved:29; ++ uint32_t targetAddr[4]; ++ uint8_t optionType; ++ uint8_t optionLength; ++ uint8_t linkLayerAddr[6]; ++} _PackedType t_IcmpV6NdHdr; ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response ICMPv6 Descriptor ++ 0x0 0-15 Control bits [0-15] ++ 0x2 0-15 NumOfBindings Number of entries in the binding list. ++ 0x4 0-15 BindingsPointer Bindings Pointer. This points to an VLAN-IPv4 Addresses Bindings list. ++ 0x6 0-15 ++ 0x8 0-15 StatisticsPointer Statistics Pointer. This field points to the ICMPv4 statistics data structure. ++ 0xA 0-15 ++ 0xC 0-15 Reserved Reserved. Must be cleared. ++ 0xE 015 ++ ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ uint16_t control; /** Control bits [0-15]. */ ++ uint16_t numOfBindings; /**< Number of VLAN-IPv6 */ ++ uint32_t p_Bindings; /**< VLAN-IPv4 Bindings table pointer. */ ++ uint32_t p_Statistics; /**< Statistics Data Structure pointer. */ ++ uint32_t solicitedAddr; /**< Solicited Node Multicast Group Address */ ++} _PackedType t_DsarNdDescriptor; ++ ++/**************************************************************************//** ++ at Description Deep Sleep Auto Response SNMP OIDs table entry ++ ++*//***************************************************************************/ ++typedef struct { ++ uint16_t oidSize; /**< Size in octets of the OID. */ ++ uint16_t resSize; /**< Size in octets of the value that is attached to the OID. */ ++ uint32_t p_Oid; /**< Pointer to the OID. OID is encoded in BER but type and length are excluded. */ ++ uint32_t resValOrPtr; /**< Value (for up to 4 octets) or pointer to the Value. Encoded in BER. */ ++ uint32_t reserved; ++} t_OidsTblEntry; ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response SNMP IPv4 Addresses Table Entry ++ Refer to the FMan Controller spec for more details. ++*//***************************************************************************/ ++typedef struct ++{ ++ uint32_t ipv4Addr; /*!< 32 bit IPv4 Address. */ ++ uint16_t vlanId; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */ ++ /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */ ++ uint16_t reserved; ++} t_DsarSnmpIpv4AddrTblEntry; ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response SNMP IPv6 Addresses Table Entry ++ Refer to the FMan Controller spec for more details. ++*//***************************************************************************/ ++#pragma pack(push,1) ++typedef struct ++{ ++ uint32_t ipv6Addr[4]; /*!< 4 * 32 bit IPv6 Address. */ ++ uint16_t vlanId; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */ ++ /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */ ++ uint16_t reserved; ++} t_DsarSnmpIpv6AddrTblEntry; ++#pragma pack(pop) ++ ++/**************************************************************************//** ++ at Description Deep Sleep Auto Response SNMP statistics table ++ ++*//***************************************************************************/ ++typedef struct { ++ uint32_t snmpErrCnt; /**< Counts SNMP errors (wrong version, BER encoding, format). */ ++ uint32_t snmpCommunityErrCnt; /**< Counts messages that were dropped due to insufficient permission. */ ++ uint32_t snmpTotalDiscardCnt; /**< Counts any message that was dropped. */ ++ uint32_t snmpGetReqCnt; /**< Counts the number of get-request messages */ ++ uint32_t snmpGetNextReqCnt; /**< Counts the number of get-next-request messages */ ++} t_DsarSnmpStatistics; ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response SNMP Descriptor ++ ++*//***************************************************************************/ ++typedef struct ++{ ++ uint16_t control; /**< Control bits [0-15]. */ ++ uint16_t maxSnmpMsgLength; /**< Maximal allowed SNMP message length. */ ++ uint16_t numOfIpv4Addresses; /**< Number of entries in IPv4 addresses table. */ ++ uint16_t numOfIpv6Addresses; /**< Number of entries in IPv6 addresses table. */ ++ uint32_t p_Ipv4AddrTbl; /**< Pointer to IPv4 addresses table. */ ++ uint32_t p_Ipv6AddrTbl; /**< Pointer to IPv6 addresses table. */ ++ uint32_t p_RdOnlyCommunityStr; /**< Pointer to the Read Only Community String. */ ++ uint32_t p_RdWrCommunityStr; /**< Pointer to the Read Write Community String. */ ++ uint32_t p_OidsTbl; /**< Pointer to OIDs table. */ ++ uint32_t oidsTblSize; /**< Number of entries in OIDs table. */ ++ uint32_t p_Statistics; /**< Pointer to SNMP statistics table. */ ++} t_DsarSnmpDescriptor; ++ ++/**************************************************************************//** ++ at Description Deep Sleep Auto Response (Common) Statistics ++ ++*//***************************************************************************/ ++typedef _Packed struct { ++ uint32_t dsarDiscarded; ++ uint32_t dsarErrDiscarded; ++ uint32_t dsarFragDiscarded; ++ uint32_t dsarTunnelDiscarded; ++ uint32_t dsarArpDiscarded; ++ uint32_t dsarIpDiscarded; ++ uint32_t dsarTcpDiscarded; ++ uint32_t dsarUdpDiscarded; ++ uint32_t dsarIcmpV6ChecksumErr; /* ICMPv6 Checksum Error counter */ ++ uint32_t dsarIcmpV6OtherType; /* ICMPv6 'Other' type (not Echo or Neighbor Solicitaion/Advertisement counter */ ++ uint32_t dsarIcmpV4OtherType; /* ICMPv4 'Other' type (not Echo) counter */ ++} _PackedType t_ArStatistics; ++ ++ ++/**************************************************************************//** ++ at Description Deep Sleep Auto Response TCP/UDP port filter table entry ++ ++*//***************************************************************************/ ++typedef _Packed struct { ++ uint32_t Ports; ++ uint32_t PortsMask; ++} _PackedType t_PortTblEntry; ++ ++ ++ ++/**************************************************************************//** ++ at Description Deep Sleep Auto Response Common Parameters Descriptor ++ ++*//***************************************************************************/ ++typedef _Packed struct { ++ uint8_t arTxPort; /* 0x00 0-7 Auto Response Transmit Port number */ ++ uint8_t controlBits; /* 0x00 8-15 Auto Response control bits */ ++ uint16_t res1; /* 0x00 16-31 Reserved */ ++ uint32_t activeHPNIA; /* 0x04 0-31 Active mode Hardware Parser NIA */ ++ uint16_t snmpPort; /* 0x08 0-15 SNMP Port. */ ++ uint8_t macStationAddr[6]; /* 0x08 16-31 and 0x0C 0-31 MAC Station Address */ ++ uint8_t res2; /* 0x10 0-7 Reserved */ ++ uint8_t filterControl; /* 0x10 8-15 Filtering Control Bits. */ ++ uint16_t tcpControlPass; /* 0x10 16-31 TCP control pass flags */ ++ uint8_t ipProtocolTblSize; /* 0x14 0-7 IP Protocol Table Size. */ ++ uint8_t udpPortTblSize; /* 0x14 8-15 UDP Port Table Size. */ ++ uint8_t tcpPortTblSize; /* 0x14 16-23 TCP Port Table Size. */ ++ uint8_t res3; /* 0x14 24-31 Reserved */ ++ uint32_t p_IpProtocolFiltTbl; /* 0x18 0-31 Pointer to IP Protocol Filter Table */ ++ uint32_t p_UdpPortFiltTbl; /* 0x1C 0-31 Pointer to UDP Port Filter Table */ ++ uint32_t p_TcpPortFiltTbl; /* 0x20 0-31 Pointer to TCP Port Filter Table */ ++ uint32_t res4; /* 0x24 Reserved */ ++ uint32_t p_ArpDescriptor; /* 0x28 0-31 ARP Descriptor Pointer. */ ++ uint32_t p_NdDescriptor; /* 0x2C 0-31 Neighbor Discovery Descriptor. */ ++ uint32_t p_IcmpV4Descriptor; /* 0x30 0-31 ICMPv4 Descriptor pointer. */ ++ uint32_t p_IcmpV6Descriptor; /* 0x34 0-31 ICMPv6 Descriptor pointer. */ ++ uint32_t p_SnmpDescriptor; /* 0x38 0-31 SNMP Descriptor pointer. */ ++ uint32_t p_ArStats; /* 0x3C 0-31 Pointer to Auto Response Statistics */ ++} _PackedType t_ArCommonDesc; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/* t_ArCommonDesc.filterControl bits */ ++#define IP_PROT_TBL_PASS_MASK 0x08 ++#define UDP_PORT_TBL_PASS_MASK 0x04 ++#define TCP_PORT_TBL_PASS_MASK 0x02 ++ ++/* Offset of TCF flags within TCP packet */ ++#define TCP_FLAGS_OFFSET 12 ++ ++ ++#endif /* __FM_PORT_DSAR_H_ */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fm_port_im.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fm_port_im.c +new file mode 100644 +index 0000000..8de8f5f +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fm_port_im.c +@@ -0,0 +1,753 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_port_im.c ++ ++ @Description FM Port Independent-Mode ... ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "string_ext.h" ++#include "error_ext.h" ++#include "memcpy_ext.h" ++#include "fm_muram_ext.h" ++ ++#include "fm_port.h" ++ ++ ++#define TX_CONF_STATUS_UNSENT 0x1 ++ ++ ++typedef enum e_TxConfType ++{ ++ e_TX_CONF_TYPE_CHECK = 0 /**< check if all the buffers were touched by the muxator, no confirmation callback */ ++ ,e_TX_CONF_TYPE_CALLBACK = 1 /**< confirm to user all the available sent buffers */ ++ ,e_TX_CONF_TYPE_FLUSH = 3 /**< confirm all buffers plus the unsent one with an appropriate status */ ++} e_TxConfType; ++ ++ ++static void ImException(t_Handle h_FmPort, uint32_t event) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ ASSERT_COND(((event & (IM_EV_RX | IM_EV_BSY)) && FmIsMaster(p_FmPort->h_Fm)) || ++ !FmIsMaster(p_FmPort->h_Fm)); ++ ++ if (event & IM_EV_RX) ++ FmPortImRx(p_FmPort); ++ if ((event & IM_EV_BSY) && p_FmPort->f_Exception) ++ p_FmPort->f_Exception(p_FmPort->h_App, e_FM_PORT_EXCEPTION_IM_BUSY); ++} ++ ++ ++static t_Error TxConf(t_FmPort *p_FmPort, e_TxConfType confType) ++{ ++ t_Error retVal = E_BUSY; ++ uint32_t bdStatus; ++ uint16_t savedStartBdId, confBdId; ++ ++ ASSERT_COND(p_FmPort); ++ ++ /* ++ if (confType==e_TX_CONF_TYPE_CHECK) ++ return (WfqEntryIsQueueEmpty(p_FmPort->im.h_WfqEntry) ? E_OK : E_BUSY); ++ */ ++ ++ confBdId = savedStartBdId = p_FmPort->im.currBdId; ++ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(confBdId)); ++ ++ /* If R bit is set, we don't enter, or we break. ++ we run till we get to R, or complete the loop */ ++ while ((!(bdStatus & BD_R_E) || (confType == e_TX_CONF_TYPE_FLUSH)) && (retVal != E_OK)) ++ { ++ if (confType & e_TX_CONF_TYPE_CALLBACK) /* if it is confirmation with user callbacks */ ++ BD_STATUS_AND_LENGTH_SET(BD_GET(confBdId), 0); ++ ++ /* case 1: R bit is 0 and Length is set -> confirm! */ ++ if ((confType & e_TX_CONF_TYPE_CALLBACK) && (bdStatus & BD_LENGTH_MASK)) ++ { ++ if (p_FmPort->im.f_TxConf) ++ { ++ if ((confType == e_TX_CONF_TYPE_FLUSH) && (bdStatus & BD_R_E)) ++ p_FmPort->im.f_TxConf(p_FmPort->h_App, ++ BdBufferGet(XX_PhysToVirt, BD_GET(confBdId)), ++ TX_CONF_STATUS_UNSENT, ++ p_FmPort->im.p_BdShadow[confBdId]); ++ else ++ p_FmPort->im.f_TxConf(p_FmPort->h_App, ++ BdBufferGet(XX_PhysToVirt, BD_GET(confBdId)), ++ 0, ++ p_FmPort->im.p_BdShadow[confBdId]); ++ } ++ } ++ /* case 2: R bit is 0 and Length is 0 -> not used yet, nop! */ ++ ++ confBdId = GetNextBdId(p_FmPort, confBdId); ++ if (confBdId == savedStartBdId) ++ retVal = E_OK; ++ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(confBdId)); ++ } ++ ++ return retVal; ++} ++ ++t_Error FmPortImEnable(t_FmPort *p_FmPort) ++{ ++ uint32_t tmpReg = GET_UINT32(p_FmPort->im.p_FmPortImPram->mode); ++ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, (uint32_t)(tmpReg & ~IM_MODE_GRC_STP)); ++ return E_OK; ++} ++ ++t_Error FmPortImDisable(t_FmPort *p_FmPort) ++{ ++ uint32_t tmpReg = GET_UINT32(p_FmPort->im.p_FmPortImPram->mode); ++ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, (uint32_t)(tmpReg | IM_MODE_GRC_STP)); ++ return E_OK; ++} ++ ++t_Error FmPortImRx(t_FmPort *p_FmPort) ++{ ++ t_Handle h_CurrUserPriv, h_NewUserPriv; ++ uint32_t bdStatus; ++ volatile uint8_t buffPos; ++ uint16_t length; ++ uint16_t errors; ++ uint8_t *p_CurData, *p_Data; ++ uint32_t flags; ++ ++ ASSERT_COND(p_FmPort); ++ ++ flags = XX_LockIntrSpinlock(p_FmPort->h_Spinlock); ++ if (p_FmPort->lock) ++ { ++ XX_UnlockIntrSpinlock(p_FmPort->h_Spinlock, flags); ++ return E_OK; ++ } ++ p_FmPort->lock = TRUE; ++ XX_UnlockIntrSpinlock(p_FmPort->h_Spinlock, flags); ++ ++ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId)); ++ ++ while (!(bdStatus & BD_R_E)) /* while there is data in the Rx BD */ ++ { ++ if ((p_Data = p_FmPort->im.rxPool.f_GetBuf(p_FmPort->im.rxPool.h_BufferPool, &h_NewUserPriv)) == NULL) ++ { ++ p_FmPort->lock = FALSE; ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Data buffer")); ++ } ++ ++ if (p_FmPort->im.firstBdOfFrameId == IM_ILEGAL_BD_ID) ++ p_FmPort->im.firstBdOfFrameId = p_FmPort->im.currBdId; ++ ++ p_CurData = BdBufferGet(p_FmPort->im.rxPool.f_PhysToVirt, BD_GET(p_FmPort->im.currBdId)); ++ h_CurrUserPriv = p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId]; ++ length = (uint16_t)((bdStatus & BD_L) ? ++ ((bdStatus & BD_LENGTH_MASK) - p_FmPort->im.rxFrameAccumLength): ++ (bdStatus & BD_LENGTH_MASK)); ++ p_FmPort->im.rxFrameAccumLength += length; ++ ++ /* determine whether buffer is first, last, first and last (single */ ++ /* buffer frame) or middle (not first and not last) */ ++ buffPos = (uint8_t)((p_FmPort->im.currBdId == p_FmPort->im.firstBdOfFrameId) ? ++ ((bdStatus & BD_L) ? SINGLE_BUF : FIRST_BUF) : ++ ((bdStatus & BD_L) ? LAST_BUF : MIDDLE_BUF)); ++ ++ if (bdStatus & BD_L) ++ { ++ p_FmPort->im.rxFrameAccumLength = 0; ++ p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID; ++ } ++ ++ BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, BD_GET(p_FmPort->im.currBdId), p_Data); ++ ++ BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), BD_R_E); ++ ++ errors = (uint16_t)((bdStatus & BD_RX_ERRORS) >> 16); ++ p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId] = h_NewUserPriv; ++ ++ p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId); ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.offsetOut, (uint16_t)(p_FmPort->im.currBdId<<4)); ++ /* Pass the buffer if one of the conditions is true: ++ - There are no errors ++ - This is a part of a larger frame ( the application has already received some buffers ) */ ++ if ((buffPos != SINGLE_BUF) || !errors) ++ { ++ if (p_FmPort->im.f_RxStore(p_FmPort->h_App, ++ p_CurData, ++ length, ++ errors, ++ buffPos, ++ h_CurrUserPriv) == e_RX_STORE_RESPONSE_PAUSE) ++ break; ++ } ++ else if (p_FmPort->im.rxPool.f_PutBuf(p_FmPort->im.rxPool.h_BufferPool, ++ p_CurData, ++ h_CurrUserPriv)) ++ { ++ p_FmPort->lock = FALSE; ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Failed freeing data buffer")); ++ } ++ ++ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId)); ++ } ++ p_FmPort->lock = FALSE; ++ return E_OK; ++} ++ ++void FmPortConfigIM (t_FmPort *p_FmPort, t_FmPortParams *p_FmPortParams) ++{ ++ ASSERT_COND(p_FmPort); ++ ++ SANITY_CHECK_RETURN(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->im.h_FmMuram = p_FmPortParams->specificParams.imRxTxParams.h_FmMuram; ++ p_FmPort->p_FmPortDriverParam->liodnOffset = p_FmPortParams->specificParams.imRxTxParams.liodnOffset; ++ p_FmPort->im.dataMemId = p_FmPortParams->specificParams.imRxTxParams.dataMemId; ++ p_FmPort->im.dataMemAttributes = p_FmPortParams->specificParams.imRxTxParams.dataMemAttributes; ++ ++ p_FmPort->im.fwExtStructsMemId = DEFAULT_PORT_ImfwExtStructsMemId; ++ p_FmPort->im.fwExtStructsMemAttr = DEFAULT_PORT_ImfwExtStructsMemAttr; ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ p_FmPort->im.rxPool.h_BufferPool = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.h_BufferPool; ++ p_FmPort->im.rxPool.f_GetBuf = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_GetBuf; ++ p_FmPort->im.rxPool.f_PutBuf = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_PutBuf; ++ p_FmPort->im.rxPool.bufferSize = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.bufferSize; ++ p_FmPort->im.rxPool.f_PhysToVirt = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_PhysToVirt; ++ if (!p_FmPort->im.rxPool.f_PhysToVirt) ++ p_FmPort->im.rxPool.f_PhysToVirt = XX_PhysToVirt; ++ p_FmPort->im.rxPool.f_VirtToPhys = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_VirtToPhys; ++ if (!p_FmPort->im.rxPool.f_VirtToPhys) ++ p_FmPort->im.rxPool.f_VirtToPhys = XX_VirtToPhys; ++ p_FmPort->im.f_RxStore = p_FmPortParams->specificParams.imRxTxParams.f_RxStore; ++ ++ p_FmPort->im.mrblr = 0x8000; ++ while (p_FmPort->im.mrblr) ++ { ++ if (p_FmPort->im.rxPool.bufferSize & p_FmPort->im.mrblr) ++ break; ++ p_FmPort->im.mrblr >>= 1; ++ } ++ if (p_FmPort->im.mrblr != p_FmPort->im.rxPool.bufferSize) ++ DBG(WARNING, ("Max-Rx-Buffer-Length set to %d", p_FmPort->im.mrblr)); ++ p_FmPort->im.bdRingSize = DEFAULT_PORT_rxBdRingLength; ++ p_FmPort->exceptions = DEFAULT_PORT_exception; ++ if (FmIsMaster(p_FmPort->h_Fm)) ++ p_FmPort->polling = FALSE; ++ else ++ p_FmPort->polling = TRUE; ++ p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ; ++ } ++ else ++ { ++ p_FmPort->im.f_TxConf = p_FmPortParams->specificParams.imRxTxParams.f_TxConf; ++ ++ p_FmPort->im.bdRingSize = DEFAULT_PORT_txBdRingLength; ++ } ++} ++ ++t_Error FmPortImCheckInitParameters(t_FmPort *p_FmPort) ++{ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_TX) && ++ (p_FmPort->portType != e_FM_PORT_TYPE_TX_10G)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ if (!POWER_OF_2(p_FmPort->im.mrblr)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("max Rx buffer length must be power of 2!!!")); ++ if (p_FmPort->im.mrblr < 256) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("max Rx buffer length must at least 256!!!")); ++ if (p_FmPort->p_FmPortDriverParam->liodnOffset & ~FM_LIODN_OFFSET_MASK) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("liodnOffset is larger than %d", FM_LIODN_OFFSET_MASK+1)); ++ } ++ ++ return E_OK; ++} ++ ++t_Error FmPortImInit(t_FmPort *p_FmPort) ++{ ++ t_FmImBd *p_Bd=NULL; ++ t_Handle h_BufContext; ++ uint64_t tmpPhysBase; ++ uint16_t log2Num; ++ uint8_t *p_Data/*, *p_Tmp*/; ++ int i; ++ t_Error err; ++ uint16_t tmpReg16; ++ uint32_t tmpReg32; ++ ++ ASSERT_COND(p_FmPort); ++ ++ p_FmPort->im.p_FmPortImPram = ++ (t_FmPortImPram *)FM_MURAM_AllocMem(p_FmPort->im.h_FmMuram, sizeof(t_FmPortImPram), IM_PRAM_ALIGN); ++ if (!p_FmPort->im.p_FmPortImPram) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Parameter-RAM!!!")); ++ WRITE_BLOCK(p_FmPort->im.p_FmPortImPram, 0, sizeof(t_FmPortImPram)); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ p_FmPort->im.p_BdRing = ++ (t_FmImBd *)XX_MallocSmart((uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize), ++ p_FmPort->im.fwExtStructsMemId, ++ 4); ++ if (!p_FmPort->im.p_BdRing) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD ring!!!")); ++ IOMemSet32(p_FmPort->im.p_BdRing, 0, (uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize)); ++ ++ p_FmPort->im.p_BdShadow = (t_Handle *)XX_Malloc((uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize)); ++ if (!p_FmPort->im.p_BdShadow) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD shadow!!!")); ++ memset(p_FmPort->im.p_BdShadow, 0, (uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize)); ++ ++ /* Initialize the Rx-BD ring */ ++ for (i=0; iim.bdRingSize; i++) ++ { ++ p_Bd = BD_GET(i); ++ BD_STATUS_AND_LENGTH_SET (p_Bd, BD_R_E); ++ ++ if ((p_Data = p_FmPort->im.rxPool.f_GetBuf(p_FmPort->im.rxPool.h_BufferPool, &h_BufContext)) == NULL) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Data buffer")); ++ BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, p_Bd, p_Data); ++ p_FmPort->im.p_BdShadow[i] = h_BufContext; ++ } ++ ++ if ((p_FmPort->im.dataMemAttributes & MEMORY_ATTR_CACHEABLE) || ++ (p_FmPort->im.fwExtStructsMemAttr & MEMORY_ATTR_CACHEABLE)) ++ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_GBL | IM_MODE_SET_BO(2)); ++ else ++ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_SET_BO(2)); ++ ++ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->rxQdPtr, ++ (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) - ++ p_FmPort->fmMuramPhysBaseAddr + 0x20)); ++ ++ LOG2((uint64_t)p_FmPort->im.mrblr, log2Num); ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->mrblr, log2Num); ++ ++ /* Initialize Rx QD */ ++ tmpPhysBase = (uint64_t)(XX_VirtToPhys(p_FmPort->im.p_BdRing)); ++ SET_ADDR(&p_FmPort->im.p_FmPortImPram->rxQd.bdRingBase, tmpPhysBase); ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.bdRingSize, (uint16_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize)); ++ ++ /* Update the IM PRAM address in the BMI */ ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfqid, ++ (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) - ++ p_FmPort->fmMuramPhysBaseAddr)); ++ if (!p_FmPort->polling || p_FmPort->exceptions) ++ { ++ /* Allocate, configure and register interrupts */ ++ err = FmAllocFmanCtrlEventReg(p_FmPort->h_Fm, &p_FmPort->fmanCtrlEventId); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ ASSERT_COND(!(p_FmPort->fmanCtrlEventId & ~IM_RXQD_FPMEVT_SEL_MASK)); ++ tmpReg16 = (uint16_t)(p_FmPort->fmanCtrlEventId & IM_RXQD_FPMEVT_SEL_MASK); ++ tmpReg32 = 0; ++ ++ if (p_FmPort->exceptions & IM_EV_BSY) ++ { ++ tmpReg16 |= IM_RXQD_BSYINTM; ++ tmpReg32 |= IM_EV_BSY; ++ } ++ if (!p_FmPort->polling) ++ { ++ tmpReg16 |= IM_RXQD_RXFINTM; ++ tmpReg32 |= IM_EV_RX; ++ } ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16); ++ ++ FmRegisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, ImException , (t_Handle)p_FmPort); ++ ++ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32); ++ } ++ else ++ p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ; ++ } ++ else ++ { ++ p_FmPort->im.p_BdRing = (t_FmImBd *)XX_MallocSmart((uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize), p_FmPort->im.fwExtStructsMemId, 4); ++ if (!p_FmPort->im.p_BdRing) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Tx BD ring!!!")); ++ IOMemSet32(p_FmPort->im.p_BdRing, 0, (uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize)); ++ ++ p_FmPort->im.p_BdShadow = (t_Handle *)XX_Malloc((uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize)); ++ if (!p_FmPort->im.p_BdShadow) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD shadow!!!")); ++ memset(p_FmPort->im.p_BdShadow, 0, (uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize)); ++ p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID; ++ ++ if ((p_FmPort->im.dataMemAttributes & MEMORY_ATTR_CACHEABLE) || ++ (p_FmPort->im.fwExtStructsMemAttr & MEMORY_ATTR_CACHEABLE)) ++ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_GBL | IM_MODE_SET_BO(2)); ++ else ++ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_SET_BO(2)); ++ ++ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->txQdPtr, ++ (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) - ++ p_FmPort->fmMuramPhysBaseAddr + 0x40)); ++ ++ /* Initialize Tx QD */ ++ tmpPhysBase = (uint64_t)(XX_VirtToPhys(p_FmPort->im.p_BdRing)); ++ SET_ADDR(&p_FmPort->im.p_FmPortImPram->txQd.bdRingBase, tmpPhysBase); ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->txQd.bdRingSize, (uint16_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize)); ++ ++ /* Update the IM PRAM address in the BMI */ ++ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfqid, ++ (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) - ++ p_FmPort->fmMuramPhysBaseAddr)); ++ } ++ ++ ++ return E_OK; ++} ++ ++void FmPortImFree(t_FmPort *p_FmPort) ++{ ++ uint32_t bdStatus; ++ uint8_t *p_CurData; ++ ++ ASSERT_COND(p_FmPort); ++ ASSERT_COND(p_FmPort->im.p_FmPortImPram); ++ ++ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || ++ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ if (!p_FmPort->polling || p_FmPort->exceptions) ++ { ++ /* Deallocate and unregister interrupts */ ++ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, 0); ++ ++ FmFreeFmanCtrlEventReg(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId); ++ ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, 0); ++ ++ FmUnregisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId); ++ } ++ /* Try first clean what has received */ ++ FmPortImRx(p_FmPort); ++ ++ /* Now, get rid of the the empty buffer! */ ++ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId)); ++ ++ while (bdStatus & BD_R_E) /* while there is data in the Rx BD */ ++ { ++ p_CurData = BdBufferGet(p_FmPort->im.rxPool.f_PhysToVirt, BD_GET(p_FmPort->im.currBdId)); ++ ++ BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, BD_GET(p_FmPort->im.currBdId), NULL); ++ BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), 0); ++ ++ p_FmPort->im.rxPool.f_PutBuf(p_FmPort->im.rxPool.h_BufferPool, ++ p_CurData, ++ p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId]); ++ ++ p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId); ++ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId)); ++ } ++ } ++ else ++ TxConf(p_FmPort, e_TX_CONF_TYPE_FLUSH); ++ ++ FM_MURAM_FreeMem(p_FmPort->im.h_FmMuram, p_FmPort->im.p_FmPortImPram); ++ ++ if (p_FmPort->im.p_BdShadow) ++ XX_Free(p_FmPort->im.p_BdShadow); ++ ++ if (p_FmPort->im.p_BdRing) ++ XX_FreeSmart(p_FmPort->im.p_BdRing); ++} ++ ++ ++t_Error FM_PORT_ConfigIMMaxRxBufLength(t_Handle h_FmPort, uint16_t newVal) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->im.mrblr = newVal; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigIMRxBdRingLength(t_Handle h_FmPort, uint16_t newVal) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->im.bdRingSize = newVal; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigIMTxBdRingLength(t_Handle h_FmPort, uint16_t newVal) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->im.bdRingSize = newVal; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigIMFmanCtrlExternalStructsMemory(t_Handle h_FmPort, ++ uint8_t memId, ++ uint32_t memAttributes) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ p_FmPort->im.fwExtStructsMemId = memId; ++ p_FmPort->im.fwExtStructsMemAttr = memAttributes; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ConfigIMPolling(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Available for Rx ports only")); ++ ++ if (!FmIsMaster(p_FmPort->h_Fm)) ++ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Available on master-partition only;" ++ "in guest-partitions, IM is always in polling!")); ++ ++ p_FmPort->polling = TRUE; ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_SetIMExceptions(t_Handle h_FmPort, e_FmPortExceptions exception, bool enable) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ t_Error err; ++ uint16_t tmpReg16; ++ uint32_t tmpReg32; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ if (exception == e_FM_PORT_EXCEPTION_IM_BUSY) ++ { ++ if (enable) ++ { ++ p_FmPort->exceptions |= IM_EV_BSY; ++ if (p_FmPort->fmanCtrlEventId == (uint8_t)NO_IRQ) ++ { ++ /* Allocate, configure and register interrupts */ ++ err = FmAllocFmanCtrlEventReg(p_FmPort->h_Fm, &p_FmPort->fmanCtrlEventId); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ASSERT_COND(!(p_FmPort->fmanCtrlEventId & ~IM_RXQD_FPMEVT_SEL_MASK)); ++ ++ FmRegisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, ImException, (t_Handle)p_FmPort); ++ tmpReg16 = (uint16_t)((p_FmPort->fmanCtrlEventId & IM_RXQD_FPMEVT_SEL_MASK) | IM_RXQD_BSYINTM); ++ tmpReg32 = IM_EV_BSY; ++ } ++ else ++ { ++ tmpReg16 = (uint16_t)(GET_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen) | IM_RXQD_BSYINTM); ++ tmpReg32 = FmGetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId) | IM_EV_BSY; ++ } ++ ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16); ++ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32); ++ } ++ else ++ { ++ p_FmPort->exceptions &= ~IM_EV_BSY; ++ if (!p_FmPort->exceptions && p_FmPort->polling) ++ { ++ FmFreeFmanCtrlEventReg(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId); ++ FmUnregisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId); ++ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, 0); ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, 0); ++ p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ; ++ } ++ else ++ { ++ tmpReg16 = (uint16_t)(GET_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen) & ~IM_RXQD_BSYINTM); ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16); ++ tmpReg32 = FmGetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId) & ~IM_EV_BSY; ++ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32); ++ } ++ } ++ } ++ else ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Invalid exception.")); ++ ++ return E_OK; ++} ++ ++t_Error FM_PORT_ImTx( t_Handle h_FmPort, ++ uint8_t *p_Data, ++ uint16_t length, ++ bool lastBuffer, ++ t_Handle h_BufContext) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ uint16_t nextBdId; ++ uint32_t bdStatus, nextBdStatus; ++ bool firstBuffer; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId)); ++ nextBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId); ++ nextBdStatus = BD_STATUS_AND_LENGTH(BD_GET(nextBdId)); ++ ++ if (!(bdStatus & BD_R_E) && !(nextBdStatus & BD_R_E)) ++ { ++ /* Confirm the current BD - BD is available */ ++ if ((bdStatus & BD_LENGTH_MASK) && (p_FmPort->im.f_TxConf)) ++ p_FmPort->im.f_TxConf (p_FmPort->h_App, ++ BdBufferGet(XX_PhysToVirt, BD_GET(p_FmPort->im.currBdId)), ++ 0, ++ p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId]); ++ ++ bdStatus = length; ++ ++ /* if this is the first BD of a frame */ ++ if (p_FmPort->im.firstBdOfFrameId == IM_ILEGAL_BD_ID) ++ { ++ firstBuffer = TRUE; ++ p_FmPort->im.txFirstBdStatus = (bdStatus | BD_R_E); ++ ++ if (!lastBuffer) ++ p_FmPort->im.firstBdOfFrameId = p_FmPort->im.currBdId; ++ } ++ else ++ firstBuffer = FALSE; ++ ++ BdBufferSet(XX_VirtToPhys, BD_GET(p_FmPort->im.currBdId), p_Data); ++ p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId] = h_BufContext; ++ ++ /* deal with last */ ++ if (lastBuffer) ++ { ++ /* if single buffer frame */ ++ if (firstBuffer) ++ BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), p_FmPort->im.txFirstBdStatus | BD_L); ++ else ++ { ++ /* Set the last BD of the frame */ ++ BD_STATUS_AND_LENGTH_SET (BD_GET(p_FmPort->im.currBdId), (bdStatus | BD_R_E | BD_L)); ++ /* Set the first BD of the frame */ ++ BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.firstBdOfFrameId), p_FmPort->im.txFirstBdStatus); ++ p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID; ++ } ++ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->txQd.offsetIn, (uint16_t)(GetNextBdId(p_FmPort, p_FmPort->im.currBdId)<<4)); ++ } ++ else if (!firstBuffer) /* mid frame buffer */ ++ BD_STATUS_AND_LENGTH_SET (BD_GET(p_FmPort->im.currBdId), bdStatus | BD_R_E); ++ ++ p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId); ++ } ++ else ++ { ++ /* Discard current frame. Return error. */ ++ if (p_FmPort->im.firstBdOfFrameId != IM_ILEGAL_BD_ID) ++ { ++ /* Error: No free BD */ ++ /* Response: Discard current frame. Return error. */ ++ uint16_t cleanBdId = p_FmPort->im.firstBdOfFrameId; ++ ++ ASSERT_COND(p_FmPort->im.firstBdOfFrameId != p_FmPort->im.currBdId); ++ ++ /* Since firstInFrame is not NULL, one buffer at least has already been ++ inserted into the BD ring. Using do-while covers the situation of a ++ frame spanned throughout the whole Tx BD ring (p_CleanBd is incremented ++ prior to testing whether or not it's equal to TxBd). */ ++ do ++ { ++ BD_STATUS_AND_LENGTH_SET(BD_GET(cleanBdId), 0); ++ /* Advance BD pointer */ ++ cleanBdId = GetNextBdId(p_FmPort, cleanBdId); ++ } while (cleanBdId != p_FmPort->im.currBdId); ++ ++ p_FmPort->im.currBdId = cleanBdId; ++ p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID; ++ } ++ ++ return ERROR_CODE(E_FULL); ++ } ++ ++ return E_OK; ++} ++ ++void FM_PORT_ImTxConf(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ TxConf(p_FmPort, e_TX_CONF_TYPE_CALLBACK); ++} ++ ++t_Error FM_PORT_ImRx(t_Handle h_FmPort) ++{ ++ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE); ++ ++ return FmPortImRx(p_FmPort); ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fman_port.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fman_port.c +new file mode 100755 +index 0000000..60acbf3 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Port/fman_port.c +@@ -0,0 +1,1568 @@ ++/* ++ * Copyright 2008-2012 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 "common/general.h" ++ ++#include "fman_common.h" ++#include "fsl_fman_port.h" ++ ++ ++/* problem Eyal: the following should not be here*/ ++#define NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME 0x00000028 ++ ++static uint32_t get_no_pcd_nia_bmi_ac_enc_frame(struct fman_port_cfg *cfg) ++{ ++ if (cfg->errata_A006675) ++ return NIA_ENG_FM_CTL | ++ NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME; ++ else ++ return NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME; ++} ++ ++static int init_bmi_rx(struct fman_port *port, ++ struct fman_port_cfg *cfg, ++ struct fman_port_params *params) ++{ ++ struct fman_port_rx_bmi_regs *regs = &port->bmi_regs->rx; ++ uint32_t tmp; ++ ++ /* Rx Configuration register */ ++ tmp = 0; ++ if (port->im_en) ++ tmp |= BMI_PORT_CFG_IM; ++ else if (cfg->discard_override) ++ tmp |= BMI_PORT_CFG_FDOVR; ++ iowrite32be(tmp, ®s->fmbm_rcfg); ++ ++ /* DMA attributes */ ++ tmp = (uint32_t)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT; ++ if (cfg->dma_ic_stash_on) ++ tmp |= BMI_DMA_ATTR_IC_STASH_ON; ++ if (cfg->dma_header_stash_on) ++ tmp |= BMI_DMA_ATTR_HDR_STASH_ON; ++ if (cfg->dma_sg_stash_on) ++ tmp |= BMI_DMA_ATTR_SG_STASH_ON; ++ if (cfg->dma_write_optimize) ++ tmp |= BMI_DMA_ATTR_WRITE_OPTIMIZE; ++ iowrite32be(tmp, ®s->fmbm_rda); ++ ++ /* Rx FIFO parameters */ ++ tmp = (cfg->rx_pri_elevation / FMAN_PORT_BMI_FIFO_UNITS - 1) << ++ BMI_RX_FIFO_PRI_ELEVATION_SHIFT; ++ tmp |= cfg->rx_fifo_thr / FMAN_PORT_BMI_FIFO_UNITS - 1; ++ iowrite32be(tmp, ®s->fmbm_rfp); ++ ++ if (cfg->excessive_threshold_register) ++ /* always allow access to the extra resources */ ++ iowrite32be(BMI_RX_FIFO_THRESHOLD_ETHE, ®s->fmbm_reth); ++ ++ /* Frame end data */ ++ tmp = (uint32_t)cfg->checksum_bytes_ignore << ++ BMI_RX_FRAME_END_CS_IGNORE_SHIFT; ++ tmp |= (uint32_t)cfg->rx_cut_end_bytes << ++ BMI_RX_FRAME_END_CUT_SHIFT; ++ if (cfg->errata_A006320) ++ tmp &= 0xffe0ffff; ++ iowrite32be(tmp, ®s->fmbm_rfed); ++ ++ /* Internal context parameters */ ++ tmp = ((uint32_t)cfg->ic_ext_offset / FMAN_PORT_IC_OFFSET_UNITS) << ++ BMI_IC_TO_EXT_SHIFT; ++ tmp |= ((uint32_t)cfg->ic_int_offset / FMAN_PORT_IC_OFFSET_UNITS) << ++ BMI_IC_FROM_INT_SHIFT; ++ tmp |= cfg->ic_size / FMAN_PORT_IC_OFFSET_UNITS; ++ iowrite32be(tmp, ®s->fmbm_ricp); ++ ++ /* Internal buffer offset */ ++ tmp = ((uint32_t)cfg->int_buf_start_margin / FMAN_PORT_IC_OFFSET_UNITS) ++ << BMI_INT_BUF_MARG_SHIFT; ++ iowrite32be(tmp, ®s->fmbm_rim); ++ ++ /* External buffer margins */ ++ if (!port->im_en) ++ { ++ tmp = (uint32_t)cfg->ext_buf_start_margin << ++ BMI_EXT_BUF_MARG_START_SHIFT; ++ tmp |= (uint32_t)cfg->ext_buf_end_margin; ++ if (cfg->fmbm_rebm_has_sgd && cfg->no_scatter_gather) ++ tmp |= BMI_SG_DISABLE; ++ iowrite32be(tmp, ®s->fmbm_rebm); ++ } ++ ++ /* Frame attributes */ ++ tmp = BMI_CMD_RX_MR_DEF; ++ if (!port->im_en) ++ { ++ tmp |= BMI_CMD_ATTR_ORDER; ++ tmp |= (uint32_t)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT; ++ if (cfg->sync_req) ++ tmp |= BMI_CMD_ATTR_SYNC; ++ } ++ iowrite32be(tmp, ®s->fmbm_rfca); ++ ++ /* NIA */ ++ if (port->im_en) ++ tmp = NIA_ENG_FM_CTL | NIA_FM_CTL_AC_IND_MODE_RX; ++ else ++ { ++ tmp = (uint32_t)cfg->rx_fd_bits << BMI_NEXT_ENG_FD_BITS_SHIFT; ++ tmp |= get_no_pcd_nia_bmi_ac_enc_frame(cfg); ++ } ++ iowrite32be(tmp, ®s->fmbm_rfne); ++ ++ /* Enqueue NIA */ ++ iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR, ®s->fmbm_rfene); ++ ++ /* Default/error queues */ ++ if (!port->im_en) ++ { ++ iowrite32be((params->dflt_fqid & 0x00FFFFFF), ®s->fmbm_rfqid); ++ iowrite32be((params->err_fqid & 0x00FFFFFF), ®s->fmbm_refqid); ++ } ++ ++ /* Discard/error masks */ ++ iowrite32be(params->discard_mask, ®s->fmbm_rfsdm); ++ iowrite32be(params->err_mask, ®s->fmbm_rfsem); ++ ++ /* Statistics counters */ ++ tmp = 0; ++ if (cfg->stats_counters_enable) ++ tmp = BMI_COUNTERS_EN; ++ iowrite32be(tmp, ®s->fmbm_rstc); ++ ++ /* Performance counters */ ++ fman_port_set_perf_cnt_params(port, &cfg->perf_cnt_params); ++ tmp = 0; ++ if (cfg->perf_counters_enable) ++ tmp = BMI_COUNTERS_EN; ++ iowrite32be(tmp, ®s->fmbm_rpc); ++ ++ return 0; ++} ++ ++static int init_bmi_tx(struct fman_port *port, ++ struct fman_port_cfg *cfg, ++ struct fman_port_params *params) ++{ ++ struct fman_port_tx_bmi_regs *regs = &port->bmi_regs->tx; ++ uint32_t tmp; ++ ++ /* Tx Configuration register */ ++ tmp = 0; ++ if (port->im_en) ++ tmp |= BMI_PORT_CFG_IM; ++ iowrite32be(tmp, ®s->fmbm_tcfg); ++ ++ /* DMA attributes */ ++ tmp = (uint32_t)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT; ++ if (cfg->dma_ic_stash_on) ++ tmp |= BMI_DMA_ATTR_IC_STASH_ON; ++ if (cfg->dma_header_stash_on) ++ tmp |= BMI_DMA_ATTR_HDR_STASH_ON; ++ if (cfg->dma_sg_stash_on) ++ tmp |= BMI_DMA_ATTR_SG_STASH_ON; ++ iowrite32be(tmp, ®s->fmbm_tda); ++ ++ /* Tx FIFO parameters */ ++ tmp = (cfg->tx_fifo_min_level / FMAN_PORT_BMI_FIFO_UNITS) << ++ BMI_TX_FIFO_MIN_FILL_SHIFT; ++ tmp |= ((uint32_t)cfg->tx_fifo_deq_pipeline_depth - 1) << ++ BMI_FIFO_PIPELINE_DEPTH_SHIFT; ++ tmp |= (uint32_t)(cfg->tx_fifo_low_comf_level / ++ FMAN_PORT_BMI_FIFO_UNITS - 1); ++ iowrite32be(tmp, ®s->fmbm_tfp); ++ ++ /* Frame end data */ ++ tmp = (uint32_t)cfg->checksum_bytes_ignore << ++ BMI_FRAME_END_CS_IGNORE_SHIFT; ++ iowrite32be(tmp, ®s->fmbm_tfed); ++ ++ /* Internal context parameters */ ++ if (!port->im_en) ++ { ++ tmp = ((uint32_t)cfg->ic_ext_offset / FMAN_PORT_IC_OFFSET_UNITS) << ++ BMI_IC_TO_EXT_SHIFT; ++ tmp |= ((uint32_t)cfg->ic_int_offset / FMAN_PORT_IC_OFFSET_UNITS) << ++ BMI_IC_FROM_INT_SHIFT; ++ tmp |= cfg->ic_size / FMAN_PORT_IC_OFFSET_UNITS; ++ iowrite32be(tmp, ®s->fmbm_ticp); ++ } ++ /* Frame attributes */ ++ tmp = BMI_CMD_TX_MR_DEF; ++ if (port->im_en) ++ tmp |= BMI_CMD_MR_DEAS; ++ else ++ { ++ tmp |= BMI_CMD_ATTR_ORDER; ++ tmp |= (uint32_t)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT; ++ } ++ iowrite32be(tmp, ®s->fmbm_tfca); ++ ++ /* Dequeue NIA + enqueue NIA */ ++ if (port->im_en) ++ { ++ iowrite32be(NIA_ENG_FM_CTL | NIA_FM_CTL_AC_IND_MODE_TX, ®s->fmbm_tfdne); ++ iowrite32be(NIA_ENG_FM_CTL | NIA_FM_CTL_AC_IND_MODE_TX, ®s->fmbm_tfene); ++ } ++ else ++ { ++ iowrite32be(NIA_ENG_QMI_DEQ, ®s->fmbm_tfdne); ++ iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR, ®s->fmbm_tfene); ++ if (cfg->fmbm_tfne_has_features) ++ iowrite32be(!params->dflt_fqid ? ++ BMI_EBD_EN | NIA_BMI_AC_FETCH_ALL_FRAME : ++ NIA_BMI_AC_FETCH_ALL_FRAME, ®s->fmbm_tfne); ++ if (!params->dflt_fqid && params->dont_release_buf) ++ { ++ iowrite32be(0x00FFFFFF, ®s->fmbm_tcfqid); ++ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE, ®s->fmbm_tfene); ++ if (cfg->fmbm_tfne_has_features) ++ iowrite32be(ioread32be(®s->fmbm_tfne) & ~BMI_EBD_EN, ®s->fmbm_tfne); ++ } ++ } ++ ++ /* Confirmation/error queues */ ++ if (!port->im_en) ++ { ++ if (params->dflt_fqid || !params->dont_release_buf) ++ iowrite32be(params->dflt_fqid & 0x00FFFFFF, ®s->fmbm_tcfqid); ++ iowrite32be((params->err_fqid & 0x00FFFFFF), ®s->fmbm_tefqid); ++ } ++ /* Statistics counters */ ++ tmp = 0; ++ if (cfg->stats_counters_enable) ++ tmp = BMI_COUNTERS_EN; ++ iowrite32be(tmp, ®s->fmbm_tstc); ++ ++ /* Performance counters */ ++ fman_port_set_perf_cnt_params(port, &cfg->perf_cnt_params); ++ tmp = 0; ++ if (cfg->perf_counters_enable) ++ tmp = BMI_COUNTERS_EN; ++ iowrite32be(tmp, ®s->fmbm_tpc); ++ ++ return 0; ++} ++ ++static int init_bmi_oh(struct fman_port *port, ++ struct fman_port_cfg *cfg, ++ struct fman_port_params *params) ++{ ++ struct fman_port_oh_bmi_regs *regs = &port->bmi_regs->oh; ++ uint32_t tmp; ++ ++ /* OP Configuration register */ ++ tmp = 0; ++ if (cfg->discard_override) ++ tmp |= BMI_PORT_CFG_FDOVR; ++ iowrite32be(tmp, ®s->fmbm_ocfg); ++ ++ /* DMA attributes */ ++ tmp = (uint32_t)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT; ++ if (cfg->dma_ic_stash_on) ++ tmp |= BMI_DMA_ATTR_IC_STASH_ON; ++ if (cfg->dma_header_stash_on) ++ tmp |= BMI_DMA_ATTR_HDR_STASH_ON; ++ if (cfg->dma_sg_stash_on) ++ tmp |= BMI_DMA_ATTR_SG_STASH_ON; ++ if (cfg->dma_write_optimize) ++ tmp |= BMI_DMA_ATTR_WRITE_OPTIMIZE; ++ iowrite32be(tmp, ®s->fmbm_oda); ++ ++ /* Tx FIFO parameters */ ++ tmp = ((uint32_t)cfg->tx_fifo_deq_pipeline_depth - 1) << ++ BMI_FIFO_PIPELINE_DEPTH_SHIFT; ++ iowrite32be(tmp, ®s->fmbm_ofp); ++ ++ /* Internal context parameters */ ++ tmp = ((uint32_t)cfg->ic_ext_offset / FMAN_PORT_IC_OFFSET_UNITS) << ++ BMI_IC_TO_EXT_SHIFT; ++ tmp |= ((uint32_t)cfg->ic_int_offset / FMAN_PORT_IC_OFFSET_UNITS) << ++ BMI_IC_FROM_INT_SHIFT; ++ tmp |= cfg->ic_size / FMAN_PORT_IC_OFFSET_UNITS; ++ iowrite32be(tmp, ®s->fmbm_oicp); ++ ++ /* Frame attributes */ ++ tmp = BMI_CMD_OP_MR_DEF; ++ tmp |= (uint32_t)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT; ++ if (cfg->sync_req) ++ tmp |= BMI_CMD_ATTR_SYNC; ++ if (port->type == E_FMAN_PORT_TYPE_OP) ++ tmp |= BMI_CMD_ATTR_ORDER; ++ iowrite32be(tmp, ®s->fmbm_ofca); ++ ++ /* Internal buffer offset */ ++ tmp = ((uint32_t)cfg->int_buf_start_margin / FMAN_PORT_IC_OFFSET_UNITS) ++ << BMI_INT_BUF_MARG_SHIFT; ++ iowrite32be(tmp, ®s->fmbm_oim); ++ ++ /* Dequeue NIA */ ++ iowrite32be(NIA_ENG_QMI_DEQ, ®s->fmbm_ofdne); ++ ++ /* NIA and Enqueue NIA */ ++ if (port->type == E_FMAN_PORT_TYPE_HC) { ++ iowrite32be(NIA_ENG_FM_CTL | NIA_FM_CTL_AC_HC, ++ ®s->fmbm_ofne); ++ iowrite32be(NIA_ENG_QMI_ENQ, ®s->fmbm_ofene); ++ } else { ++ iowrite32be(get_no_pcd_nia_bmi_ac_enc_frame(cfg), ++ ®s->fmbm_ofne); ++ iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR, ++ ®s->fmbm_ofene); ++ } ++ ++ /* Default/error queues */ ++ iowrite32be((params->dflt_fqid & 0x00FFFFFF), ®s->fmbm_ofqid); ++ iowrite32be((params->err_fqid & 0x00FFFFFF), ®s->fmbm_oefqid); ++ ++ /* Discard/error masks */ ++ if (port->type == E_FMAN_PORT_TYPE_OP) { ++ iowrite32be(params->discard_mask, ®s->fmbm_ofsdm); ++ iowrite32be(params->err_mask, ®s->fmbm_ofsem); ++ } ++ ++ /* Statistics counters */ ++ tmp = 0; ++ if (cfg->stats_counters_enable) ++ tmp = BMI_COUNTERS_EN; ++ iowrite32be(tmp, ®s->fmbm_ostc); ++ ++ /* Performance counters */ ++ fman_port_set_perf_cnt_params(port, &cfg->perf_cnt_params); ++ tmp = 0; ++ if (cfg->perf_counters_enable) ++ tmp = BMI_COUNTERS_EN; ++ iowrite32be(tmp, ®s->fmbm_opc); ++ ++ return 0; ++} ++ ++static int init_qmi(struct fman_port *port, ++ struct fman_port_cfg *cfg, ++ struct fman_port_params *params) ++{ ++ struct fman_port_qmi_regs *regs = port->qmi_regs; ++ uint32_t tmp; ++ ++ tmp = 0; ++ if (cfg->queue_counters_enable) ++ tmp |= QMI_PORT_CFG_EN_COUNTERS; ++ iowrite32be(tmp, ®s->fmqm_pnc); ++ ++ /* Rx port configuration */ ++ if ((port->type == E_FMAN_PORT_TYPE_RX) || ++ (port->type == E_FMAN_PORT_TYPE_RX_10G)) { ++ /* Enqueue NIA */ ++ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_RELEASE, ®s->fmqm_pnen); ++ return 0; ++ } ++ ++ /* Continue with Tx and O/H port configuration */ ++ if ((port->type == E_FMAN_PORT_TYPE_TX) || ++ (port->type == E_FMAN_PORT_TYPE_TX_10G)) { ++ /* Enqueue NIA */ ++ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE, ++ ®s->fmqm_pnen); ++ /* Dequeue NIA */ ++ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX, ®s->fmqm_pndn); ++ } else { ++ /* Enqueue NIA */ ++ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_RELEASE, ®s->fmqm_pnen); ++ /* Dequeue NIA */ ++ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_FETCH, ®s->fmqm_pndn); ++ } ++ ++ /* Dequeue Configuration register */ ++ tmp = 0; ++ if (cfg->deq_high_pri) ++ tmp |= QMI_DEQ_CFG_PRI; ++ ++ switch (cfg->deq_type) { ++ case E_FMAN_PORT_DEQ_BY_PRI: ++ tmp |= QMI_DEQ_CFG_TYPE1; ++ break; ++ case E_FMAN_PORT_DEQ_ACTIVE_FQ: ++ tmp |= QMI_DEQ_CFG_TYPE2; ++ break; ++ case E_FMAN_PORT_DEQ_ACTIVE_FQ_NO_ICS: ++ tmp |= QMI_DEQ_CFG_TYPE3; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (cfg->qmi_deq_options_support) { ++ if ((port->type == E_FMAN_PORT_TYPE_HC) && ++ (cfg->deq_prefetch_opt != E_FMAN_PORT_DEQ_NO_PREFETCH)) ++ return -EINVAL; ++ ++ switch (cfg->deq_prefetch_opt) { ++ case E_FMAN_PORT_DEQ_NO_PREFETCH: ++ break; ++ case E_FMAN_PORT_DEQ_PART_PREFETCH: ++ tmp |= QMI_DEQ_CFG_PREFETCH_PARTIAL; ++ break; ++ case E_FMAN_PORT_DEQ_FULL_PREFETCH: ++ tmp |= QMI_DEQ_CFG_PREFETCH_FULL; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ tmp |= (uint32_t)(params->deq_sp & QMI_DEQ_CFG_SP_MASK) << ++ QMI_DEQ_CFG_SP_SHIFT; ++ tmp |= cfg->deq_byte_cnt; ++ iowrite32be(tmp, ®s->fmqm_pndc); ++ ++ return 0; ++} ++ ++static void get_rx_stats_reg(struct fman_port *port, ++ enum fman_port_stats_counters counter, ++ uint32_t **stats_reg) ++{ ++ struct fman_port_rx_bmi_regs *regs = &port->bmi_regs->rx; ++ ++ switch (counter) { ++ case E_FMAN_PORT_STATS_CNT_FRAME: ++ *stats_reg = ®s->fmbm_rfrc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_DISCARD: ++ *stats_reg = ®s->fmbm_rfdc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_DEALLOC_BUF: ++ *stats_reg = ®s->fmbm_rbdc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_RX_BAD_FRAME: ++ *stats_reg = ®s->fmbm_rfbc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_RX_LARGE_FRAME: ++ *stats_reg = ®s->fmbm_rlfc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_RX_OUT_OF_BUF: ++ *stats_reg = ®s->fmbm_rodc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_FILTERED_FRAME: ++ *stats_reg = ®s->fmbm_rffc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_DMA_ERR: ++ *stats_reg = ®s->fmbm_rfldec; ++ break; ++ default: ++ *stats_reg = NULL; ++ } ++} ++ ++static void get_tx_stats_reg(struct fman_port *port, ++ enum fman_port_stats_counters counter, ++ uint32_t **stats_reg) ++{ ++ struct fman_port_tx_bmi_regs *regs = &port->bmi_regs->tx; ++ ++ switch (counter) { ++ case E_FMAN_PORT_STATS_CNT_FRAME: ++ *stats_reg = ®s->fmbm_tfrc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_DISCARD: ++ *stats_reg = ®s->fmbm_tfdc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_DEALLOC_BUF: ++ *stats_reg = ®s->fmbm_tbdc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_LEN_ERR: ++ *stats_reg = ®s->fmbm_tfledc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_UNSUPPORTED_FORMAT: ++ *stats_reg = ®s->fmbm_tfufdc; ++ break; ++ default: ++ *stats_reg = NULL; ++ } ++} ++ ++static void get_oh_stats_reg(struct fman_port *port, ++ enum fman_port_stats_counters counter, ++ uint32_t **stats_reg) ++{ ++ struct fman_port_oh_bmi_regs *regs = &port->bmi_regs->oh; ++ ++ switch (counter) { ++ case E_FMAN_PORT_STATS_CNT_FRAME: ++ *stats_reg = ®s->fmbm_ofrc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_DISCARD: ++ *stats_reg = ®s->fmbm_ofdc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_DEALLOC_BUF: ++ *stats_reg = ®s->fmbm_obdc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_FILTERED_FRAME: ++ *stats_reg = ®s->fmbm_offc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_DMA_ERR: ++ *stats_reg = ®s->fmbm_ofldec; ++ break; ++ case E_FMAN_PORT_STATS_CNT_LEN_ERR: ++ *stats_reg = ®s->fmbm_ofledc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_UNSUPPORTED_FORMAT: ++ *stats_reg = ®s->fmbm_ofufdc; ++ break; ++ case E_FMAN_PORT_STATS_CNT_WRED_DISCARD: ++ *stats_reg = ®s->fmbm_ofwdc; ++ break; ++ default: ++ *stats_reg = NULL; ++ } ++} ++ ++static void get_rx_perf_reg(struct fman_port *port, ++ enum fman_port_perf_counters counter, ++ uint32_t **perf_reg) ++{ ++ struct fman_port_rx_bmi_regs *regs = &port->bmi_regs->rx; ++ ++ switch (counter) { ++ case E_FMAN_PORT_PERF_CNT_CYCLE: ++ *perf_reg = ®s->fmbm_rccn; ++ break; ++ case E_FMAN_PORT_PERF_CNT_TASK_UTIL: ++ *perf_reg = ®s->fmbm_rtuc; ++ break; ++ case E_FMAN_PORT_PERF_CNT_QUEUE_UTIL: ++ *perf_reg = ®s->fmbm_rrquc; ++ break; ++ case E_FMAN_PORT_PERF_CNT_DMA_UTIL: ++ *perf_reg = ®s->fmbm_rduc; ++ break; ++ case E_FMAN_PORT_PERF_CNT_FIFO_UTIL: ++ *perf_reg = ®s->fmbm_rfuc; ++ break; ++ case E_FMAN_PORT_PERF_CNT_RX_PAUSE: ++ *perf_reg = ®s->fmbm_rpac; ++ break; ++ default: ++ *perf_reg = NULL; ++ } ++} ++ ++static void get_tx_perf_reg(struct fman_port *port, ++ enum fman_port_perf_counters counter, ++ uint32_t **perf_reg) ++{ ++ struct fman_port_tx_bmi_regs *regs = &port->bmi_regs->tx; ++ ++ switch (counter) { ++ case E_FMAN_PORT_PERF_CNT_CYCLE: ++ *perf_reg = ®s->fmbm_tccn; ++ break; ++ case E_FMAN_PORT_PERF_CNT_TASK_UTIL: ++ *perf_reg = ®s->fmbm_ttuc; ++ break; ++ case E_FMAN_PORT_PERF_CNT_QUEUE_UTIL: ++ *perf_reg = ®s->fmbm_ttcquc; ++ break; ++ case E_FMAN_PORT_PERF_CNT_DMA_UTIL: ++ *perf_reg = ®s->fmbm_tduc; ++ break; ++ case E_FMAN_PORT_PERF_CNT_FIFO_UTIL: ++ *perf_reg = ®s->fmbm_tfuc; ++ break; ++ default: ++ *perf_reg = NULL; ++ } ++} ++ ++static void get_oh_perf_reg(struct fman_port *port, ++ enum fman_port_perf_counters counter, ++ uint32_t **perf_reg) ++{ ++ struct fman_port_oh_bmi_regs *regs = &port->bmi_regs->oh; ++ ++ switch (counter) { ++ case E_FMAN_PORT_PERF_CNT_CYCLE: ++ *perf_reg = ®s->fmbm_occn; ++ break; ++ case E_FMAN_PORT_PERF_CNT_TASK_UTIL: ++ *perf_reg = ®s->fmbm_otuc; ++ break; ++ case E_FMAN_PORT_PERF_CNT_DMA_UTIL: ++ *perf_reg = ®s->fmbm_oduc; ++ break; ++ case E_FMAN_PORT_PERF_CNT_FIFO_UTIL: ++ *perf_reg = ®s->fmbm_ofuc; ++ break; ++ default: ++ *perf_reg = NULL; ++ } ++} ++ ++static void get_qmi_counter_reg(struct fman_port *port, ++ enum fman_port_qmi_counters counter, ++ uint32_t **queue_reg) ++{ ++ struct fman_port_qmi_regs *regs = port->qmi_regs; ++ ++ switch (counter) { ++ case E_FMAN_PORT_ENQ_TOTAL: ++ *queue_reg = ®s->fmqm_pnetfc; ++ break; ++ case E_FMAN_PORT_DEQ_TOTAL: ++ if ((port->type == E_FMAN_PORT_TYPE_RX) || ++ (port->type == E_FMAN_PORT_TYPE_RX_10G)) ++ /* Counter not available for Rx ports */ ++ *queue_reg = NULL; ++ else ++ *queue_reg = ®s->fmqm_pndtfc; ++ break; ++ case E_FMAN_PORT_DEQ_FROM_DFLT: ++ if ((port->type == E_FMAN_PORT_TYPE_RX) || ++ (port->type == E_FMAN_PORT_TYPE_RX_10G)) ++ /* Counter not available for Rx ports */ ++ *queue_reg = NULL; ++ else ++ *queue_reg = ®s->fmqm_pndfdc; ++ break; ++ case E_FMAN_PORT_DEQ_CONFIRM: ++ if ((port->type == E_FMAN_PORT_TYPE_RX) || ++ (port->type == E_FMAN_PORT_TYPE_RX_10G)) ++ /* Counter not available for Rx ports */ ++ *queue_reg = NULL; ++ else ++ *queue_reg = ®s->fmqm_pndcc; ++ break; ++ default: ++ *queue_reg = NULL; ++ } ++} ++ ++void fman_port_defconfig(struct fman_port_cfg *cfg, enum fman_port_type type) ++{ ++ cfg->dma_swap_data = E_FMAN_PORT_DMA_NO_SWAP; ++ cfg->dma_ic_stash_on = FALSE; ++ cfg->dma_header_stash_on = FALSE; ++ cfg->dma_sg_stash_on = FALSE; ++ cfg->dma_write_optimize = TRUE; ++ cfg->color = E_FMAN_PORT_COLOR_GREEN; ++ cfg->discard_override = FALSE; ++ cfg->checksum_bytes_ignore = 0; ++ cfg->rx_cut_end_bytes = 4; ++ cfg->rx_pri_elevation = ((0x3FF + 1) * FMAN_PORT_BMI_FIFO_UNITS); ++ cfg->rx_fifo_thr = ((0x3FF + 1) * FMAN_PORT_BMI_FIFO_UNITS); ++ cfg->rx_fd_bits = 0; ++ cfg->ic_ext_offset = 0; ++ cfg->ic_int_offset = 0; ++ cfg->ic_size = 0; ++ cfg->int_buf_start_margin = 0; ++ cfg->ext_buf_start_margin = 0; ++ cfg->ext_buf_end_margin = 0; ++ cfg->tx_fifo_min_level = 0; ++ cfg->tx_fifo_low_comf_level = (5 * KILOBYTE); ++ cfg->stats_counters_enable = TRUE; ++ cfg->perf_counters_enable = TRUE; ++ cfg->deq_type = E_FMAN_PORT_DEQ_BY_PRI; ++ ++ if (type == E_FMAN_PORT_TYPE_HC) { ++ cfg->sync_req = FALSE; ++ cfg->deq_prefetch_opt = E_FMAN_PORT_DEQ_NO_PREFETCH; ++ } else { ++ cfg->sync_req = TRUE; ++ cfg->deq_prefetch_opt = E_FMAN_PORT_DEQ_FULL_PREFETCH; ++ } ++ ++ if (type == E_FMAN_PORT_TYPE_TX_10G) { ++ cfg->tx_fifo_deq_pipeline_depth = 4; ++ cfg->deq_high_pri = TRUE; ++ cfg->deq_byte_cnt = 0x1400; ++ } else { ++ if ((type == E_FMAN_PORT_TYPE_HC) || ++ (type == E_FMAN_PORT_TYPE_OP)) ++ cfg->tx_fifo_deq_pipeline_depth = 2; ++ else ++ cfg->tx_fifo_deq_pipeline_depth = 1; ++ ++ cfg->deq_high_pri = FALSE; ++ cfg->deq_byte_cnt = 0x400; ++ } ++ cfg->no_scatter_gather = DEFAULT_FMAN_SP_NO_SCATTER_GATHER; ++} ++ ++static uint8_t fman_port_find_bpool(struct fman_port *port, uint8_t bpid) ++{ ++ uint32_t *bp_reg, tmp; ++ uint8_t i, id; ++ ++ /* Find the pool */ ++ bp_reg = port->bmi_regs->rx.fmbm_ebmpi; ++ for (i = 0; ++ (i < port->ext_pools_num && (i < FMAN_PORT_MAX_EXT_POOLS_NUM)); ++ i++) { ++ tmp = ioread32be(&bp_reg[i]); ++ id = (uint8_t)((tmp & BMI_EXT_BUF_POOL_ID_MASK) >> ++ BMI_EXT_BUF_POOL_ID_SHIFT); ++ ++ if (id == bpid) ++ break; ++ } ++ ++ return i; ++} ++ ++int fman_port_init(struct fman_port *port, ++ struct fman_port_cfg *cfg, ++ struct fman_port_params *params) ++{ ++ int err; ++ ++ /* Init BMI registers */ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ err = init_bmi_rx(port, cfg, params); ++ break; ++ case E_FMAN_PORT_TYPE_TX: ++ case E_FMAN_PORT_TYPE_TX_10G: ++ err = init_bmi_tx(port, cfg, params); ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ case E_FMAN_PORT_TYPE_HC: ++ err = init_bmi_oh(port, cfg, params); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (err) ++ return err; ++ ++ /* Init QMI registers */ ++ if (!port->im_en) ++ { ++ err = init_qmi(port, cfg, params); ++ return err; ++ } ++ return 0; ++} ++ ++int fman_port_enable(struct fman_port *port) ++{ ++ uint32_t *bmi_cfg_reg, tmp; ++ bool rx_port; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ bmi_cfg_reg = &port->bmi_regs->rx.fmbm_rcfg; ++ rx_port = TRUE; ++ break; ++ case E_FMAN_PORT_TYPE_TX: ++ case E_FMAN_PORT_TYPE_TX_10G: ++ bmi_cfg_reg = &port->bmi_regs->tx.fmbm_tcfg; ++ rx_port = FALSE; ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ case E_FMAN_PORT_TYPE_HC: ++ bmi_cfg_reg = &port->bmi_regs->oh.fmbm_ocfg; ++ rx_port = FALSE; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* Enable QMI */ ++ if (!rx_port) { ++ tmp = ioread32be(&port->qmi_regs->fmqm_pnc) | QMI_PORT_CFG_EN; ++ iowrite32be(tmp, &port->qmi_regs->fmqm_pnc); ++ } ++ ++ /* Enable BMI */ ++ tmp = ioread32be(bmi_cfg_reg) | BMI_PORT_CFG_EN; ++ iowrite32be(tmp, bmi_cfg_reg); ++ ++ return 0; ++} ++ ++int fman_port_disable(const struct fman_port *port) ++{ ++ uint32_t *bmi_cfg_reg, *bmi_status_reg, tmp; ++ bool rx_port, failure = FALSE; ++ int count; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ bmi_cfg_reg = &port->bmi_regs->rx.fmbm_rcfg; ++ bmi_status_reg = &port->bmi_regs->rx.fmbm_rst; ++ rx_port = TRUE; ++ break; ++ case E_FMAN_PORT_TYPE_TX: ++ case E_FMAN_PORT_TYPE_TX_10G: ++ bmi_cfg_reg = &port->bmi_regs->tx.fmbm_tcfg; ++ bmi_status_reg = &port->bmi_regs->tx.fmbm_tst; ++ rx_port = FALSE; ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ case E_FMAN_PORT_TYPE_HC: ++ bmi_cfg_reg = &port->bmi_regs->oh.fmbm_ocfg; ++ bmi_status_reg = &port->bmi_regs->oh.fmbm_ost; ++ rx_port = FALSE; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* Disable QMI */ ++ if (!rx_port) { ++ tmp = ioread32be(&port->qmi_regs->fmqm_pnc) & ~QMI_PORT_CFG_EN; ++ iowrite32be(tmp, &port->qmi_regs->fmqm_pnc); ++ ++ /* Wait for QMI to finish FD handling */ ++ count = 100; ++ do { ++ udelay(10); ++ tmp = ioread32be(&port->qmi_regs->fmqm_pns); ++ } while ((tmp & QMI_PORT_STATUS_DEQ_FD_BSY) && --count); ++ ++ if (count == 0) ++ { ++ /* Timeout */ ++ failure = TRUE; ++ } ++ } ++ ++ /* Disable BMI */ ++ tmp = ioread32be(bmi_cfg_reg) & ~BMI_PORT_CFG_EN; ++ iowrite32be(tmp, bmi_cfg_reg); ++ ++ /* Wait for graceful stop end */ ++ count = 500; ++ do { ++ udelay(10); ++ tmp = ioread32be(bmi_status_reg); ++ } while ((tmp & BMI_PORT_STATUS_BSY) && --count); ++ ++ if (count == 0) ++ { ++ /* Timeout */ ++ failure = TRUE; ++ } ++ ++ if (failure) ++ return -EBUSY; ++ ++ return 0; ++} ++ ++int fman_port_set_bpools(const struct fman_port *port, ++ const struct fman_port_bpools *bp) ++{ ++ uint32_t tmp, *bp_reg, *bp_depl_reg; ++ uint8_t i, max_bp_num; ++ bool grp_depl_used = FALSE, rx_port; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ max_bp_num = port->ext_pools_num; ++ rx_port = TRUE; ++ bp_reg = port->bmi_regs->rx.fmbm_ebmpi; ++ bp_depl_reg = &port->bmi_regs->rx.fmbm_mpd; ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ if (port->fm_rev_maj != 4) ++ return -EINVAL; ++ max_bp_num = FMAN_PORT_OBS_EXT_POOLS_NUM; ++ rx_port = FALSE; ++ bp_reg = port->bmi_regs->oh.fmbm_oebmpi; ++ bp_depl_reg = &port->bmi_regs->oh.fmbm_ompd; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (rx_port) { ++ /* Check buffers are provided in ascending order */ ++ for (i = 0; ++ (i < (bp->count-1) && (i < FMAN_PORT_MAX_EXT_POOLS_NUM - 1)); ++ i++) { ++ if (bp->bpool[i].size > bp->bpool[i+1].size) ++ return -EINVAL; ++ } ++ } ++ ++ /* Set up external buffers pools */ ++ for (i = 0; i < bp->count; i++) { ++ tmp = BMI_EXT_BUF_POOL_VALID; ++ tmp |= ((uint32_t)bp->bpool[i].bpid << ++ BMI_EXT_BUF_POOL_ID_SHIFT) & BMI_EXT_BUF_POOL_ID_MASK; ++ ++ if (rx_port) { ++ if (bp->counters_enable) ++ tmp |= BMI_EXT_BUF_POOL_EN_COUNTER; ++ ++ if (bp->bpool[i].is_backup) ++ tmp |= BMI_EXT_BUF_POOL_BACKUP; ++ ++ tmp |= (uint32_t)bp->bpool[i].size; ++ } ++ ++ iowrite32be(tmp, &bp_reg[i]); ++ } ++ ++ /* Clear unused pools */ ++ for (i = bp->count; i < max_bp_num; i++) ++ iowrite32be(0, &bp_reg[i]); ++ ++ /* Pools depletion */ ++ tmp = 0; ++ for (i = 0; i < FMAN_PORT_MAX_EXT_POOLS_NUM; i++) { ++ if (bp->bpool[i].grp_bp_depleted) { ++ grp_depl_used = TRUE; ++ tmp |= 0x80000000 >> i; ++ } ++ ++ if (bp->bpool[i].single_bp_depleted) ++ tmp |= 0x80 >> i; ++ ++ if (bp->bpool[i].pfc_priorities_en) ++ tmp |= 0x0100 << i; ++ } ++ ++ if (grp_depl_used) ++ tmp |= ((uint32_t)bp->grp_bp_depleted_num - 1) << ++ BMI_POOL_DEP_NUM_OF_POOLS_SHIFT; ++ ++ iowrite32be(tmp, bp_depl_reg); ++ return 0; ++} ++ ++int fman_port_set_rate_limiter(struct fman_port *port, ++ struct fman_port_rate_limiter *rate_limiter) ++{ ++ uint32_t *rate_limit_reg, *rate_limit_scale_reg; ++ uint32_t granularity, tmp; ++ uint8_t usec_bit, factor; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_TX: ++ case E_FMAN_PORT_TYPE_TX_10G: ++ rate_limit_reg = &port->bmi_regs->tx.fmbm_trlmt; ++ rate_limit_scale_reg = &port->bmi_regs->tx.fmbm_trlmts; ++ granularity = BMI_RATE_LIMIT_GRAN_TX; ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ rate_limit_reg = &port->bmi_regs->oh.fmbm_orlmt; ++ rate_limit_scale_reg = &port->bmi_regs->oh.fmbm_orlmts; ++ granularity = BMI_RATE_LIMIT_GRAN_OP; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* Factor is per 1 usec count */ ++ factor = 1; ++ usec_bit = rate_limiter->count_1micro_bit; ++ ++ /* If rate limit is too small for an 1usec factor, adjust timestamp ++ * scale and multiply the factor */ ++ while (rate_limiter->rate < (granularity / factor)) { ++ if (usec_bit == 31) ++ /* Can't configure rate limiter - rate is too small */ ++ return -EINVAL; ++ ++ usec_bit++; ++ factor <<= 1; ++ } ++ ++ /* Figure out register value. The "while" above quarantees that ++ * (rate_limiter->rate * factor / granularity) >= 1 */ ++ tmp = (uint32_t)(rate_limiter->rate * factor / granularity - 1); ++ ++ /* Check rate limit isn't too large */ ++ if (tmp >= BMI_RATE_LIMIT_MAX_RATE_IN_GRAN_UNITS) ++ return -EINVAL; ++ ++ /* Check burst size is in allowed range */ ++ if ((rate_limiter->burst_size == 0) || ++ (rate_limiter->burst_size > ++ BMI_RATE_LIMIT_MAX_BURST_SIZE)) ++ return -EINVAL; ++ ++ tmp |= (uint32_t)(rate_limiter->burst_size - 1) << ++ BMI_RATE_LIMIT_MAX_BURST_SHIFT; ++ ++ if ((port->type == E_FMAN_PORT_TYPE_OP) && ++ (port->fm_rev_maj == 4)) { ++ if (rate_limiter->high_burst_size_gran) ++ tmp |= BMI_RATE_LIMIT_HIGH_BURST_SIZE_GRAN; ++ } ++ ++ iowrite32be(tmp, rate_limit_reg); ++ ++ /* Set up rate limiter scale register */ ++ tmp = BMI_RATE_LIMIT_SCALE_EN; ++ tmp |= (31 - (uint32_t)usec_bit) << BMI_RATE_LIMIT_SCALE_TSBS_SHIFT; ++ ++ if ((port->type == E_FMAN_PORT_TYPE_OP) && ++ (port->fm_rev_maj == 4)) ++ tmp |= rate_limiter->rate_factor; ++ ++ iowrite32be(tmp, rate_limit_scale_reg); ++ ++ return 0; ++} ++ ++int fman_port_delete_rate_limiter(struct fman_port *port) ++{ ++ uint32_t *rate_limit_scale_reg; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_TX: ++ case E_FMAN_PORT_TYPE_TX_10G: ++ rate_limit_scale_reg = &port->bmi_regs->tx.fmbm_trlmts; ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ rate_limit_scale_reg = &port->bmi_regs->oh.fmbm_orlmts; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ iowrite32be(0, rate_limit_scale_reg); ++ return 0; ++} ++ ++int fman_port_set_err_mask(struct fman_port *port, uint32_t err_mask) ++{ ++ uint32_t *err_mask_reg; ++ ++ /* Obtain register address */ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ err_mask_reg = &port->bmi_regs->rx.fmbm_rfsem; ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ err_mask_reg = &port->bmi_regs->oh.fmbm_ofsem; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ iowrite32be(err_mask, err_mask_reg); ++ return 0; ++} ++ ++int fman_port_set_discard_mask(struct fman_port *port, uint32_t discard_mask) ++{ ++ uint32_t *discard_mask_reg; ++ ++ /* Obtain register address */ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ discard_mask_reg = &port->bmi_regs->rx.fmbm_rfsdm; ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ discard_mask_reg = &port->bmi_regs->oh.fmbm_ofsdm; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ iowrite32be(discard_mask, discard_mask_reg); ++ return 0; ++} ++ ++int fman_port_modify_rx_fd_bits(struct fman_port *port, ++ uint8_t rx_fd_bits, ++ bool add) ++{ ++ uint32_t tmp; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ tmp = ioread32be(&port->bmi_regs->rx.fmbm_rfne); ++ ++ if (add) ++ tmp |= (uint32_t)rx_fd_bits << BMI_NEXT_ENG_FD_BITS_SHIFT; ++ else ++ tmp &= ~((uint32_t)rx_fd_bits << BMI_NEXT_ENG_FD_BITS_SHIFT); ++ ++ iowrite32be(tmp, &port->bmi_regs->rx.fmbm_rfne); ++ return 0; ++} ++ ++int fman_port_set_perf_cnt_params(struct fman_port *port, ++ struct fman_port_perf_cnt_params *params) ++{ ++ uint32_t *pcp_reg, tmp; ++ ++ /* Obtain register address and check parameters are in range */ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ pcp_reg = &port->bmi_regs->rx.fmbm_rpcp; ++ if ((params->queue_val == 0) || ++ (params->queue_val > MAX_PERFORMANCE_RX_QUEUE_COMP)) ++ return -EINVAL; ++ break; ++ case E_FMAN_PORT_TYPE_TX: ++ case E_FMAN_PORT_TYPE_TX_10G: ++ pcp_reg = &port->bmi_regs->tx.fmbm_tpcp; ++ if ((params->queue_val == 0) || ++ (params->queue_val > MAX_PERFORMANCE_TX_QUEUE_COMP)) ++ return -EINVAL; ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ case E_FMAN_PORT_TYPE_HC: ++ pcp_reg = &port->bmi_regs->oh.fmbm_opcp; ++ if (params->queue_val != 0) ++ return -EINVAL; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if ((params->task_val == 0) || ++ (params->task_val > MAX_PERFORMANCE_TASK_COMP)) ++ return -EINVAL; ++ if ((params->dma_val == 0) || ++ (params->dma_val > MAX_PERFORMANCE_DMA_COMP)) ++ return -EINVAL; ++ if ((params->fifo_val == 0) || ++ ((params->fifo_val / FMAN_PORT_BMI_FIFO_UNITS) > ++ MAX_PERFORMANCE_FIFO_COMP)) ++ return -EINVAL; ++ tmp = (uint32_t)(params->task_val - 1) << ++ BMI_PERFORMANCE_TASK_COMP_SHIFT; ++ tmp |= (uint32_t)(params->dma_val - 1) << ++ BMI_PERFORMANCE_DMA_COMP_SHIFT; ++ tmp |= (uint32_t)(params->fifo_val / FMAN_PORT_BMI_FIFO_UNITS - 1); ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ case E_FMAN_PORT_TYPE_TX: ++ case E_FMAN_PORT_TYPE_TX_10G: ++ tmp |= (uint32_t)(params->queue_val - 1) << ++ BMI_PERFORMANCE_QUEUE_COMP_SHIFT; ++ break; ++ default: ++ break; ++ } ++ ++ ++ iowrite32be(tmp, pcp_reg); ++ return 0; ++} ++ ++int fman_port_set_stats_cnt_mode(struct fman_port *port, bool enable) ++{ ++ uint32_t *stats_reg, tmp; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ stats_reg = &port->bmi_regs->rx.fmbm_rstc; ++ break; ++ case E_FMAN_PORT_TYPE_TX: ++ case E_FMAN_PORT_TYPE_TX_10G: ++ stats_reg = &port->bmi_regs->tx.fmbm_tstc; ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ case E_FMAN_PORT_TYPE_HC: ++ stats_reg = &port->bmi_regs->oh.fmbm_ostc; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ tmp = ioread32be(stats_reg); ++ ++ if (enable) ++ tmp |= BMI_COUNTERS_EN; ++ else ++ tmp &= ~BMI_COUNTERS_EN; ++ ++ iowrite32be(tmp, stats_reg); ++ return 0; ++} ++ ++int fman_port_set_perf_cnt_mode(struct fman_port *port, bool enable) ++{ ++ uint32_t *stats_reg, tmp; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ stats_reg = &port->bmi_regs->rx.fmbm_rpc; ++ break; ++ case E_FMAN_PORT_TYPE_TX: ++ case E_FMAN_PORT_TYPE_TX_10G: ++ stats_reg = &port->bmi_regs->tx.fmbm_tpc; ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ case E_FMAN_PORT_TYPE_HC: ++ stats_reg = &port->bmi_regs->oh.fmbm_opc; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ tmp = ioread32be(stats_reg); ++ ++ if (enable) ++ tmp |= BMI_COUNTERS_EN; ++ else ++ tmp &= ~BMI_COUNTERS_EN; ++ ++ iowrite32be(tmp, stats_reg); ++ return 0; ++} ++ ++int fman_port_set_queue_cnt_mode(struct fman_port *port, bool enable) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(&port->qmi_regs->fmqm_pnc); ++ ++ if (enable) ++ tmp |= QMI_PORT_CFG_EN_COUNTERS; ++ else ++ tmp &= ~QMI_PORT_CFG_EN_COUNTERS; ++ ++ iowrite32be(tmp, &port->qmi_regs->fmqm_pnc); ++ return 0; ++} ++ ++int fman_port_set_bpool_cnt_mode(struct fman_port *port, ++ uint8_t bpid, ++ bool enable) ++{ ++ uint8_t index; ++ uint32_t tmp; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* Find the pool */ ++ index = fman_port_find_bpool(port, bpid); ++ if (index == port->ext_pools_num || index == FMAN_PORT_MAX_EXT_POOLS_NUM) ++ /* Not found */ ++ return -EINVAL; ++ ++ tmp = ioread32be(&port->bmi_regs->rx.fmbm_ebmpi[index]); ++ ++ if (enable) ++ tmp |= BMI_EXT_BUF_POOL_EN_COUNTER; ++ else ++ tmp &= ~BMI_EXT_BUF_POOL_EN_COUNTER; ++ ++ iowrite32be(tmp, &port->bmi_regs->rx.fmbm_ebmpi[index]); ++ return 0; ++} ++ ++uint32_t fman_port_get_stats_counter(struct fman_port *port, ++ enum fman_port_stats_counters counter) ++{ ++ uint32_t *stats_reg, ret_val; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ get_rx_stats_reg(port, counter, &stats_reg); ++ break; ++ case E_FMAN_PORT_TYPE_TX: ++ case E_FMAN_PORT_TYPE_TX_10G: ++ get_tx_stats_reg(port, counter, &stats_reg); ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ case E_FMAN_PORT_TYPE_HC: ++ get_oh_stats_reg(port, counter, &stats_reg); ++ break; ++ default: ++ stats_reg = NULL; ++ } ++ ++ if (stats_reg == NULL) ++ return 0; ++ ++ ret_val = ioread32be(stats_reg); ++ return ret_val; ++} ++ ++void fman_port_set_stats_counter(struct fman_port *port, ++ enum fman_port_stats_counters counter, ++ uint32_t value) ++{ ++ uint32_t *stats_reg; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ get_rx_stats_reg(port, counter, &stats_reg); ++ break; ++ case E_FMAN_PORT_TYPE_TX: ++ case E_FMAN_PORT_TYPE_TX_10G: ++ get_tx_stats_reg(port, counter, &stats_reg); ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ case E_FMAN_PORT_TYPE_HC: ++ get_oh_stats_reg(port, counter, &stats_reg); ++ break; ++ default: ++ stats_reg = NULL; ++ } ++ ++ if (stats_reg == NULL) ++ return; ++ ++ iowrite32be(value, stats_reg); ++} ++ ++uint32_t fman_port_get_perf_counter(struct fman_port *port, ++ enum fman_port_perf_counters counter) ++{ ++ uint32_t *perf_reg, ret_val; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ get_rx_perf_reg(port, counter, &perf_reg); ++ break; ++ case E_FMAN_PORT_TYPE_TX: ++ case E_FMAN_PORT_TYPE_TX_10G: ++ get_tx_perf_reg(port, counter, &perf_reg); ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ case E_FMAN_PORT_TYPE_HC: ++ get_oh_perf_reg(port, counter, &perf_reg); ++ break; ++ default: ++ perf_reg = NULL; ++ } ++ ++ if (perf_reg == NULL) ++ return 0; ++ ++ ret_val = ioread32be(perf_reg); ++ return ret_val; ++} ++ ++void fman_port_set_perf_counter(struct fman_port *port, ++ enum fman_port_perf_counters counter, ++ uint32_t value) ++{ ++ uint32_t *perf_reg; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ get_rx_perf_reg(port, counter, &perf_reg); ++ break; ++ case E_FMAN_PORT_TYPE_TX: ++ case E_FMAN_PORT_TYPE_TX_10G: ++ get_tx_perf_reg(port, counter, &perf_reg); ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ case E_FMAN_PORT_TYPE_HC: ++ get_oh_perf_reg(port, counter, &perf_reg); ++ break; ++ default: ++ perf_reg = NULL; ++ } ++ ++ if (perf_reg == NULL) ++ return; ++ ++ iowrite32be(value, perf_reg); ++} ++ ++uint32_t fman_port_get_qmi_counter(struct fman_port *port, ++ enum fman_port_qmi_counters counter) ++{ ++ uint32_t *queue_reg, ret_val; ++ ++ get_qmi_counter_reg(port, counter, &queue_reg); ++ ++ if (queue_reg == NULL) ++ return 0; ++ ++ ret_val = ioread32be(queue_reg); ++ return ret_val; ++} ++ ++void fman_port_set_qmi_counter(struct fman_port *port, ++ enum fman_port_qmi_counters counter, ++ uint32_t value) ++{ ++ uint32_t *queue_reg; ++ ++ get_qmi_counter_reg(port, counter, &queue_reg); ++ ++ if (queue_reg == NULL) ++ return; ++ ++ iowrite32be(value, queue_reg); ++} ++ ++uint32_t fman_port_get_bpool_counter(struct fman_port *port, uint8_t bpid) ++{ ++ uint8_t index; ++ uint32_t ret_val; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ break; ++ default: ++ return 0; ++ } ++ ++ /* Find the pool */ ++ index = fman_port_find_bpool(port, bpid); ++ if (index == port->ext_pools_num || index == FMAN_PORT_MAX_EXT_POOLS_NUM) ++ /* Not found */ ++ return 0; ++ ++ ret_val = ioread32be(&port->bmi_regs->rx.fmbm_acnt[index]); ++ return ret_val; ++} ++ ++void fman_port_set_bpool_counter(struct fman_port *port, ++ uint8_t bpid, ++ uint32_t value) ++{ ++ uint8_t index; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ break; ++ default: ++ return; ++ } ++ ++ /* Find the pool */ ++ index = fman_port_find_bpool(port, bpid); ++ if (index == port->ext_pools_num || index == FMAN_PORT_MAX_EXT_POOLS_NUM) ++ /* Not found */ ++ return; ++ ++ iowrite32be(value, &port->bmi_regs->rx.fmbm_acnt[index]); ++} ++ ++int fman_port_add_congestion_grps(struct fman_port *port, ++ uint32_t grps_map[FMAN_PORT_CG_MAP_NUM]) ++{ ++ int i; ++ uint32_t tmp, *grp_map_reg; ++ uint8_t max_grp_map_num; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ if (port->fm_rev_maj == 4) ++ max_grp_map_num = 1; ++ else ++ max_grp_map_num = FMAN_PORT_CG_MAP_NUM; ++ grp_map_reg = port->bmi_regs->rx.fmbm_rcgm; ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ max_grp_map_num = 1; ++ if (port->fm_rev_maj != 4) ++ return -EINVAL; ++ grp_map_reg = port->bmi_regs->oh.fmbm_ocgm; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ for (i = (max_grp_map_num - 1); i >= 0; i--) { ++ if (grps_map[i] == 0) ++ continue; ++ tmp = ioread32be(&grp_map_reg[i]); ++ tmp |= grps_map[i]; ++ iowrite32be(tmp, &grp_map_reg[i]); ++ } ++ ++ return 0; ++} ++ ++int fman_port_remove_congestion_grps(struct fman_port *port, ++ uint32_t grps_map[FMAN_PORT_CG_MAP_NUM]) ++{ ++ int i; ++ uint32_t tmp, *grp_map_reg; ++ uint8_t max_grp_map_num; ++ ++ switch (port->type) { ++ case E_FMAN_PORT_TYPE_RX: ++ case E_FMAN_PORT_TYPE_RX_10G: ++ if (port->fm_rev_maj == 4) ++ max_grp_map_num = 1; ++ else ++ max_grp_map_num = FMAN_PORT_CG_MAP_NUM; ++ grp_map_reg = port->bmi_regs->rx.fmbm_rcgm; ++ break; ++ case E_FMAN_PORT_TYPE_OP: ++ max_grp_map_num = 1; ++ if (port->fm_rev_maj != 4) ++ return -EINVAL; ++ grp_map_reg = port->bmi_regs->oh.fmbm_ocgm; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ for (i = (max_grp_map_num - 1); i >= 0; i--) { ++ if (grps_map[i] == 0) ++ continue; ++ tmp = ioread32be(&grp_map_reg[i]); ++ tmp &= ~grps_map[i]; ++ iowrite32be(tmp, &grp_map_reg[i]); ++ } ++ return 0; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Rtc/Makefile b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Rtc/Makefile +new file mode 100644 +index 0000000..d2c21d3 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Rtc/Makefile +@@ -0,0 +1,15 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++ccflags-y += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk ++ ++NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc ++ ++ccflags-y += -I$(NCSW_FM_INC) ++ ++obj-y += fsl-ncsw-RTC.o ++ ++fsl-ncsw-RTC-objs := fm_rtc.o fman_rtc.o +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Rtc/fm_rtc.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Rtc/fm_rtc.c +new file mode 100644 +index 0000000..727d5c8 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Rtc/fm_rtc.c +@@ -0,0 +1,692 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_rtc.c ++ ++ @Description FM RTC driver implementation. ++ ++ @Cautions None ++*//***************************************************************************/ ++ ++#include "error_ext.h" ++#include "debug_ext.h" ++#include "string_ext.h" ++#include "part_ext.h" ++#include "xx_ext.h" ++#include "ncsw_ext.h" ++ ++#include "fm_rtc.h" ++#include "fm_common.h" ++ ++ ++ ++/*****************************************************************************/ ++static t_Error CheckInitParameters(t_FmRtc *p_Rtc) ++{ ++ struct rtc_cfg *p_RtcDriverParam = p_Rtc->p_RtcDriverParam; ++ int i; ++ ++ if ((p_RtcDriverParam->src_clk != E_FMAN_RTC_SOURCE_CLOCK_EXTERNAL) && ++ (p_RtcDriverParam->src_clk != E_FMAN_RTC_SOURCE_CLOCK_SYSTEM) && ++ (p_RtcDriverParam->src_clk != E_FMAN_RTC_SOURCE_CLOCK_OSCILATOR)) ++ RETURN_ERROR(MAJOR, E_INVALID_CLOCK, ("Source clock undefined")); ++ ++ if (p_Rtc->outputClockDivisor == 0) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("Divisor for output clock (should be positive)")); ++ } ++ ++ for (i=0; i < FM_RTC_NUM_OF_ALARMS; i++) ++ { ++ if ((p_RtcDriverParam->alarm_polarity[i] != E_FMAN_RTC_ALARM_POLARITY_ACTIVE_LOW) && ++ (p_RtcDriverParam->alarm_polarity[i] != E_FMAN_RTC_ALARM_POLARITY_ACTIVE_HIGH)) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm %d signal polarity", i)); ++ } ++ } ++ for (i=0; i < FM_RTC_NUM_OF_EXT_TRIGGERS; i++) ++ { ++ if ((p_RtcDriverParam->trigger_polarity[i] != E_FMAN_RTC_TRIGGER_ON_FALLING_EDGE) && ++ (p_RtcDriverParam->trigger_polarity[i] != E_FMAN_RTC_TRIGGER_ON_RISING_EDGE)) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Trigger %d signal polarity", i)); ++ } ++ } ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++static void RtcExceptions(t_Handle h_FmRtc) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ struct rtc_regs *p_MemMap; ++ register uint32_t events; ++ ++ ASSERT_COND(p_Rtc); ++ p_MemMap = p_Rtc->p_MemMap; ++ ++ events = fman_rtc_check_and_clear_event(p_MemMap); ++ if (events & FMAN_RTC_TMR_TEVENT_ALM1) ++ { ++ if (p_Rtc->alarmParams[0].clearOnExpiration) ++ { ++ fman_rtc_set_timer_alarm_l(p_MemMap, 0, 0); ++ fman_rtc_disable_interupt(p_MemMap, FMAN_RTC_TMR_TEVENT_ALM1); ++ } ++ ASSERT_COND(p_Rtc->alarmParams[0].f_AlarmCallback); ++ p_Rtc->alarmParams[0].f_AlarmCallback(p_Rtc->h_App, 0); ++ } ++ if (events & FMAN_RTC_TMR_TEVENT_ALM2) ++ { ++ if (p_Rtc->alarmParams[1].clearOnExpiration) ++ { ++ fman_rtc_set_timer_alarm_l(p_MemMap, 1, 0); ++ fman_rtc_disable_interupt(p_MemMap, FMAN_RTC_TMR_TEVENT_ALM2); ++ } ++ ASSERT_COND(p_Rtc->alarmParams[1].f_AlarmCallback); ++ p_Rtc->alarmParams[1].f_AlarmCallback(p_Rtc->h_App, 1); ++ } ++ if (events & FMAN_RTC_TMR_TEVENT_PP1) ++ { ++ ASSERT_COND(p_Rtc->periodicPulseParams[0].f_PeriodicPulseCallback); ++ p_Rtc->periodicPulseParams[0].f_PeriodicPulseCallback(p_Rtc->h_App, 0); ++ } ++ if (events & FMAN_RTC_TMR_TEVENT_PP2) ++ { ++ ASSERT_COND(p_Rtc->periodicPulseParams[1].f_PeriodicPulseCallback); ++ p_Rtc->periodicPulseParams[1].f_PeriodicPulseCallback(p_Rtc->h_App, 1); ++ } ++ if (events & FMAN_RTC_TMR_TEVENT_ETS1) ++ { ++ ASSERT_COND(p_Rtc->externalTriggerParams[0].f_ExternalTriggerCallback); ++ p_Rtc->externalTriggerParams[0].f_ExternalTriggerCallback(p_Rtc->h_App, 0); ++ } ++ if (events & FMAN_RTC_TMR_TEVENT_ETS2) ++ { ++ ASSERT_COND(p_Rtc->externalTriggerParams[1].f_ExternalTriggerCallback); ++ p_Rtc->externalTriggerParams[1].f_ExternalTriggerCallback(p_Rtc->h_App, 1); ++ } ++} ++ ++ ++/*****************************************************************************/ ++t_Handle FM_RTC_Config(t_FmRtcParams *p_FmRtcParam) ++{ ++ t_FmRtc *p_Rtc; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmRtcParam, E_NULL_POINTER, NULL); ++ ++ /* Allocate memory for the FM RTC driver parameters */ ++ p_Rtc = (t_FmRtc *)XX_Malloc(sizeof(t_FmRtc)); ++ if (!p_Rtc) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM RTC driver structure")); ++ return NULL; ++ } ++ ++ memset(p_Rtc, 0, sizeof(t_FmRtc)); ++ ++ /* Allocate memory for the FM RTC driver parameters */ ++ p_Rtc->p_RtcDriverParam = (struct rtc_cfg *)XX_Malloc(sizeof(struct rtc_cfg)); ++ if (!p_Rtc->p_RtcDriverParam) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM RTC driver parameters")); ++ XX_Free(p_Rtc); ++ return NULL; ++ } ++ ++ memset(p_Rtc->p_RtcDriverParam, 0, sizeof(struct rtc_cfg)); ++ ++ /* Store RTC configuration parameters */ ++ p_Rtc->h_Fm = p_FmRtcParam->h_Fm; ++ ++ /* Set default RTC configuration parameters */ ++ fman_rtc_defconfig(p_Rtc->p_RtcDriverParam); ++ ++ p_Rtc->outputClockDivisor = DEFAULT_OUTPUT_CLOCK_DIVISOR; ++ p_Rtc->p_RtcDriverParam->bypass = DEFAULT_BYPASS; ++ p_Rtc->clockPeriodNanoSec = DEFAULT_CLOCK_PERIOD; /* 1 usec */ ++ ++ ++ /* Store RTC parameters in the RTC control structure */ ++ p_Rtc->p_MemMap = (struct rtc_regs *)UINT_TO_PTR(p_FmRtcParam->baseAddress); ++ p_Rtc->h_App = p_FmRtcParam->h_App; ++ ++ return p_Rtc; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_Init(t_Handle h_FmRtc) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ struct rtc_cfg *p_RtcDriverParam; ++ struct rtc_regs *p_MemMap; ++ uint32_t freqCompensation = 0; ++ uint64_t tmpDouble; ++ bool init_freq_comp = FALSE; ++ ++ p_RtcDriverParam = p_Rtc->p_RtcDriverParam; ++ p_MemMap = p_Rtc->p_MemMap; ++ ++ if (CheckInitParameters(p_Rtc)!=E_OK) ++ RETURN_ERROR(MAJOR, E_CONFLICT, ++ ("Init Parameters are not Valid")); ++ ++ /* TODO check that no timestamping MACs are working in this stage. */ ++ ++ /* find source clock frequency in Mhz */ ++ if (p_Rtc->p_RtcDriverParam->src_clk != E_FMAN_RTC_SOURCE_CLOCK_SYSTEM) ++ p_Rtc->srcClkFreqMhz = p_Rtc->p_RtcDriverParam->ext_src_clk_freq; ++ else ++ p_Rtc->srcClkFreqMhz = (uint32_t)(FmGetMacClockFreq(p_Rtc->h_Fm)); ++ ++ /* if timer in Master mode Initialize TMR_CTRL */ ++ /* We want the counter (TMR_CNT) to count in nano-seconds */ ++ if (!p_RtcDriverParam->timer_slave_mode && p_Rtc->p_RtcDriverParam->bypass) ++ p_Rtc->clockPeriodNanoSec = (1000 / p_Rtc->srcClkFreqMhz); ++ else ++ { ++ /* Initialize TMR_ADD with the initial frequency compensation value: ++ freqCompensation = (2^32 / frequency ratio) */ ++ /* frequency ratio = sorce clock/rtc clock = ++ * (p_Rtc->srcClkFreqMhz*1000000))/ 1/(p_Rtc->clockPeriodNanoSec * 1000000000) */ ++ init_freq_comp = TRUE; ++ freqCompensation = (uint32_t)DIV_CEIL(ACCUMULATOR_OVERFLOW * 1000, ++ p_Rtc->clockPeriodNanoSec * p_Rtc->srcClkFreqMhz); ++ } ++ ++ /* check the legality of the relation between source and destination clocks */ ++ /* should be larger than 1.0001 */ ++ tmpDouble = 10000 * (uint64_t)p_Rtc->clockPeriodNanoSec * (uint64_t)p_Rtc->srcClkFreqMhz; ++ if ((tmpDouble) <= 10001) ++ RETURN_ERROR(MAJOR, E_CONFLICT, ++ ("Invalid relation between source and destination clocks. Should be larger than 1.0001")); ++ ++ fman_rtc_init(p_RtcDriverParam, ++ p_MemMap, ++ FM_RTC_NUM_OF_ALARMS, ++ FM_RTC_NUM_OF_PERIODIC_PULSES, ++ FM_RTC_NUM_OF_EXT_TRIGGERS, ++ init_freq_comp, ++ freqCompensation, ++ p_Rtc->outputClockDivisor); ++ ++ /* Register the FM RTC interrupt */ ++ FmRegisterIntr(p_Rtc->h_Fm, e_FM_MOD_TMR, 0, e_FM_INTR_TYPE_NORMAL, RtcExceptions , p_Rtc); ++ ++ /* Free parameters structures */ ++ XX_Free(p_Rtc->p_RtcDriverParam); ++ p_Rtc->p_RtcDriverParam = NULL; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_Free(t_Handle h_FmRtc) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ ++ if (p_Rtc->p_RtcDriverParam) ++ { ++ XX_Free(p_Rtc->p_RtcDriverParam); ++ } ++ else ++ { ++ FM_RTC_Disable(h_FmRtc); ++ } ++ ++ /* Unregister FM RTC interrupt */ ++ FmUnregisterIntr(p_Rtc->h_Fm, e_FM_MOD_TMR, 0, e_FM_INTR_TYPE_NORMAL); ++ XX_Free(p_Rtc); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigSourceClock(t_Handle h_FmRtc, ++ e_FmSrcClk srcClk, ++ uint32_t freqInMhz) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ p_Rtc->p_RtcDriverParam->src_clk = (enum fman_src_clock)srcClk; ++ if (srcClk != e_FM_RTC_SOURCE_CLOCK_SYSTEM) ++ p_Rtc->p_RtcDriverParam->ext_src_clk_freq = freqInMhz; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigPeriod(t_Handle h_FmRtc, uint32_t period) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ p_Rtc->clockPeriodNanoSec = period; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigFrequencyBypass(t_Handle h_FmRtc, bool enabled) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ p_Rtc->p_RtcDriverParam->bypass = enabled; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigInvertedInputClockPhase(t_Handle h_FmRtc, bool inverted) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ p_Rtc->p_RtcDriverParam->invert_input_clk_phase = inverted; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigInvertedOutputClockPhase(t_Handle h_FmRtc, bool inverted) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ p_Rtc->p_RtcDriverParam->invert_output_clk_phase = inverted; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigOutputClockDivisor(t_Handle h_FmRtc, uint16_t divisor) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ p_Rtc->outputClockDivisor = divisor; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigPulseRealignment(t_Handle h_FmRtc, bool enable) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ p_Rtc->p_RtcDriverParam->pulse_realign = enable; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigAlarmPolarity(t_Handle h_FmRtc, ++ uint8_t alarmId, ++ e_FmRtcAlarmPolarity alarmPolarity) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ if (alarmId >= FM_RTC_NUM_OF_ALARMS) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm ID")); ++ ++ p_Rtc->p_RtcDriverParam->alarm_polarity[alarmId] = ++ (enum fman_rtc_alarm_polarity)alarmPolarity; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ConfigExternalTriggerPolarity(t_Handle h_FmRtc, ++ uint8_t triggerId, ++ e_FmRtcTriggerPolarity triggerPolarity) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ if (triggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External trigger ID")); ++ } ++ ++ p_Rtc->p_RtcDriverParam->trigger_polarity[triggerId] = ++ (enum fman_rtc_trigger_polarity)triggerPolarity; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_Enable(t_Handle h_FmRtc, bool resetClock) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ fman_rtc_enable(p_Rtc->p_MemMap, resetClock); ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_Disable(t_Handle h_FmRtc) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ /* TODO A check must be added here, that no timestamping MAC's ++ * are working in this stage. */ ++ fman_rtc_disable(p_Rtc->p_MemMap); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_SetClockOffset(t_Handle h_FmRtc, int64_t offset) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ fman_rtc_set_timer_offset(p_Rtc->p_MemMap, offset); ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_SetAlarm(t_Handle h_FmRtc, t_FmRtcAlarmParams *p_FmRtcAlarmParams) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ uint64_t tmpAlarm; ++ bool enable = FALSE; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ if (p_FmRtcAlarmParams->alarmId >= FM_RTC_NUM_OF_ALARMS) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm ID")); ++ } ++ ++ if (p_FmRtcAlarmParams->alarmTime < p_Rtc->clockPeriodNanoSec) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ++ ("Alarm time must be equal or larger than RTC period - %d nanoseconds", ++ p_Rtc->clockPeriodNanoSec)); ++ if (p_FmRtcAlarmParams->alarmTime % (uint64_t)p_Rtc->clockPeriodNanoSec) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ++ ("Alarm time must be a multiple of RTC period - %d nanoseconds", ++ p_Rtc->clockPeriodNanoSec)); ++ tmpAlarm = p_FmRtcAlarmParams->alarmTime/(uint64_t)p_Rtc->clockPeriodNanoSec; ++ ++ if (p_FmRtcAlarmParams->f_AlarmCallback) ++ { ++ p_Rtc->alarmParams[p_FmRtcAlarmParams->alarmId].f_AlarmCallback = p_FmRtcAlarmParams->f_AlarmCallback; ++ p_Rtc->alarmParams[p_FmRtcAlarmParams->alarmId].clearOnExpiration = p_FmRtcAlarmParams->clearOnExpiration; ++ enable = TRUE; ++ } ++ ++ fman_rtc_set_alarm(p_Rtc->p_MemMap, p_FmRtcAlarmParams->alarmId, (unsigned long)tmpAlarm, enable); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_SetPeriodicPulse(t_Handle h_FmRtc, t_FmRtcPeriodicPulseParams *p_FmRtcPeriodicPulseParams) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ bool enable = FALSE; ++ uint64_t tmpFiper; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ if (p_FmRtcPeriodicPulseParams->periodicPulseId >= FM_RTC_NUM_OF_PERIODIC_PULSES) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse ID")); ++ } ++ if (fman_rtc_is_enabled(p_Rtc->p_MemMap)) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Can't set Periodic pulse when RTC is enabled.")); ++ if (p_FmRtcPeriodicPulseParams->periodicPulsePeriod < p_Rtc->clockPeriodNanoSec) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ++ ("Periodic pulse must be equal or larger than RTC period - %d nanoseconds", ++ p_Rtc->clockPeriodNanoSec)); ++ if (p_FmRtcPeriodicPulseParams->periodicPulsePeriod % (uint64_t)p_Rtc->clockPeriodNanoSec) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ++ ("Periodic pulse must be a multiple of RTC period - %d nanoseconds", ++ p_Rtc->clockPeriodNanoSec)); ++ tmpFiper = p_FmRtcPeriodicPulseParams->periodicPulsePeriod/(uint64_t)p_Rtc->clockPeriodNanoSec; ++ if (tmpFiper & 0xffffffff00000000LL) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ++ ("Periodic pulse/RTC Period must be smaller than 4294967296", ++ p_Rtc->clockPeriodNanoSec)); ++ ++ if (p_FmRtcPeriodicPulseParams->f_PeriodicPulseCallback) ++ { ++ p_Rtc->periodicPulseParams[p_FmRtcPeriodicPulseParams->periodicPulseId].f_PeriodicPulseCallback = ++ p_FmRtcPeriodicPulseParams->f_PeriodicPulseCallback; ++ enable = TRUE; ++ } ++ fman_rtc_set_periodic_pulse(p_Rtc->p_MemMap, p_FmRtcPeriodicPulseParams->periodicPulseId, (uint32_t)tmpFiper, enable); ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ClearPeriodicPulse(t_Handle h_FmRtc, uint8_t periodicPulseId) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ if (periodicPulseId >= FM_RTC_NUM_OF_PERIODIC_PULSES) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse ID")); ++ } ++ ++ p_Rtc->periodicPulseParams[periodicPulseId].f_PeriodicPulseCallback = NULL; ++ fman_rtc_clear_periodic_pulse(p_Rtc->p_MemMap, periodicPulseId); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_SetExternalTrigger(t_Handle h_FmRtc, t_FmRtcExternalTriggerParams *p_FmRtcExternalTriggerParams) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ bool enable = FALSE; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ if (p_FmRtcExternalTriggerParams->externalTriggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External Trigger ID")); ++ } ++ ++ if (p_FmRtcExternalTriggerParams->f_ExternalTriggerCallback) ++ { ++ p_Rtc->externalTriggerParams[p_FmRtcExternalTriggerParams->externalTriggerId].f_ExternalTriggerCallback = p_FmRtcExternalTriggerParams->f_ExternalTriggerCallback; ++ enable = TRUE; ++ } ++ ++ fman_rtc_set_ext_trigger(p_Rtc->p_MemMap, p_FmRtcExternalTriggerParams->externalTriggerId, enable, p_FmRtcExternalTriggerParams->usePulseAsInput); ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_ClearExternalTrigger(t_Handle h_FmRtc, uint8_t externalTriggerId) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ if (externalTriggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External Trigger ID")); ++ ++ p_Rtc->externalTriggerParams[externalTriggerId].f_ExternalTriggerCallback = NULL; ++ ++ fman_rtc_clear_external_trigger(p_Rtc->p_MemMap, externalTriggerId); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_GetExternalTriggerTimeStamp(t_Handle h_FmRtc, ++ uint8_t triggerId, ++ uint64_t *p_TimeStamp) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ if (triggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS) ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External trigger ID")); ++ ++ *p_TimeStamp = fman_rtc_get_trigger_stamp(p_Rtc->p_MemMap, triggerId)*p_Rtc->clockPeriodNanoSec; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_GetCurrentTime(t_Handle h_FmRtc, uint64_t *p_Ts) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ *p_Ts = fman_rtc_get_timer(p_Rtc->p_MemMap)*p_Rtc->clockPeriodNanoSec; ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_SetCurrentTime(t_Handle h_FmRtc, uint64_t ts) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ ts = ts/p_Rtc->clockPeriodNanoSec; ++ fman_rtc_set_timer(p_Rtc->p_MemMap, (int64_t)ts); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_GetFreqCompensation(t_Handle h_FmRtc, uint32_t *p_Compensation) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ *p_Compensation = fman_rtc_get_frequency_compensation(p_Rtc->p_MemMap); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_SetFreqCompensation(t_Handle h_FmRtc, uint32_t freqCompensation) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ /* set the new freqCompensation */ ++ fman_rtc_set_frequency_compensation(p_Rtc->p_MemMap, freqCompensation); ++ ++ return E_OK; ++} ++ ++#ifdef CONFIG_PTP_1588_CLOCK_DPAA ++/*****************************************************************************/ ++t_Error FM_RTC_EnableInterrupt(t_Handle h_FmRtc, uint32_t events) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ /* enable interrupt */ ++ fman_rtc_enable_interupt(p_Rtc->p_MemMap, events); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++t_Error FM_RTC_DisableInterrupt(t_Handle h_FmRtc, uint32_t events) ++{ ++ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE); ++ ++ /* disable interrupt */ ++ fman_rtc_disable_interupt(p_Rtc->p_MemMap, events); ++ ++ return E_OK; ++} ++#endif +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Rtc/fm_rtc.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Rtc/fm_rtc.h +new file mode 100644 +index 0000000..843ca00 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Rtc/fm_rtc.h +@@ -0,0 +1,96 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_rtc.h ++ ++ @Description Memory map and internal definitions for FM RTC IEEE1588 Timer driver. ++ ++ @Cautions None ++*//***************************************************************************/ ++ ++#ifndef __FM_RTC_H__ ++#define __FM_RTC_H__ ++ ++#include "std_ext.h" ++#include "fm_rtc_ext.h" ++ ++ ++#define __ERR_MODULE__ MODULE_FM_RTC ++ ++/* General definitions */ ++ ++#define ACCUMULATOR_OVERFLOW ((uint64_t)(1LL << 32)) ++#define DEFAULT_OUTPUT_CLOCK_DIVISOR 0x00000002 ++#define DEFAULT_BYPASS FALSE ++#define DEFAULT_CLOCK_PERIOD 1000 ++ ++ ++ ++typedef struct t_FmRtcAlarm ++{ ++ t_FmRtcExceptionsCallback *f_AlarmCallback; ++ bool clearOnExpiration; ++} t_FmRtcAlarm; ++ ++typedef struct t_FmRtcPeriodicPulse ++{ ++ t_FmRtcExceptionsCallback *f_PeriodicPulseCallback; ++} t_FmRtcPeriodicPulse; ++ ++typedef struct t_FmRtcExternalTrigger ++{ ++ t_FmRtcExceptionsCallback *f_ExternalTriggerCallback; ++} t_FmRtcExternalTrigger; ++ ++ ++/**************************************************************************//** ++ @Description RTC FM driver control structure. ++*//***************************************************************************/ ++typedef struct t_FmRtc ++{ ++ t_Part *p_Part; /**< Pointer to the integration device */ ++ t_Handle h_Fm; ++ t_Handle h_App; /**< Application handle */ ++ struct rtc_regs *p_MemMap; ++ uint32_t clockPeriodNanoSec; /**< RTC clock period in nano-seconds (for FS mode) */ ++ uint32_t srcClkFreqMhz; ++ uint16_t outputClockDivisor; /**< Output clock divisor (for FS mode) */ ++ t_FmRtcAlarm alarmParams[FM_RTC_NUM_OF_ALARMS]; ++ t_FmRtcPeriodicPulse periodicPulseParams[FM_RTC_NUM_OF_PERIODIC_PULSES]; ++ t_FmRtcExternalTrigger externalTriggerParams[FM_RTC_NUM_OF_EXT_TRIGGERS]; ++ struct rtc_cfg *p_RtcDriverParam; /**< RTC Driver parameters (for Init phase) */ ++} t_FmRtc; ++ ++ ++#endif /* __FM_RTC_H__ */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Rtc/fman_rtc.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Rtc/fman_rtc.c +new file mode 100755 +index 0000000..acdf507 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Rtc/fman_rtc.c +@@ -0,0 +1,334 @@ ++/* ++ * Copyright 2008-2013 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 "fsl_fman_rtc.h" ++ ++void fman_rtc_defconfig(struct rtc_cfg *cfg) ++{ ++ int i; ++ cfg->src_clk = DEFAULT_SRC_CLOCK; ++ cfg->invert_input_clk_phase = DEFAULT_INVERT_INPUT_CLK_PHASE; ++ cfg->invert_output_clk_phase = DEFAULT_INVERT_OUTPUT_CLK_PHASE; ++ cfg->pulse_realign = DEFAULT_PULSE_REALIGN; ++ for (i = 0; i < FMAN_RTC_MAX_NUM_OF_ALARMS; i++) ++ cfg->alarm_polarity[i] = DEFAULT_ALARM_POLARITY; ++ for (i = 0; i < FMAN_RTC_MAX_NUM_OF_EXT_TRIGGERS; i++) ++ cfg->trigger_polarity[i] = DEFAULT_TRIGGER_POLARITY; ++} ++ ++uint32_t fman_rtc_get_events(struct rtc_regs *regs) ++{ ++ return ioread32be(®s->tmr_tevent); ++} ++ ++uint32_t fman_rtc_get_event(struct rtc_regs *regs, uint32_t ev_mask) ++{ ++ return ioread32be(®s->tmr_tevent) & ev_mask; ++} ++ ++uint32_t fman_rtc_get_interrupt_mask(struct rtc_regs *regs) ++{ ++ return ioread32be(®s->tmr_temask); ++} ++ ++void fman_rtc_set_interrupt_mask(struct rtc_regs *regs, uint32_t mask) ++{ ++ iowrite32be(mask, ®s->tmr_temask); ++} ++ ++void fman_rtc_ack_event(struct rtc_regs *regs, uint32_t events) ++{ ++ iowrite32be(events, ®s->tmr_tevent); ++} ++ ++uint32_t fman_rtc_check_and_clear_event(struct rtc_regs *regs) ++{ ++ uint32_t event; ++ ++ event = ioread32be(®s->tmr_tevent); ++ event &= ioread32be(®s->tmr_temask); ++ ++ if (event) ++ iowrite32be(event, ®s->tmr_tevent); ++ return event; ++} ++ ++uint32_t fman_rtc_get_frequency_compensation(struct rtc_regs *regs) ++{ ++ return ioread32be(®s->tmr_add); ++} ++ ++void fman_rtc_set_frequency_compensation(struct rtc_regs *regs, uint32_t val) ++{ ++ iowrite32be(val, ®s->tmr_add); ++} ++ ++void fman_rtc_enable_interupt(struct rtc_regs *regs, uint32_t events) ++{ ++ fman_rtc_set_interrupt_mask(regs, fman_rtc_get_interrupt_mask(regs) | events); ++} ++ ++void fman_rtc_disable_interupt(struct rtc_regs *regs, uint32_t events) ++{ ++ fman_rtc_set_interrupt_mask(regs, fman_rtc_get_interrupt_mask(regs) & ~events); ++} ++ ++void fman_rtc_set_timer_alarm_l(struct rtc_regs *regs, int index, uint32_t val) ++{ ++ iowrite32be(val, ®s->tmr_alarm[index].tmr_alarm_l); ++} ++ ++void fman_rtc_set_timer_fiper(struct rtc_regs *regs, int index, uint32_t val) ++{ ++ iowrite32be(val, ®s->tmr_fiper[index]); ++} ++ ++void fman_rtc_set_timer_alarm(struct rtc_regs *regs, int index, int64_t val) ++{ ++ iowrite32be((uint32_t)val, ®s->tmr_alarm[index].tmr_alarm_l); ++ iowrite32be((uint32_t)(val >> 32), ®s->tmr_alarm[index].tmr_alarm_h); ++} ++ ++void fman_rtc_set_timer_offset(struct rtc_regs *regs, int64_t val) ++{ ++ iowrite32be((uint32_t)val, ®s->tmr_off_l); ++ iowrite32be((uint32_t)(val >> 32), ®s->tmr_off_h); ++} ++ ++uint64_t fman_rtc_get_trigger_stamp(struct rtc_regs *regs, int id) ++{ ++ uint64_t time; ++ /* TMR_CNT_L must be read first to get an accurate value */ ++ time = (uint64_t)ioread32be(®s->tmr_etts[id].tmr_etts_l); ++ time |= ((uint64_t)ioread32be(®s->tmr_etts[id].tmr_etts_h) ++ << 32); ++ ++ return time; ++} ++ ++uint32_t fman_rtc_get_timer_ctrl(struct rtc_regs *regs) ++{ ++ return ioread32be(®s->tmr_ctrl); ++} ++ ++void fman_rtc_set_timer_ctrl(struct rtc_regs *regs, uint32_t val) ++{ ++ iowrite32be(val, ®s->tmr_ctrl); ++} ++ ++void fman_rtc_timers_soft_reset(struct rtc_regs *regs) ++{ ++ fman_rtc_set_timer_ctrl(regs, FMAN_RTC_TMR_CTRL_TMSR); ++ udelay(10); ++ fman_rtc_set_timer_ctrl(regs, 0); ++} ++ ++void fman_rtc_init(struct rtc_cfg *cfg, struct rtc_regs *regs, int num_alarms, ++ int num_fipers, int num_ext_triggers, bool init_freq_comp, ++ uint32_t freq_compensation, uint32_t output_clock_divisor) ++{ ++ uint32_t tmr_ctrl; ++ int i; ++ ++ fman_rtc_timers_soft_reset(regs); ++ ++ /* Set the source clock */ ++ switch (cfg->src_clk) { ++ case E_FMAN_RTC_SOURCE_CLOCK_SYSTEM: ++ tmr_ctrl = FMAN_RTC_TMR_CTRL_CKSEL_MAC_CLK; ++ break; ++ case E_FMAN_RTC_SOURCE_CLOCK_OSCILATOR: ++ tmr_ctrl = FMAN_RTC_TMR_CTRL_CKSEL_OSC_CLK; ++ break; ++ default: ++ /* Use a clock from the External TMR reference clock.*/ ++ tmr_ctrl = FMAN_RTC_TMR_CTRL_CKSEL_EXT_CLK; ++ break; ++ } ++ ++ /* whatever period the user picked, the timestamp will advance in '1' ++ * every time the period passed. */ ++ tmr_ctrl |= ((1 << FMAN_RTC_TMR_CTRL_TCLK_PERIOD_SHIFT) & ++ FMAN_RTC_TMR_CTRL_TCLK_PERIOD_MASK); ++ ++ if (cfg->invert_input_clk_phase) ++ tmr_ctrl |= FMAN_RTC_TMR_CTRL_CIPH; ++ if (cfg->invert_output_clk_phase) ++ tmr_ctrl |= FMAN_RTC_TMR_CTRL_COPH; ++ ++ for (i = 0; i < num_alarms; i++) { ++ if (cfg->alarm_polarity[i] == ++ E_FMAN_RTC_ALARM_POLARITY_ACTIVE_LOW) ++ tmr_ctrl |= (FMAN_RTC_TMR_CTRL_ALMP1 >> i); ++ } ++ ++ for (i = 0; i < num_ext_triggers; i++) ++ if (cfg->trigger_polarity[i] == ++ E_FMAN_RTC_TRIGGER_ON_FALLING_EDGE) ++ tmr_ctrl |= (FMAN_RTC_TMR_CTRL_ETEP1 << i); ++ ++ if (!cfg->timer_slave_mode && cfg->bypass) ++ tmr_ctrl |= FMAN_RTC_TMR_CTRL_BYP; ++ ++ fman_rtc_set_timer_ctrl(regs, tmr_ctrl); ++ if (init_freq_comp) ++ fman_rtc_set_frequency_compensation(regs, freq_compensation); ++ ++ /* Clear TMR_ALARM registers */ ++ for (i = 0; i < num_alarms; i++) ++ fman_rtc_set_timer_alarm(regs, i, 0xFFFFFFFFFFFFFFFFLL); ++ ++ /* Clear TMR_TEVENT */ ++ fman_rtc_ack_event(regs, FMAN_RTC_TMR_TEVENT_ALL); ++ ++ /* Initialize TMR_TEMASK */ ++ fman_rtc_set_interrupt_mask(regs, 0); ++ ++ /* Clear TMR_FIPER registers */ ++ for (i = 0; i < num_fipers; i++) ++ fman_rtc_set_timer_fiper(regs, i, 0xFFFFFFFF); ++ ++ /* Initialize TMR_PRSC */ ++ iowrite32be(output_clock_divisor, ®s->tmr_prsc); ++ ++ /* Clear TMR_OFF */ ++ fman_rtc_set_timer_offset(regs, 0); ++} ++ ++bool fman_rtc_is_enabled(struct rtc_regs *regs) ++{ ++ return (bool)(fman_rtc_get_timer_ctrl(regs) & FMAN_RTC_TMR_CTRL_TE); ++} ++ ++void fman_rtc_enable(struct rtc_regs *regs, bool reset_clock) ++{ ++ uint32_t tmr_ctrl = fman_rtc_get_timer_ctrl(regs); ++ ++ /* TODO check that no timestamping MACs are working in this stage. */ ++ if (reset_clock) { ++ fman_rtc_set_timer_ctrl(regs, (tmr_ctrl | FMAN_RTC_TMR_CTRL_TMSR)); ++ ++ udelay(10); ++ /* Clear TMR_OFF */ ++ fman_rtc_set_timer_offset(regs, 0); ++ } ++ ++ fman_rtc_set_timer_ctrl(regs, (tmr_ctrl | FMAN_RTC_TMR_CTRL_TE)); ++} ++ ++void fman_rtc_disable(struct rtc_regs *regs) ++{ ++ fman_rtc_set_timer_ctrl(regs, (fman_rtc_get_timer_ctrl(regs) ++ & ~(FMAN_RTC_TMR_CTRL_TE))); ++} ++ ++void fman_rtc_clear_periodic_pulse(struct rtc_regs *regs, int id) ++{ ++ uint32_t tmp_reg; ++ if (id == 0) ++ tmp_reg = FMAN_RTC_TMR_TEVENT_PP1; ++ else ++ tmp_reg = FMAN_RTC_TMR_TEVENT_PP2; ++ fman_rtc_disable_interupt(regs, tmp_reg); ++ ++ tmp_reg = fman_rtc_get_timer_ctrl(regs); ++ if (tmp_reg & FMAN_RTC_TMR_CTRL_FS) ++ fman_rtc_set_timer_ctrl(regs, tmp_reg & ~FMAN_RTC_TMR_CTRL_FS); ++ ++ fman_rtc_set_timer_fiper(regs, id, 0xFFFFFFFF); ++} ++ ++void fman_rtc_clear_external_trigger(struct rtc_regs *regs, int id) ++{ ++ uint32_t tmpReg, tmp_ctrl; ++ ++ if (id == 0) ++ tmpReg = FMAN_RTC_TMR_TEVENT_ETS1; ++ else ++ tmpReg = FMAN_RTC_TMR_TEVENT_ETS2; ++ fman_rtc_disable_interupt(regs, tmpReg); ++ ++ if (id == 0) ++ tmpReg = FMAN_RTC_TMR_CTRL_PP1L; ++ else ++ tmpReg = FMAN_RTC_TMR_CTRL_PP2L; ++ tmp_ctrl = fman_rtc_get_timer_ctrl(regs); ++ if (tmp_ctrl & tmpReg) ++ fman_rtc_set_timer_ctrl(regs, tmp_ctrl & ~tmpReg); ++} ++ ++void fman_rtc_set_alarm(struct rtc_regs *regs, int id, uint32_t val, bool enable) ++{ ++ uint32_t tmpReg; ++ fman_rtc_set_timer_alarm(regs, id, val); ++ if (enable) { ++ if (id == 0) ++ tmpReg = FMAN_RTC_TMR_TEVENT_ALM1; ++ else ++ tmpReg = FMAN_RTC_TMR_TEVENT_ALM2; ++ fman_rtc_enable_interupt(regs, tmpReg); ++ } ++} ++ ++void fman_rtc_set_periodic_pulse(struct rtc_regs *regs, int id, uint32_t val, ++ bool enable) ++{ ++ uint32_t tmpReg; ++ fman_rtc_set_timer_fiper(regs, id, val); ++ if (enable) { ++ if (id == 0) ++ tmpReg = FMAN_RTC_TMR_TEVENT_PP1; ++ else ++ tmpReg = FMAN_RTC_TMR_TEVENT_PP2; ++ fman_rtc_enable_interupt(regs, tmpReg); ++ } ++} ++ ++void fman_rtc_set_ext_trigger(struct rtc_regs *regs, int id, bool enable, ++ bool use_pulse_as_input) ++{ ++ uint32_t tmpReg; ++ if (enable) { ++ if (id == 0) ++ tmpReg = FMAN_RTC_TMR_TEVENT_ETS1; ++ else ++ tmpReg = FMAN_RTC_TMR_TEVENT_ETS2; ++ fman_rtc_enable_interupt(regs, tmpReg); ++ } ++ if (use_pulse_as_input) { ++ if (id == 0) ++ tmpReg = FMAN_RTC_TMR_CTRL_PP1L; ++ else ++ tmpReg = FMAN_RTC_TMR_CTRL_PP2L; ++ fman_rtc_set_timer_ctrl(regs, fman_rtc_get_timer_ctrl(regs) | tmpReg); ++ } ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/SP/Makefile b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/SP/Makefile +new file mode 100644 +index 0000000..fae50ce +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/SP/Makefile +@@ -0,0 +1,15 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++ccflags-y += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk ++ ++NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc ++ ++ccflags-y += -I$(NCSW_FM_INC) ++ ++obj-y += fsl-ncsw-sp.o ++ ++fsl-ncsw-sp-objs := fm_sp.o fman_sp.o +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/SP/fm_sp.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/SP/fm_sp.c +new file mode 100644 +index 0000000..0994f34 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/SP/fm_sp.c +@@ -0,0 +1,757 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_sp.c ++ ++ @Description FM PCD Storage profile ... ++*//***************************************************************************/ ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "debug_ext.h" ++#include "net_ext.h" ++ ++#include "fm_vsp_ext.h" ++#include "fm_sp.h" ++#include "fm_common.h" ++#include "fsl_fman_sp.h" ++ ++ ++#if (DPAA_VERSION >= 11) ++static t_Error CheckParamsGeneratedInternally(t_FmVspEntry *p_FmVspEntry) ++{ ++ t_Error err = E_OK; ++ ++ if ((err = FmSpCheckIntContextParams(&p_FmVspEntry->intContext))!= E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if ((err = FmSpCheckBufMargins(&p_FmVspEntry->bufMargins)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ return err; ++ ++} ++ ++static t_Error CheckParams(t_FmVspEntry *p_FmVspEntry) ++{ ++ t_Error err = E_OK; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->h_Fm, E_INVALID_HANDLE); ++ ++ if ((err = FmSpCheckBufPoolsParams(&p_FmVspEntry->p_FmVspEntryDriverParams->extBufPools, ++ p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools, ++ p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion)) != E_OK) ++ ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (p_FmVspEntry->p_FmVspEntryDriverParams->liodnOffset & ~FM_LIODN_OFFSET_MASK) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("liodnOffset is larger than %d", FM_LIODN_OFFSET_MASK+1)); ++ ++ err = FmVSPCheckRelativeProfile(p_FmVspEntry->h_Fm, ++ p_FmVspEntry->portType, ++ p_FmVspEntry->portId, ++ p_FmVspEntry->relativeProfileId); ++ ++ return err; ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ ++/*****************************************************************************/ ++/* Inter-module API routines */ ++/*****************************************************************************/ ++void FmSpSetBufPoolsInAscOrderOfBufSizes(t_FmExtPools *p_FmExtPools, ++ uint8_t *orderedArray, ++ uint16_t *sizesArray) ++{ ++ uint16_t bufSize = 0; ++ int i=0, j=0, k=0; ++ ++ /* First we copy the external buffers pools information to an ordered local array */ ++ for (i=0;inumOfPoolsUsed;i++) ++ { ++ /* get pool size */ ++ bufSize = p_FmExtPools->extBufPool[i].size; ++ ++ /* keep sizes in an array according to poolId for direct access */ ++ sizesArray[p_FmExtPools->extBufPool[i].id] = bufSize; ++ ++ /* save poolId in an ordered array according to size */ ++ for (j=0;j<=i;j++) ++ { ++ /* this is the next free place in the array */ ++ if (j==i) ++ orderedArray[i] = p_FmExtPools->extBufPool[i].id; ++ else ++ { ++ /* find the right place for this poolId */ ++ if (bufSize < sizesArray[orderedArray[j]]) ++ { ++ /* move the poolIds one place ahead to make room for this poolId */ ++ for (k=i;k>j;k--) ++ orderedArray[k] = orderedArray[k-1]; ++ ++ /* now k==j, this is the place for the new size */ ++ orderedArray[k] = p_FmExtPools->extBufPool[i].id; ++ break; ++ } ++ } ++ } ++ } ++} ++ ++t_Error FmSpCheckBufPoolsParams(t_FmExtPools *p_FmExtPools, ++ t_FmBackupBmPools *p_FmBackupBmPools, ++ t_FmBufPoolDepletion *p_FmBufPoolDepletion) ++{ ++ ++ int i = 0, j = 0; ++ bool found; ++ uint8_t count = 0; ++ ++ if (p_FmExtPools) ++ { ++ if (p_FmExtPools->numOfPoolsUsed > FM_PORT_MAX_NUM_OF_EXT_POOLS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfPoolsUsed can't be larger than %d", FM_PORT_MAX_NUM_OF_EXT_POOLS)); ++ ++ for (i=0;inumOfPoolsUsed;i++) ++ { ++ if (p_FmExtPools->extBufPool[i].id >= BM_MAX_NUM_OF_POOLS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("extBufPools.extBufPool[%d].id can't be larger than %d", i, BM_MAX_NUM_OF_POOLS)); ++ if (!p_FmExtPools->extBufPool[i].size) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("extBufPools.extBufPool[%d].size is 0", i)); ++ } ++ } ++ if (!p_FmExtPools && (p_FmBackupBmPools || p_FmBufPoolDepletion)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("backupBmPools ot bufPoolDepletion can not be defined without external pools")); ++ ++ /* backup BM pools indication is valid only for some chip derivatives ++ (limited by the config routine) */ ++ if (p_FmBackupBmPools) ++ { ++ if (p_FmBackupBmPools->numOfBackupPools >= p_FmExtPools->numOfPoolsUsed) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_BackupBmPools must be smaller than extBufPools.numOfPoolsUsed")); ++ found = FALSE; ++ for (i = 0;inumOfBackupPools;i++) ++ { ++ ++ for (j=0;jnumOfPoolsUsed;j++) ++ { ++ if (p_FmBackupBmPools->poolIds[i] == p_FmExtPools->extBufPool[j].id) ++ { ++ found = TRUE; ++ break; ++ } ++ } ++ if (!found) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("All p_BackupBmPools.poolIds must be included in extBufPools.extBufPool[n].id")); ++ else ++ found = FALSE; ++ } ++ } ++ ++ /* up to extBufPools.numOfPoolsUsed pools may be defined */ ++ if (p_FmBufPoolDepletion && p_FmBufPoolDepletion->poolsGrpModeEnable) ++ { ++ if ((p_FmBufPoolDepletion->numOfPools > p_FmExtPools->numOfPoolsUsed)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPools can't be larger than %d and can't be larger than numOfPoolsUsed", FM_PORT_MAX_NUM_OF_EXT_POOLS)); ++ ++ if (!p_FmBufPoolDepletion->numOfPools) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPoolsToConsider can not be 0 when poolsGrpModeEnable=TRUE")); ++ ++ found = FALSE; ++ count = 0; ++ /* for each pool that is in poolsToConsider, check if it is defined ++ in extBufPool */ ++ for (i=0;ipoolsToConsider[i]) ++ { ++ for (j=0;jnumOfPoolsUsed;j++) ++ { ++ if (i == p_FmExtPools->extBufPool[j].id) ++ { ++ found = TRUE; ++ count++; ++ break; ++ } ++ } ++ if (!found) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Pools selected for depletion are not used.")); ++ else ++ found = FALSE; ++ } ++ } ++ /* check that the number of pools that we have checked is equal to the number announced by the user */ ++ if (count != p_FmBufPoolDepletion->numOfPools) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPools is larger than the number of pools defined.")); ++ } ++ ++ if (p_FmBufPoolDepletion && p_FmBufPoolDepletion->singlePoolModeEnable) ++ { ++ /* calculate vector for number of pools depletion */ ++ found = FALSE; ++ count = 0; ++ for (i=0;ipoolsToConsiderForSingleMode[i]) ++ { ++ for (j=0;jnumOfPoolsUsed;j++) ++ { ++ if (i == p_FmExtPools->extBufPool[j].id) ++ { ++ found = TRUE; ++ count++; ++ break; ++ } ++ } ++ if (!found) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Pools selected for depletion are not used.")); ++ else ++ found = FALSE; ++ } ++ } ++ if (!count) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("No pools defined for single buffer mode pool depletion.")); ++ } ++ ++ return E_OK; ++} ++ ++t_Error FmSpCheckIntContextParams(t_FmSpIntContextDataCopy *p_FmSpIntContextDataCopy) ++{ ++ /* Check that divisible by 16 and not larger than 240 */ ++ if (p_FmSpIntContextDataCopy->intContextOffset >MAX_INT_OFFSET) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.intContextOffset can't be larger than %d", MAX_INT_OFFSET)); ++ if (p_FmSpIntContextDataCopy->intContextOffset % OFFSET_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.intContextOffset has to be divisible by %d", OFFSET_UNITS)); ++ ++ /* check that ic size+ic internal offset, does not exceed ic block size */ ++ if (p_FmSpIntContextDataCopy->size + p_FmSpIntContextDataCopy->intContextOffset > MAX_IC_SIZE) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.size + intContext.intContextOffset has to be smaller than %d", MAX_IC_SIZE)); ++ /* Check that divisible by 16 and not larger than 256 */ ++ if (p_FmSpIntContextDataCopy->size % OFFSET_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.size has to be divisible by %d", OFFSET_UNITS)); ++ ++ /* Check that divisible by 16 and not larger than 4K */ ++ if (p_FmSpIntContextDataCopy->extBufOffset > MAX_EXT_OFFSET) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.extBufOffset can't be larger than %d", MAX_EXT_OFFSET)); ++ if (p_FmSpIntContextDataCopy->extBufOffset % OFFSET_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.extBufOffset has to be divisible by %d", OFFSET_UNITS)); ++ ++ return E_OK; ++} ++ ++t_Error FmSpCheckBufMargins(t_FmSpBufMargins *p_FmSpBufMargins) ++{ ++ /* Check the margin definition */ ++ if (p_FmSpBufMargins->startMargins > MAX_EXT_BUFFER_OFFSET) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufMargins.startMargins can't be larger than %d", MAX_EXT_BUFFER_OFFSET)); ++ if (p_FmSpBufMargins->endMargins > MAX_EXT_BUFFER_OFFSET) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufMargins.endMargins can't be larger than %d", MAX_EXT_BUFFER_OFFSET)); ++ ++ return E_OK; ++} ++ ++t_Error FmSpBuildBufferStructure(t_FmSpIntContextDataCopy *p_FmSpIntContextDataCopy, ++ t_FmBufferPrefixContent *p_BufferPrefixContent, ++ t_FmSpBufMargins *p_FmSpBufMargins, ++ t_FmSpBufferOffsets *p_FmSpBufferOffsets, ++ uint8_t *internalBufferOffset) ++{ ++ uint32_t tmp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmSpIntContextDataCopy, E_INVALID_VALUE); ++ ASSERT_COND(p_FmSpIntContextDataCopy); ++ ASSERT_COND(p_BufferPrefixContent); ++ ASSERT_COND(p_FmSpBufMargins); ++ ASSERT_COND(p_FmSpBufferOffsets); ++ ++ /* Align start of internal context data to 16 byte */ ++ p_FmSpIntContextDataCopy->extBufOffset = ++ (uint16_t)((p_BufferPrefixContent->privDataSize & (OFFSET_UNITS-1)) ? ++ ((p_BufferPrefixContent->privDataSize + OFFSET_UNITS) & ~(uint16_t)(OFFSET_UNITS-1)) : ++ p_BufferPrefixContent->privDataSize); ++ ++ /* Translate margin and intContext params to FM parameters */ ++ /* Initialize with illegal value. Later we'll set legal values. */ ++ p_FmSpBufferOffsets->prsResultOffset = (uint32_t)ILLEGAL_BASE; ++ p_FmSpBufferOffsets->timeStampOffset = (uint32_t)ILLEGAL_BASE; ++ p_FmSpBufferOffsets->hashResultOffset= (uint32_t)ILLEGAL_BASE; ++ p_FmSpBufferOffsets->pcdInfoOffset = (uint32_t)ILLEGAL_BASE; ++ ++ /* Internally the driver supports 4 options ++ 1. prsResult/timestamp/hashResult selection (in fact 8 options, but for simplicity we'll ++ relate to it as 1). ++ 2. All IC context (from AD) not including debug.*/ ++ ++ /* This 'if' covers option 2. We copy from beginning of context. */ ++ if (p_BufferPrefixContent->passAllOtherPCDInfo) ++ { ++ p_FmSpIntContextDataCopy->size = 128; /* must be aligned to 16 */ ++ /* Start copying data after 16 bytes (FD) from the beginning of the internal context */ ++ p_FmSpIntContextDataCopy->intContextOffset = 16; ++ ++ if (p_BufferPrefixContent->passAllOtherPCDInfo) ++ p_FmSpBufferOffsets->pcdInfoOffset = p_FmSpIntContextDataCopy->extBufOffset; ++ if (p_BufferPrefixContent->passPrsResult) ++ p_FmSpBufferOffsets->prsResultOffset = ++ (uint32_t)(p_FmSpIntContextDataCopy->extBufOffset + 16); ++ if (p_BufferPrefixContent->passTimeStamp) ++ p_FmSpBufferOffsets->timeStampOffset = ++ (uint32_t)(p_FmSpIntContextDataCopy->extBufOffset + 48); ++ if (p_BufferPrefixContent->passHashResult) ++ p_FmSpBufferOffsets->hashResultOffset = ++ (uint32_t)(p_FmSpIntContextDataCopy->extBufOffset + 56); ++ } ++ else ++ { ++ /* This case covers the options under 1 */ ++ /* Copy size must be in 16-byte granularity. */ ++ p_FmSpIntContextDataCopy->size = ++ (uint16_t)((p_BufferPrefixContent->passPrsResult ? 32 : 0) + ++ ((p_BufferPrefixContent->passTimeStamp || ++ p_BufferPrefixContent->passHashResult) ? 16 : 0)); ++ ++ /* Align start of internal context data to 16 byte */ ++ p_FmSpIntContextDataCopy->intContextOffset = ++ (uint8_t)(p_BufferPrefixContent->passPrsResult ? 32 : ++ ((p_BufferPrefixContent->passTimeStamp || ++ p_BufferPrefixContent->passHashResult) ? 64 : 0)); ++ ++ if (p_BufferPrefixContent->passPrsResult) ++ p_FmSpBufferOffsets->prsResultOffset = p_FmSpIntContextDataCopy->extBufOffset; ++ if (p_BufferPrefixContent->passTimeStamp) ++ p_FmSpBufferOffsets->timeStampOffset = p_BufferPrefixContent->passPrsResult ? ++ (p_FmSpIntContextDataCopy->extBufOffset + sizeof(t_FmPrsResult)) : ++ p_FmSpIntContextDataCopy->extBufOffset; ++ if (p_BufferPrefixContent->passHashResult) ++ /* If PR is not requested, whether TS is requested or not, IC will be copied from TS */ ++ p_FmSpBufferOffsets->hashResultOffset = p_BufferPrefixContent->passPrsResult ? ++ (p_FmSpIntContextDataCopy->extBufOffset + sizeof(t_FmPrsResult) + 8) : ++ p_FmSpIntContextDataCopy->extBufOffset + 8; ++ } ++ ++ if (p_FmSpIntContextDataCopy->size) ++ p_FmSpBufMargins->startMargins = ++ (uint16_t)(p_FmSpIntContextDataCopy->extBufOffset + ++ p_FmSpIntContextDataCopy->size); ++ else ++ /* No Internal Context passing, STartMargin is immediately after privateInfo */ ++ p_FmSpBufMargins->startMargins = p_BufferPrefixContent->privDataSize; ++ ++ /* save extra space for manip in both external and internal buffers */ ++ if (p_BufferPrefixContent->manipExtraSpace) ++ { ++ uint8_t extraSpace; ++#ifdef FM_CAPWAP_SUPPORT ++ if ((p_BufferPrefixContent->manipExtraSpace + CAPWAP_FRAG_EXTRA_SPACE) >= 256) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("p_BufferPrefixContent->manipExtraSpace should be less than %d", ++ 256-CAPWAP_FRAG_EXTRA_SPACE)); ++ extraSpace = (uint8_t)(p_BufferPrefixContent->manipExtraSpace + CAPWAP_FRAG_EXTRA_SPACE); ++#else ++ extraSpace = p_BufferPrefixContent->manipExtraSpace; ++#endif /* FM_CAPWAP_SUPPORT */ ++ p_FmSpBufferOffsets->manipOffset = p_FmSpBufMargins->startMargins; ++ p_FmSpBufMargins->startMargins += extraSpace; ++ *internalBufferOffset = extraSpace; ++ } ++ ++ /* align data start */ ++ tmp = (uint32_t)(p_FmSpBufMargins->startMargins % p_BufferPrefixContent->dataAlign); ++ if (tmp) ++ p_FmSpBufMargins->startMargins += (p_BufferPrefixContent->dataAlign-tmp); ++ p_FmSpBufferOffsets->dataOffset = p_FmSpBufMargins->startMargins; ++ ++ return E_OK; ++} ++/*********************** End of inter-module routines ************************/ ++ ++ ++#if (DPAA_VERSION >= 11) ++/*****************************************************************************/ ++/* API routines */ ++/*****************************************************************************/ ++t_Handle FM_VSP_Config(t_FmVspParams *p_FmVspParams) ++{ ++ t_FmVspEntry *p_FmVspEntry = NULL; ++ struct fm_storage_profile_params fm_vsp_params; ++ ++ p_FmVspEntry = (t_FmVspEntry *)XX_Malloc(sizeof(t_FmVspEntry)); ++ if (!p_FmVspEntry) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_StorageProfile allocation failed")); ++ return NULL; ++ } ++ memset(p_FmVspEntry, 0, sizeof(t_FmVspEntry)); ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams = (t_FmVspEntryDriverParams *)XX_Malloc(sizeof(t_FmVspEntryDriverParams)); ++ if (!p_FmVspEntry->p_FmVspEntryDriverParams) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_StorageProfile allocation failed")); ++ XX_Free(p_FmVspEntry); ++ return NULL; ++ } ++ memset(p_FmVspEntry->p_FmVspEntryDriverParams, 0, sizeof(t_FmVspEntryDriverParams)); ++ fman_vsp_defconfig(&fm_vsp_params); ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaHeaderCacheAttr = fm_vsp_params.header_cache_attr; ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaIntContextCacheAttr = fm_vsp_params.int_context_cache_attr; ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaScatterGatherCacheAttr = fm_vsp_params.scatter_gather_cache_attr; ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaSwapData = fm_vsp_params.dma_swap_data; ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaWriteOptimize = fm_vsp_params.dma_write_optimize; ++ p_FmVspEntry->p_FmVspEntryDriverParams->noScatherGather = fm_vsp_params.no_scather_gather; ++ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.privDataSize = DEFAULT_FM_SP_bufferPrefixContent_privDataSize; ++ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.passPrsResult= DEFAULT_FM_SP_bufferPrefixContent_passPrsResult; ++ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.passTimeStamp= DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp; ++ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.passAllOtherPCDInfo ++ = DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp; ++ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.dataAlign = DEFAULT_FM_SP_bufferPrefixContent_dataAlign; ++ p_FmVspEntry->p_FmVspEntryDriverParams->liodnOffset = p_FmVspParams->liodnOffset; ++ ++ memcpy(&p_FmVspEntry->p_FmVspEntryDriverParams->extBufPools, &p_FmVspParams->extBufPools, sizeof(t_FmExtPools)); ++ p_FmVspEntry->h_Fm = p_FmVspParams->h_Fm; ++ p_FmVspEntry->portType = p_FmVspParams->portParams.portType; ++ p_FmVspEntry->portId = p_FmVspParams->portParams.portId; ++ ++ p_FmVspEntry->relativeProfileId = p_FmVspParams->relativeProfileId; ++ ++ return p_FmVspEntry; ++} ++ ++t_Error FM_VSP_Init(t_Handle h_FmVsp) ++{ ++ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry *)h_FmVsp; ++ struct fm_storage_profile_params fm_vsp_params; ++ uint8_t orderedArray[FM_PORT_MAX_NUM_OF_EXT_POOLS]; ++ uint16_t sizesArray[BM_MAX_NUM_OF_POOLS]; ++ t_Error err; ++ uint16_t absoluteProfileId = 0; ++ int i = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams,E_INVALID_HANDLE); ++ ++ CHECK_INIT_PARAMETERS(p_FmVspEntry, CheckParams); ++ ++ memset(&orderedArray, 0, sizeof(uint8_t) * FM_PORT_MAX_NUM_OF_EXT_POOLS); ++ memset(&sizesArray, 0, sizeof(uint16_t) * BM_MAX_NUM_OF_POOLS); ++ ++ err = FmSpBuildBufferStructure(&p_FmVspEntry->intContext, ++ &p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent, ++ &p_FmVspEntry->bufMargins, ++ &p_FmVspEntry->bufferOffsets, ++ &p_FmVspEntry->internalBufferOffset); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ ++ err = CheckParamsGeneratedInternally(p_FmVspEntry); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ ++ p_FmVspEntry->p_FmSpRegsBase = ++ (struct fm_pcd_storage_profile_regs *)FmGetVSPBaseAddr(p_FmVspEntry->h_Fm); ++ if (!p_FmVspEntry->p_FmSpRegsBase) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("impossible to initialize SpRegsBase")); ++ ++ /* order external buffer pools in ascending order of buffer pools sizes */ ++ FmSpSetBufPoolsInAscOrderOfBufSizes(&(p_FmVspEntry->p_FmVspEntryDriverParams)->extBufPools, ++ orderedArray, ++ sizesArray); ++ ++ p_FmVspEntry->extBufPools.numOfPoolsUsed = ++ p_FmVspEntry->p_FmVspEntryDriverParams->extBufPools.numOfPoolsUsed; ++ for (i = 0; i < p_FmVspEntry->extBufPools.numOfPoolsUsed; i++) ++ { ++ p_FmVspEntry->extBufPools.extBufPool[i].id = orderedArray[i]; ++ p_FmVspEntry->extBufPools.extBufPool[i].size = sizesArray[orderedArray[i]]; ++ } ++ ++ /* on user responsibility to fill it according requirement */ ++ memset(&fm_vsp_params, 0, sizeof(struct fm_storage_profile_params)); ++ fm_vsp_params.dma_swap_data = p_FmVspEntry->p_FmVspEntryDriverParams->dmaSwapData; ++ fm_vsp_params.int_context_cache_attr = p_FmVspEntry->p_FmVspEntryDriverParams->dmaIntContextCacheAttr; ++ fm_vsp_params.header_cache_attr = p_FmVspEntry->p_FmVspEntryDriverParams->dmaHeaderCacheAttr; ++ fm_vsp_params.scatter_gather_cache_attr = p_FmVspEntry->p_FmVspEntryDriverParams->dmaScatterGatherCacheAttr; ++ fm_vsp_params.dma_write_optimize = p_FmVspEntry->p_FmVspEntryDriverParams->dmaWriteOptimize; ++ fm_vsp_params.liodn_offset = p_FmVspEntry->p_FmVspEntryDriverParams->liodnOffset; ++ fm_vsp_params.no_scather_gather = p_FmVspEntry->p_FmVspEntryDriverParams->noScatherGather; ++ ++ if (p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion) ++ { ++ fm_vsp_params.buf_pool_depletion.buf_pool_depletion_enabled = TRUE; ++ fm_vsp_params.buf_pool_depletion.pools_grp_mode_enable = p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion->poolsGrpModeEnable; ++ fm_vsp_params.buf_pool_depletion.num_pools = p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion->numOfPools; ++ fm_vsp_params.buf_pool_depletion.pools_to_consider = p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion->poolsToConsider; ++ fm_vsp_params.buf_pool_depletion.single_pool_mode_enable = p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion->singlePoolModeEnable; ++ fm_vsp_params.buf_pool_depletion.pools_to_consider_for_single_mode = p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion->poolsToConsiderForSingleMode; ++ fm_vsp_params.buf_pool_depletion.has_pfc_priorities = TRUE; ++ fm_vsp_params.buf_pool_depletion.pfc_priorities_en = p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion->pfcPrioritiesEn; ++ } ++ else ++ fm_vsp_params.buf_pool_depletion.buf_pool_depletion_enabled = FALSE; ++ ++ if (p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools) ++ { ++ fm_vsp_params.backup_pools.num_backup_pools = p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools->numOfBackupPools; ++ fm_vsp_params.backup_pools.pool_ids = p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools->poolIds; ++ } ++ else ++ fm_vsp_params.backup_pools.num_backup_pools = 0; ++ ++ fm_vsp_params.fm_ext_pools.num_pools_used = p_FmVspEntry->extBufPools.numOfPoolsUsed; ++ fm_vsp_params.fm_ext_pools.ext_buf_pool = (struct fman_ext_pool_params*)&p_FmVspEntry->extBufPools.extBufPool; ++ fm_vsp_params.buf_margins = (struct fman_sp_buf_margins*)&p_FmVspEntry->bufMargins; ++ fm_vsp_params.int_context = (struct fman_sp_int_context_data_copy*)&p_FmVspEntry->intContext; ++ ++ /* no check on err - it was checked earlier */ ++ FmVSPGetAbsoluteProfileId(p_FmVspEntry->h_Fm, ++ p_FmVspEntry->portType, ++ p_FmVspEntry->portId, ++ p_FmVspEntry->relativeProfileId, ++ &absoluteProfileId); ++ ++ ASSERT_COND(p_FmVspEntry->p_FmSpRegsBase); ++ ASSERT_COND(fm_vsp_params.int_context); ++ ASSERT_COND(fm_vsp_params.buf_margins); ++ ASSERT_COND((absoluteProfileId <= FM_VSP_MAX_NUM_OF_ENTRIES)); ++ ++ /* Set all registers related to VSP */ ++ fman_vsp_init(p_FmVspEntry->p_FmSpRegsBase, absoluteProfileId, &fm_vsp_params,FM_PORT_MAX_NUM_OF_EXT_POOLS, BM_MAX_NUM_OF_POOLS, FM_MAX_NUM_OF_PFC_PRIORITIES); ++ ++ p_FmVspEntry->absoluteSpId = absoluteProfileId; ++ ++ if (p_FmVspEntry->p_FmVspEntryDriverParams) ++ XX_Free(p_FmVspEntry->p_FmVspEntryDriverParams); ++ p_FmVspEntry->p_FmVspEntryDriverParams = NULL; ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_Free(t_Handle h_FmVsp) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry *)h_FmVsp; ++ SANITY_CHECK_RETURN_ERROR(h_FmVsp, E_INVALID_HANDLE); ++ XX_Free(p_FmVspEntry); ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigBufferPrefixContent(t_Handle h_FmVsp, t_FmBufferPrefixContent *p_FmBufferPrefixContent) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ ++ memcpy(&p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent, p_FmBufferPrefixContent, sizeof(t_FmBufferPrefixContent)); ++ /* if dataAlign was not initialized by user, we return to driver's default */ ++ if (!p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.dataAlign) ++ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.dataAlign = DEFAULT_FM_SP_bufferPrefixContent_dataAlign; ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigDmaSwapData(t_Handle h_FmVsp, e_FmDmaSwapOption swapData) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaSwapData = swapData; ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigDmaIcCacheAttr(t_Handle h_FmVsp, e_FmDmaCacheOption intContextCacheAttr) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaIntContextCacheAttr = intContextCacheAttr; ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigDmaHdrAttr(t_Handle h_FmVsp, e_FmDmaCacheOption headerCacheAttr) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaHeaderCacheAttr = headerCacheAttr; ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigDmaScatterGatherAttr(t_Handle h_FmVsp, e_FmDmaCacheOption scatterGatherCacheAttr) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaScatterGatherCacheAttr = scatterGatherCacheAttr; ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigDmaWriteOptimize(t_Handle h_FmVsp, bool optimize) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->dmaWriteOptimize = optimize; ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigNoScatherGather(t_Handle h_FmVsp, bool noScatherGather) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->noScatherGather = noScatherGather; ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigPoolDepletion(t_Handle h_FmVsp, t_FmBufPoolDepletion *p_BufPoolDepletion) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmVsp, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_BufPoolDepletion, E_INVALID_HANDLE); ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion = (t_FmBufPoolDepletion *)XX_Malloc(sizeof(t_FmBufPoolDepletion)); ++ if (!p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_BufPoolDepletion allocation failed")); ++ memcpy(p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion, p_BufPoolDepletion, sizeof(t_FmBufPoolDepletion)); ++ ++ return E_OK; ++} ++ ++t_Error FM_VSP_ConfigBackupPools(t_Handle h_FmVsp, t_FmBackupBmPools *p_BackupBmPools) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmVsp, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_BackupBmPools, E_INVALID_HANDLE); ++ ++ p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools = (t_FmBackupBmPools *)XX_Malloc(sizeof(t_FmBackupBmPools)); ++ if (!p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_BackupBmPools allocation failed")); ++ memcpy(p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools, p_BackupBmPools, sizeof(t_FmBackupBmPools)); ++ ++ return E_OK; ++} ++ ++uint32_t FM_VSP_GetBufferDataOffset(t_Handle h_FmVsp) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, 0); ++ ++ return p_FmVspEntry->bufferOffsets.dataOffset; ++} ++ ++uint8_t * FM_VSP_GetBufferICInfo(t_Handle h_FmVsp, char *p_Data) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, NULL); ++ ++ if (p_FmVspEntry->bufferOffsets.pcdInfoOffset == ILLEGAL_BASE) ++ return NULL; ++ ++ return (uint8_t *)PTR_MOVE(p_Data, p_FmVspEntry->bufferOffsets.pcdInfoOffset); ++} ++ ++t_FmPrsResult * FM_VSP_GetBufferPrsResult(t_Handle h_FmVsp, char *p_Data) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, NULL); ++ ++ if (p_FmVspEntry->bufferOffsets.prsResultOffset == ILLEGAL_BASE) ++ return NULL; ++ ++ return (t_FmPrsResult *)PTR_MOVE(p_Data, p_FmVspEntry->bufferOffsets.prsResultOffset); ++} ++ ++uint64_t * FM_VSP_GetBufferTimeStamp(t_Handle h_FmVsp, char *p_Data) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, NULL); ++ ++ if (p_FmVspEntry->bufferOffsets.timeStampOffset == ILLEGAL_BASE) ++ return NULL; ++ ++ return (uint64_t *)PTR_MOVE(p_Data, p_FmVspEntry->bufferOffsets.timeStampOffset); ++} ++ ++uint8_t * FM_VSP_GetBufferHashResult(t_Handle h_FmVsp, char *p_Data) ++{ ++ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, NULL); ++ ++ if (p_FmVspEntry->bufferOffsets.hashResultOffset == ILLEGAL_BASE) ++ return NULL; ++ ++ return (uint8_t *)PTR_MOVE(p_Data, p_FmVspEntry->bufferOffsets.hashResultOffset); ++} ++ ++#endif /* (DPAA_VERSION >= 11) */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/SP/fm_sp.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/SP/fm_sp.h +new file mode 100644 +index 0000000..9c171d8 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/SP/fm_sp.h +@@ -0,0 +1,85 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_sp.h ++ ++ @Description FM SP ... ++*//***************************************************************************/ ++#ifndef __FM_SP_H ++#define __FM_SP_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++ ++#include "fm_sp_common.h" ++#include "fm_common.h" ++ ++ ++#define __ERR_MODULE__ MODULE_FM_SP ++ ++typedef struct { ++ t_FmBufferPrefixContent bufferPrefixContent; ++ e_FmDmaSwapOption dmaSwapData; ++ e_FmDmaCacheOption dmaIntContextCacheAttr; ++ e_FmDmaCacheOption dmaHeaderCacheAttr; ++ e_FmDmaCacheOption dmaScatterGatherCacheAttr; ++ bool dmaWriteOptimize; ++ uint16_t liodnOffset; ++ bool noScatherGather; ++ t_FmBufPoolDepletion *p_BufPoolDepletion; ++ t_FmBackupBmPools *p_BackupBmPools; ++ t_FmExtPools extBufPools; ++} t_FmVspEntryDriverParams; ++ ++typedef struct { ++ bool valid; ++ volatile bool lock; ++ uint8_t pointedOwners; ++ uint16_t absoluteSpId; ++ uint8_t internalBufferOffset; ++ t_FmSpBufMargins bufMargins; ++ t_FmSpIntContextDataCopy intContext; ++ t_FmSpBufferOffsets bufferOffsets; ++ t_Handle h_Fm; ++ e_FmPortType portType; /**< Port type */ ++ uint8_t portId; /**< Port Id - relative to type */ ++ uint8_t relativeProfileId; ++ struct fm_pcd_storage_profile_regs *p_FmSpRegsBase; ++ t_FmExtPools extBufPools; ++ t_FmVspEntryDriverParams *p_FmVspEntryDriverParams; ++} t_FmVspEntry; ++ ++ ++#endif /* __FM_SP_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/SP/fman_sp.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/SP/fman_sp.c +new file mode 100755 +index 0000000..0f772e9 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/SP/fman_sp.c +@@ -0,0 +1,197 @@ ++/* ++ * Copyright 2013 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 "fsl_fman_sp.h" ++ ++ ++uint32_t fman_vsp_get_statistics(struct fm_pcd_storage_profile_regs *regs, ++ uint16_t index) ++{ ++ struct fm_pcd_storage_profile_regs *sp_regs; ++ sp_regs = ®s[index]; ++ return ioread32be(&sp_regs->fm_sp_acnt); ++} ++ ++void fman_vsp_set_statistics(struct fm_pcd_storage_profile_regs *regs, ++ uint16_t index, uint32_t value) ++{ ++ struct fm_pcd_storage_profile_regs *sp_regs; ++ sp_regs = ®s[index]; ++ iowrite32be(value, &sp_regs->fm_sp_acnt); ++} ++ ++void fman_vsp_defconfig(struct fm_storage_profile_params *cfg) ++{ ++ cfg->dma_swap_data = ++ DEFAULT_FMAN_SP_DMA_SWAP_DATA; ++ cfg->int_context_cache_attr = ++ DEFAULT_FMAN_SP_DMA_INT_CONTEXT_CACHE_ATTR; ++ cfg->header_cache_attr = ++ DEFAULT_FMAN_SP_DMA_HEADER_CACHE_ATTR; ++ cfg->scatter_gather_cache_attr = ++ DEFAULT_FMAN_SP_DMA_SCATTER_GATHER_CACHE_ATTR; ++ cfg->dma_write_optimize = ++ DEFAULT_FMAN_SP_DMA_WRITE_OPTIMIZE; ++ cfg->no_scather_gather = ++ DEFAULT_FMAN_SP_NO_SCATTER_GATHER; ++} ++ ++static inline uint32_t calc_vec_dep(int max_pools, bool *pools, ++ struct fman_ext_pools *ext_buf_pools, uint32_t mask) ++{ ++ int i, j; ++ uint32_t vector = 0; ++ for (i = 0; i < max_pools; i++) ++ if (pools[i]) ++ for (j = 0; j < ext_buf_pools->num_pools_used; j++) ++ if (i == ext_buf_pools->ext_buf_pool[j].id) { ++ vector |= mask >> j; ++ break; ++ } ++ return vector; ++} ++ ++void fman_vsp_init(struct fm_pcd_storage_profile_regs *regs, ++ uint16_t index, struct fm_storage_profile_params *fm_vsp_params, ++ int port_max_num_of_ext_pools, int bm_max_num_of_pools, ++ int max_num_of_pfc_priorities) ++{ ++ int i = 0, j = 0; ++ struct fm_pcd_storage_profile_regs *sp_regs; ++ uint32_t tmp_reg, vector; ++ struct fman_ext_pools *ext_buf_pools = &fm_vsp_params->fm_ext_pools; ++ struct fman_buf_pool_depletion *buf_pool_depletion = ++ &fm_vsp_params->buf_pool_depletion; ++ struct fman_backup_bm_pools *backup_pools = ++ &fm_vsp_params->backup_pools; ++ struct fman_sp_int_context_data_copy *int_context_data_copy = ++ fm_vsp_params->int_context; ++ struct fman_sp_buf_margins *external_buffer_margins = ++ fm_vsp_params->buf_margins; ++ bool no_scather_gather = fm_vsp_params->no_scather_gather; ++ uint16_t liodn_offset = fm_vsp_params->liodn_offset; ++ ++ sp_regs = ®s[index]; ++ ++ /* fill external buffers manager pool information register*/ ++ for (i = 0; i < ext_buf_pools->num_pools_used; i++) { ++ tmp_reg = FMAN_SP_EXT_BUF_POOL_VALID | ++ FMAN_SP_EXT_BUF_POOL_EN_COUNTER; ++ tmp_reg |= ((uint32_t)ext_buf_pools->ext_buf_pool[i].id << ++ FMAN_SP_EXT_BUF_POOL_ID_SHIFT); ++ tmp_reg |= ext_buf_pools->ext_buf_pool[i].size; ++ /* functionality available only for some deriviatives ++ (limited by config) */ ++ for (j = 0; j < backup_pools->num_backup_pools; j++) ++ if (ext_buf_pools->ext_buf_pool[i].id == ++ backup_pools->pool_ids[j]) { ++ tmp_reg |= FMAN_SP_EXT_BUF_POOL_BACKUP; ++ break; ++ } ++ iowrite32be(tmp_reg, &sp_regs->fm_sp_ebmpi[i]); ++ } ++ ++ /* clear unused pools */ ++ for (i = ext_buf_pools->num_pools_used; ++ i < port_max_num_of_ext_pools; i++) ++ iowrite32be(0, &sp_regs->fm_sp_ebmpi[i]); ++ ++ /* fill pool depletion register*/ ++ tmp_reg = 0; ++ if (buf_pool_depletion->buf_pool_depletion_enabled && buf_pool_depletion->pools_grp_mode_enable) { ++ /* calculate vector for number of pools depletion */ ++ vector = calc_vec_dep(bm_max_num_of_pools, buf_pool_depletion-> ++ pools_to_consider, ext_buf_pools, 0x80000000); ++ ++ /* configure num of pools and vector for number of pools mode */ ++ tmp_reg |= (((uint32_t)buf_pool_depletion->num_pools - 1) << ++ FMAN_SP_POOL_DEP_NUM_OF_POOLS_SHIFT); ++ tmp_reg |= vector; ++ } ++ ++ if (buf_pool_depletion->buf_pool_depletion_enabled && buf_pool_depletion->single_pool_mode_enable) { ++ /* calculate vector for number of pools depletion */ ++ vector = calc_vec_dep(bm_max_num_of_pools, buf_pool_depletion-> ++ pools_to_consider_for_single_mode, ++ ext_buf_pools, 0x00000080); ++ ++ /* configure num of pools and vector for number of pools mode */ ++ tmp_reg |= vector; ++ } ++ ++ /* fill QbbPEV */ ++ if (buf_pool_depletion->buf_pool_depletion_enabled) { ++ vector = 0; ++ for (i = 0; i < max_num_of_pfc_priorities; i++) ++ if (buf_pool_depletion->pfc_priorities_en[i] == TRUE) ++ vector |= 0x00000100 << i; ++ tmp_reg |= vector; ++ } ++ iowrite32be(tmp_reg, &sp_regs->fm_sp_mpd); ++ ++ /* fill dma attributes register */ ++ tmp_reg = 0; ++ tmp_reg |= (uint32_t)fm_vsp_params->dma_swap_data << ++ FMAN_SP_DMA_ATTR_SWP_SHIFT; ++ tmp_reg |= (uint32_t)fm_vsp_params->int_context_cache_attr << ++ FMAN_SP_DMA_ATTR_IC_CACHE_SHIFT; ++ tmp_reg |= (uint32_t)fm_vsp_params->header_cache_attr << ++ FMAN_SP_DMA_ATTR_HDR_CACHE_SHIFT; ++ tmp_reg |= (uint32_t)fm_vsp_params->scatter_gather_cache_attr << ++ FMAN_SP_DMA_ATTR_SG_CACHE_SHIFT; ++ if (fm_vsp_params->dma_write_optimize) ++ tmp_reg |= FMAN_SP_DMA_ATTR_WRITE_OPTIMIZE; ++ iowrite32be(tmp_reg, &sp_regs->fm_sp_da); ++ ++ /* IC parameters - fill internal context parameters register */ ++ tmp_reg = 0; ++ tmp_reg |= (((uint32_t)int_context_data_copy->ext_buf_offset/ ++ OFFSET_UNITS) << FMAN_SP_IC_TO_EXT_SHIFT); ++ tmp_reg |= (((uint32_t)int_context_data_copy->int_context_offset/ ++ OFFSET_UNITS) << FMAN_SP_IC_FROM_INT_SHIFT); ++ tmp_reg |= (((uint32_t)int_context_data_copy->size/OFFSET_UNITS) << ++ FMAN_SP_IC_SIZE_SHIFT); ++ iowrite32be(tmp_reg, &sp_regs->fm_sp_icp); ++ ++ /* buffer margins - fill external buffer margins register */ ++ tmp_reg = 0; ++ tmp_reg |= (((uint32_t)external_buffer_margins->start_margins) << ++ FMAN_SP_EXT_BUF_MARG_START_SHIFT); ++ tmp_reg |= (((uint32_t)external_buffer_margins->end_margins) << ++ FMAN_SP_EXT_BUF_MARG_END_SHIFT); ++ if (no_scather_gather) ++ tmp_reg |= FMAN_SP_SG_DISABLE; ++ iowrite32be(tmp_reg, &sp_regs->fm_sp_ebm); ++ ++ /* buffer margins - fill spliodn register */ ++ iowrite32be(liodn_offset, &sp_regs->fm_sp_spliodn); ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.c +new file mode 100644 +index 0000000..7b9f084 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.c +@@ -0,0 +1,5191 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm.c ++ ++ @Description FM driver routines implementation. ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "xx_ext.h" ++#include "string_ext.h" ++#include "sprint_ext.h" ++#include "debug_ext.h" ++#include "fm_muram_ext.h" ++ ++#include "fm_common.h" ++#include "fm_ipc.h" ++#include "fm.h" ++#include ++#include "fsl_fman.h" ++ ++ ++/****************************************/ ++/* static functions */ ++/****************************************/ ++ ++static volatile bool blockingFlag = FALSE; ++static void IpcMsgCompletionCB(t_Handle h_Fm, ++ uint8_t *p_Msg, ++ uint8_t *p_Reply, ++ uint32_t replyLength, ++ t_Error status) ++{ ++ UNUSED(h_Fm);UNUSED(p_Msg);UNUSED(p_Reply);UNUSED(replyLength);UNUSED(status); ++ blockingFlag = FALSE; ++} ++ ++static void FreeInitResources(t_Fm *p_Fm) ++{ ++ if (p_Fm->camBaseAddr) ++ FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->camBaseAddr)); ++ if (p_Fm->fifoBaseAddr) ++ FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->fifoBaseAddr)); ++ if (p_Fm->resAddr) ++ FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->resAddr)); ++} ++ ++static bool IsFmanCtrlCodeLoaded(t_Fm *p_Fm) ++{ ++ t_FMIramRegs *p_Iram; ++ ++ ASSERT_COND(p_Fm); ++ p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); ++ ++ return (bool)!!(GET_UINT32(p_Iram->iready) & IRAM_READY); ++} ++ ++static t_Error CheckFmParameters(t_Fm *p_Fm) ++{ ++ if (IsFmanCtrlCodeLoaded(p_Fm) && !p_Fm->resetOnInit) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Old FMan CTRL code is loaded; FM must be reset!")); ++#if (DPAA_VERSION < 11) ++ if (!p_Fm->p_FmDriverParam->dma_axi_dbg_num_of_beats || ++ (p_Fm->p_FmDriverParam->dma_axi_dbg_num_of_beats > DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("axiDbgNumOfBeats has to be in the range 1 - %d", DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS)); ++#endif /* (DPAA_VERSION < 11) */ ++ if (p_Fm->p_FmDriverParam->dma_cam_num_of_entries % DMA_CAM_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_cam_num_of_entries has to be divisble by %d", DMA_CAM_UNITS)); ++// if (!p_Fm->p_FmDriverParam->dma_cam_num_of_entries || (p_Fm->p_FmDriverParam->dma_cam_num_of_entries > DMA_MODE_MAX_CAM_NUM_OF_ENTRIES)) ++// RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_cam_num_of_entries has to be in the range 1 - %d", DMA_MODE_MAX_CAM_NUM_OF_ENTRIES)); ++ if (p_Fm->p_FmDriverParam->dma_comm_qtsh_asrt_emer > DMA_THRESH_MAX_COMMQ) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_comm_qtsh_asrt_emer can not be larger than %d", DMA_THRESH_MAX_COMMQ)); ++ if (p_Fm->p_FmDriverParam->dma_comm_qtsh_clr_emer > DMA_THRESH_MAX_COMMQ) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_comm_qtsh_clr_emer can not be larger than %d", DMA_THRESH_MAX_COMMQ)); ++ if (p_Fm->p_FmDriverParam->dma_comm_qtsh_clr_emer >= p_Fm->p_FmDriverParam->dma_comm_qtsh_asrt_emer) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_comm_qtsh_clr_emer must be smaller than dma_comm_qtsh_asrt_emer")); ++#if (DPAA_VERSION < 11) ++ if (p_Fm->p_FmDriverParam->dma_read_buf_tsh_asrt_emer > DMA_THRESH_MAX_BUF) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_read_buf_tsh_asrt_emer can not be larger than %d", DMA_THRESH_MAX_BUF)); ++ if (p_Fm->p_FmDriverParam->dma_read_buf_tsh_clr_emer > DMA_THRESH_MAX_BUF) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_read_buf_tsh_clr_emer can not be larger than %d", DMA_THRESH_MAX_BUF)); ++ if (p_Fm->p_FmDriverParam->dma_read_buf_tsh_clr_emer >= p_Fm->p_FmDriverParam->dma_read_buf_tsh_asrt_emer) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_read_buf_tsh_clr_emer must be smaller than dma_read_buf_tsh_asrt_emer")); ++ if (p_Fm->p_FmDriverParam->dma_write_buf_tsh_asrt_emer > DMA_THRESH_MAX_BUF) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_write_buf_tsh_asrt_emer can not be larger than %d", DMA_THRESH_MAX_BUF)); ++ if (p_Fm->p_FmDriverParam->dma_write_buf_tsh_clr_emer > DMA_THRESH_MAX_BUF) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_write_buf_tsh_clr_emer can not be larger than %d", DMA_THRESH_MAX_BUF)); ++ if (p_Fm->p_FmDriverParam->dma_write_buf_tsh_clr_emer >= p_Fm->p_FmDriverParam->dma_write_buf_tsh_asrt_emer) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_write_buf_tsh_clr_emer must be smaller than dma_write_buf_tsh_asrt_emer")); ++#else /* (DPAA_VERSION >= 11) */ ++ if ((p_Fm->p_FmDriverParam->dma_dbg_cnt_mode == E_FMAN_DMA_DBG_CNT_INT_READ_EM)|| ++ (p_Fm->p_FmDriverParam->dma_dbg_cnt_mode == E_FMAN_DMA_DBG_CNT_INT_WRITE_EM) || ++ (p_Fm->p_FmDriverParam->dma_dbg_cnt_mode == E_FMAN_DMA_DBG_CNT_RAW_WAR_PROT)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_dbg_cnt_mode value not supported by this integration.")); ++ if ((p_Fm->p_FmDriverParam->dma_emergency_bus_select == FM_DMA_MURAM_READ_EMERGENCY)|| ++ (p_Fm->p_FmDriverParam->dma_emergency_bus_select == FM_DMA_MURAM_WRITE_EMERGENCY)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("emergencyBusSelect value not supported by this integration.")); ++ if (p_Fm->p_FmDriverParam->dma_stop_on_bus_error) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_stop_on_bus_error not supported by this integration.")); ++#ifdef FM_AID_MODE_NO_TNUM_SW005 ++ if (p_Fm->p_FmDriverParam->dma_aid_mode != E_FMAN_DMA_AID_OUT_PORT_ID) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_aid_mode not supported by this integration.")); ++#endif /* FM_AID_MODE_NO_TNUM_SW005 */ ++ if (p_Fm->p_FmDriverParam->dma_axi_dbg_num_of_beats) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_axi_dbg_num_of_beats not supported by this integration.")); ++#endif /* (DPAA_VERSION < 11) */ ++ ++ if (!p_Fm->p_FmStateStruct->fmClkFreq) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fmClkFreq must be set.")); ++ if (USEC_TO_CLK(p_Fm->p_FmDriverParam->dma_watchdog, p_Fm->p_FmStateStruct->fmClkFreq) > DMA_MAX_WATCHDOG) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("dma_watchdog depends on FM clock. dma_watchdog(in microseconds) * clk (in Mhz), may not exceed 0x08x", DMA_MAX_WATCHDOG)); ++ ++#if (DPAA_VERSION >= 11) ++ if ((p_Fm->partVSPBase + p_Fm->partNumOfVSPs) > FM_VSP_MAX_NUM_OF_ENTRIES) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partVSPBase+partNumOfVSPs out of range!!!")); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (p_Fm->p_FmStateStruct->totalFifoSize % BMI_FIFO_UNITS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalFifoSize number has to be divisible by %d", BMI_FIFO_UNITS)); ++ if (!p_Fm->p_FmStateStruct->totalFifoSize || ++ (p_Fm->p_FmStateStruct->totalFifoSize > BMI_MAX_FIFO_SIZE)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("totalFifoSize (currently defined as %d) has to be in the range of 256 to %d", ++ p_Fm->p_FmStateStruct->totalFifoSize, ++ BMI_MAX_FIFO_SIZE)); ++ if (!p_Fm->p_FmStateStruct->totalNumOfTasks || ++ (p_Fm->p_FmStateStruct->totalNumOfTasks > BMI_MAX_NUM_OF_TASKS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalNumOfTasks number has to be in the range 1 - %d", BMI_MAX_NUM_OF_TASKS)); ++ ++#ifdef FM_HAS_TOTAL_DMAS ++ if (!p_Fm->p_FmStateStruct->maxNumOfOpenDmas || ++ (p_Fm->p_FmStateStruct->maxNumOfOpenDmas > BMI_MAX_NUM_OF_DMAS)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxNumOfOpenDmas number has to be in the range 1 - %d", BMI_MAX_NUM_OF_DMAS)); ++#endif /* FM_HAS_TOTAL_DMAS */ ++ ++ if (p_Fm->p_FmDriverParam->disp_limit_tsh > FPM_MAX_DISP_LIMIT) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("disp_limit_tsh can't be greater than %d", FPM_MAX_DISP_LIMIT)); ++ ++ if (!p_Fm->f_Exception) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceptions callback not provided")); ++ if (!p_Fm->f_BusError) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceptions callback not provided")); ++ ++#ifdef FM_NO_WATCHDOG ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev == 2) && ++ (p_Fm->p_FmDriverParam->dma_watchdog)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("watchdog!")); ++#endif /* FM_NO_WATCHDOG */ ++ ++#ifdef FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008 ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev < 6) && ++ (p_Fm->p_FmDriverParam->halt_on_unrecov_ecc_err)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("HaltOnEccError!")); ++#endif /* FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008 */ ++ ++#ifdef FM_NO_TNUM_AGING ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev != 4) && ++ (p_Fm->p_FmStateStruct->revInfo.majorRev < 6)) ++ if (p_Fm->p_FmDriverParam->tnum_aging_period) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Tnum aging!")); ++#endif /* FM_NO_TNUM_AGING */ ++ ++ /* check that user did not set revision-dependent exceptions */ ++#ifdef FM_NO_DISPATCH_RAM_ECC ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev != 4) && ++ (p_Fm->p_FmStateStruct->revInfo.majorRev < 6)) ++ if (p_Fm->userSetExceptions & FM_EX_BMI_DISPATCH_RAM_ECC) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("exception e_FM_EX_BMI_DISPATCH_RAM_ECC!")); ++#endif /* FM_NO_DISPATCH_RAM_ECC */ ++ ++#ifdef FM_QMI_NO_ECC_EXCEPTIONS ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev == 4) ++ if (p_Fm->userSetExceptions & (FM_EX_QMI_SINGLE_ECC | FM_EX_QMI_DOUBLE_ECC)) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("exception e_FM_EX_QMI_SINGLE_ECC/e_FM_EX_QMI_DOUBLE_ECC!")); ++#endif /* FM_QMI_NO_ECC_EXCEPTIONS */ ++ ++#ifdef FM_QMI_NO_SINGLE_ECC_EXCEPTION ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ if (p_Fm->userSetExceptions & FM_EX_QMI_SINGLE_ECC) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("exception e_FM_EX_QMI_SINGLE_ECC!")); ++#endif /* FM_QMI_NO_SINGLE_ECC_EXCEPTION */ ++ ++ return E_OK; ++} ++ ++ ++static void SendIpcIsr(t_Fm *p_Fm, uint32_t macEvent, uint32_t pendingReg) ++{ ++ ASSERT_COND(p_Fm->guestId == NCSW_MASTER_ID); ++ ++ if (p_Fm->intrMng[macEvent].guestId == NCSW_MASTER_ID) ++ p_Fm->intrMng[macEvent].f_Isr(p_Fm->intrMng[macEvent].h_SrcHandle); ++ ++ /* If the MAC is running on guest-partition and we have IPC session with it, ++ we inform him about the event through IPC; otherwise, we ignore the event. */ ++ else if (p_Fm->h_IpcSessions[p_Fm->intrMng[macEvent].guestId]) ++ { ++ t_Error err; ++ t_FmIpcIsr fmIpcIsr; ++ t_FmIpcMsg msg; ++ ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_GUEST_ISR; ++ fmIpcIsr.pendingReg = pendingReg; ++ fmIpcIsr.boolErr = FALSE; ++ memcpy(msg.msgBody, &fmIpcIsr, sizeof(fmIpcIsr)); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[p_Fm->intrMng[macEvent].guestId], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(fmIpcIsr), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ } ++ else ++ DBG(TRACE, ("FM Guest mode, without IPC - can't call ISR!")); ++} ++ ++static void BmiErrEvent(t_Fm *p_Fm) ++{ ++ uint32_t event; ++ struct fman_bmi_regs *bmi_rg = p_Fm->p_FmBmiRegs; ++ ++ ++ event = fman_get_bmi_err_event(bmi_rg); ++ ++ if (event & BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_STORAGE_PROFILE_ECC); ++ if (event & BMI_ERR_INTR_EN_LIST_RAM_ECC) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_LIST_RAM_ECC); ++ if (event & BMI_ERR_INTR_EN_STATISTICS_RAM_ECC) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_STATISTICS_RAM_ECC); ++ if (event & BMI_ERR_INTR_EN_DISPATCH_RAM_ECC) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_DISPATCH_RAM_ECC); ++} ++ ++static void QmiErrEvent(t_Fm *p_Fm) ++{ ++ uint32_t event; ++ struct fman_qmi_regs *qmi_rg = p_Fm->p_FmQmiRegs; ++ ++ event = fman_get_qmi_err_event(qmi_rg); ++ ++ if (event & QMI_ERR_INTR_EN_DOUBLE_ECC) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_QMI_DOUBLE_ECC); ++ if (event & QMI_ERR_INTR_EN_DEQ_FROM_DEF) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID); ++} ++ ++static void DmaErrEvent(t_Fm *p_Fm) ++{ ++ uint32_t status, com_id; ++ uint8_t tnum; ++ uint8_t hardwarePortId; ++ uint8_t relativePortId; ++ uint16_t liodn; ++ struct fman_dma_regs *dma_rg = p_Fm->p_FmDmaRegs; ++ ++ status = fman_get_dma_err_event(dma_rg); ++ ++ if (status & DMA_STATUS_BUS_ERR) ++ { ++ com_id = fman_get_dma_com_id(dma_rg); ++ hardwarePortId = (uint8_t)(((com_id & DMA_TRANSFER_PORTID_MASK) >> DMA_TRANSFER_PORTID_SHIFT)); ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ HW_PORT_ID_TO_SW_PORT_ID(relativePortId, hardwarePortId); ++ tnum = (uint8_t)((com_id & DMA_TRANSFER_TNUM_MASK) >> DMA_TRANSFER_TNUM_SHIFT); ++ liodn = (uint16_t)(com_id & DMA_TRANSFER_LIODN_MASK); ++ ASSERT_COND(p_Fm->p_FmStateStruct->portsTypes[hardwarePortId] != e_FM_PORT_TYPE_DUMMY); ++ p_Fm->f_BusError(p_Fm->h_App, ++ p_Fm->p_FmStateStruct->portsTypes[hardwarePortId], ++ relativePortId, ++ fman_get_dma_addr(dma_rg), ++ tnum, ++ liodn); ++ } ++ if (status & DMA_STATUS_FM_SPDAT_ECC) ++ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_SINGLE_PORT_ECC); ++ if (status & DMA_STATUS_READ_ECC) ++ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_READ_ECC); ++ if (status & DMA_STATUS_SYSTEM_WRITE_ECC) ++ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_SYSTEM_WRITE_ECC); ++ if (status & DMA_STATUS_FM_WRITE_ECC) ++ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_FM_WRITE_ECC); ++ } ++ ++static void FpmErrEvent(t_Fm *p_Fm) ++{ ++ uint32_t event; ++ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; ++ ++ event = fman_get_fpm_err_event(fpm_rg); ++ ++ if ((event & FPM_EV_MASK_DOUBLE_ECC) && (event & FPM_EV_MASK_DOUBLE_ECC_EN)) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_FPM_DOUBLE_ECC); ++ if ((event & FPM_EV_MASK_STALL) && (event & FPM_EV_MASK_STALL_EN)) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_FPM_STALL_ON_TASKS); ++ if ((event & FPM_EV_MASK_SINGLE_ECC) && (event & FPM_EV_MASK_SINGLE_ECC_EN)) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_FPM_SINGLE_ECC); ++} ++ ++static void MuramErrIntr(t_Fm *p_Fm) ++{ ++ uint32_t event; ++ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; ++ ++ event = fman_get_muram_err_event(fpm_rg); ++ ++ if (event & FPM_RAM_MURAM_ECC) ++ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_MURAM_ECC); ++} ++ ++static void IramErrIntr(t_Fm *p_Fm) ++{ ++ uint32_t event; ++ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; ++ ++ event = fman_get_iram_err_event(fpm_rg); ++ ++ if (event & FPM_RAM_IRAM_ECC) ++ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_IRAM_ECC); ++} ++ ++static void QmiEvent(t_Fm *p_Fm) ++{ ++ uint32_t event; ++ struct fman_qmi_regs *qmi_rg = p_Fm->p_FmQmiRegs; ++ ++ event = fman_get_qmi_event(qmi_rg); ++ ++ if (event & QMI_INTR_EN_SINGLE_ECC) ++ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_QMI_SINGLE_ECC); ++} ++ ++static void UnimplementedIsr(t_Handle h_Arg) ++{ ++ UNUSED(h_Arg); ++ ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unimplemented ISR!")); ++} ++ ++static void UnimplementedFmanCtrlIsr(t_Handle h_Arg, uint32_t event) ++{ ++ UNUSED(h_Arg); UNUSED(event); ++ ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unimplemented FmCtl ISR!")); ++} ++ ++static void EnableTimeStamp(t_Fm *p_Fm) ++{ ++ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; ++ ++ ASSERT_COND(p_Fm->p_FmStateStruct); ++ ASSERT_COND(p_Fm->p_FmStateStruct->count1MicroBit); ++ ++ fman_enable_time_stamp(fpm_rg, p_Fm->p_FmStateStruct->count1MicroBit, p_Fm->p_FmStateStruct->fmClkFreq); ++ ++ p_Fm->p_FmStateStruct->enabledTimeStamp = TRUE; ++} ++ ++static t_Error ClearIRam(t_Fm *p_Fm) ++{ ++ t_FMIramRegs *p_Iram; ++ int i; ++ int iram_size; ++ ++ ASSERT_COND(p_Fm); ++ p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); ++ iram_size = FM_IRAM_SIZE(p_Fm->p_FmStateStruct->revInfo.majorRev,p_Fm->p_FmStateStruct->revInfo.minorRev); ++ ++ /* Enable the auto-increment */ ++ WRITE_UINT32(p_Iram->iadd, IRAM_IADD_AIE); ++ while (GET_UINT32(p_Iram->iadd) != IRAM_IADD_AIE) ; ++ ++ for (i=0; i < (iram_size/4); i++) ++ WRITE_UINT32(p_Iram->idata, 0xffffffff); ++ ++ WRITE_UINT32(p_Iram->iadd, iram_size - 4); ++ CORE_MemoryBarrier(); ++ while (GET_UINT32(p_Iram->idata) != 0xffffffff) ; ++ ++ return E_OK; ++} ++ ++static t_Error LoadFmanCtrlCode(t_Fm *p_Fm) ++{ ++ t_FMIramRegs *p_Iram; ++ int i; ++ uint32_t tmp; ++ uint8_t compTo16; ++ ++ ASSERT_COND(p_Fm); ++ p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); ++ ++ /* Enable the auto-increment */ ++ WRITE_UINT32(p_Iram->iadd, IRAM_IADD_AIE); ++ while (GET_UINT32(p_Iram->iadd) != IRAM_IADD_AIE) ; ++ ++ for (i=0; i < (p_Fm->firmware.size / 4); i++) ++ WRITE_UINT32(p_Iram->idata, p_Fm->firmware.p_Code[i]); ++ ++ compTo16 = (uint8_t)(p_Fm->firmware.size % 16); ++ if (compTo16) ++ for (i=0; i < ((16-compTo16) / 4); i++) ++ WRITE_UINT32(p_Iram->idata, 0xffffffff); ++ ++ WRITE_UINT32(p_Iram->iadd,p_Fm->firmware.size-4); ++ while (GET_UINT32(p_Iram->iadd) != (p_Fm->firmware.size-4)) ; ++ ++ /* verify that writing has completed */ ++ while (GET_UINT32(p_Iram->idata) != p_Fm->firmware.p_Code[(p_Fm->firmware.size / 4)-1]) ; ++ ++ if (p_Fm->fwVerify) ++ { ++ WRITE_UINT32(p_Iram->iadd, IRAM_IADD_AIE); ++ while (GET_UINT32(p_Iram->iadd) != IRAM_IADD_AIE) ; ++ for (i=0; i < (p_Fm->firmware.size / 4); i++) ++ { ++ tmp = GET_UINT32(p_Iram->idata); ++ if (tmp != p_Fm->firmware.p_Code[i]) ++ RETURN_ERROR(MAJOR, E_WRITE_FAILED, ++ ("UCode write error : write 0x%x, read 0x%x", ++ p_Fm->firmware.p_Code[i],tmp)); ++ } ++ WRITE_UINT32(p_Iram->iadd, 0x0); ++ } ++ ++ /* Enable patch from IRAM */ ++ WRITE_UINT32(p_Iram->iready, IRAM_READY); ++ XX_UDelay(1000); ++ ++ DBG(INFO, ("FMan-Controller code (ver %d.%d.%d) loaded to IRAM.", ++ ((uint16_t *)p_Fm->firmware.p_Code)[2], ++ ((uint8_t *)p_Fm->firmware.p_Code)[6], ++ ((uint8_t *)p_Fm->firmware.p_Code)[7])); ++ ++ return E_OK; ++} ++ ++#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 ++static t_Error FwNotResetErratumBugzilla6173WA(t_Fm *p_Fm) ++{ ++ t_FMIramRegs *p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); ++ uint32_t tmpReg; ++ uint32_t savedSpliodn[63]; ++ ++ /* write to IRAM first location the debug instruction */ ++ WRITE_UINT32(p_Iram->iadd, 0); ++ while (GET_UINT32(p_Iram->iadd) != 0) ; ++ WRITE_UINT32(p_Iram->idata, FM_FW_DEBUG_INSTRUCTION); ++ ++ WRITE_UINT32(p_Iram->iadd, 0); ++ while (GET_UINT32(p_Iram->iadd) != 0) ; ++ while (GET_UINT32(p_Iram->idata) != FM_FW_DEBUG_INSTRUCTION) ; ++ ++ /* Enable patch from IRAM */ ++ WRITE_UINT32(p_Iram->iready, IRAM_READY); ++ CORE_MemoryBarrier(); ++ XX_UDelay(100); ++ IO2MemCpy32((uint8_t *)savedSpliodn, ++ (uint8_t *)p_Fm->p_FmBmiRegs->fmbm_spliodn, ++ 63*sizeof(uint32_t)); ++ ++ /* reset FMAN */ ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, FPM_RSTC_FM_RESET); ++ CORE_MemoryBarrier(); ++ XX_UDelay(100); ++ ++ /* verify breakpoint debug status register */ ++ tmpReg = GET_UINT32(*(uint32_t *)UINT_TO_PTR(p_Fm->baseAddr + FM_DEBUG_STATUS_REGISTER_OFFSET)); ++ if (!tmpReg) ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Invalid debug status register value is '0'")); ++ ++ /*************************************/ ++ /* Load FMan-Controller code to IRAM */ ++ /*************************************/ ++ ClearIRam(p_Fm); ++ if (p_Fm->firmware.p_Code && ++ (LoadFmanCtrlCode(p_Fm) != E_OK)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ XX_UDelay(100); ++ ++ /* reset FMAN again to start the microcode */ ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, FPM_RSTC_FM_RESET); ++ CORE_MemoryBarrier(); ++ XX_UDelay(100); ++ Mem2IOCpy32((uint8_t *)p_Fm->p_FmBmiRegs->fmbm_spliodn, ++ (uint8_t *)savedSpliodn, ++ 63*sizeof(uint32_t)); ++ ++ if (fman_is_qmi_halt_not_busy_state(p_Fm->p_FmQmiRegs)) ++ { ++ fman_resume(p_Fm->p_FmFpmRegs); ++ CORE_MemoryBarrier(); ++ XX_UDelay(100); ++ } ++ ++ return E_OK; ++} ++#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */ ++ ++static void GuestErrorIsr(t_Fm *p_Fm, uint32_t pending) ++{ ++#define FM_G_CALL_1G_MAC_ERR_ISR(_id) \ ++do { \ ++ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].h_SrcHandle);\ ++} while (0) ++#define FM_G_CALL_10G_MAC_ERR_ISR(_id) \ ++do { \ ++ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].h_SrcHandle);\ ++} while (0) ++ ++ /* error interrupts */ ++ if (pending & ERR_INTR_EN_1G_MAC0) ++ FM_G_CALL_1G_MAC_ERR_ISR(0); ++ if (pending & ERR_INTR_EN_1G_MAC1) ++ FM_G_CALL_1G_MAC_ERR_ISR(1); ++ if (pending & ERR_INTR_EN_1G_MAC2) ++ FM_G_CALL_1G_MAC_ERR_ISR(2); ++ if (pending & ERR_INTR_EN_1G_MAC3) ++ FM_G_CALL_1G_MAC_ERR_ISR(3); ++ if (pending & ERR_INTR_EN_1G_MAC4) ++ FM_G_CALL_1G_MAC_ERR_ISR(4); ++ if (pending & ERR_INTR_EN_1G_MAC5) ++ FM_G_CALL_1G_MAC_ERR_ISR(5); ++ if (pending & ERR_INTR_EN_1G_MAC6) ++ FM_G_CALL_1G_MAC_ERR_ISR(6); ++ if (pending & ERR_INTR_EN_1G_MAC7) ++ FM_G_CALL_1G_MAC_ERR_ISR(7); ++ if (pending & ERR_INTR_EN_10G_MAC0) ++ FM_G_CALL_10G_MAC_ERR_ISR(0); ++ if (pending & ERR_INTR_EN_10G_MAC1) ++ FM_G_CALL_10G_MAC_ERR_ISR(1); ++} ++ ++static void GuestEventIsr(t_Fm *p_Fm, uint32_t pending) ++{ ++#define FM_G_CALL_1G_MAC_ISR(_id) \ ++do { \ ++ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].h_SrcHandle);\ ++} while (0) ++#define FM_G_CALL_10G_MAC_ISR(_id) \ ++do { \ ++ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].h_SrcHandle);\ ++} while (0) ++ ++ if (pending & INTR_EN_1G_MAC0) ++ FM_G_CALL_1G_MAC_ISR(0); ++ if (pending & INTR_EN_1G_MAC1) ++ FM_G_CALL_1G_MAC_ISR(1); ++ if (pending & INTR_EN_1G_MAC2) ++ FM_G_CALL_1G_MAC_ISR(2); ++ if (pending & INTR_EN_1G_MAC3) ++ FM_G_CALL_1G_MAC_ISR(3); ++ if (pending & INTR_EN_1G_MAC4) ++ FM_G_CALL_1G_MAC_ISR(4); ++ if (pending & INTR_EN_1G_MAC5) ++ FM_G_CALL_1G_MAC_ISR(5); ++ if (pending & INTR_EN_1G_MAC6) ++ FM_G_CALL_1G_MAC_ISR(6); ++ if (pending & INTR_EN_1G_MAC7) ++ FM_G_CALL_1G_MAC_ISR(7); ++ if (pending & INTR_EN_10G_MAC0) ++ FM_G_CALL_10G_MAC_ISR(0); ++ if (pending & INTR_EN_10G_MAC1) ++ FM_G_CALL_10G_MAC_ISR(1); ++ if (pending & INTR_EN_TMR) ++ p_Fm->intrMng[e_FM_EV_TMR].f_Isr(p_Fm->intrMng[e_FM_EV_TMR].h_SrcHandle); ++} ++ ++#if (DPAA_VERSION >= 11) ++static t_Error SetVSPWindow(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint8_t baseStorageProfile, ++ uint8_t log2NumOfProfiles) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ ++ ASSERT_COND(h_Fm); ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->p_FmBmiRegs && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcVspSetPortWindow fmIpcVspSetPortWindow; ++ t_FmIpcMsg msg; ++ t_Error err = E_OK; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&fmIpcVspSetPortWindow, 0, sizeof(t_FmIpcVspSetPortWindow)); ++ fmIpcVspSetPortWindow.hardwarePortId = hardwarePortId; ++ fmIpcVspSetPortWindow.baseStorageProfile = baseStorageProfile; ++ fmIpcVspSetPortWindow.log2NumOfProfiles = log2NumOfProfiles; ++ msg.msgId = FM_VSP_SET_PORT_WINDOW; ++ memcpy(msg.msgBody, &fmIpcVspSetPortWindow, sizeof(t_FmIpcVspSetPortWindow)); ++ ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ return E_OK; ++ } ++ else if (!p_Fm->p_FmBmiRegs) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ ++ fman_set_vsp_window(p_Fm->p_FmBmiRegs, ++ hardwarePortId, ++ baseStorageProfile, ++ log2NumOfProfiles); ++ ++ return E_OK; ++} ++ ++static uint8_t AllocVSPsForPartition(t_Handle h_Fm, uint8_t base, uint8_t numOfProfiles, uint8_t guestId) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ uint8_t profilesFound = 0; ++ int i = 0; ++ uint32_t intFlags; ++ ++ if (!numOfProfiles) ++ return E_OK; ++ ++ if ((numOfProfiles > FM_VSP_MAX_NUM_OF_ENTRIES) || ++ (base + numOfProfiles > FM_VSP_MAX_NUM_OF_ENTRIES)) ++ return (uint8_t)ILLEGAL_BASE; ++ ++ if (p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ t_Error err; ++ uint32_t replyLength; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); ++ ipcAllocParams.guestId = p_Fm->guestId; ++ ipcAllocParams.num = p_Fm->partNumOfVSPs; ++ ipcAllocParams.base = p_Fm->partVSPBase; ++ msg.msgId = FM_VSP_ALLOC; ++ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); ++ replyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if ((err != E_OK) || ++ (replyLength != (sizeof(uint32_t) + sizeof(uint8_t)))) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ else ++ memcpy((uint8_t*)&p_Fm->partVSPBase, reply.replyBody, sizeof(uint8_t)); ++ if (p_Fm->partVSPBase == (uint8_t)(ILLEGAL_BASE)) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++ DBG(WARNING, ("FM Guest mode, without IPC - can't validate VSP range!")); ++ return (uint8_t)ILLEGAL_BASE; ++ } ++ ++ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock); ++ for (i = base; i < base + numOfProfiles; i++) ++ if (p_Fm->p_FmSp->profiles[i].profilesMng.ownerId == (uint8_t)ILLEGAL_BASE) ++ profilesFound++; ++ else ++ break; ++ ++ if (profilesFound == numOfProfiles) ++ for (i = base; ip_FmSp->profiles[i].profilesMng.ownerId = guestId; ++ else ++ { ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ return (uint8_t)ILLEGAL_BASE; ++ } ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ ++ return base; ++} ++ ++static void FreeVSPsForPartition(t_Handle h_Fm, uint8_t base, uint8_t numOfProfiles, uint8_t guestId) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ int i = 0; ++ ++ ASSERT_COND(p_Fm); ++ ++ if (p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ t_Error err; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); ++ ipcAllocParams.guestId = p_Fm->guestId; ++ ipcAllocParams.num = p_Fm->partNumOfVSPs; ++ ipcAllocParams.base = p_Fm->partVSPBase; ++ msg.msgId = FM_VSP_FREE; ++ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); ++ replyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return; ++ } ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++ DBG(WARNING, ("FM Guest mode, without IPC - can't validate VSP range!")); ++ return; ++ } ++ ++ ASSERT_COND(p_Fm->p_FmSp); ++ ++ for (i=base; ip_FmSp->profiles[i].profilesMng.ownerId == guestId) ++ p_Fm->p_FmSp->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE; ++ else ++ DBG(WARNING, ("Request for freeing storage profile window which wasn't allocated to this partition")); ++ } ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++static t_Error FmGuestHandleIpcMsgCB(t_Handle h_Fm, ++ uint8_t *p_Msg, ++ uint32_t msgLength, ++ uint8_t *p_Reply, ++ uint32_t *p_ReplyLength) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_FmIpcMsg *p_IpcMsg = (t_FmIpcMsg*)p_Msg; ++ ++ UNUSED(p_Reply); ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((msgLength > sizeof(uint32_t)), E_INVALID_VALUE); ++ ++#ifdef DISABLE_SANITY_CHECKS ++ UNUSED(msgLength); ++#endif /* DISABLE_SANITY_CHECKS */ ++ ++ ASSERT_COND(p_Msg); ++ ++ *p_ReplyLength = 0; ++ ++ switch (p_IpcMsg->msgId) ++ { ++ case (FM_GUEST_ISR): ++ { ++ t_FmIpcIsr ipcIsr; ++ ++ memcpy((uint8_t*)&ipcIsr, p_IpcMsg->msgBody, sizeof(t_FmIpcIsr)); ++ if (ipcIsr.boolErr) ++ GuestErrorIsr(p_Fm, ipcIsr.pendingReg); ++ else ++ GuestEventIsr(p_Fm, ipcIsr.pendingReg); ++ break; ++ } ++ default: ++ *p_ReplyLength = 0; ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!")); ++ } ++ return E_OK; ++} ++ ++static t_Error FmHandleIpcMsgCB(t_Handle h_Fm, ++ uint8_t *p_Msg, ++ uint32_t msgLength, ++ uint8_t *p_Reply, ++ uint32_t *p_ReplyLength) ++{ ++ t_Error err; ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_FmIpcMsg *p_IpcMsg = (t_FmIpcMsg*)p_Msg; ++ t_FmIpcReply *p_IpcReply = (t_FmIpcReply*)p_Reply; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((msgLength >= sizeof(uint32_t)), E_INVALID_VALUE); ++ ++#ifdef DISABLE_SANITY_CHECKS ++ UNUSED(msgLength); ++#endif /* DISABLE_SANITY_CHECKS */ ++ ++ ASSERT_COND(p_IpcMsg); ++ ++ memset(p_IpcReply, 0, (sizeof(uint8_t) * FM_IPC_MAX_REPLY_SIZE)); ++ *p_ReplyLength = 0; ++ ++ switch (p_IpcMsg->msgId) ++ { ++ case (FM_GET_SET_PORT_PARAMS): ++ { ++ t_FmIpcPortInInitParams ipcInitParams; ++ t_FmInterModulePortInitParams initParams; ++ t_FmIpcPortOutInitParams ipcOutInitParams; ++ ++ memcpy((uint8_t*)&ipcInitParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortInInitParams)); ++ initParams.hardwarePortId = ipcInitParams.hardwarePortId; ++ initParams.portType = (e_FmPortType)ipcInitParams.enumPortType; ++ initParams.independentMode = (bool)(ipcInitParams.boolIndependentMode); ++ initParams.liodnOffset = ipcInitParams.liodnOffset; ++ initParams.numOfTasks = ipcInitParams.numOfTasks; ++ initParams.numOfExtraTasks = ipcInitParams.numOfExtraTasks; ++ initParams.numOfOpenDmas = ipcInitParams.numOfOpenDmas; ++ initParams.numOfExtraOpenDmas = ipcInitParams.numOfExtraOpenDmas; ++ initParams.sizeOfFifo = ipcInitParams.sizeOfFifo; ++ initParams.extraSizeOfFifo = ipcInitParams.extraSizeOfFifo; ++ initParams.deqPipelineDepth = ipcInitParams.deqPipelineDepth; ++ initParams.maxFrameLength = ipcInitParams.maxFrameLength; ++ initParams.liodnBase = ipcInitParams.liodnBase; ++ ++ p_IpcReply->error = (uint32_t)FmGetSetPortParams(h_Fm, &initParams); ++ ++ ipcOutInitParams.ipcPhysAddr.high = initParams.fmMuramPhysBaseAddr.high; ++ ipcOutInitParams.ipcPhysAddr.low = initParams.fmMuramPhysBaseAddr.low; ++ ipcOutInitParams.sizeOfFifo = initParams.sizeOfFifo; ++ ipcOutInitParams.extraSizeOfFifo = initParams.extraSizeOfFifo; ++ ipcOutInitParams.numOfTasks = initParams.numOfTasks; ++ ipcOutInitParams.numOfExtraTasks = initParams.numOfExtraTasks; ++ ipcOutInitParams.numOfOpenDmas = initParams.numOfOpenDmas; ++ ipcOutInitParams.numOfExtraOpenDmas = initParams.numOfExtraOpenDmas; ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcOutInitParams, sizeof(ipcOutInitParams)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcPortOutInitParams); ++ break; ++ } ++ case (FM_SET_SIZE_OF_FIFO): ++ { ++ t_FmIpcPortRsrcParams ipcPortRsrcParams; ++ ++ memcpy((uint8_t*)&ipcPortRsrcParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortRsrcParams)); ++ p_IpcReply->error = (uint32_t)FmSetSizeOfFifo(h_Fm, ++ ipcPortRsrcParams.hardwarePortId, ++ &ipcPortRsrcParams.val, ++ &ipcPortRsrcParams.extra, ++ (bool)ipcPortRsrcParams.boolInitialConfig); ++ *p_ReplyLength = sizeof(uint32_t); ++ break; ++ } ++ case (FM_SET_NUM_OF_TASKS): ++ { ++ t_FmIpcPortRsrcParams ipcPortRsrcParams; ++ ++ memcpy((uint8_t*)&ipcPortRsrcParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortRsrcParams)); ++ p_IpcReply->error = (uint32_t)FmSetNumOfTasks(h_Fm, ipcPortRsrcParams.hardwarePortId, ++ (uint8_t*)&ipcPortRsrcParams.val, ++ (uint8_t*)&ipcPortRsrcParams.extra, ++ (bool)ipcPortRsrcParams.boolInitialConfig); ++ *p_ReplyLength = sizeof(uint32_t); ++ break; ++ } ++ case (FM_SET_NUM_OF_OPEN_DMAS): ++ { ++ t_FmIpcPortRsrcParams ipcPortRsrcParams; ++ ++ memcpy((uint8_t*)&ipcPortRsrcParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortRsrcParams)); ++ p_IpcReply->error = (uint32_t)FmSetNumOfOpenDmas(h_Fm, ipcPortRsrcParams.hardwarePortId, ++ (uint8_t*)&ipcPortRsrcParams.val, ++ (uint8_t*)&ipcPortRsrcParams.extra, ++ (bool)ipcPortRsrcParams.boolInitialConfig); ++ *p_ReplyLength = sizeof(uint32_t); ++ break; ++ } ++ case (FM_RESUME_STALLED_PORT): ++ *p_ReplyLength = sizeof(uint32_t); ++ p_IpcReply->error = (uint32_t)FmResumeStalledPort(h_Fm, p_IpcMsg->msgBody[0]); ++ break; ++ case (FM_MASTER_IS_ALIVE): ++ { ++ uint8_t guestId = p_IpcMsg->msgBody[0]; ++ /* build the FM master partition IPC address */ ++ memset(p_Fm->fmIpcHandlerModuleName[guestId], 0, (sizeof(char)) * MODULE_NAME_SIZE); ++ if (Sprint (p_Fm->fmIpcHandlerModuleName[guestId], "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, guestId) != (guestId<10 ? 6:7)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ p_Fm->h_IpcSessions[guestId] = XX_IpcInitSession(p_Fm->fmIpcHandlerModuleName[guestId], p_Fm->fmModuleName); ++ if (p_Fm->h_IpcSessions[guestId] == NULL) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM Master IPC session for guest %d", guestId)); ++ *(uint8_t*)(p_IpcReply->replyBody) = 1; ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ break; ++ } ++ case (FM_IS_PORT_STALLED): ++ { ++ bool tmp; ++ ++ p_IpcReply->error = (uint32_t)FmIsPortStalled(h_Fm, p_IpcMsg->msgBody[0], &tmp); ++ *(uint8_t*)(p_IpcReply->replyBody) = (uint8_t)tmp; ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ break; ++ } ++ case (FM_RESET_MAC): ++ { ++ t_FmIpcMacParams ipcMacParams; ++ ++ memcpy((uint8_t*)&ipcMacParams, p_IpcMsg->msgBody, sizeof(t_FmIpcMacParams)); ++ p_IpcReply->error = (uint32_t)FmResetMac(p_Fm, ++ (e_FmMacType)(ipcMacParams.enumType), ++ ipcMacParams.id); ++ *p_ReplyLength = sizeof(uint32_t); ++ break; ++ } ++ case (FM_SET_MAC_MAX_FRAME): ++ { ++ t_FmIpcMacMaxFrameParams ipcMacMaxFrameParams; ++ ++ memcpy((uint8_t*)&ipcMacMaxFrameParams, p_IpcMsg->msgBody, sizeof(t_FmIpcMacMaxFrameParams)); ++ err = FmSetMacMaxFrame(p_Fm, ++ (e_FmMacType)(ipcMacMaxFrameParams.macParams.enumType), ++ ipcMacMaxFrameParams.macParams.id, ++ ipcMacMaxFrameParams.maxFrameLength); ++ if (err != E_OK) ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ break; ++ } ++#if (DPAA_VERSION >= 11) ++ case (FM_VSP_ALLOC) : ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ uint8_t vspBase; ++ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams)); ++ vspBase = AllocVSPsForPartition(h_Fm, (uint8_t)ipcAllocParams.base, (uint8_t)ipcAllocParams.num, ipcAllocParams.guestId); ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&vspBase, sizeof(uint8_t)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ break; ++ } ++ case (FM_VSP_FREE) : ++ { ++ t_FmIpcResourceAllocParams ipcAllocParams; ++ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams)); ++ FreeVSPsForPartition(h_Fm, (uint8_t)ipcAllocParams.base, (uint8_t)ipcAllocParams.num, ipcAllocParams.guestId); ++ break; ++ } ++ case (FM_VSP_SET_PORT_WINDOW) : ++ { ++ t_FmIpcVspSetPortWindow ipcVspSetPortWindow; ++ memcpy(&ipcVspSetPortWindow, p_IpcMsg->msgBody, sizeof(t_FmIpcVspSetPortWindow)); ++ err = SetVSPWindow(h_Fm, ++ ipcVspSetPortWindow.hardwarePortId, ++ ipcVspSetPortWindow.baseStorageProfile, ++ ipcVspSetPortWindow.log2NumOfProfiles); ++ return err; ++ } ++ case (FM_SET_CONG_GRP_PFC_PRIO) : ++ { ++ t_FmIpcSetCongestionGroupPfcPriority fmIpcSetCongestionGroupPfcPriority; ++ memcpy(&fmIpcSetCongestionGroupPfcPriority, p_IpcMsg->msgBody, sizeof(t_FmIpcSetCongestionGroupPfcPriority)); ++ err = FmSetCongestionGroupPFCpriority(h_Fm, ++ fmIpcSetCongestionGroupPfcPriority.congestionGroupId, ++ fmIpcSetCongestionGroupPfcPriority.priorityBitMap); ++ return err; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ case (FM_FREE_PORT): ++ { ++ t_FmInterModulePortFreeParams portParams; ++ t_FmIpcPortFreeParams ipcPortParams; ++ ++ memcpy((uint8_t*)&ipcPortParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortFreeParams)); ++ portParams.hardwarePortId = ipcPortParams.hardwarePortId; ++ portParams.portType = (e_FmPortType)(ipcPortParams.enumPortType); ++ portParams.deqPipelineDepth = ipcPortParams.deqPipelineDepth; ++ FmFreePortParams(h_Fm, &portParams); ++ break; ++ } ++ case (FM_REGISTER_INTR): ++ { ++ t_FmIpcRegisterIntr ipcRegIntr; ++ ++ memcpy((uint8_t*)&ipcRegIntr, p_IpcMsg->msgBody, sizeof(ipcRegIntr)); ++ p_Fm->intrMng[ipcRegIntr.event].guestId = ipcRegIntr.guestId; ++ break; ++ } ++ case (FM_GET_PARAMS): ++ { ++ t_FmIpcParams ipcParams; ++ ++ /* Get clock frequency */ ++ ipcParams.fmClkFreq = p_Fm->p_FmStateStruct->fmClkFreq; ++ ipcParams.fmMacClkFreq = p_Fm->p_FmStateStruct->fmMacClkFreq; ++ ++ fman_get_revision(p_Fm->p_FmFpmRegs,&ipcParams.majorRev,&ipcParams.minorRev); ++ ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcParams, sizeof(t_FmIpcParams)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcParams); ++ break; ++ } ++ case (FM_GET_FMAN_CTRL_CODE_REV): ++ { ++ t_FmCtrlCodeRevisionInfo fmanCtrlRevInfo; ++ t_FmIpcFmanCtrlCodeRevisionInfo ipcRevInfo; ++ ++ p_IpcReply->error = (uint32_t)FM_GetFmanCtrlCodeRevision(h_Fm, &fmanCtrlRevInfo); ++ ipcRevInfo.packageRev = fmanCtrlRevInfo.packageRev; ++ ipcRevInfo.majorRev = fmanCtrlRevInfo.majorRev; ++ ipcRevInfo.minorRev = fmanCtrlRevInfo.minorRev; ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcRevInfo, sizeof(t_FmIpcFmanCtrlCodeRevisionInfo)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcFmanCtrlCodeRevisionInfo); ++ break; ++ } ++ ++ case (FM_DMA_STAT): ++ { ++ t_FmDmaStatus dmaStatus; ++ t_FmIpcDmaStatus ipcDmaStatus; ++ ++ FM_GetDmaStatus(h_Fm, &dmaStatus); ++ ipcDmaStatus.boolCmqNotEmpty = (uint8_t)dmaStatus.cmqNotEmpty; ++ ipcDmaStatus.boolBusError = (uint8_t)dmaStatus.busError; ++ ipcDmaStatus.boolReadBufEccError = (uint8_t)dmaStatus.readBufEccError; ++ ipcDmaStatus.boolWriteBufEccSysError = (uint8_t)dmaStatus.writeBufEccSysError; ++ ipcDmaStatus.boolWriteBufEccFmError = (uint8_t)dmaStatus.writeBufEccFmError; ++ ipcDmaStatus.boolSinglePortEccError = (uint8_t)dmaStatus.singlePortEccError; ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcDmaStatus, sizeof(t_FmIpcDmaStatus)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcDmaStatus); ++ break; ++ } ++ case (FM_ALLOC_FMAN_CTRL_EVENT_REG): ++ p_IpcReply->error = (uint32_t)FmAllocFmanCtrlEventReg(h_Fm, (uint8_t*)p_IpcReply->replyBody); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ break; ++ case (FM_FREE_FMAN_CTRL_EVENT_REG): ++ FmFreeFmanCtrlEventReg(h_Fm, p_IpcMsg->msgBody[0]); ++ break; ++ case (FM_GET_TIMESTAMP_SCALE): ++ { ++ uint32_t timeStamp = FmGetTimeStampScale(h_Fm); ++ ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&timeStamp, sizeof(uint32_t)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ break; ++ } ++ case (FM_GET_COUNTER): ++ { ++ e_FmCounters inCounter; ++ uint32_t outCounter; ++ ++ memcpy((uint8_t*)&inCounter, p_IpcMsg->msgBody, sizeof(uint32_t)); ++ outCounter = FM_GetCounter(h_Fm, inCounter); ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&outCounter, sizeof(uint32_t)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ break; ++ } ++ case (FM_SET_FMAN_CTRL_EVENTS_ENABLE): ++ { ++ t_FmIpcFmanEvents ipcFmanEvents; ++ ++ memcpy((uint8_t*)&ipcFmanEvents, p_IpcMsg->msgBody, sizeof(t_FmIpcFmanEvents)); ++ FmSetFmanCtrlIntr(h_Fm, ++ ipcFmanEvents.eventRegId, ++ ipcFmanEvents.enableEvents); ++ break; ++ } ++ case (FM_GET_FMAN_CTRL_EVENTS_ENABLE): ++ { ++ uint32_t tmp = FmGetFmanCtrlIntr(h_Fm, p_IpcMsg->msgBody[0]); ++ ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&tmp, sizeof(uint32_t)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ break; ++ } ++ case (FM_GET_PHYS_MURAM_BASE): ++ { ++ t_FmPhysAddr physAddr; ++ t_FmIpcPhysAddr ipcPhysAddr; ++ ++ FmGetPhysicalMuramBase(h_Fm, &physAddr); ++ ipcPhysAddr.high = physAddr.high; ++ ipcPhysAddr.low = physAddr.low; ++ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcPhysAddr, sizeof(t_FmIpcPhysAddr)); ++ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcPhysAddr); ++ break; ++ } ++ case (FM_ENABLE_RAM_ECC): ++ { ++ if (((err = FM_EnableRamsEcc(h_Fm)) != E_OK) || ++ ((err = FM_SetException(h_Fm, e_FM_EX_IRAM_ECC, TRUE)) != E_OK) || ++ ((err = FM_SetException(h_Fm, e_FM_EX_MURAM_ECC, TRUE)) != E_OK)) ++#if (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) ++ UNUSED(err); ++#else ++ REPORT_ERROR(MINOR, err, NO_MSG); ++#endif /* (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) */ ++ break; ++ } ++ case (FM_DISABLE_RAM_ECC): ++ { ++ ++ if (((err = FM_SetException(h_Fm, e_FM_EX_IRAM_ECC, FALSE)) != E_OK) || ++ ((err = FM_SetException(h_Fm, e_FM_EX_MURAM_ECC, FALSE)) != E_OK) || ++ ((err = FM_DisableRamsEcc(h_Fm)) != E_OK)) ++#if (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) ++ UNUSED(err); ++#else ++ REPORT_ERROR(MINOR, err, NO_MSG); ++#endif /* (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) */ ++ break; ++ } ++ case (FM_SET_NUM_OF_FMAN_CTRL): ++ { ++ t_FmIpcPortNumOfFmanCtrls ipcPortNumOfFmanCtrls; ++ ++ memcpy((uint8_t*)&ipcPortNumOfFmanCtrls, p_IpcMsg->msgBody, sizeof(t_FmIpcPortNumOfFmanCtrls)); ++ err = FmSetNumOfRiscsPerPort(h_Fm, ++ ipcPortNumOfFmanCtrls.hardwarePortId, ++ ipcPortNumOfFmanCtrls.numOfFmanCtrls, ++ ipcPortNumOfFmanCtrls.orFmanCtrl); ++ if (err != E_OK) ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ break; ++ } ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++ case (FM_10G_TX_ECC_WA): ++ p_IpcReply->error = (uint32_t)Fm10GTxEccWorkaround(h_Fm, p_IpcMsg->msgBody[0]); ++ *p_ReplyLength = sizeof(uint32_t); ++ break; ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ default: ++ *p_ReplyLength = 0; ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!")); ++ } ++ return E_OK; ++} ++ ++ ++/****************************************/ ++/* Inter-Module functions */ ++/****************************************/ ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++t_Error Fm10GTxEccWorkaround(t_Handle h_Fm, uint8_t macId) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_Error err = E_OK; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ uint8_t rxHardwarePortId, txHardwarePortId; ++ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; ++ ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_10G_TX_ECC_WA; ++ msg.msgBody[0] = macId; ++ replyLength = sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(macId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return (t_Error)(reply.error); ++ } ++ ++ SANITY_CHECK_RETURN_ERROR((macId == 0), E_NOT_SUPPORTED); ++ SANITY_CHECK_RETURN_ERROR(IsFmanCtrlCodeLoaded(p_Fm), E_INVALID_STATE); ++ ++ rxHardwarePortId = SwPortIdToHwPortId(e_FM_PORT_TYPE_RX_10G, ++ macId, ++ p_Fm->p_FmStateStruct->revInfo.majorRev, ++ p_Fm->p_FmStateStruct->revInfo.minorRev); ++ txHardwarePortId = SwPortIdToHwPortId(e_FM_PORT_TYPE_TX_10G, ++ macId, ++ p_Fm->p_FmStateStruct->revInfo.majorRev, ++ p_Fm->p_FmStateStruct->revInfo.minorRev); ++ if ((p_Fm->p_FmStateStruct->portsTypes[rxHardwarePortId] != e_FM_PORT_TYPE_DUMMY) || ++ (p_Fm->p_FmStateStruct->portsTypes[txHardwarePortId] != e_FM_PORT_TYPE_DUMMY)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("MAC should be initialized prior to Rx and Tx ports!")); ++ ++ return fman_set_erratum_10gmac_a004_wa(fpm_rg); ++} ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++uint16_t FmGetTnumAgingPeriod(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_Fm->p_FmDriverParam, E_INVALID_STATE, 0); ++ ++ return p_Fm->tnumAgingPeriod; ++} ++ ++t_Error FmSetPortPreFetchConfiguration(t_Handle h_Fm, ++ uint8_t portNum, ++ bool preFetchConfigured) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ ++ p_Fm->portsPreFetchConfigured[portNum] = TRUE; ++ p_Fm->portsPreFetchValue[portNum] = preFetchConfigured; ++ ++ return E_OK; ++} ++ ++t_Error FmGetPortPreFetchConfiguration(t_Handle h_Fm, ++ uint8_t portNum, ++ bool *p_PortConfigured, ++ bool *p_PreFetchConfigured) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ ++ /* If the prefetch wasn't configured yet (not enable or disabled) ++ we return the value TRUE as it was already configured */ ++ if (!p_Fm->portsPreFetchConfigured[portNum]) ++ { ++ *p_PortConfigured = FALSE; ++ *p_PreFetchConfigured = FALSE; ++ } ++ else ++ { ++ *p_PortConfigured = TRUE; ++ *p_PreFetchConfigured = (p_Fm->portsPreFetchConfigured[portNum]); ++ } ++ ++ return E_OK; ++} ++ ++t_Error FmSetCongestionGroupPFCpriority(t_Handle h_Fm, ++ uint32_t congestionGroupId, ++ uint8_t priorityBitMap) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ uint32_t regNum; ++ ++ ASSERT_COND(h_Fm); ++ ++ if (congestionGroupId > FM_PORT_NUM_OF_CONGESTION_GRPS) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("Congestion group ID bigger than %d", ++ FM_PORT_NUM_OF_CONGESTION_GRPS)); ++ ++ if (p_Fm->guestId == NCSW_MASTER_ID) ++ { ++ ASSERT_COND(p_Fm->baseAddr); ++ regNum = (FM_PORT_NUM_OF_CONGESTION_GRPS - 1 - congestionGroupId) / 4; ++ fman_set_congestion_group_pfc_priority((uint32_t *)((p_Fm->baseAddr+FM_MM_CGP)), ++ congestionGroupId, ++ priorityBitMap, ++ regNum); ++ } ++ else if (p_Fm->h_IpcSessions[0]) ++ { ++ t_Error err; ++ t_FmIpcMsg msg; ++ t_FmIpcSetCongestionGroupPfcPriority fmIpcSetCongestionGroupPfcPriority; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&fmIpcSetCongestionGroupPfcPriority, 0, sizeof(t_FmIpcSetCongestionGroupPfcPriority)); ++ fmIpcSetCongestionGroupPfcPriority.congestionGroupId = congestionGroupId; ++ fmIpcSetCongestionGroupPfcPriority.priorityBitMap = priorityBitMap; ++ ++ msg.msgId = FM_SET_CONG_GRP_PFC_PRIO; ++ memcpy(msg.msgBody, &fmIpcSetCongestionGroupPfcPriority, sizeof(t_FmIpcSetCongestionGroupPfcPriority)); ++ ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("guest without IPC!")); ++ ++ return E_OK; ++} ++ ++uintptr_t FmGetPcdPrsBaseAddr(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); ++ ++ if (!p_Fm->baseAddr) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ++ ("No base-addr; probably Guest with IPC!")); ++ return 0; ++ } ++ ++ return (p_Fm->baseAddr + FM_MM_PRS); ++} ++ ++uintptr_t FmGetPcdKgBaseAddr(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); ++ ++ if (!p_Fm->baseAddr) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ++ ("No base-addr; probably Guest with IPC!")); ++ return 0; ++ } ++ ++ return (p_Fm->baseAddr + FM_MM_KG); ++} ++ ++uintptr_t FmGetPcdPlcrBaseAddr(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); ++ ++ if (!p_Fm->baseAddr) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ++ ("No base-addr; probably Guest with IPC!")); ++ return 0; ++ } ++ ++ return (p_Fm->baseAddr + FM_MM_PLCR); ++} ++ ++#if (DPAA_VERSION >= 11) ++uintptr_t FmGetVSPBaseAddr(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); ++ ++ return p_Fm->vspBaseAddr; ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++t_Handle FmGetMuramHandle(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, NULL); ++ ++ return (p_Fm->h_FmMuram); ++} ++ ++void FmGetPhysicalMuramBase(t_Handle h_Fm, t_FmPhysAddr *p_FmPhysAddr) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ if (p_Fm->fmMuramPhysBaseAddr) ++ { ++ /* General FM driver initialization */ ++ p_FmPhysAddr->low = (uint32_t)p_Fm->fmMuramPhysBaseAddr; ++ p_FmPhysAddr->high = (uint8_t)((p_Fm->fmMuramPhysBaseAddr & 0x000000ff00000000LL) >> 32); ++ return; ++ } ++ ++ ASSERT_COND(p_Fm->guestId != NCSW_MASTER_ID); ++ ++ if (p_Fm->h_IpcSessions[0]) ++ { ++ t_Error err; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ t_FmIpcPhysAddr ipcPhysAddr; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_GET_PHYS_MURAM_BASE; ++ replyLength = sizeof(uint32_t) + sizeof(t_FmPhysAddr); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return; ++ } ++ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmPhysAddr))) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_VALUE,("IPC reply length mismatch")); ++ return; ++ } ++ memcpy((uint8_t*)&ipcPhysAddr, reply.replyBody, sizeof(t_FmIpcPhysAddr)); ++ p_FmPhysAddr->high = ipcPhysAddr.high; ++ p_FmPhysAddr->low = ipcPhysAddr.low; ++ } ++ else ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without neither IPC nor mapped register!")); ++} ++ ++#if (DPAA_VERSION >= 11) ++t_Error FmVSPAllocForPort (t_Handle h_Fm, ++ e_FmPortType portType, ++ uint8_t portId, ++ uint8_t numOfVSPs) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ t_Error err = E_OK; ++ uint32_t profilesFound, intFlags; ++ uint8_t first, i; ++ uint8_t log2Num; ++ uint8_t swPortIndex=0, hardwarePortId; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ ++ if (!numOfVSPs) ++ return E_OK; ++ ++ if (numOfVSPs > FM_VSP_MAX_NUM_OF_ENTRIES) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles can not be bigger than %d.",FM_VSP_MAX_NUM_OF_ENTRIES)); ++ ++ if (!POWER_OF_2(numOfVSPs)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numProfiles must be a power of 2.")); ++ ++ LOG2((uint64_t)numOfVSPs, log2Num); ++ ++ if ((log2Num == 0) || (p_Fm->partVSPBase == 0)) ++ first = 0; ++ else ++ first = 1< (p_Fm->partVSPBase + p_Fm->partNumOfVSPs)) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("can not allocate storage profile port window")); ++ ++ if (first < p_Fm->partVSPBase) ++ while (first < p_Fm->partVSPBase) ++ first = first + numOfVSPs; ++ ++ if ((first + numOfVSPs) > (p_Fm->partVSPBase + p_Fm->partNumOfVSPs)) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("can not allocate storage profile port window")); ++ ++ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock); ++ profilesFound = 0; ++ for (i=first; i < p_Fm->partVSPBase + p_Fm->partNumOfVSPs; ) ++ { ++ if (!p_Fm->p_FmSp->profiles[i].profilesMng.allocated) ++ { ++ profilesFound++; ++ i++; ++ if (profilesFound == numOfVSPs) ++ break; ++ } ++ else ++ { ++ profilesFound = 0; ++ /* advance i to the next aligned address */ ++ first = i = (uint8_t)(first + numOfVSPs); ++ } ++ } ++ if (profilesFound == numOfVSPs) ++ for (i = first; ip_FmSp->profiles[i].profilesMng.allocated = TRUE; ++ else ++ { ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ RETURN_ERROR(MINOR, E_FULL, ("No profiles.")); ++ } ++ ++ hardwarePortId = SwPortIdToHwPortId(portType, ++ portId, ++ p_Fm->p_FmStateStruct->revInfo.majorRev, ++ p_Fm->p_FmStateStruct->revInfo.minorRev); ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ ++ p_Fm->p_FmSp->portsMapping[swPortIndex].numOfProfiles = numOfVSPs; ++ p_Fm->p_FmSp->portsMapping[swPortIndex].profilesBase = first; ++ ++ if ((err = SetVSPWindow(h_Fm,hardwarePortId, first,log2Num)) != E_OK) ++ for (i = first; i < first + numOfVSPs; i++) ++ p_Fm->p_FmSp->profiles[i].profilesMng.allocated = FALSE; ++ ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ ++ return err; ++} ++ ++t_Error FmVSPFreeForPort(t_Handle h_Fm, ++ e_FmPortType portType, ++ uint8_t portId) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ uint8_t swPortIndex=0, hardwarePortId, first, numOfVSPs, i; ++ uint32_t intFlags; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ ++ hardwarePortId = SwPortIdToHwPortId(portType, ++ portId, ++ p_Fm->p_FmStateStruct->revInfo.majorRev, ++ p_Fm->p_FmStateStruct->revInfo.minorRev); ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ ++ numOfVSPs = (uint8_t)p_Fm->p_FmSp->portsMapping[swPortIndex].numOfProfiles; ++ first = (uint8_t)p_Fm->p_FmSp->portsMapping[swPortIndex].profilesBase; ++ ++ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock); ++ for (i = first; i < first + numOfVSPs; i++) ++ p_Fm->p_FmSp->profiles[i].profilesMng.allocated = FALSE; ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ ++ p_Fm->p_FmSp->portsMapping[swPortIndex].numOfProfiles = 0; ++ p_Fm->p_FmSp->portsMapping[swPortIndex].profilesBase = 0; ++ ++ return E_OK; ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++t_Error FmAllocFmanCtrlEventReg(t_Handle h_Fm, uint8_t *p_EventId) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint8_t i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_Error err; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_ALLOC_FMAN_CTRL_EVENT_REG; ++ replyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (replyLength != (sizeof(uint32_t) + sizeof(uint8_t))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ ++ *p_EventId = *(uint8_t*)(reply.replyBody); ++ ++ return (t_Error)(reply.error); ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++ ++ for (i=0;iusedEventRegs[i]) ++ { ++ p_Fm->usedEventRegs[i] = TRUE; ++ *p_EventId = i; ++ break; ++ } ++ ++ if (i==FM_NUM_OF_FMAN_CTRL_EVENT_REGS) ++ RETURN_ERROR(MAJOR, E_BUSY, ("No resource - FMan controller event register.")); ++ ++ return E_OK; ++} ++ ++void FmFreeFmanCtrlEventReg(t_Handle h_Fm, uint8_t eventId) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_Error err; ++ t_FmIpcMsg msg; ++ ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_FREE_FMAN_CTRL_EVENT_REG; ++ msg.msgBody[0] = eventId; ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(eventId), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return; ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++ return; ++ } ++ ++ ((t_Fm*)h_Fm)->usedEventRegs[eventId] = FALSE; ++} ++ ++void FmSetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, uint32_t enableEvents) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->p_FmFpmRegs && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcFmanEvents fmanCtrl; ++ t_Error err; ++ t_FmIpcMsg msg; ++ ++ fmanCtrl.eventRegId = eventRegId; ++ fmanCtrl.enableEvents = enableEvents; ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_SET_FMAN_CTRL_EVENTS_ENABLE; ++ memcpy(msg.msgBody, &fmanCtrl, sizeof(fmanCtrl)); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(fmanCtrl), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return; ++ } ++ else if (!p_Fm->p_FmFpmRegs) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ return; ++ } ++ ++ ASSERT_COND(eventRegId < FM_NUM_OF_FMAN_CTRL_EVENT_REGS); ++ fman_set_ctrl_intr(fpm_rg, eventRegId, enableEvents); ++} ++ ++uint32_t FmGetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->p_FmFpmRegs && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_Error err; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength, ctrlIntr; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_GET_FMAN_CTRL_EVENTS_ENABLE; ++ msg.msgBody[0] = eventRegId; ++ replyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(eventRegId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return 0; ++ } ++ if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t))) ++ { ++ REPORT_ERROR(MINOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return 0; ++ } ++ memcpy((uint8_t*)&ctrlIntr, reply.replyBody, sizeof(uint32_t)); ++ return ctrlIntr; ++ } ++ else if (!p_Fm->p_FmFpmRegs) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ return 0; ++ } ++ ++ return fman_get_ctrl_intr(fpm_rg, eventRegId); ++} ++ ++void FmRegisterIntr(t_Handle h_Fm, ++ e_FmEventModules module, ++ uint8_t modId, ++ e_FmIntrType intrType, ++ void (*f_Isr) (t_Handle h_Arg), ++ t_Handle h_Arg) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ int event = 0; ++ ++ ASSERT_COND(h_Fm); ++ ++ GET_FM_MODULE_EVENT(module, modId, intrType, event); ++ ASSERT_COND(event < e_FM_EV_DUMMY_LAST); ++ ++ /* register in local FM structure */ ++ p_Fm->intrMng[event].f_Isr = f_Isr; ++ p_Fm->intrMng[event].h_SrcHandle = h_Arg; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcRegisterIntr fmIpcRegisterIntr; ++ t_Error err; ++ t_FmIpcMsg msg; ++ ++ /* register in Master FM structure */ ++ fmIpcRegisterIntr.event = (uint32_t)event; ++ fmIpcRegisterIntr.guestId = p_Fm->guestId; ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_REGISTER_INTR; ++ memcpy(msg.msgBody, &fmIpcRegisterIntr, sizeof(fmIpcRegisterIntr)); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(fmIpcRegisterIntr), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++} ++ ++void FmUnregisterIntr(t_Handle h_Fm, ++ e_FmEventModules module, ++ uint8_t modId, ++ e_FmIntrType intrType) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ int event = 0; ++ ++ ASSERT_COND(h_Fm); ++ ++ GET_FM_MODULE_EVENT(module, modId,intrType, event); ++ ASSERT_COND(event < e_FM_EV_DUMMY_LAST); ++ ++ p_Fm->intrMng[event].f_Isr = UnimplementedIsr; ++ p_Fm->intrMng[event].h_SrcHandle = NULL; ++} ++ ++void FmRegisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, void (*f_Isr) (t_Handle h_Arg, uint32_t event), t_Handle h_Arg) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ ASSERT_COND(eventRegIdguestId != NCSW_MASTER_ID) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM in guest-mode")); ++ return; ++ } ++ ++ p_Fm->fmanCtrlIntr[eventRegId].f_Isr = f_Isr; ++ p_Fm->fmanCtrlIntr[eventRegId].h_SrcHandle = h_Arg; ++} ++ ++void FmUnregisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ ASSERT_COND(eventRegIdguestId != NCSW_MASTER_ID) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM in guest-mode")); ++ return; ++ } ++ ++ p_Fm->fmanCtrlIntr[eventRegId].f_Isr = UnimplementedFmanCtrlIsr; ++ p_Fm->fmanCtrlIntr[eventRegId].h_SrcHandle = NULL; ++} ++ ++void FmRegisterPcd(t_Handle h_Fm, t_Handle h_FmPcd) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ if (p_Fm->h_Pcd) ++ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("PCD already set")); ++ ++ p_Fm->h_Pcd = h_FmPcd; ++} ++ ++void FmUnregisterPcd(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ if (!p_Fm->h_Pcd) ++ REPORT_ERROR(MAJOR, E_NOT_FOUND, ("PCD handle!")); ++ ++ p_Fm->h_Pcd = NULL; ++} ++ ++t_Handle FmGetPcdHandle(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ return p_Fm->h_Pcd; ++} ++ ++uint8_t FmGetId(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0xff); ++ ++ return p_Fm->p_FmStateStruct->fmId; ++} ++ ++t_Error FmSetNumOfRiscsPerPort(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint8_t numOfFmanCtrls, ++ t_FmFmanCtrl orFmanCtrl) ++{ ++ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ struct fman_fpm_regs *fpm_rg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(((numOfFmanCtrls > 0) && (numOfFmanCtrls < 3)) , E_INVALID_HANDLE); ++ ++ fpm_rg = p_Fm->p_FmFpmRegs; ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->p_FmFpmRegs && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_Error err; ++ t_FmIpcPortNumOfFmanCtrls params; ++ t_FmIpcMsg msg; ++ ++ memset(&msg, 0, sizeof(msg)); ++ params.hardwarePortId = hardwarePortId; ++ params.numOfFmanCtrls = numOfFmanCtrls; ++ params.orFmanCtrl = orFmanCtrl; ++ msg.msgId = FM_SET_NUM_OF_FMAN_CTRL; ++ memcpy(msg.msgBody, ¶ms, sizeof(params)); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) +sizeof(params), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ return E_OK; ++ } ++ else if (!p_Fm->p_FmFpmRegs) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ ++ fman_set_num_of_riscs_per_port(fpm_rg, hardwarePortId, numOfFmanCtrls, orFmanCtrl); ++ ++ return E_OK; ++} ++ ++t_Error FmGetSetPortParams(t_Handle h_Fm, t_FmInterModulePortInitParams *p_PortParams) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_Error err; ++ uint32_t intFlags; ++ uint8_t hardwarePortId = p_PortParams->hardwarePortId, macId; ++ struct fman_rg fman_rg; ++ ++ fman_rg.bmi_rg = p_Fm->p_FmBmiRegs; ++ fman_rg.qmi_rg = p_Fm->p_FmQmiRegs; ++ fman_rg.fpm_rg = p_Fm->p_FmFpmRegs; ++ fman_rg.dma_rg = p_Fm->p_FmDmaRegs; ++ ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++ t_FmIpcPortInInitParams portInParams; ++ t_FmIpcPortOutInitParams portOutParams; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ portInParams.hardwarePortId = p_PortParams->hardwarePortId; ++ portInParams.enumPortType = (uint32_t)p_PortParams->portType; ++ portInParams.boolIndependentMode= (uint8_t)p_PortParams->independentMode; ++ portInParams.liodnOffset = p_PortParams->liodnOffset; ++ portInParams.numOfTasks = p_PortParams->numOfTasks; ++ portInParams.numOfExtraTasks = p_PortParams->numOfExtraTasks; ++ portInParams.numOfOpenDmas = p_PortParams->numOfOpenDmas; ++ portInParams.numOfExtraOpenDmas = p_PortParams->numOfExtraOpenDmas; ++ portInParams.sizeOfFifo = p_PortParams->sizeOfFifo; ++ portInParams.extraSizeOfFifo = p_PortParams->extraSizeOfFifo; ++ portInParams.deqPipelineDepth = p_PortParams->deqPipelineDepth; ++ portInParams.maxFrameLength = p_PortParams->maxFrameLength; ++ portInParams.liodnBase = p_PortParams->liodnBase; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_GET_SET_PORT_PARAMS; ++ memcpy(msg.msgBody, &portInParams, sizeof(portInParams)); ++ replyLength = (sizeof(uint32_t) + sizeof(t_FmIpcPortOutInitParams)); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) +sizeof(portInParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmIpcPortOutInitParams))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ memcpy((uint8_t*)&portOutParams, reply.replyBody, sizeof(t_FmIpcPortOutInitParams)); ++ ++ p_PortParams->fmMuramPhysBaseAddr.high = portOutParams.ipcPhysAddr.high; ++ p_PortParams->fmMuramPhysBaseAddr.low = portOutParams.ipcPhysAddr.low; ++ p_PortParams->numOfTasks = portOutParams.numOfTasks; ++ p_PortParams->numOfExtraTasks = portOutParams.numOfExtraTasks; ++ p_PortParams->numOfOpenDmas = portOutParams.numOfOpenDmas; ++ p_PortParams->numOfExtraOpenDmas = portOutParams.numOfExtraOpenDmas; ++ p_PortParams->sizeOfFifo = portOutParams.sizeOfFifo; ++ p_PortParams->extraSizeOfFifo = portOutParams.extraSizeOfFifo; ++ ++ return (t_Error)(reply.error); ++ } ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ ++ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock); ++ if (p_PortParams->independentMode) ++ { ++ /* set port parameters */ ++ p_Fm->independentMode = p_PortParams->independentMode; ++ /* disable dispatch limit */ ++ fman_qmi_disable_dispatch_limit(fman_rg.fpm_rg); ++ } ++ ++ if (p_PortParams->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) ++ { ++ if (p_Fm->hcPortInitialized) ++ { ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Only one host command port is allowed.")); ++ } ++ else ++ p_Fm->hcPortInitialized = TRUE; ++ } ++ p_Fm->p_FmStateStruct->portsTypes[hardwarePortId] = p_PortParams->portType; ++ ++ err = FmSetNumOfTasks(p_Fm, hardwarePortId, &p_PortParams->numOfTasks, &p_PortParams->numOfExtraTasks, TRUE); ++ if (err) ++ { ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4) ++#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ ++ if ((p_PortParams->portType != e_FM_PORT_TYPE_RX) && ++ (p_PortParams->portType != e_FM_PORT_TYPE_RX_10G)) ++ /* for transmit & O/H ports */ ++ { ++ uint8_t enqTh; ++ uint8_t deqTh; ++ ++ /* update qmi ENQ/DEQ threshold */ ++ p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums += p_PortParams->deqPipelineDepth; ++ enqTh = fman_get_qmi_enq_th(fman_rg.qmi_rg); ++ /* if enqTh is too big, we reduce it to the max value that is still OK */ ++ if (enqTh >= (QMI_MAX_NUM_OF_TNUMS - p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums)) ++ { ++ enqTh = (uint8_t)(QMI_MAX_NUM_OF_TNUMS - p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums - 1); ++ fman_set_qmi_enq_th(fman_rg.qmi_rg, enqTh); ++ } ++ ++ deqTh = fman_get_qmi_deq_th(fman_rg.qmi_rg); ++ /* if deqTh is too small, we enlarge it to the min value that is still OK. ++ deqTh may not be larger than 63 (QMI_MAX_NUM_OF_TNUMS-1). */ ++ if ((deqTh <= p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums) && (deqTh < QMI_MAX_NUM_OF_TNUMS-1)) ++ { ++ deqTh = (uint8_t)(p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums + 1); ++ fman_set_qmi_deq_th(fman_rg.qmi_rg, deqTh); ++ } ++ } ++ ++#ifdef FM_LOW_END_RESTRICTION ++ if ((hardwarePortId==0x1) || (hardwarePortId==0x29)) ++ { ++ if (p_Fm->p_FmStateStruct->lowEndRestriction) ++ { ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("OP #0 cannot work with Tx Port #1.")); ++ } ++ else ++ p_Fm->p_FmStateStruct->lowEndRestriction = TRUE; ++ } ++#endif /* FM_LOW_END_RESTRICTION */ ++ ++ err = FmSetSizeOfFifo(p_Fm, ++ hardwarePortId, ++ &p_PortParams->sizeOfFifo, ++ &p_PortParams->extraSizeOfFifo, ++ TRUE); ++ if (err) ++ { ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ err = FmSetNumOfOpenDmas(p_Fm, ++ hardwarePortId, ++ &p_PortParams->numOfOpenDmas, ++ &p_PortParams->numOfExtraOpenDmas, ++ TRUE); ++ if (err) ++ { ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ fman_set_liodn_per_port(&fman_rg, ++ hardwarePortId, ++ p_PortParams->liodnBase, ++ p_PortParams->liodnOffset); ++ ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6) ++ fman_set_order_restoration_per_port(fman_rg.fpm_rg, ++ hardwarePortId, ++ p_PortParams->independentMode, ++ !!((p_PortParams->portType==e_FM_PORT_TYPE_RX) || (p_PortParams->portType==e_FM_PORT_TYPE_RX_10G))); ++ ++ HW_PORT_ID_TO_SW_PORT_ID(macId, hardwarePortId); ++ ++#if defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS) ++ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX_10G) || ++ (p_PortParams->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ ASSERT_COND(macId < FM_MAX_NUM_OF_10G_MACS); ++ if (p_PortParams->maxFrameLength >= p_Fm->p_FmStateStruct->macMaxFrameLengths10G[macId]) ++ p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId] = p_PortParams->maxFrameLength; ++ else ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Port maxFrameLength is smaller than MAC current MTU")); ++ } ++ else ++#endif /* defined(FM_MAX_NUM_OF_10G_MACS) && ... */ ++ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX) || ++ (p_PortParams->portType == e_FM_PORT_TYPE_RX)) ++ { ++ ASSERT_COND(macId < FM_MAX_NUM_OF_1G_MACS); ++ if (p_PortParams->maxFrameLength >= p_Fm->p_FmStateStruct->macMaxFrameLengths1G[macId]) ++ p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId] = p_PortParams->maxFrameLength; ++ else ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Port maxFrameLength is smaller than MAC current MTU")); ++ } ++ ++ FmGetPhysicalMuramBase(p_Fm, &p_PortParams->fmMuramPhysBaseAddr); ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++ ++ return E_OK; ++} ++ ++void FmFreePortParams(t_Handle h_Fm,t_FmInterModulePortFreeParams *p_PortParams) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t intFlags; ++ uint8_t hardwarePortId = p_PortParams->hardwarePortId; ++ uint8_t numOfTasks, numOfDmas, macId; ++ uint16_t sizeOfFifo; ++ t_Error err; ++ t_FmIpcPortFreeParams portParams; ++ t_FmIpcMsg msg; ++ struct fman_qmi_regs *qmi_rg = p_Fm->p_FmQmiRegs; ++ struct fman_bmi_regs *bmi_rg = p_Fm->p_FmBmiRegs; ++ ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++ portParams.hardwarePortId = p_PortParams->hardwarePortId; ++ portParams.enumPortType = (uint32_t)p_PortParams->portType; ++ portParams.deqPipelineDepth = p_PortParams->deqPipelineDepth; ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_FREE_PORT; ++ memcpy(msg.msgBody, &portParams, sizeof(portParams)); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(portParams), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return; ++ } ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ ++ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock); ++ ++ if (p_PortParams->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) ++ { ++ ASSERT_COND(p_Fm->hcPortInitialized); ++ p_Fm->hcPortInitialized = FALSE; ++ } ++ ++ p_Fm->p_FmStateStruct->portsTypes[hardwarePortId] = e_FM_PORT_TYPE_DUMMY; ++ ++ /* free numOfTasks */ ++ numOfTasks = fman_get_num_of_tasks(bmi_rg, hardwarePortId); ++ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfTasks >= numOfTasks); ++ p_Fm->p_FmStateStruct->accumulatedNumOfTasks -= numOfTasks; ++ ++ /* free numOfOpenDmas */ ++ numOfDmas = fman_get_num_of_dmas(bmi_rg, hardwarePortId); ++ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas >= numOfDmas); ++ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas -= numOfDmas; ++ ++#ifdef FM_HAS_TOTAL_DMAS ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6) ++ { ++ /* update total num of DMA's with committed number of open DMAS, and max uncommitted pool. */ ++ fman_set_num_of_open_dmas(bmi_rg, ++ hardwarePortId, ++ 1, ++ 0, ++ (uint8_t)(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas + p_Fm->p_FmStateStruct->extraOpenDmasPoolSize)); ++ } ++#endif /* FM_HAS_TOTAL_DMAS */ ++ ++ /* free sizeOfFifo */ ++ sizeOfFifo = fman_get_size_of_fifo(bmi_rg, hardwarePortId); ++ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedFifoSize >= (sizeOfFifo * BMI_FIFO_UNITS)); ++ p_Fm->p_FmStateStruct->accumulatedFifoSize -= (sizeOfFifo * BMI_FIFO_UNITS); ++ ++#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4) ++#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ ++ if ((p_PortParams->portType != e_FM_PORT_TYPE_RX) && ++ (p_PortParams->portType != e_FM_PORT_TYPE_RX_10G)) ++ /* for transmit & O/H ports */ ++ { ++ uint8_t enqTh; ++ uint8_t deqTh; ++ ++ /* update qmi ENQ/DEQ threshold */ ++ p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums -= p_PortParams->deqPipelineDepth; ++ ++ /* p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums is now smaller, ++ so we can enlarge enqTh */ ++ enqTh = (uint8_t)(QMI_MAX_NUM_OF_TNUMS - p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums - 1); ++ ++ /* p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums is now smaller, ++ so we can reduce deqTh */ ++ deqTh = (uint8_t)(p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums + 1); ++ ++ fman_set_qmi_enq_th(qmi_rg, enqTh); ++ fman_set_qmi_deq_th(qmi_rg, deqTh); ++ } ++ ++ HW_PORT_ID_TO_SW_PORT_ID(macId, hardwarePortId); ++ ++#if defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS) ++ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX_10G) || ++ (p_PortParams->portType == e_FM_PORT_TYPE_RX_10G)) ++ { ++ ASSERT_COND(macId < FM_MAX_NUM_OF_10G_MACS); ++ p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId] = 0; ++ } ++ else ++#endif /* defined(FM_MAX_NUM_OF_10G_MACS) && ... */ ++ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX) || ++ (p_PortParams->portType == e_FM_PORT_TYPE_RX)) ++ { ++ ASSERT_COND(macId < FM_MAX_NUM_OF_1G_MACS); ++ p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId] = 0; ++ } ++ ++#ifdef FM_LOW_END_RESTRICTION ++ if ((hardwarePortId==0x1) || (hardwarePortId==0x29)) ++ p_Fm->p_FmStateStruct->lowEndRestriction = FALSE; ++#endif /* FM_LOW_END_RESTRICTION */ ++ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); ++} ++ ++t_Error FmIsPortStalled(t_Handle h_Fm, uint8_t hardwarePortId, bool *p_IsStalled) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_Error err; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_IS_PORT_STALLED; ++ msg.msgBody[0] = hardwarePortId; ++ replyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(hardwarePortId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != (sizeof(uint32_t) + sizeof(uint8_t))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ ++ *p_IsStalled = (bool)!!(*(uint8_t*)(reply.replyBody)); ++ ++ return (t_Error)(reply.error); ++ } ++ else if (!p_Fm->baseAddr) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ ++ *p_IsStalled = fman_is_port_stalled(fpm_rg, hardwarePortId); ++ ++ return E_OK; ++} ++ ++t_Error FmResumeStalledPort(t_Handle h_Fm, uint8_t hardwarePortId) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_Error err; ++ bool isStalled; ++ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_RESUME_STALLED_PORT; ++ msg.msgBody[0] = hardwarePortId; ++ replyLength = sizeof(uint32_t); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(hardwarePortId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return (t_Error)(reply.error); ++ } ++ else if (!p_Fm->baseAddr) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ RETURN_ERROR(MINOR, E_NOT_AVAILABLE, ("Not available for this FM revision!")); ++ ++ /* Get port status */ ++ err = FmIsPortStalled(h_Fm, hardwarePortId, &isStalled); ++ if (err) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't get port status")); ++ if (!isStalled) ++ return E_OK; ++ ++ fman_resume_stalled_port(fpm_rg, hardwarePortId); ++ ++ return E_OK; ++} ++ ++t_Error FmResetMac(t_Handle h_Fm, e_FmMacType type, uint8_t macId) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_Error err; ++ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; ++ ++#if (DPAA_VERSION >= 11) ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("FMan MAC reset!")); ++#endif /*(DPAA_VERSION >= 11)*/ ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcMacParams macParams; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ macParams.id = macId; ++ macParams.enumType = (uint32_t)type; ++ msg.msgId = FM_RESET_MAC; ++ memcpy(msg.msgBody, &macParams, sizeof(macParams)); ++ replyLength = sizeof(uint32_t); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(macParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return (t_Error)(reply.error); ++ } ++ else if (!p_Fm->baseAddr) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ ++ err = (t_Error)fman_reset_mac(fpm_rg, macId, !!(type == e_FM_MAC_10G)); ++ ++ if (err == -EBUSY) ++ return ERROR_CODE(E_TIMEOUT); ++ else if (err) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal MAC ID")); ++ ++ return E_OK; ++} ++ ++t_Error FmSetMacMaxFrame(t_Handle h_Fm, e_FmMacType type, uint8_t macId, uint16_t mtu) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcMacMaxFrameParams macMaxFrameLengthParams; ++ t_Error err; ++ t_FmIpcMsg msg; ++ ++ memset(&msg, 0, sizeof(msg)); ++ macMaxFrameLengthParams.macParams.id = macId; ++ macMaxFrameLengthParams.macParams.enumType = (uint32_t)type; ++ macMaxFrameLengthParams.maxFrameLength = (uint16_t)mtu; ++ msg.msgId = FM_SET_MAC_MAX_FRAME; ++ memcpy(msg.msgBody, &macMaxFrameLengthParams, sizeof(macMaxFrameLengthParams)); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(macMaxFrameLengthParams), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ return E_OK; ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++ ++ /* if port is already initialized, check that MaxFrameLength is smaller ++ * or equal to the port's max */ ++#if (defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS)) ++ if (type == e_FM_MAC_10G) ++ { ++ if ((!p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId]) ++ || (p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId] && ++ (mtu <= p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId]))) ++ p_Fm->p_FmStateStruct->macMaxFrameLengths10G[macId] = mtu; ++ else ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("MAC maxFrameLength is larger than Port maxFrameLength")); ++ ++ } ++ else ++#else ++ UNUSED(type); ++#endif /* (defined(FM_MAX_NUM_OF_10G_MACS) && ... */ ++ if ((!p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId]) ++ || (p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId] && ++ (mtu <= p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId]))) ++ p_Fm->p_FmStateStruct->macMaxFrameLengths1G[macId] = mtu; ++ else ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("MAC maxFrameLength is larger than Port maxFrameLength")); ++ ++ return E_OK; ++} ++ ++uint16_t FmGetClockFreq(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ /* for multicore environment: this depends on the ++ * fact that fmClkFreq was properly initialized at "init". */ ++ return p_Fm->p_FmStateStruct->fmClkFreq; ++} ++ ++uint16_t FmGetMacClockFreq(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ return p_Fm->p_FmStateStruct->fmMacClkFreq; ++} ++ ++uint32_t FmGetTimeStampScale(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_Error err; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength, timeStamp; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_GET_TIMESTAMP_SCALE; ++ replyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return 0; ++ } ++ if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t))) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return 0; ++ } ++ ++ memcpy((uint8_t*)&timeStamp, reply.replyBody, sizeof(uint32_t)); ++ return timeStamp; ++ } ++ else if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->baseAddr) ++ { ++ if (!(GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_tsc1) & FPM_TS_CTL_EN)) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("timestamp is not enabled!")); ++ return 0; ++ } ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ DBG(WARNING, ("No IPC - can't validate FM if timestamp enabled.")); ++ ++ return p_Fm->p_FmStateStruct->count1MicroBit; ++} ++ ++t_Error FmEnableRamsEcc(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ ++ p_Fm->p_FmStateStruct->ramsEccOwners++; ++ p_Fm->p_FmStateStruct->internalCall = TRUE; ++ ++ return FM_EnableRamsEcc(p_Fm); ++} ++ ++t_Error FmDisableRamsEcc(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ ++ ASSERT_COND(p_Fm->p_FmStateStruct->ramsEccOwners); ++ p_Fm->p_FmStateStruct->ramsEccOwners--; ++ ++ if (p_Fm->p_FmStateStruct->ramsEccOwners==0) ++ { ++ p_Fm->p_FmStateStruct->internalCall = TRUE; ++ return FM_DisableRamsEcc(p_Fm); ++ } ++ ++ return E_OK; ++} ++ ++uint8_t FmGetGuestId(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ return p_Fm->guestId; ++} ++ ++bool FmIsMaster(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ return (p_Fm->guestId == NCSW_MASTER_ID); ++} ++ ++t_Error FmSetSizeOfFifo(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint32_t *p_SizeOfFifo, ++ uint32_t *p_ExtraSizeOfFifo, ++ bool initialConfig) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_FmIpcPortRsrcParams rsrcParams; ++ t_Error err; ++ struct fman_bmi_regs *bmi_rg = p_Fm->p_FmBmiRegs; ++ uint32_t sizeOfFifo = *p_SizeOfFifo, extraSizeOfFifo = *p_ExtraSizeOfFifo; ++ uint16_t currentVal = 0, currentExtraVal = 0; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ rsrcParams.hardwarePortId = hardwarePortId; ++ rsrcParams.val = sizeOfFifo; ++ rsrcParams.extra = extraSizeOfFifo; ++ rsrcParams.boolInitialConfig = (uint8_t)initialConfig; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_SET_SIZE_OF_FIFO; ++ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams)); ++ replyLength = sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(rsrcParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return (t_Error)(reply.error); ++ } ++ else if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->baseAddr) ++ { ++ DBG(WARNING, ("No IPC - can't validate FM total-fifo size.")); ++ fman_set_size_of_fifo(bmi_rg, hardwarePortId, sizeOfFifo, extraSizeOfFifo); ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without neither IPC nor mapped register!")); ++ ++ if (!initialConfig) ++ { ++ /* !initialConfig - runtime change of existing value. ++ * - read the current FIFO and extra FIFO size */ ++ currentExtraVal = fman_get_size_of_extra_fifo(bmi_rg, hardwarePortId); ++ currentVal = fman_get_size_of_fifo(bmi_rg, hardwarePortId); ++ } ++ ++ if (extraSizeOfFifo > currentExtraVal) ++ { ++ if (extraSizeOfFifo && !p_Fm->p_FmStateStruct->extraFifoPoolSize) ++ /* if this is the first time a port requires extraFifoPoolSize, the total extraFifoPoolSize ++ * must be initialized to 1 buffer per port ++ */ ++ p_Fm->p_FmStateStruct->extraFifoPoolSize = FM_MAX_NUM_OF_RX_PORTS*BMI_FIFO_UNITS; ++ ++ p_Fm->p_FmStateStruct->extraFifoPoolSize = MAX(p_Fm->p_FmStateStruct->extraFifoPoolSize, extraSizeOfFifo); ++ } ++ ++ /* check that there are enough uncommitted fifo size */ ++ if ((p_Fm->p_FmStateStruct->accumulatedFifoSize - currentVal + sizeOfFifo) > ++ (p_Fm->p_FmStateStruct->totalFifoSize - p_Fm->p_FmStateStruct->extraFifoPoolSize)){ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("Port request fifo size + accumulated size > total FIFO size:")); ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ++ ("port 0x%x requested %d bytes, extra size = %d, accumulated size = %d total size = %d", ++ hardwarePortId, sizeOfFifo, p_Fm->p_FmStateStruct->extraFifoPoolSize, ++ p_Fm->p_FmStateStruct->accumulatedFifoSize, ++ p_Fm->p_FmStateStruct->totalFifoSize)); ++ } ++ else ++ { ++ /* update accumulated */ ++ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedFifoSize >= currentVal); ++ p_Fm->p_FmStateStruct->accumulatedFifoSize -= currentVal; ++ p_Fm->p_FmStateStruct->accumulatedFifoSize += sizeOfFifo; ++ fman_set_size_of_fifo(bmi_rg, hardwarePortId, sizeOfFifo, extraSizeOfFifo); ++ } ++ ++ return E_OK; ++} ++ ++t_Error FmSetNumOfTasks(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint8_t *p_NumOfTasks, ++ uint8_t *p_NumOfExtraTasks, ++ bool initialConfig) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ t_Error err; ++ struct fman_bmi_regs *bmi_rg = p_Fm->p_FmBmiRegs; ++ uint8_t currentVal = 0, currentExtraVal = 0, numOfTasks = *p_NumOfTasks, numOfExtraTasks = *p_NumOfExtraTasks; ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcPortRsrcParams rsrcParams; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ rsrcParams.hardwarePortId = hardwarePortId; ++ rsrcParams.val = numOfTasks; ++ rsrcParams.extra = numOfExtraTasks; ++ rsrcParams.boolInitialConfig = (uint8_t)initialConfig; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_SET_NUM_OF_TASKS; ++ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams)); ++ replyLength = sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(rsrcParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return (t_Error)(reply.error); ++ } ++ else if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->baseAddr) ++ { ++ DBG(WARNING, ("No IPC - can't validate FM total-num-of-tasks.")); ++ fman_set_num_of_tasks(bmi_rg, hardwarePortId, numOfTasks, numOfExtraTasks); ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without neither IPC nor mapped register!")); ++ ++ if (!initialConfig) ++ { ++ /* !initialConfig - runtime change of existing value. ++ * - read the current number of tasks */ ++ currentVal = fman_get_num_of_tasks(bmi_rg, hardwarePortId); ++ currentExtraVal = fman_get_num_extra_tasks(bmi_rg, hardwarePortId); ++ } ++ ++ if (numOfExtraTasks > currentExtraVal) ++ p_Fm->p_FmStateStruct->extraTasksPoolSize = ++ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraTasksPoolSize, numOfExtraTasks); ++ ++ /* check that there are enough uncommitted tasks */ ++ if ((p_Fm->p_FmStateStruct->accumulatedNumOfTasks - currentVal + numOfTasks) > ++ (p_Fm->p_FmStateStruct->totalNumOfTasks - p_Fm->p_FmStateStruct->extraTasksPoolSize)) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ++ ("Requested numOfTasks and extra tasks pool for fm%d exceed total numOfTasks.", ++ p_Fm->p_FmStateStruct->fmId)); ++ else ++ { ++ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfTasks >= currentVal); ++ /* update accumulated */ ++ p_Fm->p_FmStateStruct->accumulatedNumOfTasks -= currentVal; ++ p_Fm->p_FmStateStruct->accumulatedNumOfTasks += numOfTasks; ++ fman_set_num_of_tasks(bmi_rg, hardwarePortId, numOfTasks, numOfExtraTasks); ++ } ++ ++ return E_OK; ++} ++ ++t_Error FmSetNumOfOpenDmas(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint8_t *p_NumOfOpenDmas, ++ uint8_t *p_NumOfExtraOpenDmas, ++ bool initialConfig) ++ ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ t_Error err; ++ struct fman_bmi_regs *bmi_rg = p_Fm->p_FmBmiRegs; ++ uint8_t numOfOpenDmas = *p_NumOfOpenDmas, numOfExtraOpenDmas = *p_NumOfExtraOpenDmas; ++ uint8_t totalNumDmas = 0, currentVal = 0, currentExtraVal = 0; ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcPortRsrcParams rsrcParams; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ rsrcParams.hardwarePortId = hardwarePortId; ++ rsrcParams.val = numOfOpenDmas; ++ rsrcParams.extra = numOfExtraOpenDmas; ++ rsrcParams.boolInitialConfig = (uint8_t)initialConfig; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_SET_NUM_OF_OPEN_DMAS; ++ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams)); ++ replyLength = sizeof(uint32_t); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) + sizeof(rsrcParams), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != sizeof(uint32_t)) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return (t_Error)(reply.error); ++ } ++#ifdef FM_HAS_TOTAL_DMAS ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("running in guest-mode without IPC!")); ++#else ++ else if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->baseAddr && ++ (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)) ++ { ++ /*DBG(WARNING, ("No IPC - can't validate FM total-num-of-dmas."));*/ ++ ++ if (!numOfOpenDmas) ++ { ++ /* first config without explic it value: Do Nothing - reset value shouldn't be ++ changed, read register for port save */ ++ *p_NumOfOpenDmas = fman_get_num_of_dmas(bmi_rg, hardwarePortId); ++ *p_NumOfExtraOpenDmas = fman_get_num_extra_dmas(bmi_rg, hardwarePortId); ++ } ++ else ++ /* whether it is the first time with explicit value, or runtime "set" - write register */ ++ fman_set_num_of_open_dmas(bmi_rg, ++ hardwarePortId, ++ numOfOpenDmas, ++ numOfExtraOpenDmas, ++ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas + p_Fm->p_FmStateStruct->extraOpenDmasPoolSize); ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without neither IPC nor mapped register!")); ++#endif /* FM_HAS_TOTAL_DMAS */ ++ ++ if (!initialConfig) ++ { ++ /* !initialConfig - runtime change of existing value. ++ * - read the current number of open Dma's */ ++ currentExtraVal = fman_get_num_extra_dmas(bmi_rg, hardwarePortId); ++ currentVal = fman_get_num_of_dmas(bmi_rg, hardwarePortId); ++ } ++ ++#ifdef FM_NO_GUARANTEED_RESET_VALUES ++ /* it's illegal to be in a state where this is not the first set and no value is specified */ ++ ASSERT_COND(initialConfig || numOfOpenDmas); ++ if (!numOfOpenDmas) ++ { ++ /* !numOfOpenDmas - first configuration according to values in regs. ++ * - read the current number of open Dma's */ ++ currentExtraVal = fman_get_num_extra_dmas(bmi_rg, hardwarePortId); ++ currentVal = fman_get_num_of_dmas(bmi_rg, hardwarePortId); ++ /* This is the first configuration and user did not specify value (!numOfOpenDmas), ++ * reset values will be used and we just save these values for resource management */ ++ p_Fm->p_FmStateStruct->extraOpenDmasPoolSize = ++ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraOpenDmasPoolSize, currentExtraVal); ++ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas += currentVal; ++ *p_NumOfOpenDmas = currentVal; ++ *p_NumOfExtraOpenDmas = currentExtraVal; ++ return E_OK; ++ } ++#endif /* FM_NO_GUARANTEED_RESET_VALUES */ ++ ++ if (numOfExtraOpenDmas > currentExtraVal) ++ p_Fm->p_FmStateStruct->extraOpenDmasPoolSize = ++ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraOpenDmasPoolSize, numOfExtraOpenDmas); ++ ++#ifdef FM_HAS_TOTAL_DMAS ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev < 6) && ++ (p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas - currentVal + numOfOpenDmas > ++ p_Fm->p_FmStateStruct->maxNumOfOpenDmas)) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ++ ("Requested numOfOpenDmas for fm%d exceeds total numOfOpenDmas.", ++ p_Fm->p_FmStateStruct->fmId)); ++#else ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) && ++#ifdef FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981 ++ !((p_Fm->p_FmStateStruct->revInfo.majorRev == 6) && ++ (p_Fm->p_FmStateStruct->revInfo.minorRev == 0)) && ++#endif /* FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981 */ ++ (p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas - currentVal + numOfOpenDmas > DMA_THRESH_MAX_COMMQ + 1)) ++ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ++ ("Requested numOfOpenDmas for fm%d exceeds DMA Command queue (%d)", ++ p_Fm->p_FmStateStruct->fmId, DMA_THRESH_MAX_COMMQ+1)); ++#endif /* FM_HAS_TOTAL_DMAS */ ++ else ++ { ++ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas >= currentVal); ++ /* update acummulated */ ++ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas -= currentVal; ++ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas += numOfOpenDmas; ++ ++#ifdef FM_HAS_TOTAL_DMAS ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6) ++ totalNumDmas = (uint8_t)(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas + p_Fm->p_FmStateStruct->extraOpenDmasPoolSize); ++#endif /* FM_HAS_TOTAL_DMAS */ ++ fman_set_num_of_open_dmas(bmi_rg, ++ hardwarePortId, ++ numOfOpenDmas, ++ numOfExtraOpenDmas, ++ totalNumDmas); ++ } ++ ++ return E_OK; ++} ++ ++#if (DPAA_VERSION >= 11) ++t_Error FmVSPCheckRelativeProfile(t_Handle h_Fm, ++ e_FmPortType portType, ++ uint8_t portId, ++ uint16_t relativeProfile) ++{ ++ t_Fm *p_Fm; ++ t_FmSp *p_FmPcdSp; ++ uint8_t swPortIndex=0, hardwarePortId; ++ ++ ASSERT_COND(h_Fm); ++ p_Fm = (t_Fm*)h_Fm; ++ ++ hardwarePortId = SwPortIdToHwPortId(portType, ++ portId, ++ p_Fm->p_FmStateStruct->revInfo.majorRev, ++ p_Fm->p_FmStateStruct->revInfo.minorRev); ++ ASSERT_COND(hardwarePortId); ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ ++ p_FmPcdSp = p_Fm->p_FmSp; ++ ASSERT_COND(p_FmPcdSp); ++ ++ if (!p_FmPcdSp->portsMapping[swPortIndex].numOfProfiles) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE , ("Port has no allocated profiles")); ++ if (relativeProfile >= p_FmPcdSp->portsMapping[swPortIndex].numOfProfiles) ++ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE , ("Profile id is out of range")); ++ ++ return E_OK; ++} ++ ++t_Error FmVSPGetAbsoluteProfileId(t_Handle h_Fm, ++ e_FmPortType portType, ++ uint8_t portId, ++ uint16_t relativeProfile, ++ uint16_t *p_AbsoluteId) ++{ ++ t_Fm *p_Fm; ++ t_FmSp *p_FmPcdSp; ++ uint8_t swPortIndex=0, hardwarePortId; ++ t_Error err; ++ ++ ASSERT_COND(h_Fm); ++ p_Fm = (t_Fm*)h_Fm; ++ ++ err = FmVSPCheckRelativeProfile(h_Fm, portType, portId, relativeProfile); ++ if (err != E_OK) ++ return err; ++ ++ hardwarePortId = SwPortIdToHwPortId(portType, ++ portId, ++ p_Fm->p_FmStateStruct->revInfo.majorRev, ++ p_Fm->p_FmStateStruct->revInfo.minorRev); ++ ASSERT_COND(hardwarePortId); ++ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); ++ ++ p_FmPcdSp = p_Fm->p_FmSp; ++ ASSERT_COND(p_FmPcdSp); ++ ++ *p_AbsoluteId = (uint16_t)(p_FmPcdSp->portsMapping[swPortIndex].profilesBase + relativeProfile); ++ ++ return E_OK; ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++static t_Error InitFmDma(t_Fm *p_Fm) ++{ ++ t_Error err; ++ ++ err = (t_Error)fman_dma_init(p_Fm->p_FmDmaRegs, p_Fm->p_FmDriverParam); ++ if (err != E_OK) ++ return err; ++ ++ /* Allocate MURAM for CAM */ ++ p_Fm->camBaseAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram, ++ (uint32_t)(p_Fm->p_FmDriverParam->dma_cam_num_of_entries*DMA_CAM_SIZEOF_ENTRY), ++ DMA_CAM_ALIGN)); ++ if (!p_Fm->camBaseAddr) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for DMA CAM failed")); ++ ++ WRITE_BLOCK(UINT_TO_PTR(p_Fm->camBaseAddr), ++ 0, ++ (uint32_t)(p_Fm->p_FmDriverParam->dma_cam_num_of_entries*DMA_CAM_SIZEOF_ENTRY)); ++ ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev == 2) ++ { ++ FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->camBaseAddr)); ++ ++ p_Fm->camBaseAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram, ++ (uint32_t)(p_Fm->p_FmDriverParam->dma_cam_num_of_entries*72 + 128), ++ 64)); ++ if (!p_Fm->camBaseAddr) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for DMA CAM failed")); ++ ++ WRITE_BLOCK(UINT_TO_PTR(p_Fm->camBaseAddr), ++ 0, ++ (uint32_t)(p_Fm->p_FmDriverParam->dma_cam_num_of_entries*72 + 128)); ++ ++ switch(p_Fm->p_FmDriverParam->dma_cam_num_of_entries) ++ { ++ case (8): ++ WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xff000000); ++ break; ++ case (16): ++ WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xffff0000); ++ break; ++ case (24): ++ WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xffffff00); ++ break; ++ case (32): ++ WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xffffffff); ++ break; ++ default: ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("wrong dma_cam_num_of_entries")); ++ } ++ } ++ ++ p_Fm->p_FmDriverParam->cam_base_addr = ++ (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->camBaseAddr)) - p_Fm->fmMuramPhysBaseAddr); ++ ++ return E_OK; ++} ++ ++static t_Error InitFmFpm(t_Fm *p_Fm) ++{ ++ return (t_Error)fman_fpm_init(p_Fm->p_FmFpmRegs, p_Fm->p_FmDriverParam); ++} ++ ++static t_Error InitFmBmi(t_Fm *p_Fm) ++{ ++ return (t_Error)fman_bmi_init(p_Fm->p_FmBmiRegs, p_Fm->p_FmDriverParam); ++} ++ ++static t_Error InitFmQmi(t_Fm *p_Fm) ++{ ++ return (t_Error)fman_qmi_init(p_Fm->p_FmQmiRegs, p_Fm->p_FmDriverParam); ++} ++ ++static t_Error InitGuestMode(t_Fm *p_Fm) ++{ ++ t_Error err = E_OK; ++ int i; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ ++ ASSERT_COND(p_Fm); ++ ASSERT_COND(p_Fm->guestId != NCSW_MASTER_ID); ++ ++ /* build the FM guest partition IPC address */ ++ if (Sprint (p_Fm->fmModuleName, "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, p_Fm->guestId) != (p_Fm->guestId<10 ? 6:7)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ ++ /* build the FM master partition IPC address */ ++ memset(p_Fm->fmIpcHandlerModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE); ++ if (Sprint (p_Fm->fmIpcHandlerModuleName[0], "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, NCSW_MASTER_ID) != 6) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ ++ for (i=0;iintrMng[i].f_Isr = UnimplementedIsr; ++ ++ p_Fm->h_IpcSessions[0] = XX_IpcInitSession(p_Fm->fmIpcHandlerModuleName[0], p_Fm->fmModuleName); ++ if (p_Fm->h_IpcSessions[0]) ++ { ++ uint8_t isMasterAlive; ++ t_FmIpcParams ipcParams; ++ ++ err = XX_IpcRegisterMsgHandler(p_Fm->fmModuleName, FmGuestHandleIpcMsgCB, p_Fm, FM_IPC_MAX_REPLY_SIZE); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_MASTER_IS_ALIVE; ++ msg.msgBody[0] = p_Fm->guestId; ++ replyLength = sizeof(uint32_t) + sizeof(uint8_t); ++ do ++ { ++ blockingFlag = TRUE; ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId)+sizeof(p_Fm->guestId), ++ (uint8_t*)&reply, ++ &replyLength, ++ IpcMsgCompletionCB, ++ p_Fm)) != E_OK) ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ while (blockingFlag) ; ++ if (replyLength != (sizeof(uint32_t) + sizeof(uint8_t))) ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ isMasterAlive = *(uint8_t*)(reply.replyBody); ++ } while (!isMasterAlive); ++ ++ /* read FM parameters and save */ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_GET_PARAMS; ++ replyLength = sizeof(uint32_t) + sizeof(t_FmIpcParams); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmIpcParams))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ memcpy((uint8_t*)&ipcParams, reply.replyBody, sizeof(t_FmIpcParams)); ++ ++ p_Fm->p_FmStateStruct->fmClkFreq = ipcParams.fmClkFreq; ++ p_Fm->p_FmStateStruct->fmMacClkFreq = ipcParams.fmMacClkFreq; ++ p_Fm->p_FmStateStruct->revInfo.majorRev = ipcParams.majorRev; ++ p_Fm->p_FmStateStruct->revInfo.minorRev = ipcParams.minorRev; ++ } ++ else ++ { ++ DBG(WARNING, ("FM Guest mode - without IPC")); ++ if (!p_Fm->p_FmStateStruct->fmClkFreq) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("No fmClkFreq configured for guest without IPC")); ++ if (p_Fm->baseAddr) ++ { ++ fman_get_revision(p_Fm->p_FmFpmRegs, ++ &p_Fm->p_FmStateStruct->revInfo.majorRev, ++ &p_Fm->p_FmStateStruct->revInfo.minorRev); ++ ++ } ++ } ++ ++#if (DPAA_VERSION >= 11) ++ p_Fm->partVSPBase = AllocVSPsForPartition(p_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId); ++ if (p_Fm->partVSPBase == (uint8_t)(ILLEGAL_BASE)) ++ DBG(WARNING, ("partition VSPs allocation is FAILED")); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ /* General FM driver initialization */ ++ if (p_Fm->baseAddr) ++ p_Fm->fmMuramPhysBaseAddr = ++ (uint64_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->baseAddr + FM_MM_MURAM))); ++ ++ XX_Free(p_Fm->p_FmDriverParam); ++ p_Fm->p_FmDriverParam = NULL; ++ ++ if ((p_Fm->guestId == NCSW_MASTER_ID) || ++ (p_Fm->h_IpcSessions[0])) ++ { ++ FM_DisableRamsEcc(p_Fm); ++ FmMuramClear(p_Fm->h_FmMuram); ++ FM_EnableRamsEcc(p_Fm); ++ } ++ ++ return E_OK; ++} ++ ++static __inline__ enum fman_exceptions FmanExceptionTrans(e_FmExceptions exception) ++{ ++ switch (exception) { ++ case e_FM_EX_DMA_BUS_ERROR: ++ return E_FMAN_EX_DMA_BUS_ERROR; ++ case e_FM_EX_DMA_READ_ECC: ++ return E_FMAN_EX_DMA_READ_ECC; ++ case e_FM_EX_DMA_SYSTEM_WRITE_ECC: ++ return E_FMAN_EX_DMA_SYSTEM_WRITE_ECC; ++ case e_FM_EX_DMA_FM_WRITE_ECC: ++ return E_FMAN_EX_DMA_FM_WRITE_ECC; ++ case e_FM_EX_FPM_STALL_ON_TASKS: ++ return E_FMAN_EX_FPM_STALL_ON_TASKS; ++ case e_FM_EX_FPM_SINGLE_ECC: ++ return E_FMAN_EX_FPM_SINGLE_ECC; ++ case e_FM_EX_FPM_DOUBLE_ECC: ++ return E_FMAN_EX_FPM_DOUBLE_ECC; ++ case e_FM_EX_QMI_SINGLE_ECC: ++ return E_FMAN_EX_QMI_SINGLE_ECC; ++ case e_FM_EX_QMI_DOUBLE_ECC: ++ return E_FMAN_EX_QMI_DOUBLE_ECC; ++ case e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: ++ return E_FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID; ++ case e_FM_EX_BMI_LIST_RAM_ECC: ++ return E_FMAN_EX_BMI_LIST_RAM_ECC; ++ case e_FM_EX_BMI_STORAGE_PROFILE_ECC: ++ return E_FMAN_EX_BMI_STORAGE_PROFILE_ECC; ++ case e_FM_EX_BMI_STATISTICS_RAM_ECC: ++ return E_FMAN_EX_BMI_STATISTICS_RAM_ECC; ++ case e_FM_EX_BMI_DISPATCH_RAM_ECC: ++ return E_FMAN_EX_BMI_DISPATCH_RAM_ECC; ++ case e_FM_EX_IRAM_ECC: ++ return E_FMAN_EX_IRAM_ECC; ++ case e_FM_EX_MURAM_ECC: ++ return E_FMAN_EX_MURAM_ECC; ++ default: ++ return E_FMAN_EX_DMA_BUS_ERROR; ++ } ++} ++ ++uint8_t SwPortIdToHwPortId(e_FmPortType type, uint8_t relativePortId, uint8_t majorRev, uint8_t minorRev) ++{ ++ switch (type) ++ { ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ CHECK_PORT_ID_OH_PORTS(relativePortId); ++ return (uint8_t)(BASE_OH_PORTID + (relativePortId)); ++ case (e_FM_PORT_TYPE_RX): ++ CHECK_PORT_ID_1G_RX_PORTS(relativePortId); ++ return (uint8_t)(BASE_1G_RX_PORTID + (relativePortId)); ++ case (e_FM_PORT_TYPE_RX_10G): ++ /* The 10G port in T1024 (FMan Version 6.4) is the first port. ++ * This is the reason why the 1G port offset is used. ++ */ ++ if (majorRev == 6 && minorRev == 4) ++ { ++ CHECK_PORT_ID_1G_RX_PORTS(relativePortId); ++ return (uint8_t)(BASE_1G_RX_PORTID + (relativePortId)); ++ } ++ else ++ { ++ CHECK_PORT_ID_10G_RX_PORTS(relativePortId); ++ return (uint8_t)(BASE_10G_RX_PORTID + (relativePortId)); ++ } ++ case (e_FM_PORT_TYPE_TX): ++ CHECK_PORT_ID_1G_TX_PORTS(relativePortId); ++ return (uint8_t)(BASE_1G_TX_PORTID + (relativePortId)); ++ case (e_FM_PORT_TYPE_TX_10G): ++ /* The 10G port in T1024 (FMan Version 6.4) is the first port. ++ * This is the reason why the 1G port offset is used. ++ */ ++ if (majorRev == 6 && minorRev == 4) ++ { ++ CHECK_PORT_ID_1G_TX_PORTS(relativePortId); ++ return (uint8_t)(BASE_1G_TX_PORTID + (relativePortId)); ++ } ++ else ++ { ++ CHECK_PORT_ID_10G_TX_PORTS(relativePortId); ++ return (uint8_t)(BASE_10G_TX_PORTID + (relativePortId)); ++ } ++ default: ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal port type")); ++ return 0; ++ } ++} ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++t_Error FmDumpPortRegs (t_Handle h_Fm, uint8_t hardwarePortId) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ ++ DECLARE_DUMP; ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(((p_Fm->guestId == NCSW_MASTER_ID) || ++ p_Fm->baseAddr), E_INVALID_OPERATION); ++ ++ DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], ("fmbm_pp for port %u", (hardwarePortId))); ++ DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], sizeof(uint32_t)); ++ ++ DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], ("fmbm_pfs for port %u", (hardwarePortId ))); ++ DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], sizeof(uint32_t)); ++ ++ DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1], ("fmbm_spliodn for port %u", (hardwarePortId))); ++ DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1], sizeof(uint32_t)); ++ ++ DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_ps[hardwarePortId], ("fmfp_ps for port %u", (hardwarePortId))); ++ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_ps[hardwarePortId], sizeof(uint32_t)); ++ ++ DUMP_TITLE(&p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId/2], ("fmdmplr for port %u", (hardwarePortId))); ++ DUMP_MEMORY(&p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId/2], sizeof(uint32_t)); ++ ++ return E_OK; ++} ++#endif /* (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) */ ++ ++ ++/*****************************************************************************/ ++/* API Init unit functions */ ++/*****************************************************************************/ ++t_Handle FM_Config(t_FmParams *p_FmParam) ++{ ++ t_Fm *p_Fm; ++ uint8_t i; ++ uintptr_t baseAddr; ++ ++ SANITY_CHECK_RETURN_VALUE(p_FmParam, E_NULL_POINTER, NULL); ++ SANITY_CHECK_RETURN_VALUE(((p_FmParam->firmware.p_Code && p_FmParam->firmware.size) || ++ (!p_FmParam->firmware.p_Code && !p_FmParam->firmware.size)), ++ E_INVALID_VALUE, NULL); ++ ++ baseAddr = p_FmParam->baseAddr; ++ ++ /* Allocate FM structure */ ++ p_Fm = (t_Fm *) XX_Malloc(sizeof(t_Fm)); ++ if (!p_Fm) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM driver structure")); ++ return NULL; ++ } ++ memset(p_Fm, 0, sizeof(t_Fm)); ++ ++ p_Fm->p_FmStateStruct = (t_FmStateStruct *) XX_Malloc(sizeof(t_FmStateStruct)); ++ if (!p_Fm->p_FmStateStruct) ++ { ++ XX_Free(p_Fm); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Status structure")); ++ return NULL; ++ } ++ memset(p_Fm->p_FmStateStruct, 0, sizeof(t_FmStateStruct)); ++ ++ /* Initialize FM parameters which will be kept by the driver */ ++ p_Fm->p_FmStateStruct->fmId = p_FmParam->fmId; ++ p_Fm->guestId = p_FmParam->guestId; ++ ++ for (i=0; ip_FmStateStruct->portsTypes[i] = e_FM_PORT_TYPE_DUMMY; ++ ++ /* Allocate the FM driver's parameters structure */ ++ p_Fm->p_FmDriverParam = (struct fman_cfg *)XX_Malloc(sizeof(struct fman_cfg)); ++ if (!p_Fm->p_FmDriverParam) ++ { ++ XX_Free(p_Fm->p_FmStateStruct); ++ XX_Free(p_Fm); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM driver parameters")); ++ return NULL; ++ } ++ memset(p_Fm->p_FmDriverParam, 0, sizeof(struct fman_cfg)); ++ ++#if (DPAA_VERSION >= 11) ++ p_Fm->p_FmSp = (t_FmSp *)XX_Malloc(sizeof(t_FmSp)); ++ if (!p_Fm->p_FmSp) ++ { ++ XX_Free(p_Fm->p_FmDriverParam); ++ XX_Free(p_Fm->p_FmStateStruct); ++ XX_Free(p_Fm); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("allocation for internal data structure failed")); ++ return NULL; ++ } ++ memset(p_Fm->p_FmSp, 0, sizeof(t_FmSp)); ++ ++ for (i=0; ip_FmSp->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ /* Initialize FM parameters which will be kept by the driver */ ++ p_Fm->p_FmStateStruct->fmId = p_FmParam->fmId; ++ p_Fm->h_FmMuram = p_FmParam->h_FmMuram; ++ p_Fm->h_App = p_FmParam->h_App; ++ p_Fm->p_FmStateStruct->fmClkFreq = p_FmParam->fmClkFreq; ++ p_Fm->p_FmStateStruct->fmMacClkFreq = p_FmParam->fmClkFreq / ((!p_FmParam->fmMacClkRatio)? 2: p_FmParam->fmMacClkRatio); ++ p_Fm->f_Exception = p_FmParam->f_Exception; ++ p_Fm->f_BusError = p_FmParam->f_BusError; ++ p_Fm->p_FmFpmRegs = (struct fman_fpm_regs *)UINT_TO_PTR(baseAddr + FM_MM_FPM); ++ p_Fm->p_FmBmiRegs = (struct fman_bmi_regs *)UINT_TO_PTR(baseAddr + FM_MM_BMI); ++ p_Fm->p_FmQmiRegs = (struct fman_qmi_regs *)UINT_TO_PTR(baseAddr + FM_MM_QMI); ++ p_Fm->p_FmDmaRegs = (struct fman_dma_regs *)UINT_TO_PTR(baseAddr + FM_MM_DMA); ++ p_Fm->p_FmRegs = (struct fman_regs *)UINT_TO_PTR(baseAddr + FM_MM_BMI); ++ p_Fm->baseAddr = baseAddr; ++ p_Fm->p_FmStateStruct->irq = p_FmParam->irq; ++ p_Fm->p_FmStateStruct->errIrq = p_FmParam->errIrq; ++ p_Fm->hcPortInitialized = FALSE; ++ p_Fm->independentMode = FALSE; ++ ++ p_Fm->h_Spinlock = XX_InitSpinlock(); ++ if (!p_Fm->h_Spinlock) ++ { ++ XX_Free(p_Fm->p_FmDriverParam); ++ XX_Free(p_Fm->p_FmStateStruct); ++ XX_Free(p_Fm); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("can't allocate spinlock!")); ++ return NULL; ++ } ++ ++#if (DPAA_VERSION >= 11) ++ p_Fm->partVSPBase = p_FmParam->partVSPBase; ++ p_Fm->partNumOfVSPs = p_FmParam->partNumOfVSPs; ++ p_Fm->vspBaseAddr = p_FmParam->vspBaseAddr; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ fman_defconfig(p_Fm->p_FmDriverParam, ++ !!(p_Fm->guestId == NCSW_MASTER_ID)); ++/* overide macros dependent parameters */ ++#ifdef FM_PEDANTIC_DMA ++ p_Fm->p_FmDriverParam->pedantic_dma = TRUE; ++ p_Fm->p_FmDriverParam->dma_aid_override = TRUE; ++#endif /* FM_PEDANTIC_DMA */ ++#ifndef FM_QMI_NO_DEQ_OPTIONS_SUPPORT ++ p_Fm->p_FmDriverParam->qmi_deq_option_support = TRUE; ++#endif /* !FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ ++ ++ p_Fm->p_FmStateStruct->ramsEccEnable = FALSE; ++ p_Fm->p_FmStateStruct->extraFifoPoolSize = 0; ++ p_Fm->p_FmStateStruct->exceptions = DEFAULT_exceptions; ++ p_Fm->resetOnInit = DEFAULT_resetOnInit; ++ p_Fm->fwVerify = DEFAULT_VerifyUcode; ++ p_Fm->firmware.size = p_FmParam->firmware.size; ++ if (p_Fm->firmware.size) ++ { ++ p_Fm->firmware.p_Code = (uint32_t *)XX_Malloc(p_Fm->firmware.size); ++ if (!p_Fm->firmware.p_Code) ++ { ++ XX_FreeSpinlock(p_Fm->h_Spinlock); ++ XX_Free(p_Fm->p_FmStateStruct); ++ XX_Free(p_Fm->p_FmDriverParam); ++ XX_Free(p_Fm); ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM firmware code")); ++ return NULL; ++ } ++ memcpy(p_Fm->firmware.p_Code, p_FmParam->firmware.p_Code ,p_Fm->firmware.size); ++ } ++ ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ return p_Fm; ++ ++ /* read revision */ ++ /* Chip dependent, will be configured in Init */ ++ fman_get_revision(p_Fm->p_FmFpmRegs, ++ &p_Fm->p_FmStateStruct->revInfo.majorRev, ++ &p_Fm->p_FmStateStruct->revInfo.minorRev); ++ ++#ifdef FM_AID_MODE_NO_TNUM_SW005 ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ p_Fm->p_FmDriverParam->dma_aid_mode = e_FM_DMA_AID_OUT_PORT_ID; ++#endif /* FM_AID_MODE_NO_TNUM_SW005 */ ++#ifndef FM_QMI_NO_DEQ_OPTIONS_SUPPORT ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4) ++ p_Fm->p_FmDriverParam->qmi_def_tnums_thresh = QMI_DEF_TNUMS_THRESH; ++#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ ++ ++ p_Fm->p_FmStateStruct->totalFifoSize = 0; ++ p_Fm->p_FmStateStruct->totalNumOfTasks = ++ DEFAULT_totalNumOfTasks(p_Fm->p_FmStateStruct->revInfo.majorRev, ++ p_Fm->p_FmStateStruct->revInfo.minorRev); ++ ++#ifdef FM_HAS_TOTAL_DMAS ++ p_Fm->p_FmStateStruct->maxNumOfOpenDmas = BMI_MAX_NUM_OF_DMAS; ++#endif /* FM_HAS_TOTAL_DMAS */ ++#if (DPAA_VERSION < 11) ++ p_Fm->p_FmDriverParam->dma_comm_qtsh_clr_emer = DEFAULT_dmaCommQLow; ++ p_Fm->p_FmDriverParam->dma_comm_qtsh_asrt_emer = DEFAULT_dmaCommQHigh; ++ p_Fm->p_FmDriverParam->dma_cam_num_of_entries = DEFAULT_dmaCamNumOfEntries; ++ p_Fm->p_FmDriverParam->dma_read_buf_tsh_clr_emer = DEFAULT_dmaReadIntBufLow; ++ p_Fm->p_FmDriverParam->dma_read_buf_tsh_asrt_emer = DEFAULT_dmaReadIntBufHigh; ++ p_Fm->p_FmDriverParam->dma_write_buf_tsh_clr_emer = DEFAULT_dmaWriteIntBufLow; ++ p_Fm->p_FmDriverParam->dma_write_buf_tsh_asrt_emer = DEFAULT_dmaWriteIntBufHigh; ++ p_Fm->p_FmDriverParam->dma_axi_dbg_num_of_beats = DEFAULT_axiDbgNumOfBeats; ++#endif /* (DPAA_VERSION < 11) */ ++#ifdef FM_NO_TNUM_AGING ++ p_Fm->p_FmDriverParam->tnum_aging_period = 0; ++#endif ++ p_Fm->tnumAgingPeriod = p_Fm->p_FmDriverParam->tnum_aging_period; ++ ++ return p_Fm; ++} ++ ++/**************************************************************************//** ++ @Function FM_Init ++ ++ @Description Initializes the FM module ++ ++ @Param[in] h_Fm - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_Init(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ struct fman_cfg *p_FmDriverParam = NULL; ++ t_Error err = E_OK; ++ int i; ++ t_FmRevisionInfo revInfo; ++ struct fman_rg fman_rg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ ++ fman_rg.bmi_rg = p_Fm->p_FmBmiRegs; ++ fman_rg.qmi_rg = p_Fm->p_FmQmiRegs; ++ fman_rg.fpm_rg = p_Fm->p_FmFpmRegs; ++ fman_rg.dma_rg = p_Fm->p_FmDmaRegs; ++ ++ p_Fm->p_FmStateStruct->count1MicroBit = FM_TIMESTAMP_1_USEC_BIT; ++ p_Fm->p_FmDriverParam->num_of_fman_ctrl_evnt_regs = FM_NUM_OF_FMAN_CTRL_EVENT_REGS; ++ ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ return InitGuestMode(p_Fm); ++ ++ /* if user didn't configured totalFifoSize - (totalFifoSize=0) we configure default ++ * according to chip. otherwise, we use user's configuration. ++ */ ++ if (p_Fm->p_FmStateStruct->totalFifoSize == 0) ++ p_Fm->p_FmStateStruct->totalFifoSize = DEFAULT_totalFifoSize(p_Fm->p_FmStateStruct->revInfo.majorRev, ++ p_Fm->p_FmStateStruct->revInfo.minorRev); ++ ++ CHECK_INIT_PARAMETERS(p_Fm, CheckFmParameters); ++ ++ p_FmDriverParam = p_Fm->p_FmDriverParam; ++ ++ FM_GetRevision(p_Fm, &revInfo); ++ ++ /* clear revision-dependent non existing exception */ ++#ifdef FM_NO_DISPATCH_RAM_ECC ++ if ((revInfo.majorRev != 4) && ++ (revInfo.majorRev < 6)) ++ p_Fm->p_FmStateStruct->exceptions &= ~FM_EX_BMI_DISPATCH_RAM_ECC; ++#endif /* FM_NO_DISPATCH_RAM_ECC */ ++ ++#ifdef FM_QMI_NO_ECC_EXCEPTIONS ++ if (revInfo.majorRev == 4) ++ p_Fm->p_FmStateStruct->exceptions &= ~(FM_EX_QMI_SINGLE_ECC | FM_EX_QMI_DOUBLE_ECC); ++#endif /* FM_QMI_NO_ECC_EXCEPTIONS */ ++ ++#ifdef FM_QMI_NO_SINGLE_ECC_EXCEPTION ++ if (revInfo.majorRev >= 6) ++ p_Fm->p_FmStateStruct->exceptions &= ~FM_EX_QMI_SINGLE_ECC; ++#endif /* FM_QMI_NO_SINGLE_ECC_EXCEPTION */ ++ ++ FmMuramClear(p_Fm->h_FmMuram); ++ ++ /* clear CPG */ ++ IOMemSet32(UINT_TO_PTR(p_Fm->baseAddr + FM_MM_CGP), 0, FM_PORT_NUM_OF_CONGESTION_GRPS); ++ ++ /* add to the default exceptions the user's definitions */ ++ p_Fm->p_FmStateStruct->exceptions |= p_Fm->userSetExceptions; ++ ++ /* Reset the FM if required */ ++ if (p_Fm->resetOnInit) ++ { ++#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 ++ if ((err = FwNotResetErratumBugzilla6173WA(p_Fm)) != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++#else /* not FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */ ++ { ++ u32 svr = mfspr(SPRN_SVR); ++ ++ if (((SVR_SOC_VER(svr) == SVR_T4240 && SVR_REV(svr) > 0x10)) || ++ ((SVR_SOC_VER(svr) == SVR_T4160 && SVR_REV(svr) > 0x10)) || ++ ((SVR_SOC_VER(svr) == SVR_T4080 && SVR_REV(svr) > 0x10)) || ++ (SVR_SOC_VER(svr) == SVR_T1024) || ++ (SVR_SOC_VER(svr) == SVR_T1023) || ++ (SVR_SOC_VER(svr) == SVR_T2080) || ++ (SVR_SOC_VER(svr) == SVR_T2081)) { ++ DBG(WARNING, ("Hack: No FM reset!\n")); ++ } else { ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, FPM_RSTC_FM_RESET); ++ CORE_MemoryBarrier(); ++ XX_UDelay(100); ++ } ++ } ++ if (fman_is_qmi_halt_not_busy_state(p_Fm->p_FmQmiRegs)) ++ { ++ fman_resume(p_Fm->p_FmFpmRegs); ++ XX_UDelay(100); ++ } ++#endif /* not FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */ ++ } ++ ++#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 ++ if (!p_Fm->resetOnInit) /* Skip operations done in errata workaround */ ++ { ++#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */ ++ /* Load FMan-Controller code to IRAM */ ++ ++ ClearIRam(p_Fm); ++ ++ if (p_Fm->firmware.p_Code && (LoadFmanCtrlCode(p_Fm) != E_OK)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 ++ } ++#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */ ++ ++#ifdef FM_CAPWAP_SUPPORT ++ /* save first 256 byte in MURAM */ ++ p_Fm->resAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram, 256, 0)); ++ if (!p_Fm->resAddr) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for reserved Area failed")); ++ ++ WRITE_BLOCK(UINT_TO_PTR(p_Fm->resAddr), 0, 256); ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++#if (DPAA_VERSION >= 11) ++ p_Fm->partVSPBase = AllocVSPsForPartition(h_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId); ++ if (p_Fm->partVSPBase == (uint8_t)(ILLEGAL_BASE)) ++ DBG(WARNING, ("partition VSPs allocation is FAILED")); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ /* General FM driver initialization */ ++ p_Fm->fmMuramPhysBaseAddr = ++ (uint64_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->baseAddr + FM_MM_MURAM))); ++ ++ for (i=0;iintrMng[i].f_Isr = UnimplementedIsr; ++ for (i=0;ifmanCtrlIntr[i].f_Isr = UnimplementedFmanCtrlIsr; ++ ++ p_FmDriverParam->exceptions = p_Fm->p_FmStateStruct->exceptions; ++ ++ /**********************/ ++ /* Init DMA Registers */ ++ /**********************/ ++ err = InitFmDma(p_Fm); ++ if (err != E_OK) ++ { ++ FreeInitResources(p_Fm); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ /**********************/ ++ /* Init FPM Registers */ ++ /**********************/ ++ err = InitFmFpm(p_Fm); ++ if (err != E_OK) ++ { ++ FreeInitResources(p_Fm); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ /* define common resources */ ++ /* allocate MURAM for FIFO according to total size */ ++ p_Fm->fifoBaseAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram, ++ p_Fm->p_FmStateStruct->totalFifoSize, ++ BMI_FIFO_ALIGN)); ++ if (!p_Fm->fifoBaseAddr) ++ { ++ FreeInitResources(p_Fm); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for BMI FIFO failed")); ++ } ++ ++ p_FmDriverParam->fifo_base_addr = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->fifoBaseAddr)) - p_Fm->fmMuramPhysBaseAddr); ++ p_FmDriverParam->total_fifo_size = p_Fm->p_FmStateStruct->totalFifoSize; ++ p_FmDriverParam->total_num_of_tasks = p_Fm->p_FmStateStruct->totalNumOfTasks; ++ p_FmDriverParam->clk_freq = p_Fm->p_FmStateStruct->fmClkFreq; ++ ++ /**********************/ ++ /* Init BMI Registers */ ++ /**********************/ ++ err = InitFmBmi(p_Fm); ++ if (err != E_OK) ++ { ++ FreeInitResources(p_Fm); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ /**********************/ ++ /* Init QMI Registers */ ++ /**********************/ ++ err = InitFmQmi(p_Fm); ++ if (err != E_OK) ++ { ++ FreeInitResources(p_Fm); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ /* build the FM master partition IPC address */ ++ if (Sprint (p_Fm->fmModuleName, "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, NCSW_MASTER_ID) != 6) ++ { ++ FreeInitResources(p_Fm); ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); ++ } ++ ++ err = XX_IpcRegisterMsgHandler(p_Fm->fmModuleName, FmHandleIpcMsgCB, p_Fm, FM_IPC_MAX_REPLY_SIZE); ++ if (err) ++ { ++ FreeInitResources(p_Fm); ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ } ++ ++ /* Register the FM interrupts handlers */ ++ if (p_Fm->p_FmStateStruct->irq != NO_IRQ) ++ { ++ XX_SetIntr(p_Fm->p_FmStateStruct->irq, FM_EventIsr, p_Fm); ++ XX_EnableIntr(p_Fm->p_FmStateStruct->irq); ++ } ++ ++ if (p_Fm->p_FmStateStruct->errIrq != NO_IRQ) ++ { ++ XX_SetIntr(p_Fm->p_FmStateStruct->errIrq, (void (*) (t_Handle))FM_ErrorIsr, p_Fm); ++ XX_EnableIntr(p_Fm->p_FmStateStruct->errIrq); ++ } ++ ++ err = (t_Error)fman_enable(&fman_rg , p_FmDriverParam); ++ if (err != E_OK) ++ return err; /* FIXME */ ++ ++ EnableTimeStamp(p_Fm); ++ ++ if (p_Fm->firmware.p_Code) ++ { ++ XX_Free(p_Fm->firmware.p_Code); ++ p_Fm->firmware.p_Code = NULL; ++ } ++ ++ XX_Free(p_Fm->p_FmDriverParam); ++ p_Fm->p_FmDriverParam = NULL; ++ ++ return E_OK; ++} ++ ++/**************************************************************************//** ++ @Function FM_Free ++ ++ @Description Frees all resources that were assigned to FM module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_Fm - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_Free(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ struct fman_rg fman_rg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ ++ fman_rg.bmi_rg = p_Fm->p_FmBmiRegs; ++ fman_rg.qmi_rg = p_Fm->p_FmQmiRegs; ++ fman_rg.fpm_rg = p_Fm->p_FmFpmRegs; ++ fman_rg.dma_rg = p_Fm->p_FmDmaRegs; ++ ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++#if (DPAA_VERSION >= 11) ++ FreeVSPsForPartition(h_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId); ++ ++ if (p_Fm->p_FmSp) ++ { ++ XX_Free(p_Fm->p_FmSp); ++ p_Fm->p_FmSp = NULL; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (p_Fm->fmModuleName[0] != 0) ++ XX_IpcUnregisterMsgHandler(p_Fm->fmModuleName); ++ ++ if (!p_Fm->recoveryMode) ++ XX_Free(p_Fm->p_FmStateStruct); ++ ++ XX_Free(p_Fm); ++ ++ return E_OK; ++ } ++ ++ fman_free_resources(&fman_rg); ++ ++ if ((p_Fm->guestId == NCSW_MASTER_ID) && (p_Fm->fmModuleName[0] != 0)) ++ XX_IpcUnregisterMsgHandler(p_Fm->fmModuleName); ++ ++ if (p_Fm->p_FmStateStruct) ++ { ++ if (p_Fm->p_FmStateStruct->irq != NO_IRQ) ++ { ++ XX_DisableIntr(p_Fm->p_FmStateStruct->irq); ++ XX_FreeIntr(p_Fm->p_FmStateStruct->irq); ++ } ++ if (p_Fm->p_FmStateStruct->errIrq != NO_IRQ) ++ { ++ XX_DisableIntr(p_Fm->p_FmStateStruct->errIrq); ++ XX_FreeIntr(p_Fm->p_FmStateStruct->errIrq); ++ } ++ } ++ ++#if (DPAA_VERSION >= 11) ++ FreeVSPsForPartition(h_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId); ++ ++ if (p_Fm->p_FmSp) ++ { ++ XX_Free(p_Fm->p_FmSp); ++ p_Fm->p_FmSp = NULL; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ if (p_Fm->h_Spinlock) ++ XX_FreeSpinlock(p_Fm->h_Spinlock); ++ ++ if (p_Fm->p_FmDriverParam) ++ { ++ if (p_Fm->firmware.p_Code) ++ XX_Free(p_Fm->firmware.p_Code); ++ XX_Free(p_Fm->p_FmDriverParam); ++ p_Fm->p_FmDriverParam = NULL; ++ } ++ ++ FreeInitResources(p_Fm); ++ ++ if (!p_Fm->recoveryMode && p_Fm->p_FmStateStruct) ++ XX_Free(p_Fm->p_FmStateStruct); ++ ++ XX_Free(p_Fm); ++ ++ return E_OK; ++} ++ ++/*************************************************/ ++/* API Advanced Init unit functions */ ++/*************************************************/ ++ ++t_Error FM_ConfigResetOnInit(t_Handle h_Fm, bool enable) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->resetOnInit = enable; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigTotalFifoSize(t_Handle h_Fm, uint32_t totalFifoSize) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmStateStruct->totalFifoSize = totalFifoSize; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaCacheOverride(t_Handle h_Fm, e_FmDmaCacheOverride cacheOverride) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ enum fman_dma_cache_override fsl_cache_override; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ FMAN_CACHE_OVERRIDE_TRANS(fsl_cache_override, cacheOverride) ++ p_Fm->p_FmDriverParam->dma_cache_override = fsl_cache_override; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaAidOverride(t_Handle h_Fm, bool aidOverride) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dma_aid_override = aidOverride; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaAidMode(t_Handle h_Fm, e_FmDmaAidMode aidMode) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ enum fman_dma_aid_mode fsl_aid_mode; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ FMAN_AID_MODE_TRANS(fsl_aid_mode, aidMode); ++ p_Fm->p_FmDriverParam->dma_aid_mode = fsl_aid_mode; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaAxiDbgNumOfBeats(t_Handle h_Fm, uint8_t axiDbgNumOfBeats) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++#if (DPAA_VERSION >= 11) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); ++#else ++ p_Fm->p_FmDriverParam->dma_axi_dbg_num_of_beats = axiDbgNumOfBeats; ++ ++ return E_OK; ++#endif /* (DPAA_VERSION >= 11) */ ++} ++ ++t_Error FM_ConfigDmaCamNumOfEntries(t_Handle h_Fm, uint8_t numOfEntries) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dma_cam_num_of_entries = numOfEntries; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaDbgCounter(t_Handle h_Fm, e_FmDmaDbgCntMode fmDmaDbgCntMode) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ enum fman_dma_dbg_cnt_mode fsl_dma_dbg_cnt; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ FMAN_DMA_DBG_CNT_TRANS(fsl_dma_dbg_cnt, fmDmaDbgCntMode); ++ p_Fm->p_FmDriverParam->dma_dbg_cnt_mode = fsl_dma_dbg_cnt; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaStopOnBusErr(t_Handle h_Fm, bool stop) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dma_stop_on_bus_error = stop; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaEmergency(t_Handle h_Fm, t_FmDmaEmergency *p_Emergency) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ enum fman_dma_emergency_level fsl_dma_emer; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ FMAN_DMA_EMER_TRANS(fsl_dma_emer, p_Emergency->emergencyLevel); ++ p_Fm->p_FmDriverParam->dma_en_emergency = TRUE; ++ p_Fm->p_FmDriverParam->dma_emergency_bus_select = (uint32_t)p_Emergency->emergencyBusSelect; ++ p_Fm->p_FmDriverParam->dma_emergency_level = fsl_dma_emer; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaEmergencySmoother(t_Handle h_Fm, uint32_t emergencyCnt) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dma_en_emergency_smoother = TRUE; ++ p_Fm->p_FmDriverParam->dma_emergency_switch_counter = emergencyCnt; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaErr(t_Handle h_Fm, e_FmDmaErr dmaErr) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ enum fman_dma_err fsl_dma_err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ FMAN_DMA_ERR_TRANS(fsl_dma_err, dmaErr); ++ p_Fm->p_FmDriverParam->dma_err = fsl_dma_err; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigCatastrophicErr(t_Handle h_Fm, e_FmCatastrophicErr catastrophicErr) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ enum fman_catastrophic_err fsl_catastrophic_err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ FMAN_CATASTROPHIC_ERR_TRANS(fsl_catastrophic_err, catastrophicErr); ++ p_Fm->p_FmDriverParam->catastrophic_err = fsl_catastrophic_err; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigEnableMuramTestMode(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); ++ ++ p_Fm->p_FmDriverParam->en_muram_test_mode = TRUE; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigEnableIramTestMode(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE ); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); ++ ++ p_Fm->p_FmDriverParam->en_iram_test_mode = TRUE; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigHaltOnExternalActivation(t_Handle h_Fm, bool enable) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->halt_on_external_activ = enable; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigHaltOnUnrecoverableEccError(t_Handle h_Fm, bool enable) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); ++ ++ p_Fm->p_FmDriverParam->halt_on_unrecov_ecc_err = enable; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigException(t_Handle h_Fm, e_FmExceptions exception, bool enable) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t bitMask = 0; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_Fm->userSetExceptions |= bitMask; ++ else ++ p_Fm->p_FmStateStruct->exceptions &= ~bitMask; ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigExternalEccRamsEnable(t_Handle h_Fm, bool enable) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->external_ecc_rams_enable = enable; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigTnumAgingPeriod(t_Handle h_Fm, uint16_t tnumAgingPeriod) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->tnum_aging_period = tnumAgingPeriod; ++ p_Fm->tnumAgingPeriod = p_Fm->p_FmDriverParam->tnum_aging_period; ++ ++ return E_OK; ++} ++ ++/****************************************************/ ++/* Hidden-DEBUG Only API */ ++/****************************************************/ ++ ++t_Error FM_ConfigThresholds(t_Handle h_Fm, t_FmThresholds *p_FmThresholds) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->disp_limit_tsh = p_FmThresholds->dispLimit; ++ p_Fm->p_FmDriverParam->prs_disp_tsh = p_FmThresholds->prsDispTh; ++ p_Fm->p_FmDriverParam->plcr_disp_tsh = p_FmThresholds->plcrDispTh; ++ p_Fm->p_FmDriverParam->kg_disp_tsh = p_FmThresholds->kgDispTh; ++ p_Fm->p_FmDriverParam->bmi_disp_tsh = p_FmThresholds->bmiDispTh; ++ p_Fm->p_FmDriverParam->qmi_enq_disp_tsh = p_FmThresholds->qmiEnqDispTh; ++ p_Fm->p_FmDriverParam->qmi_deq_disp_tsh = p_FmThresholds->qmiDeqDispTh; ++ p_Fm->p_FmDriverParam->fm_ctl1_disp_tsh = p_FmThresholds->fmCtl1DispTh; ++ p_Fm->p_FmDriverParam->fm_ctl2_disp_tsh = p_FmThresholds->fmCtl2DispTh; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaSosEmergencyThreshold(t_Handle h_Fm, uint32_t dmaSosEmergency) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dma_sos_emergency = dmaSosEmergency; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaWriteBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds) ++ ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++#if (DPAA_VERSION >= 11) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); ++#else ++ p_Fm->p_FmDriverParam->dma_write_buf_tsh_asrt_emer = p_FmDmaThresholds->assertEmergency; ++ p_Fm->p_FmDriverParam->dma_write_buf_tsh_clr_emer = p_FmDmaThresholds->clearEmergency; ++ ++ return E_OK; ++#endif ++} ++ ++t_Error FM_ConfigDmaCommQThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dma_comm_qtsh_asrt_emer = p_FmDmaThresholds->assertEmergency; ++ p_Fm->p_FmDriverParam->dma_comm_qtsh_clr_emer = p_FmDmaThresholds->clearEmergency; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigDmaReadBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++#if (DPAA_VERSION >= 11) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); ++#else ++ p_Fm->p_FmDriverParam->dma_read_buf_tsh_clr_emer = p_FmDmaThresholds->clearEmergency; ++ p_Fm->p_FmDriverParam->dma_read_buf_tsh_asrt_emer = p_FmDmaThresholds->assertEmergency; ++ ++ return E_OK; ++#endif ++} ++ ++t_Error FM_ConfigDmaWatchdog(t_Handle h_Fm, uint32_t watchdogValue) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ p_Fm->p_FmDriverParam->dma_watchdog = watchdogValue; ++ ++ return E_OK; ++} ++ ++t_Error FM_ConfigEnableCounters(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++UNUSED(p_Fm); ++ ++ return E_OK; ++} ++ ++t_Error FmGetSetParams(t_Handle h_Fm, t_FmGetSetParams *p_Params) ++{ ++ t_Fm* p_Fm = (t_Fm*)h_Fm; ++ if (p_Params->setParams.type & UPDATE_FM_CLD) ++ { ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_cld, GET_UINT32( ++ p_Fm->p_FmFpmRegs->fm_cld) | 0x00000800); ++ } ++ if (p_Params->setParams.type & CLEAR_IRAM_READY) ++ { ++ t_FMIramRegs *p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); ++ WRITE_UINT32(p_Iram->iready,GET_UINT32(p_Iram->iready) & ~IRAM_READY); ++ } ++ if (p_Params->setParams.type & UPDATE_FPM_EXTC) ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_extc,0x80000000); ++ if (p_Params->setParams.type & UPDATE_FPM_EXTC_CLEAR) ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_extc,0x00800000); ++ if (p_Params->setParams.type & UPDATE_FPM_BRKC_SLP) ++ { ++ if (p_Params->setParams.sleep) ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc, GET_UINT32( ++ p_Fm->p_FmFpmRegs->fmfp_brkc) | FPM_BRKC_SLP); ++ else ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc, GET_UINT32( ++ p_Fm->p_FmFpmRegs->fmfp_brkc) & ~FPM_BRKC_SLP); ++ } ++ if (p_Params->getParams.type & GET_FM_CLD) ++ p_Params->getParams.fm_cld = GET_UINT32(p_Fm->p_FmFpmRegs->fm_cld); ++ if (p_Params->getParams.type & GET_FMQM_GS) ++ p_Params->getParams.fmqm_gs = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gs); ++ if (p_Params->getParams.type & GET_FM_NPI) ++ p_Params->getParams.fm_npi = GET_UINT32(p_Fm->p_FmFpmRegs->fm_npi); ++ if (p_Params->getParams.type & GET_FMFP_EXTC) ++ p_Params->getParams.fmfp_extc = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_extc); ++ return E_OK; ++} ++ ++ ++/****************************************************/ ++/* API Run-time Control uint functions */ ++/****************************************************/ ++void FM_EventIsr(t_Handle h_Fm) ++{ ++#define FM_M_CALL_1G_MAC_ISR(_id) \ ++ { \ ++ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].guestId) \ ++ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id), pending); \ ++ else \ ++ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].h_SrcHandle);\ ++ } ++#define FM_M_CALL_10G_MAC_ISR(_id) \ ++ { \ ++ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].guestId) \ ++ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id), pending); \ ++ else \ ++ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].h_SrcHandle);\ ++ } ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t pending, event; ++ struct fman_fpm_regs *fpm_rg; ++ ++ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ fpm_rg = p_Fm->p_FmFpmRegs; ++ ++ /* normal interrupts */ ++ pending = fman_get_normal_pending(fpm_rg); ++ if (!pending) ++ return; ++ if (pending & INTR_EN_WAKEUP) // this is a wake up from sleep interrupt ++ { ++ t_FmGetSetParams fmGetSetParams; ++ memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); ++ fmGetSetParams.setParams.type = UPDATE_FPM_BRKC_SLP; ++ fmGetSetParams.setParams.sleep = 0; ++ FmGetSetParams(h_Fm, &fmGetSetParams); ++ } ++ if (pending & INTR_EN_QMI) ++ QmiEvent(p_Fm); ++ if (pending & INTR_EN_PRS) ++ p_Fm->intrMng[e_FM_EV_PRS].f_Isr(p_Fm->intrMng[e_FM_EV_PRS].h_SrcHandle); ++ if (pending & INTR_EN_PLCR) ++ p_Fm->intrMng[e_FM_EV_PLCR].f_Isr(p_Fm->intrMng[e_FM_EV_PLCR].h_SrcHandle); ++ if (pending & INTR_EN_TMR) ++ p_Fm->intrMng[e_FM_EV_TMR].f_Isr(p_Fm->intrMng[e_FM_EV_TMR].h_SrcHandle); ++ ++ /* MAC events may belong to different partitions */ ++ if (pending & INTR_EN_1G_MAC0) ++ FM_M_CALL_1G_MAC_ISR(0); ++ if (pending & INTR_EN_1G_MAC1) ++ FM_M_CALL_1G_MAC_ISR(1); ++ if (pending & INTR_EN_1G_MAC2) ++ FM_M_CALL_1G_MAC_ISR(2); ++ if (pending & INTR_EN_1G_MAC3) ++ FM_M_CALL_1G_MAC_ISR(3); ++ if (pending & INTR_EN_1G_MAC4) ++ FM_M_CALL_1G_MAC_ISR(4); ++ if (pending & INTR_EN_1G_MAC5) ++ FM_M_CALL_1G_MAC_ISR(5); ++ if (pending & INTR_EN_1G_MAC6) ++ FM_M_CALL_1G_MAC_ISR(6); ++ if (pending & INTR_EN_1G_MAC7) ++ FM_M_CALL_1G_MAC_ISR(7); ++ if (pending & INTR_EN_10G_MAC0) ++ FM_M_CALL_10G_MAC_ISR(0); ++ if (pending & INTR_EN_10G_MAC1) ++ FM_M_CALL_10G_MAC_ISR(1); ++ ++ /* IM port events may belong to different partitions */ ++ if (pending & INTR_EN_REV0) ++ { ++ event = fman_get_controller_event(fpm_rg, 0); ++ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_0].guestId) ++ /*TODO IPC ISR For Fman Ctrl */ ++ ASSERT_COND(0); ++ /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_0, pending); */ ++ else ++ p_Fm->fmanCtrlIntr[0].f_Isr(p_Fm->fmanCtrlIntr[0].h_SrcHandle, event); ++ ++ } ++ if (pending & INTR_EN_REV1) ++ { ++ event = fman_get_controller_event(fpm_rg, 1); ++ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_1].guestId) ++ /*TODO IPC ISR For Fman Ctrl */ ++ ASSERT_COND(0); ++ /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_1, pending); */ ++ else ++ p_Fm->fmanCtrlIntr[1].f_Isr(p_Fm->fmanCtrlIntr[1].h_SrcHandle, event); ++ } ++ if (pending & INTR_EN_REV2) ++ { ++ event = fman_get_controller_event(fpm_rg, 2); ++ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_2].guestId) ++ /*TODO IPC ISR For Fman Ctrl */ ++ ASSERT_COND(0); ++ /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_2, pending); */ ++ else ++ p_Fm->fmanCtrlIntr[2].f_Isr(p_Fm->fmanCtrlIntr[2].h_SrcHandle, event); ++ } ++ if (pending & INTR_EN_REV3) ++ { ++ event = fman_get_controller_event(fpm_rg, 3); ++ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_3].guestId) ++ /*TODO IPC ISR For Fman Ctrl */ ++ ASSERT_COND(0); ++ /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_2, pendin3); */ ++ else ++ p_Fm->fmanCtrlIntr[3].f_Isr(p_Fm->fmanCtrlIntr[3].h_SrcHandle, event); ++ } ++#ifdef FM_MACSEC_SUPPORT ++ if (pending & INTR_EN_MACSEC_MAC0) ++ { ++ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_MACSEC_MAC0].guestId) ++ SendIpcIsr(p_Fm, e_FM_EV_MACSEC_MAC0, pending); ++ else ++ p_Fm->intrMng[e_FM_EV_MACSEC_MAC0].f_Isr(p_Fm->intrMng[e_FM_EV_MACSEC_MAC0].h_SrcHandle); ++ } ++#endif /* FM_MACSEC_SUPPORT */ ++} ++ ++t_Error FM_ErrorIsr(t_Handle h_Fm) ++{ ++#define FM_M_CALL_1G_MAC_ERR_ISR(_id) \ ++ { \ ++ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].guestId) \ ++ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id), pending); \ ++ else \ ++ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].h_SrcHandle);\ ++ } ++#define FM_M_CALL_10G_MAC_ERR_ISR(_id) \ ++ { \ ++ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].guestId) \ ++ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id), pending); \ ++ else \ ++ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].h_SrcHandle);\ ++ } ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t pending; ++ struct fman_fpm_regs *fpm_rg; ++ ++ SANITY_CHECK_RETURN_ERROR(h_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ fpm_rg = p_Fm->p_FmFpmRegs; ++ ++ /* error interrupts */ ++ pending = fman_get_fpm_error_interrupts(fpm_rg); ++ if (!pending) ++ return ERROR_CODE(E_EMPTY); ++ ++ if (pending & ERR_INTR_EN_BMI) ++ BmiErrEvent(p_Fm); ++ if (pending & ERR_INTR_EN_QMI) ++ QmiErrEvent(p_Fm); ++ if (pending & ERR_INTR_EN_FPM) ++ FpmErrEvent(p_Fm); ++ if (pending & ERR_INTR_EN_DMA) ++ DmaErrEvent(p_Fm); ++ if (pending & ERR_INTR_EN_IRAM) ++ IramErrIntr(p_Fm); ++ if (pending & ERR_INTR_EN_MURAM) ++ MuramErrIntr(p_Fm); ++ if (pending & ERR_INTR_EN_PRS) ++ p_Fm->intrMng[e_FM_EV_ERR_PRS].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_PRS].h_SrcHandle); ++ if (pending & ERR_INTR_EN_PLCR) ++ p_Fm->intrMng[e_FM_EV_ERR_PLCR].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_PLCR].h_SrcHandle); ++ if (pending & ERR_INTR_EN_KG) ++ p_Fm->intrMng[e_FM_EV_ERR_KG].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_KG].h_SrcHandle); ++ ++ /* MAC events may belong to different partitions */ ++ if (pending & ERR_INTR_EN_1G_MAC0) ++ FM_M_CALL_1G_MAC_ERR_ISR(0); ++ if (pending & ERR_INTR_EN_1G_MAC1) ++ FM_M_CALL_1G_MAC_ERR_ISR(1); ++ if (pending & ERR_INTR_EN_1G_MAC2) ++ FM_M_CALL_1G_MAC_ERR_ISR(2); ++ if (pending & ERR_INTR_EN_1G_MAC3) ++ FM_M_CALL_1G_MAC_ERR_ISR(3); ++ if (pending & ERR_INTR_EN_1G_MAC4) ++ FM_M_CALL_1G_MAC_ERR_ISR(4); ++ if (pending & ERR_INTR_EN_1G_MAC5) ++ FM_M_CALL_1G_MAC_ERR_ISR(5); ++ if (pending & ERR_INTR_EN_1G_MAC6) ++ FM_M_CALL_1G_MAC_ERR_ISR(6); ++ if (pending & ERR_INTR_EN_1G_MAC7) ++ FM_M_CALL_1G_MAC_ERR_ISR(7); ++ if (pending & ERR_INTR_EN_10G_MAC0) ++ FM_M_CALL_10G_MAC_ERR_ISR(0); ++ if (pending & ERR_INTR_EN_10G_MAC1) ++ FM_M_CALL_10G_MAC_ERR_ISR(1); ++ ++#ifdef FM_MACSEC_SUPPORT ++ if (pending & ERR_INTR_EN_MACSEC_MAC0) ++ { ++ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_ERR_MACSEC_MAC0].guestId) ++ SendIpcIsr(p_Fm, e_FM_EV_ERR_MACSEC_MAC0, pending); ++ else ++ p_Fm->intrMng[e_FM_EV_ERR_MACSEC_MAC0].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_MACSEC_MAC0].h_SrcHandle); ++ } ++#endif /* FM_MACSEC_SUPPORT */ ++ ++ return E_OK; ++} ++ ++t_Error FM_SetPortsBandwidth(t_Handle h_Fm, t_FmPortsBandwidthParams *p_PortsBandwidth) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ int i; ++ uint8_t sum; ++ uint8_t hardwarePortId; ++ uint8_t weights[64]; ++ uint8_t weight, maxPercent = 0; ++ struct fman_bmi_regs *bmi_rg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ bmi_rg = p_Fm->p_FmBmiRegs; ++ ++ memset(weights, 0, (sizeof(uint8_t) * 64)); ++ ++ /* check that all ports add up to 100% */ ++ sum = 0; ++ for (i=0; i < p_PortsBandwidth->numOfPorts; i++) ++ sum +=p_PortsBandwidth->portsBandwidths[i].bandwidth; ++ if (sum != 100) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Sum of ports bandwidth differ from 100%")); ++ ++ /* find highest percent */ ++ for (i=0; i < p_PortsBandwidth->numOfPorts; i++) ++ { ++ if (p_PortsBandwidth->portsBandwidths[i].bandwidth > maxPercent) ++ maxPercent = p_PortsBandwidth->portsBandwidths[i].bandwidth; ++ } ++ ++ ASSERT_COND(maxPercent > 0); /* guaranteed by sum = 100 */ ++ ++ /* calculate weight for each port */ ++ for (i=0; i < p_PortsBandwidth->numOfPorts; i++) ++ { ++ weight = (uint8_t)((p_PortsBandwidth->portsBandwidths[i].bandwidth * PORT_MAX_WEIGHT ) / maxPercent); ++ /* we want even division between 1-to-PORT_MAX_WEIGHT. so if exact division ++ is not reached, we round up so that: ++ 0 until maxPercent/PORT_MAX_WEIGHT get "1" ++ maxPercent/PORT_MAX_WEIGHT+1 until (maxPercent/PORT_MAX_WEIGHT)*2 get "2" ++ ... ++ maxPercent - maxPercent/PORT_MAX_WEIGHT until maxPercent get "PORT_MAX_WEIGHT: */ ++ if ((uint8_t)((p_PortsBandwidth->portsBandwidths[i].bandwidth * PORT_MAX_WEIGHT ) % maxPercent)) ++ weight++; ++ ++ /* find the location of this port within the register */ ++ hardwarePortId = ++ SwPortIdToHwPortId(p_PortsBandwidth->portsBandwidths[i].type, ++ p_PortsBandwidth->portsBandwidths[i].relativePortId, ++ p_Fm->p_FmStateStruct->revInfo.majorRev, ++ p_Fm->p_FmStateStruct->revInfo.minorRev); ++ ++ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); ++ weights[hardwarePortId] = weight; ++ } ++ ++ fman_set_ports_bandwidth(bmi_rg, weights); ++ ++ return E_OK; ++} ++ ++t_Error FM_EnableRamsEcc(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ struct fman_fpm_regs *fpm_rg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ ++ fpm_rg = p_Fm->p_FmFpmRegs; ++ ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++ t_FmIpcMsg msg; ++ t_Error err; ++ ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_ENABLE_RAM_ECC; ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ NULL, ++ NULL, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ return E_OK; ++ } ++ ++ if (!p_Fm->p_FmStateStruct->internalCall) ++ p_Fm->p_FmStateStruct->explicitEnable = TRUE; ++ p_Fm->p_FmStateStruct->internalCall = FALSE; ++ ++ if (p_Fm->p_FmStateStruct->ramsEccEnable) ++ return E_OK; ++ else ++ { ++ fman_enable_rams_ecc(fpm_rg); ++ p_Fm->p_FmStateStruct->ramsEccEnable = TRUE; ++ } ++ ++ return E_OK; ++} ++ ++t_Error FM_DisableRamsEcc(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ bool explicitDisable = FALSE; ++ struct fman_fpm_regs *fpm_rg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_HANDLE); ++ ++ fpm_rg = p_Fm->p_FmFpmRegs; ++ ++ if (p_Fm->guestId != NCSW_MASTER_ID) ++ { ++ t_Error err; ++ t_FmIpcMsg msg; ++ ++ memset(&msg, 0, sizeof(msg)); ++ msg.msgId = FM_DISABLE_RAM_ECC; ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ NULL, ++ NULL, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ return E_OK; ++ } ++ ++ if (!p_Fm->p_FmStateStruct->internalCall) ++ explicitDisable = TRUE; ++ p_Fm->p_FmStateStruct->internalCall = FALSE; ++ ++ /* if rams are already disabled, or if rams were explicitly enabled and are ++ currently called indirectly (not explicitly), ignore this call. */ ++ if (!p_Fm->p_FmStateStruct->ramsEccEnable || ++ (p_Fm->p_FmStateStruct->explicitEnable && !explicitDisable)) ++ return E_OK; ++ else ++ { ++ if (p_Fm->p_FmStateStruct->explicitEnable) ++ /* This is the case were both explicit are TRUE. ++ Turn off this flag for cases were following ramsEnable ++ routines are called */ ++ p_Fm->p_FmStateStruct->explicitEnable = FALSE; ++ ++ fman_enable_rams_ecc(fpm_rg); ++ p_Fm->p_FmStateStruct->ramsEccEnable = FALSE; ++ } ++ ++ return E_OK; ++} ++ ++t_Error FM_SetException(t_Handle h_Fm, e_FmExceptions exception, bool enable) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t bitMask = 0; ++ enum fman_exceptions fslException; ++ struct fman_rg fman_rg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ ++ fman_rg.bmi_rg = p_Fm->p_FmBmiRegs; ++ fman_rg.qmi_rg = p_Fm->p_FmQmiRegs; ++ fman_rg.fpm_rg = p_Fm->p_FmFpmRegs; ++ fman_rg.dma_rg = p_Fm->p_FmDmaRegs; ++ ++ GET_EXCEPTION_FLAG(bitMask, exception); ++ if (bitMask) ++ { ++ if (enable) ++ p_Fm->p_FmStateStruct->exceptions |= bitMask; ++ else ++ p_Fm->p_FmStateStruct->exceptions &= ~bitMask; ++ ++ fslException = FmanExceptionTrans(exception); ++ ++ return (t_Error)fman_set_exception(&fman_rg, ++ fslException, ++ enable); ++ } ++ else ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); ++ ++ return E_OK; ++} ++ ++t_Error FM_GetRevision(t_Handle h_Fm, t_FmRevisionInfo *p_FmRevisionInfo) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ p_FmRevisionInfo->majorRev = p_Fm->p_FmStateStruct->revInfo.majorRev; ++ p_FmRevisionInfo->minorRev = p_Fm->p_FmStateStruct->revInfo.minorRev; ++ ++ return E_OK; ++} ++ ++t_Error FM_GetFmanCtrlCodeRevision(t_Handle h_Fm, t_FmCtrlCodeRevisionInfo *p_RevisionInfo) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_FMIramRegs *p_Iram; ++ uint32_t revInfo; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_RevisionInfo, E_NULL_POINTER); ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_Error err; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength; ++ t_FmIpcFmanCtrlCodeRevisionInfo ipcRevInfo; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_GET_FMAN_CTRL_CODE_REV; ++ replyLength = sizeof(uint32_t) + sizeof(t_FmCtrlCodeRevisionInfo); ++ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmCtrlCodeRevisionInfo))) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ memcpy((uint8_t*)&ipcRevInfo, reply.replyBody, sizeof(t_FmCtrlCodeRevisionInfo)); ++ p_RevisionInfo->packageRev = ipcRevInfo.packageRev; ++ p_RevisionInfo->majorRev = ipcRevInfo.majorRev; ++ p_RevisionInfo->minorRev = ipcRevInfo.minorRev; ++ return (t_Error)(reply.error); ++ } ++ else if (p_Fm->guestId != NCSW_MASTER_ID) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("running in guest-mode without IPC!")); ++ ++ p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); ++ WRITE_UINT32(p_Iram->iadd, 0x4); ++ while (GET_UINT32(p_Iram->iadd) != 0x4) ; ++ revInfo = GET_UINT32(p_Iram->idata); ++ p_RevisionInfo->packageRev = (uint16_t)((revInfo & 0xFFFF0000) >> 16); ++ p_RevisionInfo->majorRev = (uint8_t)((revInfo & 0x0000FF00) >> 8); ++ p_RevisionInfo->minorRev = (uint8_t)(revInfo & 0x000000FF); ++ ++ return E_OK; ++} ++ ++uint32_t FM_GetCounter(t_Handle h_Fm, e_FmCounters counter) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_Error err; ++ uint32_t counterValue; ++ struct fman_rg fman_rg; ++ enum fman_counters fsl_counter; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(!p_Fm->p_FmDriverParam, E_INVALID_STATE, 0); ++ ++ fman_rg.bmi_rg = p_Fm->p_FmBmiRegs; ++ fman_rg.qmi_rg = p_Fm->p_FmQmiRegs; ++ fman_rg.fpm_rg = p_Fm->p_FmFpmRegs; ++ fman_rg.dma_rg = p_Fm->p_FmDmaRegs; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ uint32_t replyLength, outCounter; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_GET_COUNTER; ++ memcpy(msg.msgBody, (uint8_t *)&counter, sizeof(uint32_t)); ++ replyLength = sizeof(uint32_t) + sizeof(uint32_t); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId) +sizeof(counterValue), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MAJOR, err, NO_MSG); ++ return 0; ++ } ++ if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t))) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return 0; ++ } ++ ++ memcpy((uint8_t*)&outCounter, reply.replyBody, sizeof(uint32_t)); ++ return outCounter; ++ } ++ else if (!p_Fm->baseAddr) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Either IPC or 'baseAddress' is required!")); ++ return 0; ++ } ++ ++ /* When applicable (when there is an 'enable counters' bit, ++ check that counters are enabled */ ++ switch (counter) ++ { ++ case (e_FM_COUNTERS_DEQ_1): ++ case (e_FM_COUNTERS_DEQ_2): ++ case (e_FM_COUNTERS_DEQ_3): ++ if ((p_Fm->p_FmStateStruct->revInfo.majorRev == 4) || ++ (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Requested counter not supported")); ++ return 0; ++ } ++ case (e_FM_COUNTERS_ENQ_TOTAL_FRAME): ++ case (e_FM_COUNTERS_DEQ_TOTAL_FRAME): ++ case (e_FM_COUNTERS_DEQ_0): ++ case (e_FM_COUNTERS_DEQ_FROM_DEFAULT): ++ case (e_FM_COUNTERS_DEQ_FROM_CONTEXT): ++ case (e_FM_COUNTERS_DEQ_FROM_FD): ++ case (e_FM_COUNTERS_DEQ_CONFIRM): ++ if (!(GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc) & QMI_CFG_EN_COUNTERS)) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Requested counter was not enabled")); ++ return 0; ++ } ++ break; ++ default: ++ break; ++ } ++ ++ FMAN_COUNTERS_TRANS(fsl_counter, counter); ++ return fman_get_counter(&fman_rg, fsl_counter); ++} ++ ++t_Error FM_ModifyCounter(t_Handle h_Fm, e_FmCounters counter, uint32_t val) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ struct fman_rg fman_rg; ++ enum fman_counters fsl_counter; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ ++ fman_rg.bmi_rg = p_Fm->p_FmBmiRegs; ++ fman_rg.qmi_rg = p_Fm->p_FmQmiRegs; ++ fman_rg.fpm_rg = p_Fm->p_FmFpmRegs; ++ fman_rg.dma_rg = p_Fm->p_FmDmaRegs; ++ ++ FMAN_COUNTERS_TRANS(fsl_counter, counter); ++ return (t_Error)fman_modify_counter(&fman_rg, fsl_counter, val); ++} ++ ++void FM_SetDmaEmergency(t_Handle h_Fm, e_FmDmaMuramPort muramPort, bool enable) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ struct fman_dma_regs *dma_rg; ++ ++ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ ++ dma_rg = p_Fm->p_FmDmaRegs; ++ ++ fman_set_dma_emergency(dma_rg, !!(muramPort==e_FM_DMA_MURAM_PORT_WRITE), enable); ++} ++ ++void FM_SetDmaExtBusPri(t_Handle h_Fm, e_FmDmaExtBusPri pri) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ struct fman_dma_regs *dma_rg; ++ ++ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ ++ dma_rg = p_Fm->p_FmDmaRegs; ++ ++ fman_set_dma_ext_bus_pri(dma_rg, pri); ++} ++ ++void FM_GetDmaStatus(t_Handle h_Fm, t_FmDmaStatus *p_FmDmaStatus) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ uint32_t dmaStatus; ++ struct fman_dma_regs *dma_rg; ++ ++ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ ++ dma_rg = p_Fm->p_FmDmaRegs; ++ ++ if ((p_Fm->guestId != NCSW_MASTER_ID) && ++ !p_Fm->baseAddr && ++ p_Fm->h_IpcSessions[0]) ++ { ++ t_FmIpcDmaStatus ipcDmaStatus; ++ t_FmIpcMsg msg; ++ t_FmIpcReply reply; ++ t_Error err; ++ uint32_t replyLength; ++ ++ memset(&msg, 0, sizeof(msg)); ++ memset(&reply, 0, sizeof(reply)); ++ msg.msgId = FM_DMA_STAT; ++ replyLength = sizeof(uint32_t) + sizeof(t_FmIpcDmaStatus); ++ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], ++ (uint8_t*)&msg, ++ sizeof(msg.msgId), ++ (uint8_t*)&reply, ++ &replyLength, ++ NULL, ++ NULL); ++ if (err != E_OK) ++ { ++ REPORT_ERROR(MINOR, err, NO_MSG); ++ return; ++ } ++ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmIpcDmaStatus))) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); ++ return; ++ } ++ memcpy((uint8_t*)&ipcDmaStatus, reply.replyBody, sizeof(t_FmIpcDmaStatus)); ++ ++ p_FmDmaStatus->cmqNotEmpty = (bool)ipcDmaStatus.boolCmqNotEmpty; /**< Command queue is not empty */ ++ p_FmDmaStatus->busError = (bool)ipcDmaStatus.boolBusError; /**< Bus error occurred */ ++ p_FmDmaStatus->readBufEccError = (bool)ipcDmaStatus.boolReadBufEccError; /**< Double ECC error on buffer Read */ ++ p_FmDmaStatus->writeBufEccSysError =(bool)ipcDmaStatus.boolWriteBufEccSysError; /**< Double ECC error on buffer write from system side */ ++ p_FmDmaStatus->writeBufEccFmError = (bool)ipcDmaStatus.boolWriteBufEccFmError; /**< Double ECC error on buffer write from FM side */ ++ p_FmDmaStatus->singlePortEccError = (bool)ipcDmaStatus.boolSinglePortEccError; /**< Double ECC error on buffer write from FM side */ ++ return; ++ } ++ else if (!p_Fm->baseAddr) ++ { ++ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ++ ("Either IPC or 'baseAddress' is required!")); ++ return; ++ } ++ ++ dmaStatus = fman_get_dma_status(dma_rg); ++ ++ p_FmDmaStatus->cmqNotEmpty = (bool)(dmaStatus & DMA_STATUS_CMD_QUEUE_NOT_EMPTY); ++ p_FmDmaStatus->busError = (bool)(dmaStatus & DMA_STATUS_BUS_ERR); ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ p_FmDmaStatus->singlePortEccError = (bool)(dmaStatus & DMA_STATUS_FM_SPDAT_ECC); ++ else ++ { ++ p_FmDmaStatus->readBufEccError = (bool)(dmaStatus & DMA_STATUS_READ_ECC); ++ p_FmDmaStatus->writeBufEccSysError = (bool)(dmaStatus & DMA_STATUS_SYSTEM_WRITE_ECC); ++ p_FmDmaStatus->writeBufEccFmError = (bool)(dmaStatus & DMA_STATUS_FM_WRITE_ECC); ++ } ++} ++ ++void FM_Resume(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ struct fman_fpm_regs *fpm_rg; ++ ++ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ fpm_rg = p_Fm->p_FmFpmRegs; ++ ++ fman_resume(fpm_rg); ++} ++ ++t_Error FM_GetSpecialOperationCoding(t_Handle h_Fm, ++ fmSpecialOperations_t spOper, ++ uint8_t *p_SpOperCoding) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ t_FmCtrlCodeRevisionInfo revInfo; ++ t_Error err; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR(p_SpOperCoding, E_NULL_POINTER); ++ ++ if (!spOper) ++ { ++ *p_SpOperCoding = 0; ++ return E_OK; ++ } ++ ++ if ((err = FM_GetFmanCtrlCodeRevision(p_Fm, &revInfo)) != E_OK) ++ { ++ DBG(WARNING, ("FM in guest-mode without IPC, can't validate firmware revision.")); ++ revInfo.packageRev = IP_OFFLOAD_PACKAGE_NUMBER; ++ } ++ else if (!IS_OFFLOAD_PACKAGE(revInfo.packageRev)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Fman ctrl code package")); ++ ++ switch (spOper) ++ { ++ case (FM_SP_OP_CAPWAP_DTLS_DEC): ++ *p_SpOperCoding = 9; ++ break; ++ case (FM_SP_OP_CAPWAP_DTLS_ENC): ++ *p_SpOperCoding = 10; ++ break; ++ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN|FM_SP_OP_IPSEC_MANIP): ++ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN|FM_SP_OP_IPSEC_MANIP|FM_SP_OP_RPD): ++ *p_SpOperCoding = 5; ++ break; ++ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_MANIP): ++ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_MANIP|FM_SP_OP_RPD): ++ *p_SpOperCoding = 6; ++ break; ++ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN|FM_SP_OP_RPD): ++ *p_SpOperCoding = 3; ++ break; ++ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN): ++ *p_SpOperCoding = 1; ++ break; ++ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN|FM_SP_OP_IPSEC_NO_ETH_HDR): ++ *p_SpOperCoding = 12; ++ break; ++ case (FM_SP_OP_IPSEC|FM_SP_OP_RPD): ++ *p_SpOperCoding = 4; ++ break; ++ case (FM_SP_OP_IPSEC): ++ *p_SpOperCoding = 2; ++ break; ++ case (FM_SP_OP_DCL4C): ++ *p_SpOperCoding = 7; ++ break; ++ case (FM_SP_OP_CLEAR_RPD): ++ *p_SpOperCoding = 8; ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); ++ } ++ ++ return E_OK; ++} ++ ++t_Error FM_CtrlMonStart(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ t_FmTrbRegs *p_MonRegs; ++ uint8_t i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc, ++ GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc) | FPM_BRKC_RDBG); ++ ++ for (i = 0; i < FM_NUM_OF_CTRL; i++) ++ { ++ p_MonRegs = (t_FmTrbRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_TRB(i)); ++ ++ /* Reset control registers */ ++ WRITE_UINT32(p_MonRegs->tcrh, TRB_TCRH_RESET); ++ WRITE_UINT32(p_MonRegs->tcrl, TRB_TCRL_RESET); ++ ++ /* Configure: counter #1 counts all stalls in risc - ldsched stall ++ counter #2 counts all stalls in risc - other stall*/ ++ WRITE_UINT32(p_MonRegs->tcrl, TRB_TCRL_RESET | TRB_TCRL_UTIL); ++ ++ /* Enable monitoring */ ++ WRITE_UINT32(p_MonRegs->tcrh, TRB_TCRH_ENABLE_COUNTERS); ++ } ++ ++ return E_OK; ++} ++ ++t_Error FM_CtrlMonStop(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ t_FmTrbRegs *p_MonRegs; ++ uint8_t i; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ ++ for (i = 0; i < FM_NUM_OF_CTRL; i++) ++ { ++ p_MonRegs = (t_FmTrbRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_TRB(i)); ++ WRITE_UINT32(p_MonRegs->tcrh, TRB_TCRH_DISABLE_COUNTERS); ++ } ++ ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc, ++ GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc) & ~FPM_BRKC_RDBG); ++ ++ return E_OK; ++} ++ ++t_Error FM_CtrlMonGetCounters(t_Handle h_Fm, uint8_t fmCtrlIndex, t_FmCtrlMon *p_Mon) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_Fm; ++ t_FmTrbRegs *p_MonRegs; ++ uint64_t clkCnt, utilValue, effValue; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); ++ SANITY_CHECK_RETURN_ERROR(p_Mon, E_NULL_POINTER); ++ ++ if (fmCtrlIndex >= FM_NUM_OF_CTRL) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FM Controller index")); ++ ++ p_MonRegs = (t_FmTrbRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_TRB(fmCtrlIndex)); ++ ++ clkCnt = (uint64_t) ++ ((uint64_t)GET_UINT32(p_MonRegs->tpcch) << 32 | GET_UINT32(p_MonRegs->tpccl)); ++ ++ utilValue = (uint64_t) ++ ((uint64_t)GET_UINT32(p_MonRegs->tpc1h) << 32 | GET_UINT32(p_MonRegs->tpc1l)); ++ ++ effValue = (uint64_t) ++ ((uint64_t)GET_UINT32(p_MonRegs->tpc2h) << 32 | GET_UINT32(p_MonRegs->tpc2l)); ++ ++ p_Mon->percentCnt[0] = (uint8_t)((clkCnt - utilValue) * 100 / clkCnt); ++ if (clkCnt != utilValue) ++ p_Mon->percentCnt[1] = (uint8_t)(((clkCnt - utilValue) - effValue) * 100 / (clkCnt - utilValue)); ++ else ++ p_Mon->percentCnt[1] = 0; ++ ++ return E_OK; ++} ++ ++t_Handle FM_GetMuramHandle(t_Handle h_Fm) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ ++ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, NULL); ++ ++ return (p_Fm->h_FmMuram); ++} ++ ++/****************************************************/ ++/* Hidden-DEBUG Only API */ ++/****************************************************/ ++t_Error FM_ForceIntr (t_Handle h_Fm, e_FmExceptions exception) ++{ ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ enum fman_exceptions fslException; ++ struct fman_rg fman_rg; ++ ++ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); ++ ++ fman_rg.bmi_rg = p_Fm->p_FmBmiRegs; ++ fman_rg.qmi_rg = p_Fm->p_FmQmiRegs; ++ fman_rg.fpm_rg = p_Fm->p_FmFpmRegs; ++ fman_rg.dma_rg = p_Fm->p_FmDmaRegs; ++ ++ switch (exception) ++ { ++ case e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: ++ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ break; ++ case e_FM_EX_QMI_SINGLE_ECC: ++ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("e_FM_EX_QMI_SINGLE_ECC not supported on this integration.")); ++ ++ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_SINGLE_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ break; ++ case e_FM_EX_QMI_DOUBLE_ECC: ++ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_DOUBLE_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ break; ++ case e_FM_EX_BMI_LIST_RAM_ECC: ++ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_LIST_RAM_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ break; ++ case e_FM_EX_BMI_STORAGE_PROFILE_ECC: ++ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_STORAGE_PROFILE_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ break; ++ case e_FM_EX_BMI_STATISTICS_RAM_ECC: ++ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_STATISTICS_RAM_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ break; ++ case e_FM_EX_BMI_DISPATCH_RAM_ECC: ++ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_DISPATCH_RAM_ECC)) ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); ++ break; ++ default: ++ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception may not be forced")); ++ } ++ ++ fslException = FmanExceptionTrans(exception); ++ fman_force_intr (&fman_rg, fslException); ++ ++ return E_OK; ++} ++ ++t_Handle FmGetPcd(t_Handle h_Fm) ++{ ++ return ((t_Fm*)h_Fm)->h_Pcd; ++} ++#if (DPAA_VERSION >= 11) ++extern void *g_MemacRegs; ++void fm_clk_down(void); ++uint32_t fman_memac_get_event(void *regs, uint32_t ev_mask); ++void FM_ChangeClock(t_Handle h_Fm, int hardwarePortId) ++{ ++ int macId; ++ uint32_t event, rcr; ++ t_Fm *p_Fm = (t_Fm*)h_Fm; ++ rcr = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rcr); ++ rcr |= 0x04000000; ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, rcr); ++ ++ HW_PORT_ID_TO_SW_PORT_ID(macId, hardwarePortId); ++ do ++ { ++ event = fman_memac_get_event(g_MemacRegs, 0xFFFFFFFF); ++ } while ((event & 0x00000020) == 0); ++ fm_clk_down(); ++ rcr = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rcr); ++ rcr &= ~0x04000000; ++ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, rcr); ++} ++#endif +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.h +new file mode 100644 +index 0000000..fc7662d +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.h +@@ -0,0 +1,646 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm.h ++ ++ @Description FM internal structures and definitions. ++*//***************************************************************************/ ++#ifndef __FM_H ++#define __FM_H ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "fm_ext.h" ++#include "fm_ipc.h" ++ ++#include "fsl_fman.h" ++ ++#define __ERR_MODULE__ MODULE_FM ++ ++#define FM_MAX_NUM_OF_HW_PORT_IDS 64 ++#define FM_MAX_NUM_OF_GUESTS 100 ++ ++/**************************************************************************//** ++ @Description Exceptions ++*//***************************************************************************/ ++#define FM_EX_DMA_BUS_ERROR 0x80000000 /**< DMA bus error. */ ++#define FM_EX_DMA_READ_ECC 0x40000000 ++#define FM_EX_DMA_SYSTEM_WRITE_ECC 0x20000000 ++#define FM_EX_DMA_FM_WRITE_ECC 0x10000000 ++#define FM_EX_FPM_STALL_ON_TASKS 0x08000000 /**< Stall of tasks on FPM */ ++#define FM_EX_FPM_SINGLE_ECC 0x04000000 /**< Single ECC on FPM */ ++#define FM_EX_FPM_DOUBLE_ECC 0x02000000 ++#define FM_EX_QMI_SINGLE_ECC 0x01000000 /**< Single ECC on FPM */ ++#define FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID 0x00800000 /**< Dequeu from default queue id */ ++#define FM_EX_QMI_DOUBLE_ECC 0x00400000 ++#define FM_EX_BMI_LIST_RAM_ECC 0x00200000 ++#define FM_EX_BMI_STORAGE_PROFILE_ECC 0x00100000 ++#define FM_EX_BMI_STATISTICS_RAM_ECC 0x00080000 ++#define FM_EX_IRAM_ECC 0x00040000 ++#define FM_EX_MURAM_ECC 0x00020000 ++#define FM_EX_BMI_DISPATCH_RAM_ECC 0x00010000 ++#define FM_EX_DMA_SINGLE_PORT_ECC 0x00008000 ++ ++#define DMA_EMSR_EMSTR_MASK 0x0000FFFF ++ ++#define DMA_THRESH_COMMQ_MASK 0xFF000000 ++#define DMA_THRESH_READ_INT_BUF_MASK 0x007F0000 ++#define DMA_THRESH_WRITE_INT_BUF_MASK 0x0000007F ++ ++#define GET_EXCEPTION_FLAG(bitMask, exception) \ ++switch (exception){ \ ++ case e_FM_EX_DMA_BUS_ERROR: \ ++ bitMask = FM_EX_DMA_BUS_ERROR; break; \ ++ case e_FM_EX_DMA_SINGLE_PORT_ECC: \ ++ bitMask = FM_EX_DMA_SINGLE_PORT_ECC; break; \ ++ case e_FM_EX_DMA_READ_ECC: \ ++ bitMask = FM_EX_DMA_READ_ECC; break; \ ++ case e_FM_EX_DMA_SYSTEM_WRITE_ECC: \ ++ bitMask = FM_EX_DMA_SYSTEM_WRITE_ECC; break; \ ++ case e_FM_EX_DMA_FM_WRITE_ECC: \ ++ bitMask = FM_EX_DMA_FM_WRITE_ECC; break; \ ++ case e_FM_EX_FPM_STALL_ON_TASKS: \ ++ bitMask = FM_EX_FPM_STALL_ON_TASKS; break; \ ++ case e_FM_EX_FPM_SINGLE_ECC: \ ++ bitMask = FM_EX_FPM_SINGLE_ECC; break; \ ++ case e_FM_EX_FPM_DOUBLE_ECC: \ ++ bitMask = FM_EX_FPM_DOUBLE_ECC; break; \ ++ case e_FM_EX_QMI_SINGLE_ECC: \ ++ bitMask = FM_EX_QMI_SINGLE_ECC; break; \ ++ case e_FM_EX_QMI_DOUBLE_ECC: \ ++ bitMask = FM_EX_QMI_DOUBLE_ECC; break; \ ++ case e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: \ ++ bitMask = FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID; break; \ ++ case e_FM_EX_BMI_LIST_RAM_ECC: \ ++ bitMask = FM_EX_BMI_LIST_RAM_ECC; break; \ ++ case e_FM_EX_BMI_STORAGE_PROFILE_ECC: \ ++ bitMask = FM_EX_BMI_STORAGE_PROFILE_ECC; break; \ ++ case e_FM_EX_BMI_STATISTICS_RAM_ECC: \ ++ bitMask = FM_EX_BMI_STATISTICS_RAM_ECC; break; \ ++ case e_FM_EX_BMI_DISPATCH_RAM_ECC: \ ++ bitMask = FM_EX_BMI_DISPATCH_RAM_ECC; break; \ ++ case e_FM_EX_IRAM_ECC: \ ++ bitMask = FM_EX_IRAM_ECC; break; \ ++ case e_FM_EX_MURAM_ECC: \ ++ bitMask = FM_EX_MURAM_ECC; break; \ ++ default: bitMask = 0;break; \ ++} ++ ++#define GET_FM_MODULE_EVENT(_mod, _id, _intrType, _event) \ ++ switch (_mod) { \ ++ case e_FM_MOD_PRS: \ ++ if (_id) _event = e_FM_EV_DUMMY_LAST; \ ++ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_ERR_PRS : e_FM_EV_PRS; \ ++ break; \ ++ case e_FM_MOD_KG: \ ++ if (_id) _event = e_FM_EV_DUMMY_LAST; \ ++ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_ERR_KG : e_FM_EV_DUMMY_LAST; \ ++ break; \ ++ case e_FM_MOD_PLCR: \ ++ if (_id) _event = e_FM_EV_DUMMY_LAST; \ ++ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_ERR_PLCR : e_FM_EV_PLCR; \ ++ break; \ ++ case e_FM_MOD_TMR: \ ++ if (_id) _event = e_FM_EV_DUMMY_LAST; \ ++ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_DUMMY_LAST : e_FM_EV_TMR; \ ++ break; \ ++ case e_FM_MOD_10G_MAC: \ ++ if (_id >= FM_MAX_NUM_OF_10G_MACS) _event = e_FM_EV_DUMMY_LAST; \ ++ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? (e_FM_EV_ERR_10G_MAC0 + _id) : (e_FM_EV_10G_MAC0 + _id); \ ++ break; \ ++ case e_FM_MOD_1G_MAC: \ ++ if (_id >= FM_MAX_NUM_OF_1G_MACS) _event = e_FM_EV_DUMMY_LAST; \ ++ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? (e_FM_EV_ERR_1G_MAC0 + _id) : (e_FM_EV_1G_MAC0 + _id); \ ++ break; \ ++ case e_FM_MOD_MACSEC: \ ++ switch (_id){ \ ++ case (0): _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_ERR_MACSEC_MAC0:e_FM_EV_MACSEC_MAC0; \ ++ break; \ ++ } \ ++ break; \ ++ case e_FM_MOD_FMAN_CTRL: \ ++ if (_intrType == e_FM_INTR_TYPE_ERR) _event = e_FM_EV_DUMMY_LAST; \ ++ else _event = (e_FM_EV_FMAN_CTRL_0 + _id); \ ++ break; \ ++ default: _event = e_FM_EV_DUMMY_LAST; \ ++ break; \ ++ } ++ ++#define FMAN_CACHE_OVERRIDE_TRANS(fsl_cache_override, _cache_override) \ ++ switch (_cache_override){ \ ++ case e_FM_DMA_NO_CACHE_OR: \ ++ fsl_cache_override = E_FMAN_DMA_NO_CACHE_OR; break; \ ++ case e_FM_DMA_NO_STASH_DATA: \ ++ fsl_cache_override = E_FMAN_DMA_NO_STASH_DATA; break; \ ++ case e_FM_DMA_MAY_STASH_DATA: \ ++ fsl_cache_override = E_FMAN_DMA_MAY_STASH_DATA; break; \ ++ case e_FM_DMA_STASH_DATA: \ ++ fsl_cache_override = E_FMAN_DMA_STASH_DATA; break; \ ++ default: \ ++ fsl_cache_override = E_FMAN_DMA_NO_CACHE_OR; break; \ ++ } ++ ++#define FMAN_AID_MODE_TRANS(fsl_aid_mode, _aid_mode) \ ++ switch (_aid_mode){ \ ++ case e_FM_DMA_AID_OUT_PORT_ID: \ ++ fsl_aid_mode = E_FMAN_DMA_AID_OUT_PORT_ID; break; \ ++ case e_FM_DMA_AID_OUT_TNUM: \ ++ fsl_aid_mode = E_FMAN_DMA_AID_OUT_TNUM; break; \ ++ default: \ ++ fsl_aid_mode = E_FMAN_DMA_AID_OUT_PORT_ID; break; \ ++ } ++ ++#define FMAN_DMA_DBG_CNT_TRANS(fsl_dma_dbg_cnt, _dma_dbg_cnt) \ ++ switch (_dma_dbg_cnt){ \ ++ case e_FM_DMA_DBG_NO_CNT: \ ++ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_NO_CNT; break; \ ++ case e_FM_DMA_DBG_CNT_DONE: \ ++ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_CNT_DONE; break; \ ++ case e_FM_DMA_DBG_CNT_COMM_Q_EM: \ ++ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_CNT_COMM_Q_EM; break; \ ++ case e_FM_DMA_DBG_CNT_INT_READ_EM: \ ++ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_CNT_INT_READ_EM; break; \ ++ case e_FM_DMA_DBG_CNT_INT_WRITE_EM: \ ++ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_CNT_INT_WRITE_EM ; break; \ ++ case e_FM_DMA_DBG_CNT_FPM_WAIT: \ ++ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_CNT_FPM_WAIT ; break; \ ++ case e_FM_DMA_DBG_CNT_SIGLE_BIT_ECC: \ ++ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_CNT_SIGLE_BIT_ECC ; break; \ ++ case e_FM_DMA_DBG_CNT_RAW_WAR_PROT: \ ++ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_CNT_RAW_WAR_PROT ; break; \ ++ default: \ ++ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_NO_CNT; break; \ ++ } ++ ++#define FMAN_DMA_EMER_TRANS(fsl_dma_emer, _dma_emer) \ ++ switch (_dma_emer){ \ ++ case e_FM_DMA_EM_EBS: \ ++ fsl_dma_emer = E_FMAN_DMA_EM_EBS; break; \ ++ case e_FM_DMA_EM_SOS: \ ++ fsl_dma_emer = E_FMAN_DMA_EM_SOS; break; \ ++ default: \ ++ fsl_dma_emer = E_FMAN_DMA_EM_EBS; break; \ ++ } ++ ++#define FMAN_DMA_ERR_TRANS(fsl_dma_err, _dma_err) \ ++ switch (_dma_err){ \ ++ case e_FM_DMA_ERR_CATASTROPHIC: \ ++ fsl_dma_err = E_FMAN_DMA_ERR_CATASTROPHIC; break; \ ++ case e_FM_DMA_ERR_REPORT: \ ++ fsl_dma_err = E_FMAN_DMA_ERR_REPORT; break; \ ++ default: \ ++ fsl_dma_err = E_FMAN_DMA_ERR_CATASTROPHIC; break; \ ++ } ++ ++#define FMAN_CATASTROPHIC_ERR_TRANS(fsl_catastrophic_err, _catastrophic_err) \ ++ switch (_catastrophic_err){ \ ++ case e_FM_CATASTROPHIC_ERR_STALL_PORT: \ ++ fsl_catastrophic_err = E_FMAN_CATAST_ERR_STALL_PORT; break; \ ++ case e_FM_CATASTROPHIC_ERR_STALL_TASK: \ ++ fsl_catastrophic_err = E_FMAN_CATAST_ERR_STALL_TASK; break; \ ++ default: \ ++ fsl_catastrophic_err = E_FMAN_CATAST_ERR_STALL_PORT; break; \ ++ } ++ ++#define FMAN_COUNTERS_TRANS(fsl_counters, _counters) \ ++ switch (_counters){ \ ++ case e_FM_COUNTERS_ENQ_TOTAL_FRAME: \ ++ fsl_counters = E_FMAN_COUNTERS_ENQ_TOTAL_FRAME; break; \ ++ case e_FM_COUNTERS_DEQ_TOTAL_FRAME: \ ++ fsl_counters = E_FMAN_COUNTERS_DEQ_TOTAL_FRAME; break; \ ++ case e_FM_COUNTERS_DEQ_0: \ ++ fsl_counters = E_FMAN_COUNTERS_DEQ_0; break; \ ++ case e_FM_COUNTERS_DEQ_1: \ ++ fsl_counters = E_FMAN_COUNTERS_DEQ_1; break; \ ++ case e_FM_COUNTERS_DEQ_2: \ ++ fsl_counters = E_FMAN_COUNTERS_DEQ_2; break; \ ++ case e_FM_COUNTERS_DEQ_3: \ ++ fsl_counters = E_FMAN_COUNTERS_DEQ_3; break; \ ++ case e_FM_COUNTERS_DEQ_FROM_DEFAULT: \ ++ fsl_counters = E_FMAN_COUNTERS_DEQ_FROM_DEFAULT; break; \ ++ case e_FM_COUNTERS_DEQ_FROM_CONTEXT: \ ++ fsl_counters = E_FMAN_COUNTERS_DEQ_FROM_CONTEXT; break; \ ++ case e_FM_COUNTERS_DEQ_FROM_FD: \ ++ fsl_counters = E_FMAN_COUNTERS_DEQ_FROM_FD; break; \ ++ case e_FM_COUNTERS_DEQ_CONFIRM: \ ++ fsl_counters = E_FMAN_COUNTERS_DEQ_CONFIRM; break; \ ++ default: \ ++ fsl_counters = E_FMAN_COUNTERS_ENQ_TOTAL_FRAME; break; \ ++ } ++ ++/**************************************************************************//** ++ @Description defaults ++*//***************************************************************************/ ++#define DEFAULT_exceptions (FM_EX_DMA_BUS_ERROR |\ ++ FM_EX_DMA_READ_ECC |\ ++ FM_EX_DMA_SYSTEM_WRITE_ECC |\ ++ FM_EX_DMA_FM_WRITE_ECC |\ ++ FM_EX_FPM_STALL_ON_TASKS |\ ++ FM_EX_FPM_SINGLE_ECC |\ ++ FM_EX_FPM_DOUBLE_ECC |\ ++ FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID|\ ++ FM_EX_BMI_LIST_RAM_ECC |\ ++ FM_EX_BMI_STORAGE_PROFILE_ECC |\ ++ FM_EX_BMI_STATISTICS_RAM_ECC |\ ++ FM_EX_IRAM_ECC |\ ++ FM_EX_MURAM_ECC |\ ++ FM_EX_BMI_DISPATCH_RAM_ECC |\ ++ FM_EX_QMI_DOUBLE_ECC |\ ++ FM_EX_QMI_SINGLE_ECC) ++ ++#define DEFAULT_eccEnable FALSE ++#ifdef FM_PEDANTIC_DMA ++#define DEFAULT_aidOverride TRUE ++#else ++#define DEFAULT_aidOverride FALSE ++#endif /* FM_PEDANTIC_DMA */ ++#define DEFAULT_aidMode e_FM_DMA_AID_OUT_TNUM ++#define DEFAULT_dmaStopOnBusError FALSE ++#define DEFAULT_stopAtBusError FALSE ++#define DEFAULT_axiDbgNumOfBeats 1 ++#define DEFAULT_dmaReadIntBufLow ((DMA_THRESH_MAX_BUF+1)/2) ++#define DEFAULT_dmaReadIntBufHigh ((DMA_THRESH_MAX_BUF+1)*3/4) ++#define DEFAULT_dmaWriteIntBufLow ((DMA_THRESH_MAX_BUF+1)/2) ++#define DEFAULT_dmaWriteIntBufHigh ((DMA_THRESH_MAX_BUF+1)*3/4) ++#define DEFAULT_catastrophicErr e_FM_CATASTROPHIC_ERR_STALL_PORT ++#define DEFAULT_dmaErr e_FM_DMA_ERR_CATASTROPHIC ++#define DEFAULT_resetOnInit FALSE ++#define DEFAULT_haltOnExternalActivation FALSE /* do not change! if changed, must be disabled for rev1 ! */ ++#define DEFAULT_haltOnUnrecoverableEccError FALSE /* do not change! if changed, must be disabled for rev1 ! */ ++#define DEFAULT_externalEccRamsEnable FALSE ++#define DEFAULT_VerifyUcode FALSE ++ ++#if (DPAA_VERSION < 11) ++#define DEFAULT_totalFifoSize(major, minor) \ ++ (((major == 2) || (major == 5)) ? \ ++ (100*KILOBYTE) : ((major == 4) ? \ ++ (49*KILOBYTE) : (122*KILOBYTE))) ++#define DEFAULT_totalNumOfTasks(major, minor) \ ++ BMI_MAX_NUM_OF_TASKS ++ ++#define DEFAULT_dmaCommQLow ((DMA_THRESH_MAX_COMMQ+1)/2) ++#define DEFAULT_dmaCommQHigh ((DMA_THRESH_MAX_COMMQ+1)*3/4) ++#define DEFAULT_cacheOverride e_FM_DMA_NO_CACHE_OR ++#define DEFAULT_dmaCamNumOfEntries 32 ++#define DEFAULT_dmaDbgCntMode e_FM_DMA_DBG_NO_CNT ++#define DEFAULT_dmaEnEmergency FALSE ++#define DEFAULT_dmaSosEmergency 0 ++#define DEFAULT_dmaWatchdog 0 /* disabled */ ++#define DEFAULT_dmaEnEmergencySmoother FALSE ++#define DEFAULT_dmaEmergencySwitchCounter 0 ++ ++#define DEFAULT_dispLimit 0 ++#define DEFAULT_prsDispTh 16 ++#define DEFAULT_plcrDispTh 16 ++#define DEFAULT_kgDispTh 16 ++#define DEFAULT_bmiDispTh 16 ++#define DEFAULT_qmiEnqDispTh 16 ++#define DEFAULT_qmiDeqDispTh 16 ++#define DEFAULT_fmCtl1DispTh 16 ++#define DEFAULT_fmCtl2DispTh 16 ++ ++#else /* (DPAA_VERSION < 11) */ ++/* Defaults are registers' reset values */ ++#define DEFAULT_totalFifoSize(major, minor) \ ++ (((major == 6) && ((minor == 1) || (minor == 4))) ? \ ++ (156*KILOBYTE) : (295*KILOBYTE)) ++ ++/* According to the default value of FMBM_CFG2[TNTSKS] */ ++#define DEFAULT_totalNumOfTasks(major, minor) \ ++ (((major == 6) && ((minor == 1) || (minor == 4))) ? 59 : 124) ++ ++#define DEFAULT_dmaCommQLow 0x2A ++#define DEFAULT_dmaCommQHigh 0x3F ++#define DEFAULT_cacheOverride e_FM_DMA_NO_CACHE_OR ++#define DEFAULT_dmaCamNumOfEntries 64 ++#define DEFAULT_dmaDbgCntMode e_FM_DMA_DBG_NO_CNT ++#define DEFAULT_dmaEnEmergency FALSE ++#define DEFAULT_dmaSosEmergency 0 ++#define DEFAULT_dmaWatchdog 0 /* disabled */ ++#define DEFAULT_dmaEnEmergencySmoother FALSE ++#define DEFAULT_dmaEmergencySwitchCounter 0 ++ ++#define DEFAULT_dispLimit 0 ++#define DEFAULT_prsDispTh 16 ++#define DEFAULT_plcrDispTh 16 ++#define DEFAULT_kgDispTh 16 ++#define DEFAULT_bmiDispTh 16 ++#define DEFAULT_qmiEnqDispTh 16 ++#define DEFAULT_qmiDeqDispTh 16 ++#define DEFAULT_fmCtl1DispTh 16 ++#define DEFAULT_fmCtl2DispTh 16 ++#endif /* (DPAA_VERSION < 11) */ ++ ++#define FM_TIMESTAMP_1_USEC_BIT 8 ++ ++/**************************************************************************//** ++ @Collection Defines used for enabling/disabling FM interrupts ++ @{ ++*//***************************************************************************/ ++#define ERR_INTR_EN_DMA 0x00010000 ++#define ERR_INTR_EN_FPM 0x80000000 ++#define ERR_INTR_EN_BMI 0x00800000 ++#define ERR_INTR_EN_QMI 0x00400000 ++#define ERR_INTR_EN_PRS 0x00200000 ++#define ERR_INTR_EN_KG 0x00100000 ++#define ERR_INTR_EN_PLCR 0x00080000 ++#define ERR_INTR_EN_MURAM 0x00040000 ++#define ERR_INTR_EN_IRAM 0x00020000 ++#define ERR_INTR_EN_10G_MAC0 0x00008000 ++#define ERR_INTR_EN_10G_MAC1 0x00000040 ++#define ERR_INTR_EN_1G_MAC0 0x00004000 ++#define ERR_INTR_EN_1G_MAC1 0x00002000 ++#define ERR_INTR_EN_1G_MAC2 0x00001000 ++#define ERR_INTR_EN_1G_MAC3 0x00000800 ++#define ERR_INTR_EN_1G_MAC4 0x00000400 ++#define ERR_INTR_EN_1G_MAC5 0x00000200 ++#define ERR_INTR_EN_1G_MAC6 0x00000100 ++#define ERR_INTR_EN_1G_MAC7 0x00000080 ++#define ERR_INTR_EN_MACSEC_MAC0 0x00000001 ++ ++#define INTR_EN_QMI 0x40000000 ++#define INTR_EN_PRS 0x20000000 ++#define INTR_EN_WAKEUP 0x10000000 ++#define INTR_EN_PLCR 0x08000000 ++#define INTR_EN_1G_MAC0 0x00080000 ++#define INTR_EN_1G_MAC1 0x00040000 ++#define INTR_EN_1G_MAC2 0x00020000 ++#define INTR_EN_1G_MAC3 0x00010000 ++#define INTR_EN_1G_MAC4 0x00000040 ++#define INTR_EN_1G_MAC5 0x00000020 ++#define INTR_EN_1G_MAC6 0x00000008 ++#define INTR_EN_1G_MAC7 0x00000002 ++#define INTR_EN_10G_MAC0 0x00200000 ++#define INTR_EN_10G_MAC1 0x00100000 ++#define INTR_EN_REV0 0x00008000 ++#define INTR_EN_REV1 0x00004000 ++#define INTR_EN_REV2 0x00002000 ++#define INTR_EN_REV3 0x00001000 ++#define INTR_EN_BRK 0x00000080 ++#define INTR_EN_TMR 0x01000000 ++#define INTR_EN_MACSEC_MAC0 0x00000001 ++/* @} */ ++ ++/**************************************************************************//** ++ @Description Memory Mapped Registers ++*//***************************************************************************/ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++typedef struct ++{ ++ volatile uint32_t iadd; /**< FM IRAM instruction address register */ ++ volatile uint32_t idata; /**< FM IRAM instruction data register */ ++ volatile uint32_t itcfg; /**< FM IRAM timing config register */ ++ volatile uint32_t iready; /**< FM IRAM ready register */ ++ volatile uint32_t res[0x1FFFC]; ++} t_FMIramRegs; ++ ++/* Trace buffer registers - ++ each FM Controller has its own trace buffer residing at FM_MM_TRB(fmCtrlIndex) offset */ ++typedef struct t_FmTrbRegs ++{ ++ volatile uint32_t tcrh; ++ volatile uint32_t tcrl; ++ volatile uint32_t tesr; ++ volatile uint32_t tecr0h; ++ volatile uint32_t tecr0l; ++ volatile uint32_t terf0h; ++ volatile uint32_t terf0l; ++ volatile uint32_t tecr1h; ++ volatile uint32_t tecr1l; ++ volatile uint32_t terf1h; ++ volatile uint32_t terf1l; ++ volatile uint32_t tpcch; ++ volatile uint32_t tpccl; ++ volatile uint32_t tpc1h; ++ volatile uint32_t tpc1l; ++ volatile uint32_t tpc2h; ++ volatile uint32_t tpc2l; ++ volatile uint32_t twdimr; ++ volatile uint32_t twicvr; ++ volatile uint32_t tar; ++ volatile uint32_t tdr; ++ volatile uint32_t tsnum1; ++ volatile uint32_t tsnum2; ++ volatile uint32_t tsnum3; ++ volatile uint32_t tsnum4; ++} t_FmTrbRegs; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/**************************************************************************//** ++ @Description General defines ++*//***************************************************************************/ ++#define FM_DEBUG_STATUS_REGISTER_OFFSET 0x000d1084UL ++#define FM_FW_DEBUG_INSTRUCTION 0x6ffff805UL ++ ++/**************************************************************************//** ++ @Description FPM defines ++*//***************************************************************************/ ++/* masks */ ++#define FPM_BRKC_RDBG 0x00000200 ++#define FPM_BRKC_SLP 0x00000800 ++/**************************************************************************//** ++ @Description BMI defines ++*//***************************************************************************/ ++/* masks */ ++#define BMI_INIT_START 0x80000000 ++#define BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC 0x80000000 ++#define BMI_ERR_INTR_EN_LIST_RAM_ECC 0x40000000 ++#define BMI_ERR_INTR_EN_STATISTICS_RAM_ECC 0x20000000 ++#define BMI_ERR_INTR_EN_DISPATCH_RAM_ECC 0x10000000 ++/**************************************************************************//** ++ @Description QMI defines ++*//***************************************************************************/ ++/* masks */ ++#define QMI_ERR_INTR_EN_DOUBLE_ECC 0x80000000 ++#define QMI_ERR_INTR_EN_DEQ_FROM_DEF 0x40000000 ++#define QMI_INTR_EN_SINGLE_ECC 0x80000000 ++ ++/**************************************************************************//** ++ @Description IRAM defines ++*//***************************************************************************/ ++/* masks */ ++#define IRAM_IADD_AIE 0x80000000 ++#define IRAM_READY 0x80000000 ++ ++/**************************************************************************//** ++ @Description TRB defines ++*//***************************************************************************/ ++/* masks */ ++#define TRB_TCRH_RESET 0x04000000 ++#define TRB_TCRH_ENABLE_COUNTERS 0x84008000 ++#define TRB_TCRH_DISABLE_COUNTERS 0x8400C000 ++#define TRB_TCRL_RESET 0x20000000 ++#define TRB_TCRL_UTIL 0x00000460 ++typedef struct { ++ void (*f_Isr) (t_Handle h_Arg, uint32_t event); ++ t_Handle h_SrcHandle; ++} t_FmanCtrlIntrSrc; ++ ++ ++typedef void (t_FmanCtrlIsr)( t_Handle h_Fm, uint32_t event); ++ ++typedef struct ++{ ++/***************************/ ++/* Master/Guest parameters */ ++/***************************/ ++ uint8_t fmId; ++ e_FmPortType portsTypes[FM_MAX_NUM_OF_HW_PORT_IDS]; ++ uint16_t fmClkFreq; ++ uint16_t fmMacClkFreq; ++ t_FmRevisionInfo revInfo; ++/**************************/ ++/* Master Only parameters */ ++/**************************/ ++ bool enabledTimeStamp; ++ uint8_t count1MicroBit; ++ uint8_t totalNumOfTasks; ++ uint32_t totalFifoSize; ++ uint8_t maxNumOfOpenDmas; ++ uint8_t accumulatedNumOfTasks; ++ uint32_t accumulatedFifoSize; ++ uint8_t accumulatedNumOfOpenDmas; ++ uint8_t accumulatedNumOfDeqTnums; ++#ifdef FM_LOW_END_RESTRICTION ++ bool lowEndRestriction; ++#endif /* FM_LOW_END_RESTRICTION */ ++ uint32_t exceptions; ++ int irq; ++ int errIrq; ++ bool ramsEccEnable; ++ bool explicitEnable; ++ bool internalCall; ++ uint8_t ramsEccOwners; ++ uint32_t extraFifoPoolSize; ++ uint8_t extraTasksPoolSize; ++ uint8_t extraOpenDmasPoolSize; ++#if defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS) ++ uint16_t portMaxFrameLengths10G[FM_MAX_NUM_OF_10G_MACS]; ++ uint16_t macMaxFrameLengths10G[FM_MAX_NUM_OF_10G_MACS]; ++#endif /* defined(FM_MAX_NUM_OF_10G_MACS) && ... */ ++ uint16_t portMaxFrameLengths1G[FM_MAX_NUM_OF_1G_MACS]; ++ uint16_t macMaxFrameLengths1G[FM_MAX_NUM_OF_1G_MACS]; ++} t_FmStateStruct; ++ ++#if (DPAA_VERSION >= 11) ++typedef struct t_FmMapParam { ++ uint16_t profilesBase; ++ uint16_t numOfProfiles; ++ t_Handle h_FmPort; ++} t_FmMapParam; ++ ++typedef struct t_FmAllocMng { ++ bool allocated; ++ uint8_t ownerId; /* guestId for KG in multi-partition only, ++ portId for PLCR in any environment */ ++} t_FmAllocMng; ++ ++typedef struct t_FmPcdSpEntry { ++ bool valid; ++ t_FmAllocMng profilesMng; ++} t_FmPcdSpEntry; ++ ++typedef struct t_FmSp { ++ void *p_FmPcdStoragePrflRegs; ++ t_FmPcdSpEntry profiles[FM_VSP_MAX_NUM_OF_ENTRIES]; ++ t_FmMapParam portsMapping[FM_MAX_NUM_OF_PORTS]; ++} t_FmSp; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++typedef struct t_Fm ++{ ++/***************************/ ++/* Master/Guest parameters */ ++/***************************/ ++/* locals for recovery */ ++ uintptr_t baseAddr; ++ ++/* un-needed for recovery */ ++ t_Handle h_Pcd; ++ char fmModuleName[MODULE_NAME_SIZE]; ++ char fmIpcHandlerModuleName[FM_MAX_NUM_OF_GUESTS][MODULE_NAME_SIZE]; ++ t_Handle h_IpcSessions[FM_MAX_NUM_OF_GUESTS]; ++ t_FmIntrSrc intrMng[e_FM_EV_DUMMY_LAST]; /* FM exceptions user callback */ ++ uint8_t guestId; ++/**************************/ ++/* Master Only parameters */ ++/**************************/ ++/* locals for recovery */ ++ struct fman_fpm_regs *p_FmFpmRegs; ++ struct fman_bmi_regs *p_FmBmiRegs; ++ struct fman_qmi_regs *p_FmQmiRegs; ++ struct fman_dma_regs *p_FmDmaRegs; ++ struct fman_regs *p_FmRegs; ++ t_FmExceptionsCallback *f_Exception; ++ t_FmBusErrorCallback *f_BusError; ++ t_Handle h_App; /* Application handle */ ++ t_Handle h_Spinlock; ++ bool recoveryMode; ++ t_FmStateStruct *p_FmStateStruct; ++ uint16_t tnumAgingPeriod; ++#if (DPAA_VERSION >= 11) ++ t_FmSp *p_FmSp; ++ uint8_t partNumOfVSPs; ++ uint8_t partVSPBase; ++ uintptr_t vspBaseAddr; ++#endif /* (DPAA_VERSION >= 11) */ ++ bool portsPreFetchConfigured[FM_MAX_NUM_OF_HW_PORT_IDS]; /* Prefetch configration per Tx-port */ ++ bool portsPreFetchValue[FM_MAX_NUM_OF_HW_PORT_IDS]; /* Prefetch configration per Tx-port */ ++ ++/* un-needed for recovery */ ++ struct fman_cfg *p_FmDriverParam; ++ t_Handle h_FmMuram; ++ uint64_t fmMuramPhysBaseAddr; ++ bool independentMode; ++ bool hcPortInitialized; ++ uintptr_t camBaseAddr; /* save for freeing */ ++ uintptr_t resAddr; ++ uintptr_t fifoBaseAddr; /* save for freeing */ ++ t_FmanCtrlIntrSrc fmanCtrlIntr[FM_NUM_OF_FMAN_CTRL_EVENT_REGS]; /* FM exceptions user callback */ ++ bool usedEventRegs[FM_NUM_OF_FMAN_CTRL_EVENT_REGS]; ++ t_FmFirmwareParams firmware; ++ bool fwVerify; ++ bool resetOnInit; ++ uint32_t userSetExceptions; ++} t_Fm; ++ ++ ++#endif /* __FM_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm_ipc.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm_ipc.h +new file mode 100644 +index 0000000..7ce36a7 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm_ipc.h +@@ -0,0 +1,465 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File fm_ipc.h ++ ++ @Description FM Inter-Partition prototypes, structures and definitions. ++*//***************************************************************************/ ++#ifndef __FM_IPC_H ++#define __FM_IPC_H ++ ++#include "error_ext.h" ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_IPC_grp FM Inter-Partition messaging Unit ++ ++ @Description FM Inter-Partition messaging unit API definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/**************************************************************************//** ++ @Description enum for defining MAC types ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description A structure of parameters for specifying a MAC. ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ uint8_t id; ++ uint32_t enumType; ++} _PackedType t_FmIpcMacParams; ++ ++/**************************************************************************//** ++ @Description A structure of parameters for specifying a MAC. ++*//***************************************************************************/ ++typedef _Packed struct ++{ ++ t_FmIpcMacParams macParams; ++ uint16_t maxFrameLength; ++} _PackedType t_FmIpcMacMaxFrameParams; ++ ++/**************************************************************************//** ++ @Description FM physical Address ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcPhysAddr ++{ ++ volatile uint8_t high; ++ volatile uint32_t low; ++} _PackedType t_FmIpcPhysAddr; ++ ++ ++typedef _Packed struct t_FmIpcPortOutInitParams { ++ uint8_t numOfTasks; /**< OUT */ ++ uint8_t numOfExtraTasks; /**< OUT */ ++ uint8_t numOfOpenDmas; /**< OUT */ ++ uint8_t numOfExtraOpenDmas; /**< OUT */ ++ uint32_t sizeOfFifo; /**< OUT */ ++ uint32_t extraSizeOfFifo; /**< OUT */ ++ t_FmIpcPhysAddr ipcPhysAddr; /**< OUT */ ++} _PackedType t_FmIpcPortOutInitParams; ++ ++/**************************************************************************//** ++ @Description Structure for IPC communication during FM_PORT_Init. ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcPortInInitParams { ++ uint8_t hardwarePortId; /**< IN. port Id */ ++ uint32_t enumPortType; /**< IN. Port type */ ++ uint8_t boolIndependentMode;/**< IN. TRUE if FM Port operates in independent mode */ ++ uint16_t liodnOffset; /**< IN. Port's requested resource */ ++ uint8_t numOfTasks; /**< IN. Port's requested resource */ ++ uint8_t numOfExtraTasks; /**< IN. Port's requested resource */ ++ uint8_t numOfOpenDmas; /**< IN. Port's requested resource */ ++ uint8_t numOfExtraOpenDmas; /**< IN. Port's requested resource */ ++ uint32_t sizeOfFifo; /**< IN. Port's requested resource */ ++ uint32_t extraSizeOfFifo; /**< IN. Port's requested resource */ ++ uint8_t deqPipelineDepth; /**< IN. Port's requested resource */ ++ uint16_t maxFrameLength; /**< IN. Port's max frame length. */ ++ uint16_t liodnBase; /**< IN. Irrelevant for P4080 rev 1. ++ LIODN base for this port, to be ++ used together with LIODN offset. */ ++} _PackedType t_FmIpcPortInInitParams; ++ ++ ++/**************************************************************************//** ++ @Description Structure for IPC communication between port and FM ++ regarding tasks and open DMA resources management. ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcPortRsrcParams { ++ uint8_t hardwarePortId; /**< IN. port Id */ ++ uint32_t val; /**< IN. Port's requested resource */ ++ uint32_t extra; /**< IN. Port's requested resource */ ++ uint8_t boolInitialConfig; ++} _PackedType t_FmIpcPortRsrcParams; ++ ++ ++/**************************************************************************//** ++ @Description Structure for IPC communication between port and FM ++ regarding tasks and open DMA resources management. ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcPortFifoParams { ++ t_FmIpcPortRsrcParams rsrcParams; ++ uint32_t enumPortType; ++ uint8_t boolIndependentMode; ++ uint8_t deqPipelineDepth; ++ uint8_t numOfPools; ++ uint16_t secondLargestBufSize; ++ uint16_t largestBufSize; ++ uint8_t boolInitialConfig; ++} _PackedType t_FmIpcPortFifoParams; ++ ++/**************************************************************************//** ++ @Description Structure for port-FM communication during FM_PORT_Free. ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcPortFreeParams { ++ uint8_t hardwarePortId; /**< IN. port Id */ ++ uint32_t enumPortType; /**< IN. Port type */ ++ uint8_t deqPipelineDepth; /**< IN. Port's requested resource */ ++} _PackedType t_FmIpcPortFreeParams; ++ ++/**************************************************************************//** ++ @Description Structure for defining DMA status ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcDmaStatus { ++ uint8_t boolCmqNotEmpty; /**< Command queue is not empty */ ++ uint8_t boolBusError; /**< Bus error occurred */ ++ uint8_t boolReadBufEccError; /**< Double ECC error on buffer Read */ ++ uint8_t boolWriteBufEccSysError; /**< Double ECC error on buffer write from system side */ ++ uint8_t boolWriteBufEccFmError; /**< Double ECC error on buffer write from FM side */ ++ uint8_t boolSinglePortEccError; /**< Single port ECC error from FM side */ ++} _PackedType t_FmIpcDmaStatus; ++ ++typedef _Packed struct t_FmIpcRegisterIntr ++{ ++ uint8_t guestId; /* IN */ ++ uint32_t event; /* IN */ ++} _PackedType t_FmIpcRegisterIntr; ++ ++typedef _Packed struct t_FmIpcIsr ++{ ++ uint8_t boolErr; /* IN */ ++ uint32_t pendingReg; /* IN */ ++} _PackedType t_FmIpcIsr; ++ ++/**************************************************************************//** ++ @Description structure for returning FM parameters ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcParams { ++ uint16_t fmClkFreq; /**< OUT: FM Clock frequency */ ++ uint16_t fmMacClkFreq; /**< OUT: FM MAC clock frequence */ ++ uint8_t majorRev; /**< OUT: FM Major revision */ ++ uint8_t minorRev; /**< OUT: FM Minor revision */ ++} _PackedType t_FmIpcParams; ++ ++ ++/**************************************************************************//** ++ @Description structure for returning Fman Ctrl Code revision information ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcFmanCtrlCodeRevisionInfo { ++ uint16_t packageRev; /**< OUT: Package revision */ ++ uint8_t majorRev; /**< OUT: Major revision */ ++ uint8_t minorRev; /**< OUT: Minor revision */ ++} _PackedType t_FmIpcFmanCtrlCodeRevisionInfo; ++ ++/**************************************************************************//** ++ @Description Structure for defining Fm number of Fman controlers ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcPortNumOfFmanCtrls { ++ uint8_t hardwarePortId; /**< IN. port Id */ ++ uint8_t numOfFmanCtrls; /**< IN. Port type */ ++ t_FmFmanCtrl orFmanCtrl; /**< IN. fman controller for order restoration*/ ++} t_FmIpcPortNumOfFmanCtrls; ++ ++/**************************************************************************//** ++ @Description structure for setting Fman contriller events ++*//***************************************************************************/ ++typedef _Packed struct t_FmIpcFmanEvents { ++ uint8_t eventRegId; /**< IN: Fman controller event register id */ ++ uint32_t enableEvents; /**< IN/OUT: required enabled events mask */ ++} _PackedType t_FmIpcFmanEvents; ++ ++typedef _Packed struct t_FmIpcResourceAllocParams { ++ uint8_t guestId; ++ uint16_t base; ++ uint16_t num; ++}_PackedType t_FmIpcResourceAllocParams; ++ ++typedef _Packed struct t_FmIpcVspSetPortWindow { ++ uint8_t hardwarePortId; ++ uint8_t baseStorageProfile; ++ uint8_t log2NumOfProfiles; ++}_PackedType t_FmIpcVspSetPortWindow; ++ ++typedef _Packed struct t_FmIpcSetCongestionGroupPfcPriority { ++ uint32_t congestionGroupId; ++ uint8_t priorityBitMap; ++}_PackedType t_FmIpcSetCongestionGroupPfcPriority; ++ ++#define FM_IPC_MAX_REPLY_BODY_SIZE 20 ++#define FM_IPC_MAX_REPLY_SIZE (FM_IPC_MAX_REPLY_BODY_SIZE + sizeof(uint32_t)) ++#define FM_IPC_MAX_MSG_SIZE 30 ++ ++typedef _Packed struct t_FmIpcMsg ++{ ++ uint32_t msgId; ++ uint8_t msgBody[FM_IPC_MAX_MSG_SIZE]; ++} _PackedType t_FmIpcMsg; ++ ++typedef _Packed struct t_FmIpcReply ++{ ++ uint32_t error; ++ uint8_t replyBody[FM_IPC_MAX_REPLY_BODY_SIZE]; ++} _PackedType t_FmIpcReply; ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/***************************************************************************/ ++/************************ FRONT-END-TO-BACK-END*****************************/ ++/***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_GET_TIMESTAMP_SCALE ++ ++ @Description Used by FM front-end. ++ ++ @Param[out] uint32_t Pointer ++*//***************************************************************************/ ++#define FM_GET_TIMESTAMP_SCALE 1 ++ ++/**************************************************************************//** ++ @Function FM_GET_COUNTER ++ ++ @Description Used by FM front-end. ++ ++ @Param[in/out] t_FmIpcGetCounter Pointer ++*//***************************************************************************/ ++#define FM_GET_COUNTER 2 ++ ++/**************************************************************************//** ++ @Function FM_GET_SET_PORT_PARAMS ++ ++ @Description Used by FM front-end for the PORT module in order to set and get ++ parameters in/from master FM module on FM PORT initialization time. ++ ++ @Param[in/out] t_FmIcPortInitParams Pointer ++*//***************************************************************************/ ++#define FM_GET_SET_PORT_PARAMS 4 ++ ++/**************************************************************************//** ++ @Function FM_FREE_PORT ++ ++ @Description Used by FM front-end for the PORT module when a port is freed ++ to free all FM PORT resources. ++ ++ @Param[in] uint8_t Pointer ++*//***************************************************************************/ ++#define FM_FREE_PORT 5 ++ ++/**************************************************************************//** ++ @Function FM_RESET_MAC ++ ++ @Description Used by front-end for the MAC module to reset the MAC registers ++ ++ @Param[in] t_FmIpcMacParams Pointer . ++*//***************************************************************************/ ++#define FM_RESET_MAC 6 ++ ++/**************************************************************************//** ++ @Function FM_RESUME_STALLED_PORT ++ ++ @Description Used by FM front-end for the PORT module in order to ++ release a stalled FM Port. ++ ++ @Param[in] uint8_t Pointer ++*//***************************************************************************/ ++#define FM_RESUME_STALLED_PORT 7 ++ ++/**************************************************************************//** ++ @Function FM_IS_PORT_STALLED ++ ++ @Description Used by FM front-end for the PORT module in order to check whether ++ an FM port is stalled. ++ ++ @Param[in/out] t_FmIcPortIsStalled Pointer ++*//***************************************************************************/ ++#define FM_IS_PORT_STALLED 8 ++ ++/**************************************************************************//** ++ @Function FM_GET_PARAMS ++ ++ @Description Used by FM front-end for the PORT module in order to dump ++ return FM parameters. ++ ++ @Param[in] uint8_t Pointer ++*//***************************************************************************/ ++#define FM_GET_PARAMS 10 ++ ++/**************************************************************************//** ++ @Function FM_REGISTER_INTR ++ ++ @Description Used by FM front-end to register an interrupt handler to ++ be called upon interrupt for guest. ++ ++ @Param[out] t_FmIpcRegisterIntr Pointer ++*//***************************************************************************/ ++#define FM_REGISTER_INTR 11 ++ ++/**************************************************************************//** ++ @Function FM_DMA_STAT ++ ++ @Description Used by FM front-end to read the FM DMA status. ++ ++ @Param[out] t_FmIpcDmaStatus Pointer ++*//***************************************************************************/ ++#define FM_DMA_STAT 13 ++ ++/**************************************************************************//** ++ @Function FM_ALLOC_FMAN_CTRL_EVENT_REG ++ ++ @Description Used by FM front-end to allocate event register. ++ ++ @Param[out] Event register id Pointer ++*//***************************************************************************/ ++#define FM_ALLOC_FMAN_CTRL_EVENT_REG 14 ++ ++/**************************************************************************//** ++ @Function FM_FREE_FMAN_CTRL_EVENT_REG ++ ++ @Description Used by FM front-end to free locate event register. ++ ++ @Param[in] uint8_t Pointer - Event register id ++*//***************************************************************************/ ++#define FM_FREE_FMAN_CTRL_EVENT_REG 15 ++ ++/**************************************************************************//** ++ @Function FM_SET_FMAN_CTRL_EVENTS_ENABLE ++ ++ @Description Used by FM front-end to enable events in the FPM ++ Fman controller event register. ++ ++ @Param[in] t_FmIpcFmanEvents Pointer ++*//***************************************************************************/ ++#define FM_SET_FMAN_CTRL_EVENTS_ENABLE 16 ++ ++/**************************************************************************//** ++ @Function FM_SET_FMAN_CTRL_EVENTS_ENABLE ++ ++ @Description Used by FM front-end to enable events in the FPM ++ Fman controller event register. ++ ++ @Param[in/out] t_FmIpcFmanEvents Pointer ++*//***************************************************************************/ ++#define FM_GET_FMAN_CTRL_EVENTS_ENABLE 17 ++ ++/**************************************************************************//** ++ @Function FM_SET_MAC_MAX_FRAME ++ ++ @Description Used by FM front-end to set MAC's MTU/RTU's in ++ back-end. ++ ++ @Param[in/out] t_FmIpcMacMaxFrameParams Pointer ++*//***************************************************************************/ ++#define FM_SET_MAC_MAX_FRAME 18 ++ ++/**************************************************************************//** ++ @Function FM_GET_PHYS_MURAM_BASE ++ ++ @Description Used by FM front-end in order to get MURAM base address ++ ++ @Param[in/out] t_FmIpcPhysAddr Pointer ++*//***************************************************************************/ ++#define FM_GET_PHYS_MURAM_BASE 19 ++ ++/**************************************************************************//** ++ @Function FM_MASTER_IS_ALIVE ++ ++ @Description Used by FM front-end in order to verify Master is up ++ ++ @Param[in/out] bool ++*//***************************************************************************/ ++#define FM_MASTER_IS_ALIVE 20 ++ ++#define FM_ENABLE_RAM_ECC 21 ++#define FM_DISABLE_RAM_ECC 22 ++#define FM_SET_NUM_OF_FMAN_CTRL 23 ++#define FM_SET_SIZE_OF_FIFO 24 ++#define FM_SET_NUM_OF_TASKS 25 ++#define FM_SET_NUM_OF_OPEN_DMAS 26 ++#define FM_VSP_ALLOC 27 ++#define FM_VSP_FREE 28 ++#define FM_VSP_SET_PORT_WINDOW 29 ++#define FM_GET_FMAN_CTRL_CODE_REV 30 ++#define FM_SET_CONG_GRP_PFC_PRIO 31 ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++#define FM_10G_TX_ECC_WA 100 ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++/***************************************************************************/ ++/************************ BACK-END-TO-FRONT-END*****************************/ ++/***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_GUEST_ISR ++ ++ @Description Used by FM back-end to report an interrupt to the front-end. ++ ++ @Param[out] t_FmIpcIsr Pointer ++*//***************************************************************************/ ++#define FM_GUEST_ISR 1 ++ ++ ++ ++/** @} */ /* end of FM_IPC_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++#endif /* __FM_IPC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm_muram.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm_muram.c +new file mode 100644 +index 0000000..0bc67cb +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm_muram.c +@@ -0,0 +1,174 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File FM_muram.c ++ ++ @Description FM MURAM ... ++*//***************************************************************************/ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "mm_ext.h" ++#include "string_ext.h" ++#include "sprint_ext.h" ++#include "fm_muram_ext.h" ++#include "fm_common.h" ++ ++#define __ERR_MODULE__ MODULE_FM_MURAM ++ ++ ++typedef struct ++{ ++ t_Handle h_Mem; ++ uintptr_t baseAddr; ++ uint32_t size; ++} t_FmMuram; ++ ++ ++void FmMuramClear(t_Handle h_FmMuram) ++{ ++ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram; ++ ++ SANITY_CHECK_RETURN(h_FmMuram, E_INVALID_HANDLE); ++ IOMemSet32(UINT_TO_PTR(p_FmMuram->baseAddr), 0, p_FmMuram->size); ++} ++ ++ ++t_Handle FM_MURAM_ConfigAndInit(uintptr_t baseAddress, uint32_t size) ++{ ++ t_Handle h_Mem; ++ t_FmMuram *p_FmMuram; ++ ++ if (!baseAddress) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("baseAddress 0 is not supported")); ++ return NULL; ++ } ++ ++ if (baseAddress%4) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("baseAddress not 4 bytes aligned!")); ++ return NULL; ++ } ++ ++ /* Allocate FM MURAM structure */ ++ p_FmMuram = (t_FmMuram *) XX_Malloc(sizeof(t_FmMuram)); ++ if (!p_FmMuram) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM MURAM driver structure")); ++ return NULL; ++ } ++ memset(p_FmMuram, 0, sizeof(t_FmMuram)); ++ ++ ++ if ((MM_Init(&h_Mem, baseAddress, size) != E_OK) || (!h_Mem)) ++ { ++ XX_Free(p_FmMuram); ++ REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("FM-MURAM partition!!!")); ++ return NULL; ++ } ++ ++ /* Initialize FM MURAM parameters which will be kept by the driver */ ++ p_FmMuram->baseAddr = baseAddress; ++ p_FmMuram->size = size; ++ p_FmMuram->h_Mem = h_Mem; ++ ++ return p_FmMuram; ++} ++ ++t_Error FM_MURAM_Free(t_Handle h_FmMuram) ++{ ++ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram; ++ ++ if (p_FmMuram->h_Mem) ++ MM_Free(p_FmMuram->h_Mem); ++ ++ XX_Free(h_FmMuram); ++ ++ return E_OK; ++} ++ ++void * FM_MURAM_AllocMem(t_Handle h_FmMuram, uint32_t size, uint32_t align) ++{ ++ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram; ++ uintptr_t addr; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmMuram, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_FmMuram->h_Mem, E_INVALID_HANDLE, NULL); ++ ++ addr = (uintptr_t)MM_Get(p_FmMuram->h_Mem, size, align ,"FM MURAM"); ++ ++ if (addr == ILLEGAL_BASE) ++ return NULL; ++ ++ return UINT_TO_PTR(addr); ++} ++ ++void * FM_MURAM_AllocMemForce(t_Handle h_FmMuram, uint64_t base, uint32_t size) ++{ ++ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram; ++ uintptr_t addr; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmMuram, E_INVALID_HANDLE, NULL); ++ SANITY_CHECK_RETURN_VALUE(p_FmMuram->h_Mem, E_INVALID_HANDLE, NULL); ++ ++ addr = (uintptr_t)MM_GetForce(p_FmMuram->h_Mem, base, size, "FM MURAM"); ++ ++ if (addr == ILLEGAL_BASE) ++ return NULL; ++ ++ return UINT_TO_PTR(addr); ++} ++ ++t_Error FM_MURAM_FreeMem(t_Handle h_FmMuram, void *ptr) ++{ ++ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram; ++ ++ SANITY_CHECK_RETURN_ERROR(h_FmMuram, E_INVALID_HANDLE); ++ SANITY_CHECK_RETURN_ERROR(p_FmMuram->h_Mem, E_INVALID_HANDLE); ++ ++ if (MM_Put(p_FmMuram->h_Mem, PTR_TO_UINT(ptr)) == 0) ++ RETURN_ERROR(MINOR, E_INVALID_ADDRESS, ("memory pointer!!!")); ++ ++ return E_OK; ++} ++ ++uint64_t FM_MURAM_GetFreeMemSize(t_Handle h_FmMuram) ++{ ++ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram; ++ ++ SANITY_CHECK_RETURN_VALUE(h_FmMuram, E_INVALID_HANDLE, 0); ++ SANITY_CHECK_RETURN_VALUE(p_FmMuram->h_Mem, E_INVALID_HANDLE, 0); ++ ++ return MM_GetFreeMemSize(p_FmMuram->h_Mem); ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fman.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fman.c +new file mode 100755 +index 0000000..97adbbf +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fman.c +@@ -0,0 +1,1399 @@ ++/* ++ * Copyright 2008-2012 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 "fsl_fman.h" ++#include "dpaa_integration_ext.h" ++ ++uint32_t fman_get_bmi_err_event(struct fman_bmi_regs *bmi_rg) ++{ ++ uint32_t event, mask, force; ++ ++ event = ioread32be(&bmi_rg->fmbm_ievr); ++ mask = ioread32be(&bmi_rg->fmbm_ier); ++ event &= mask; ++ /* clear the forced events */ ++ force = ioread32be(&bmi_rg->fmbm_ifr); ++ if (force & event) ++ iowrite32be(force & ~event, &bmi_rg->fmbm_ifr); ++ /* clear the acknowledged events */ ++ iowrite32be(event, &bmi_rg->fmbm_ievr); ++ return event; ++} ++ ++uint32_t fman_get_qmi_err_event(struct fman_qmi_regs *qmi_rg) ++{ ++ uint32_t event, mask, force; ++ ++ event = ioread32be(&qmi_rg->fmqm_eie); ++ mask = ioread32be(&qmi_rg->fmqm_eien); ++ event &= mask; ++ ++ /* clear the forced events */ ++ force = ioread32be(&qmi_rg->fmqm_eif); ++ if (force & event) ++ iowrite32be(force & ~event, &qmi_rg->fmqm_eif); ++ /* clear the acknowledged events */ ++ iowrite32be(event, &qmi_rg->fmqm_eie); ++ return event; ++} ++ ++uint32_t fman_get_dma_com_id(struct fman_dma_regs *dma_rg) ++{ ++ return ioread32be(&dma_rg->fmdmtcid); ++} ++ ++uint64_t fman_get_dma_addr(struct fman_dma_regs *dma_rg) ++{ ++ uint64_t addr; ++ ++ addr = (uint64_t)ioread32be(&dma_rg->fmdmtal); ++ addr |= ((uint64_t)(ioread32be(&dma_rg->fmdmtah)) << 32); ++ ++ return addr; ++} ++ ++uint32_t fman_get_dma_err_event(struct fman_dma_regs *dma_rg) ++{ ++ uint32_t status, mask; ++ ++ status = ioread32be(&dma_rg->fmdmsr); ++ mask = ioread32be(&dma_rg->fmdmmr); ++ ++ /* clear DMA_STATUS_BUS_ERR if mask has no DMA_MODE_BER */ ++ if ((mask & DMA_MODE_BER) != DMA_MODE_BER) ++ status &= ~DMA_STATUS_BUS_ERR; ++ ++ /* clear relevant bits if mask has no DMA_MODE_ECC */ ++ if ((mask & DMA_MODE_ECC) != DMA_MODE_ECC) ++ status &= ~(DMA_STATUS_FM_SPDAT_ECC | ++ DMA_STATUS_READ_ECC | ++ DMA_STATUS_SYSTEM_WRITE_ECC | ++ DMA_STATUS_FM_WRITE_ECC); ++ ++ /* clear set events */ ++ iowrite32be(status, &dma_rg->fmdmsr); ++ ++ return status; ++} ++ ++uint32_t fman_get_fpm_err_event(struct fman_fpm_regs *fpm_rg) ++{ ++ uint32_t event; ++ ++ event = ioread32be(&fpm_rg->fmfp_ee); ++ /* clear the all occurred events */ ++ iowrite32be(event, &fpm_rg->fmfp_ee); ++ return event; ++} ++ ++uint32_t fman_get_muram_err_event(struct fman_fpm_regs *fpm_rg) ++{ ++ uint32_t event, mask; ++ ++ event = ioread32be(&fpm_rg->fm_rcr); ++ mask = ioread32be(&fpm_rg->fm_rie); ++ ++ /* clear MURAM event bit (do not clear IRAM event) */ ++ iowrite32be(event & ~FPM_RAM_IRAM_ECC, &fpm_rg->fm_rcr); ++ ++ if ((mask & FPM_MURAM_ECC_ERR_EX_EN)) ++ return event; ++ else ++ return 0; ++} ++ ++uint32_t fman_get_iram_err_event(struct fman_fpm_regs *fpm_rg) ++{ ++ uint32_t event, mask; ++ ++ event = ioread32be(&fpm_rg->fm_rcr) ; ++ mask = ioread32be(&fpm_rg->fm_rie); ++ /* clear IRAM event bit (do not clear MURAM event) */ ++ iowrite32be(event & ~FPM_RAM_MURAM_ECC, ++ &fpm_rg->fm_rcr); ++ ++ if ((mask & FPM_IRAM_ECC_ERR_EX_EN)) ++ return event; ++ else ++ return 0; ++} ++ ++uint32_t fman_get_qmi_event(struct fman_qmi_regs *qmi_rg) ++{ ++ uint32_t event, mask, force; ++ ++ event = ioread32be(&qmi_rg->fmqm_ie); ++ mask = ioread32be(&qmi_rg->fmqm_ien); ++ event &= mask; ++ /* clear the forced events */ ++ force = ioread32be(&qmi_rg->fmqm_if); ++ if (force & event) ++ iowrite32be(force & ~event, &qmi_rg->fmqm_if); ++ /* clear the acknowledged events */ ++ iowrite32be(event, &qmi_rg->fmqm_ie); ++ return event; ++} ++ ++void fman_enable_time_stamp(struct fman_fpm_regs *fpm_rg, ++ uint8_t count1ubit, ++ uint16_t fm_clk_freq) ++{ ++ uint32_t tmp; ++ uint64_t frac; ++ uint32_t intgr; ++ uint32_t ts_freq = (uint32_t)(1 << count1ubit); /* in Mhz */ ++ ++ /* configure timestamp so that bit 8 will count 1 microsecond ++ * Find effective count rate at TIMESTAMP least significant bits: ++ * Effective_Count_Rate = 1MHz x 2^8 = 256MHz ++ * Find frequency ratio between effective count rate and the clock: ++ * Effective_Count_Rate / CLK e.g. for 600 MHz clock: ++ * 256/600 = 0.4266666... */ ++ ++ intgr = ts_freq / fm_clk_freq; ++ /* we multiply by 2^16 to keep the fraction of the division ++ * we do not div back, since we write this value as a fraction ++ * see spec */ ++ ++ frac = (((uint64_t)ts_freq << 16) - ((uint64_t)intgr << 16) * fm_clk_freq) ++ / fm_clk_freq; ++ /* we check remainder of the division in order to round up if not int */ ++ if (((ts_freq << 16) - (intgr << 16)*fm_clk_freq) % fm_clk_freq) ++ frac++; ++ ++ tmp = (intgr << FPM_TS_INT_SHIFT) | (uint16_t)frac; ++ iowrite32be(tmp, &fpm_rg->fmfp_tsc2); ++ ++ /* enable timestamp with original clock */ ++ iowrite32be(FPM_TS_CTL_EN, &fpm_rg->fmfp_tsc1); ++} ++ ++uint32_t fman_get_fpm_error_interrupts(struct fman_fpm_regs *fpm_rg) ++{ ++ return ioread32be(&fpm_rg->fm_epi); ++} ++ ++ ++int fman_set_erratum_10gmac_a004_wa(struct fman_fpm_regs *fpm_rg) ++{ ++ int timeout = 100; ++ ++ iowrite32be(0x40000000, &fpm_rg->fmfp_extc); ++ ++ while ((ioread32be(&fpm_rg->fmfp_extc) & 0x40000000) && --timeout) ++ udelay(10); ++ ++ if (!timeout) ++ return -EBUSY; ++ return 0; ++} ++ ++void fman_set_ctrl_intr(struct fman_fpm_regs *fpm_rg, ++ uint8_t event_reg_id, ++ uint32_t enable_events) ++{ ++ iowrite32be(enable_events, &fpm_rg->fmfp_cee[event_reg_id]); ++} ++ ++uint32_t fman_get_ctrl_intr(struct fman_fpm_regs *fpm_rg, uint8_t event_reg_id) ++{ ++ return ioread32be(&fpm_rg->fmfp_cee[event_reg_id]); ++} ++ ++void fman_set_num_of_riscs_per_port(struct fman_fpm_regs *fpm_rg, ++ uint8_t port_id, ++ uint8_t num_fman_ctrls, ++ uint32_t or_fman_ctrl) ++{ ++ uint32_t tmp = 0; ++ ++ tmp = (uint32_t)(port_id << FPM_PORT_FM_CTL_PORTID_SHIFT); ++ /*TODO - maybe to put CTL# according to another criteria*/ ++ if (num_fman_ctrls == 2) ++ tmp = FPM_PRT_FM_CTL2 | FPM_PRT_FM_CTL1; ++ /* order restoration */ ++ tmp |= (or_fman_ctrl << FPM_PRC_ORA_FM_CTL_SEL_SHIFT) | or_fman_ctrl; ++ ++ iowrite32be(tmp, &fpm_rg->fmfp_prc); ++} ++ ++void fman_set_order_restoration_per_port(struct fman_fpm_regs *fpm_rg, ++ uint8_t port_id, ++ bool independent_mode, ++ bool is_rx_port) ++{ ++ uint32_t tmp = 0; ++ ++ tmp = (uint32_t)(port_id << FPM_PORT_FM_CTL_PORTID_SHIFT); ++ if (independent_mode) { ++ if (is_rx_port) ++ tmp |= (FPM_PRT_FM_CTL1 << ++ FPM_PRC_ORA_FM_CTL_SEL_SHIFT) | FPM_PRT_FM_CTL1; ++ else ++ tmp |= (FPM_PRT_FM_CTL2 << ++ FPM_PRC_ORA_FM_CTL_SEL_SHIFT) | FPM_PRT_FM_CTL2; ++ } else { ++ tmp |= (FPM_PRT_FM_CTL2|FPM_PRT_FM_CTL1); ++ ++ /* order restoration */ ++ if (port_id % 2) ++ tmp |= (FPM_PRT_FM_CTL1 << ++ FPM_PRC_ORA_FM_CTL_SEL_SHIFT); ++ else ++ tmp |= (FPM_PRT_FM_CTL2 << ++ FPM_PRC_ORA_FM_CTL_SEL_SHIFT); ++ } ++ iowrite32be(tmp, &fpm_rg->fmfp_prc); ++} ++ ++uint8_t fman_get_qmi_deq_th(struct fman_qmi_regs *qmi_rg) ++{ ++ return (uint8_t)ioread32be(&qmi_rg->fmqm_gc); ++} ++ ++uint8_t fman_get_qmi_enq_th(struct fman_qmi_regs *qmi_rg) ++{ ++ return (uint8_t)(ioread32be(&qmi_rg->fmqm_gc) >> 8); ++} ++ ++void fman_set_qmi_enq_th(struct fman_qmi_regs *qmi_rg, uint8_t val) ++{ ++ uint32_t tmp_reg; ++ ++ tmp_reg = ioread32be(&qmi_rg->fmqm_gc); ++ tmp_reg &= ~QMI_CFG_ENQ_MASK; ++ tmp_reg |= ((uint32_t)val << 8); ++ iowrite32be(tmp_reg, &qmi_rg->fmqm_gc); ++} ++ ++void fman_set_qmi_deq_th(struct fman_qmi_regs *qmi_rg, uint8_t val) ++{ ++ uint32_t tmp_reg; ++ ++ tmp_reg = ioread32be(&qmi_rg->fmqm_gc); ++ tmp_reg &= ~QMI_CFG_DEQ_MASK; ++ tmp_reg |= (uint32_t)val; ++ iowrite32be(tmp_reg, &qmi_rg->fmqm_gc); ++} ++ ++void fman_qmi_disable_dispatch_limit(struct fman_fpm_regs *fpm_rg) ++{ ++ iowrite32be(0, &fpm_rg->fmfp_mxd); ++} ++ ++void fman_set_liodn_per_port(struct fman_rg *fman_rg, uint8_t port_id, ++ uint16_t liodn_base, ++ uint16_t liodn_ofst) ++{ ++ uint32_t tmp; ++ ++ if ((port_id > 63) || (port_id < 1)) ++ return; ++ ++ /* set LIODN base for this port */ ++ tmp = ioread32be(&fman_rg->dma_rg->fmdmplr[port_id / 2]); ++ if (port_id % 2) { ++ tmp &= ~FM_LIODN_BASE_MASK; ++ tmp |= (uint32_t)liodn_base; ++ } else { ++ tmp &= ~(FM_LIODN_BASE_MASK << DMA_LIODN_SHIFT); ++ tmp |= (uint32_t)liodn_base << DMA_LIODN_SHIFT; ++ } ++ iowrite32be(tmp, &fman_rg->dma_rg->fmdmplr[port_id / 2]); ++ iowrite32be((uint32_t)liodn_ofst, ++ &fman_rg->bmi_rg->fmbm_spliodn[port_id - 1]); ++} ++ ++bool fman_is_port_stalled(struct fman_fpm_regs *fpm_rg, uint8_t port_id) ++{ ++ return (bool)!!(ioread32be(&fpm_rg->fmfp_ps[port_id]) & FPM_PS_STALLED); ++} ++ ++void fman_resume_stalled_port(struct fman_fpm_regs *fpm_rg, uint8_t port_id) ++{ ++ uint32_t tmp; ++ ++ tmp = (uint32_t)((port_id << FPM_PORT_FM_CTL_PORTID_SHIFT) | ++ FPM_PRC_REALSE_STALLED); ++ iowrite32be(tmp, &fpm_rg->fmfp_prc); ++} ++ ++int fman_reset_mac(struct fman_fpm_regs *fpm_rg, uint8_t mac_id, bool is_10g) ++{ ++ uint32_t msk, timeout = 100; ++ ++ /* Get the relevant bit mask */ ++ if (is_10g) { ++ switch (mac_id) { ++ case(0): ++ msk = FPM_RSTC_10G0_RESET; ++ break; ++ case(1): ++ msk = FPM_RSTC_10G1_RESET; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } else { ++ switch (mac_id) { ++ case(0): ++ msk = FPM_RSTC_1G0_RESET; ++ break; ++ case(1): ++ msk = FPM_RSTC_1G1_RESET; ++ break; ++ case(2): ++ msk = FPM_RSTC_1G2_RESET; ++ break; ++ case(3): ++ msk = FPM_RSTC_1G3_RESET; ++ break; ++ case(4): ++ msk = FPM_RSTC_1G4_RESET; ++ break; ++ case (5): ++ msk = FPM_RSTC_1G5_RESET; ++ break; ++ case (6): ++ msk = FPM_RSTC_1G6_RESET; ++ break; ++ case (7): ++ msk = FPM_RSTC_1G7_RESET; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ /* reset */ ++ iowrite32be(msk, &fpm_rg->fm_rstc); ++ while ((ioread32be(&fpm_rg->fm_rstc) & msk) && --timeout) ++ udelay(10); ++ ++ if (!timeout) ++ return -EBUSY; ++ return 0; ++} ++ ++uint16_t fman_get_size_of_fifo(struct fman_bmi_regs *bmi_rg, uint8_t port_id) ++{ ++ uint32_t tmp_reg; ++ ++ if ((port_id > 63) || (port_id < 1)) ++ return 0; ++ ++ tmp_reg = ioread32be(&bmi_rg->fmbm_pfs[port_id - 1]); ++ return (uint16_t)((tmp_reg & BMI_FIFO_SIZE_MASK) + 1); ++} ++ ++uint32_t fman_get_total_fifo_size(struct fman_bmi_regs *bmi_rg) ++{ ++ uint32_t reg, res; ++ ++ reg = ioread32be(&bmi_rg->fmbm_cfg1); ++ res = (reg >> BMI_CFG1_FIFO_SIZE_SHIFT) & 0x3ff; ++ return res * FMAN_BMI_FIFO_UNITS; ++} ++ ++uint16_t fman_get_size_of_extra_fifo(struct fman_bmi_regs *bmi_rg, ++ uint8_t port_id) ++{ ++ uint32_t tmp_reg; ++ ++ if ((port_id > 63) || (port_id < 1)) ++ return 0; ++ ++ tmp_reg = ioread32be(&bmi_rg->fmbm_pfs[port_id-1]); ++ return (uint16_t)((tmp_reg & BMI_EXTRA_FIFO_SIZE_MASK) >> ++ BMI_EXTRA_FIFO_SIZE_SHIFT); ++} ++ ++void fman_set_size_of_fifo(struct fman_bmi_regs *bmi_rg, ++ uint8_t port_id, ++ uint32_t sz_fifo, ++ uint32_t extra_sz_fifo) ++{ ++ uint32_t tmp; ++ ++ if ((port_id > 63) || (port_id < 1)) ++ return; ++ ++ /* calculate reg */ ++ tmp = (uint32_t)((sz_fifo / FMAN_BMI_FIFO_UNITS - 1) | ++ ((extra_sz_fifo / FMAN_BMI_FIFO_UNITS) << ++ BMI_EXTRA_FIFO_SIZE_SHIFT)); ++ iowrite32be(tmp, &bmi_rg->fmbm_pfs[port_id - 1]); ++} ++ ++uint8_t fman_get_num_of_tasks(struct fman_bmi_regs *bmi_rg, uint8_t port_id) ++{ ++ uint32_t tmp; ++ ++ if ((port_id > 63) || (port_id < 1)) ++ return 0; ++ ++ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]); ++ return (uint8_t)(((tmp & BMI_NUM_OF_TASKS_MASK) >> ++ BMI_NUM_OF_TASKS_SHIFT) + 1); ++} ++ ++uint8_t fman_get_num_extra_tasks(struct fman_bmi_regs *bmi_rg, uint8_t port_id) ++{ ++ uint32_t tmp; ++ ++ if ((port_id > 63) || (port_id < 1)) ++ return 0; ++ ++ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]); ++ return (uint8_t)((tmp & BMI_NUM_OF_EXTRA_TASKS_MASK) >> ++ BMI_EXTRA_NUM_OF_TASKS_SHIFT); ++} ++ ++void fman_set_num_of_tasks(struct fman_bmi_regs *bmi_rg, ++ uint8_t port_id, ++ uint8_t num_tasks, ++ uint8_t num_extra_tasks) ++{ ++ uint32_t tmp; ++ ++ if ((port_id > 63) || (port_id < 1)) ++ return; ++ ++ /* calculate reg */ ++ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]) & ++ ~(BMI_NUM_OF_TASKS_MASK | BMI_NUM_OF_EXTRA_TASKS_MASK); ++ tmp |= (uint32_t)(((num_tasks - 1) << BMI_NUM_OF_TASKS_SHIFT) | ++ (num_extra_tasks << BMI_EXTRA_NUM_OF_TASKS_SHIFT)); ++ iowrite32be(tmp, &bmi_rg->fmbm_pp[port_id - 1]); ++} ++ ++uint8_t fman_get_num_of_dmas(struct fman_bmi_regs *bmi_rg, uint8_t port_id) ++{ ++ uint32_t tmp; ++ ++ if ((port_id > 63) || (port_id < 1)) ++ return 0; ++ ++ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]); ++ return (uint8_t)(((tmp & BMI_NUM_OF_DMAS_MASK) >> ++ BMI_NUM_OF_DMAS_SHIFT) + 1); ++} ++ ++uint8_t fman_get_num_extra_dmas(struct fman_bmi_regs *bmi_rg, uint8_t port_id) ++{ ++ uint32_t tmp; ++ ++ if ((port_id > 63) || (port_id < 1)) ++ return 0; ++ ++ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]); ++ return (uint8_t)((tmp & BMI_NUM_OF_EXTRA_DMAS_MASK) >> ++ BMI_EXTRA_NUM_OF_DMAS_SHIFT); ++} ++ ++void fman_set_num_of_open_dmas(struct fman_bmi_regs *bmi_rg, ++ uint8_t port_id, ++ uint8_t num_open_dmas, ++ uint8_t num_extra_open_dmas, ++ uint8_t total_num_dmas) ++{ ++ uint32_t tmp = 0; ++ ++ if ((port_id > 63) || (port_id < 1)) ++ return; ++ ++ /* calculate reg */ ++ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]) & ++ ~(BMI_NUM_OF_DMAS_MASK | BMI_NUM_OF_EXTRA_DMAS_MASK); ++ tmp |= (uint32_t)(((num_open_dmas-1) << BMI_NUM_OF_DMAS_SHIFT) | ++ (num_extra_open_dmas << BMI_EXTRA_NUM_OF_DMAS_SHIFT)); ++ iowrite32be(tmp, &bmi_rg->fmbm_pp[port_id - 1]); ++ ++ /* update total num of DMA's with committed number of open DMAS, ++ * and max uncommitted pool. */ ++ if (total_num_dmas) ++ { ++ tmp = ioread32be(&bmi_rg->fmbm_cfg2) & ~BMI_CFG2_DMAS_MASK; ++ tmp |= (uint32_t)(total_num_dmas - 1) << BMI_CFG2_DMAS_SHIFT; ++ iowrite32be(tmp, &bmi_rg->fmbm_cfg2); ++ } ++} ++ ++void fman_set_vsp_window(struct fman_bmi_regs *bmi_rg, ++ uint8_t port_id, ++ uint8_t base_storage_profile, ++ uint8_t log2_num_of_profiles) ++{ ++ uint32_t tmp = 0; ++ if ((port_id > 63) || (port_id < 1)) ++ return; ++ ++ tmp = ioread32be(&bmi_rg->fmbm_spliodn[port_id-1]); ++ tmp |= (uint32_t)((uint32_t)base_storage_profile & 0x3f) << 16; ++ tmp |= (uint32_t)log2_num_of_profiles << 28; ++ iowrite32be(tmp, &bmi_rg->fmbm_spliodn[port_id-1]); ++} ++ ++void fman_set_congestion_group_pfc_priority(uint32_t *cpg_rg, ++ uint32_t congestion_group_id, ++ uint8_t priority_bit_map, ++ uint32_t reg_num) ++{ ++ uint32_t offset, tmp = 0; ++ ++ offset = (congestion_group_id%4)*8; ++ ++ tmp = ioread32be(&cpg_rg[reg_num]); ++ tmp &= ~(0xFF<catastrophic_err = DEFAULT_CATASTROPHIC_ERR; ++ cfg->dma_err = DEFAULT_DMA_ERR; ++ cfg->halt_on_external_activ = DEFAULT_HALT_ON_EXTERNAL_ACTIVATION; ++ cfg->halt_on_unrecov_ecc_err = DEFAULT_HALT_ON_UNRECOVERABLE_ECC_ERROR; ++ cfg->en_iram_test_mode = FALSE; ++ cfg->en_muram_test_mode = FALSE; ++ cfg->external_ecc_rams_enable = DEFAULT_EXTERNAL_ECC_RAMS_ENABLE; ++ ++ if (!is_master) ++ return; ++ ++ cfg->dma_aid_override = DEFAULT_AID_OVERRIDE; ++ cfg->dma_aid_mode = DEFAULT_AID_MODE; ++ cfg->dma_comm_qtsh_clr_emer = DEFAULT_DMA_COMM_Q_LOW; ++ cfg->dma_comm_qtsh_asrt_emer = DEFAULT_DMA_COMM_Q_HIGH; ++ cfg->dma_cache_override = DEFAULT_CACHE_OVERRIDE; ++ cfg->dma_cam_num_of_entries = DEFAULT_DMA_CAM_NUM_OF_ENTRIES; ++ cfg->dma_dbg_cnt_mode = DEFAULT_DMA_DBG_CNT_MODE; ++ cfg->dma_en_emergency = DEFAULT_DMA_EN_EMERGENCY; ++ cfg->dma_sos_emergency = DEFAULT_DMA_SOS_EMERGENCY; ++ cfg->dma_watchdog = DEFAULT_DMA_WATCHDOG; ++ cfg->dma_en_emergency_smoother = DEFAULT_DMA_EN_EMERGENCY_SMOOTHER; ++ cfg->dma_emergency_switch_counter = DEFAULT_DMA_EMERGENCY_SWITCH_COUNTER; ++ cfg->disp_limit_tsh = DEFAULT_DISP_LIMIT; ++ cfg->prs_disp_tsh = DEFAULT_PRS_DISP_TH; ++ cfg->plcr_disp_tsh = DEFAULT_PLCR_DISP_TH; ++ cfg->kg_disp_tsh = DEFAULT_KG_DISP_TH; ++ cfg->bmi_disp_tsh = DEFAULT_BMI_DISP_TH; ++ cfg->qmi_enq_disp_tsh = DEFAULT_QMI_ENQ_DISP_TH; ++ cfg->qmi_deq_disp_tsh = DEFAULT_QMI_DEQ_DISP_TH; ++ cfg->fm_ctl1_disp_tsh = DEFAULT_FM_CTL1_DISP_TH; ++ cfg->fm_ctl2_disp_tsh = DEFAULT_FM_CTL2_DISP_TH; ++ ++ cfg->pedantic_dma = FALSE; ++ cfg->tnum_aging_period = DEFAULT_TNUM_AGING_PERIOD; ++ cfg->dma_stop_on_bus_error = FALSE; ++ cfg->qmi_deq_option_support = FALSE; ++} ++ ++void fman_regconfig(struct fman_rg *fman_rg, struct fman_cfg *cfg) ++{ ++ uint32_t tmp_reg; ++ ++ /* read the values from the registers as they are initialized by the HW with ++ * the required values. ++ */ ++ tmp_reg = ioread32be(&fman_rg->bmi_rg->fmbm_cfg1); ++ cfg->total_fifo_size = ++ (((tmp_reg & BMI_TOTAL_FIFO_SIZE_MASK) >> BMI_CFG1_FIFO_SIZE_SHIFT) + 1) * FMAN_BMI_FIFO_UNITS; ++ ++ tmp_reg = ioread32be(&fman_rg->bmi_rg->fmbm_cfg2); ++ cfg->total_num_of_tasks = ++ (uint8_t)(((tmp_reg & BMI_TOTAL_NUM_OF_TASKS_MASK) >> BMI_CFG2_TASKS_SHIFT) + 1); ++ ++ tmp_reg = ioread32be(&fman_rg->dma_rg->fmdmtr); ++ cfg->dma_comm_qtsh_asrt_emer = (uint8_t)(tmp_reg >> DMA_THRESH_COMMQ_SHIFT); ++ ++ tmp_reg = ioread32be(&fman_rg->dma_rg->fmdmhy); ++ cfg->dma_comm_qtsh_clr_emer = (uint8_t)(tmp_reg >> DMA_THRESH_COMMQ_SHIFT); ++ ++ tmp_reg = ioread32be(&fman_rg->dma_rg->fmdmmr); ++ cfg->dma_cache_override = (enum fman_dma_cache_override)((tmp_reg & DMA_MODE_CACHE_OR_MASK) >> DMA_MODE_CACHE_OR_SHIFT); ++ cfg->dma_cam_num_of_entries = (uint8_t)((((tmp_reg & DMA_MODE_CEN_MASK) >> DMA_MODE_CEN_SHIFT) +1)*DMA_CAM_UNITS); ++ cfg->dma_aid_override = (bool)((tmp_reg & DMA_MODE_AID_OR)? TRUE:FALSE); ++ cfg->dma_dbg_cnt_mode = (enum fman_dma_dbg_cnt_mode)((tmp_reg & DMA_MODE_DBG_MASK) >> DMA_MODE_DBG_SHIFT); ++ cfg->dma_en_emergency = (bool)((tmp_reg & DMA_MODE_EB)? TRUE : FALSE); ++ ++ tmp_reg = ioread32be(&fman_rg->fpm_rg->fmfp_mxd); ++ cfg->disp_limit_tsh = (uint8_t)((tmp_reg & FPM_DISP_LIMIT_MASK) >> FPM_DISP_LIMIT_SHIFT); ++ ++ tmp_reg = ioread32be(&fman_rg->fpm_rg->fmfp_dist1); ++ cfg->prs_disp_tsh = (uint8_t)((tmp_reg & FPM_THR1_PRS_MASK ) >> FPM_THR1_PRS_SHIFT); ++ cfg->plcr_disp_tsh = (uint8_t)((tmp_reg & FPM_THR1_KG_MASK ) >> FPM_THR1_KG_SHIFT); ++ cfg->kg_disp_tsh = (uint8_t)((tmp_reg & FPM_THR1_PLCR_MASK ) >> FPM_THR1_PLCR_SHIFT); ++ cfg->bmi_disp_tsh = (uint8_t)((tmp_reg & FPM_THR1_BMI_MASK ) >> FPM_THR1_BMI_SHIFT); ++ ++ tmp_reg = ioread32be(&fman_rg->fpm_rg->fmfp_dist2); ++ cfg->qmi_enq_disp_tsh = (uint8_t)((tmp_reg & FPM_THR2_QMI_ENQ_MASK ) >> FPM_THR2_QMI_ENQ_SHIFT); ++ cfg->qmi_deq_disp_tsh = (uint8_t)((tmp_reg & FPM_THR2_QMI_DEQ_MASK ) >> FPM_THR2_QMI_DEQ_SHIFT); ++ cfg->fm_ctl1_disp_tsh = (uint8_t)((tmp_reg & FPM_THR2_FM_CTL1_MASK ) >> FPM_THR2_FM_CTL1_SHIFT); ++ cfg->fm_ctl2_disp_tsh = (uint8_t)((tmp_reg & FPM_THR2_FM_CTL2_MASK ) >> FPM_THR2_FM_CTL2_SHIFT); ++ ++ tmp_reg = ioread32be(&fman_rg->dma_rg->fmdmsetr); ++ cfg->dma_sos_emergency = tmp_reg; ++ ++ tmp_reg = ioread32be(&fman_rg->dma_rg->fmdmwcr); ++ cfg->dma_watchdog = tmp_reg/cfg->clk_freq; ++ ++ tmp_reg = ioread32be(&fman_rg->dma_rg->fmdmemsr); ++ cfg->dma_en_emergency_smoother = (bool)((tmp_reg & DMA_EMSR_EMSTR_MASK)? TRUE : FALSE); ++ cfg->dma_emergency_switch_counter = (tmp_reg & DMA_EMSR_EMSTR_MASK); ++} ++ ++void fman_reset(struct fman_fpm_regs *fpm_rg) ++{ ++ iowrite32be(FPM_RSTC_FM_RESET, &fpm_rg->fm_rstc); ++} ++ ++/**************************************************************************//** ++ @Function FM_Init ++ ++ @Description Initializes the FM module ++ ++ @Param[in] h_Fm - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++int fman_dma_init(struct fman_dma_regs *dma_rg, struct fman_cfg *cfg) ++{ ++ uint32_t tmp_reg; ++ ++ /**********************/ ++ /* Init DMA Registers */ ++ /**********************/ ++ /* clear status reg events */ ++ /* oren - check!!! */ ++ tmp_reg = (DMA_STATUS_BUS_ERR | DMA_STATUS_READ_ECC | ++ DMA_STATUS_SYSTEM_WRITE_ECC | DMA_STATUS_FM_WRITE_ECC); ++ iowrite32be(ioread32be(&dma_rg->fmdmsr) | tmp_reg, ++ &dma_rg->fmdmsr); ++ ++ /* configure mode register */ ++ tmp_reg = 0; ++ tmp_reg |= cfg->dma_cache_override << DMA_MODE_CACHE_OR_SHIFT; ++ if (cfg->dma_aid_override) ++ tmp_reg |= DMA_MODE_AID_OR; ++ if (cfg->exceptions & FMAN_EX_DMA_BUS_ERROR) ++ tmp_reg |= DMA_MODE_BER; ++ if ((cfg->exceptions & FMAN_EX_DMA_SYSTEM_WRITE_ECC) | ++ (cfg->exceptions & FMAN_EX_DMA_READ_ECC) | ++ (cfg->exceptions & FMAN_EX_DMA_FM_WRITE_ECC)) ++ tmp_reg |= DMA_MODE_ECC; ++ if (cfg->dma_stop_on_bus_error) ++ tmp_reg |= DMA_MODE_SBER; ++ if(cfg->dma_axi_dbg_num_of_beats) ++ tmp_reg |= (uint32_t)(DMA_MODE_AXI_DBG_MASK & ++ ((cfg->dma_axi_dbg_num_of_beats - 1) << DMA_MODE_AXI_DBG_SHIFT)); ++ ++ if (cfg->dma_en_emergency) { ++ tmp_reg |= cfg->dma_emergency_bus_select; ++ tmp_reg |= cfg->dma_emergency_level << DMA_MODE_EMER_LVL_SHIFT; ++ if (cfg->dma_en_emergency_smoother) ++ iowrite32be(cfg->dma_emergency_switch_counter, ++ &dma_rg->fmdmemsr); ++ } ++ tmp_reg |= ((cfg->dma_cam_num_of_entries / DMA_CAM_UNITS) - 1) << ++ DMA_MODE_CEN_SHIFT; ++ tmp_reg |= DMA_MODE_SECURE_PROT; ++ tmp_reg |= cfg->dma_dbg_cnt_mode << DMA_MODE_DBG_SHIFT; ++ tmp_reg |= cfg->dma_aid_mode << DMA_MODE_AID_MODE_SHIFT; ++ ++ if (cfg->pedantic_dma) ++ tmp_reg |= DMA_MODE_EMER_READ; ++ ++ iowrite32be(tmp_reg, &dma_rg->fmdmmr); ++ ++ /* configure thresholds register */ ++ tmp_reg = ((uint32_t)cfg->dma_comm_qtsh_asrt_emer << ++ DMA_THRESH_COMMQ_SHIFT) | ++ ((uint32_t)cfg->dma_read_buf_tsh_asrt_emer << ++ DMA_THRESH_READ_INT_BUF_SHIFT) | ++ ((uint32_t)cfg->dma_write_buf_tsh_asrt_emer); ++ ++ iowrite32be(tmp_reg, &dma_rg->fmdmtr); ++ ++ /* configure hysteresis register */ ++ tmp_reg = ((uint32_t)cfg->dma_comm_qtsh_clr_emer << ++ DMA_THRESH_COMMQ_SHIFT) | ++ ((uint32_t)cfg->dma_read_buf_tsh_clr_emer << ++ DMA_THRESH_READ_INT_BUF_SHIFT) | ++ ((uint32_t)cfg->dma_write_buf_tsh_clr_emer); ++ ++ iowrite32be(tmp_reg, &dma_rg->fmdmhy); ++ ++ /* configure emergency threshold */ ++ iowrite32be(cfg->dma_sos_emergency, &dma_rg->fmdmsetr); ++ ++ /* configure Watchdog */ ++ iowrite32be((cfg->dma_watchdog * cfg->clk_freq), ++ &dma_rg->fmdmwcr); ++ ++ iowrite32be(cfg->cam_base_addr, &dma_rg->fmdmebcr); ++ ++ return 0; ++} ++ ++int fman_fpm_init(struct fman_fpm_regs *fpm_rg, struct fman_cfg *cfg) ++{ ++ uint32_t tmp_reg; ++ int i; ++ ++ /**********************/ ++ /* Init FPM Registers */ ++ /**********************/ ++ tmp_reg = (uint32_t)(cfg->disp_limit_tsh << FPM_DISP_LIMIT_SHIFT); ++ iowrite32be(tmp_reg, &fpm_rg->fmfp_mxd); ++ ++ tmp_reg = (((uint32_t)cfg->prs_disp_tsh << FPM_THR1_PRS_SHIFT) | ++ ((uint32_t)cfg->kg_disp_tsh << FPM_THR1_KG_SHIFT) | ++ ((uint32_t)cfg->plcr_disp_tsh << FPM_THR1_PLCR_SHIFT) | ++ ((uint32_t)cfg->bmi_disp_tsh << FPM_THR1_BMI_SHIFT)); ++ iowrite32be(tmp_reg, &fpm_rg->fmfp_dist1); ++ ++ tmp_reg = (((uint32_t)cfg->qmi_enq_disp_tsh << FPM_THR2_QMI_ENQ_SHIFT) | ++ ((uint32_t)cfg->qmi_deq_disp_tsh << FPM_THR2_QMI_DEQ_SHIFT) | ++ ((uint32_t)cfg->fm_ctl1_disp_tsh << FPM_THR2_FM_CTL1_SHIFT) | ++ ((uint32_t)cfg->fm_ctl2_disp_tsh << FPM_THR2_FM_CTL2_SHIFT)); ++ iowrite32be(tmp_reg, &fpm_rg->fmfp_dist2); ++ ++ /* define exceptions and error behavior */ ++ tmp_reg = 0; ++ /* Clear events */ ++ tmp_reg |= (FPM_EV_MASK_STALL | FPM_EV_MASK_DOUBLE_ECC | ++ FPM_EV_MASK_SINGLE_ECC); ++ /* enable interrupts */ ++ if (cfg->exceptions & FMAN_EX_FPM_STALL_ON_TASKS) ++ tmp_reg |= FPM_EV_MASK_STALL_EN; ++ if (cfg->exceptions & FMAN_EX_FPM_SINGLE_ECC) ++ tmp_reg |= FPM_EV_MASK_SINGLE_ECC_EN; ++ if (cfg->exceptions & FMAN_EX_FPM_DOUBLE_ECC) ++ tmp_reg |= FPM_EV_MASK_DOUBLE_ECC_EN; ++ tmp_reg |= (cfg->catastrophic_err << FPM_EV_MASK_CAT_ERR_SHIFT); ++ tmp_reg |= (cfg->dma_err << FPM_EV_MASK_DMA_ERR_SHIFT); ++ if (!cfg->halt_on_external_activ) ++ tmp_reg |= FPM_EV_MASK_EXTERNAL_HALT; ++ if (!cfg->halt_on_unrecov_ecc_err) ++ tmp_reg |= FPM_EV_MASK_ECC_ERR_HALT; ++ iowrite32be(tmp_reg, &fpm_rg->fmfp_ee); ++ ++ /* clear all fmCtls event registers */ ++ for (i = 0; i < cfg->num_of_fman_ctrl_evnt_regs; i++) ++ iowrite32be(0xFFFFFFFF, &fpm_rg->fmfp_cev[i]); ++ ++ /* RAM ECC - enable and clear events*/ ++ /* first we need to clear all parser memory, ++ * as it is uninitialized and may cause ECC errors */ ++ /* event bits */ ++ tmp_reg = (FPM_RAM_MURAM_ECC | FPM_RAM_IRAM_ECC); ++ /* Rams enable not effected by RCR bit, but by a COP configuration */ ++ if (cfg->external_ecc_rams_enable) ++ tmp_reg |= FPM_RAM_RAMS_ECC_EN_SRC_SEL; ++ ++ /* enable test mode */ ++ if (cfg->en_muram_test_mode) ++ tmp_reg |= FPM_RAM_MURAM_TEST_ECC; ++ if (cfg->en_iram_test_mode) ++ tmp_reg |= FPM_RAM_IRAM_TEST_ECC; ++ iowrite32be(tmp_reg, &fpm_rg->fm_rcr); ++ ++ tmp_reg = 0; ++ if (cfg->exceptions & FMAN_EX_IRAM_ECC) { ++ tmp_reg |= FPM_IRAM_ECC_ERR_EX_EN; ++ fman_enable_rams_ecc(fpm_rg); ++ } ++ if (cfg->exceptions & FMAN_EX_NURAM_ECC) { ++ tmp_reg |= FPM_MURAM_ECC_ERR_EX_EN; ++ fman_enable_rams_ecc(fpm_rg); ++ } ++ iowrite32be(tmp_reg, &fpm_rg->fm_rie); ++ ++ return 0; ++} ++ ++int fman_bmi_init(struct fman_bmi_regs *bmi_rg, struct fman_cfg *cfg) ++{ ++ uint32_t tmp_reg; ++ ++ /**********************/ ++ /* Init BMI Registers */ ++ /**********************/ ++ ++ /* define common resources */ ++ tmp_reg = cfg->fifo_base_addr; ++ tmp_reg = tmp_reg / BMI_FIFO_ALIGN; ++ ++ tmp_reg |= ((cfg->total_fifo_size / FMAN_BMI_FIFO_UNITS - 1) << ++ BMI_CFG1_FIFO_SIZE_SHIFT); ++ iowrite32be(tmp_reg, &bmi_rg->fmbm_cfg1); ++ ++ tmp_reg = ((uint32_t)(cfg->total_num_of_tasks - 1) << ++ BMI_CFG2_TASKS_SHIFT); ++ /* num of DMA's will be dynamically updated when each port is set */ ++ iowrite32be(tmp_reg, &bmi_rg->fmbm_cfg2); ++ ++ /* define unmaskable exceptions, enable and clear events */ ++ tmp_reg = 0; ++ iowrite32be(BMI_ERR_INTR_EN_LIST_RAM_ECC | ++ BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC | ++ BMI_ERR_INTR_EN_STATISTICS_RAM_ECC | ++ BMI_ERR_INTR_EN_DISPATCH_RAM_ECC, ++ &bmi_rg->fmbm_ievr); ++ ++ if (cfg->exceptions & FMAN_EX_BMI_LIST_RAM_ECC) ++ tmp_reg |= BMI_ERR_INTR_EN_LIST_RAM_ECC; ++ if (cfg->exceptions & FMAN_EX_BMI_PIPELINE_ECC) ++ tmp_reg |= BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC; ++ if (cfg->exceptions & FMAN_EX_BMI_STATISTICS_RAM_ECC) ++ tmp_reg |= BMI_ERR_INTR_EN_STATISTICS_RAM_ECC; ++ if (cfg->exceptions & FMAN_EX_BMI_DISPATCH_RAM_ECC) ++ tmp_reg |= BMI_ERR_INTR_EN_DISPATCH_RAM_ECC; ++ iowrite32be(tmp_reg, &bmi_rg->fmbm_ier); ++ ++ return 0; ++} ++ ++int fman_qmi_init(struct fman_qmi_regs *qmi_rg, struct fman_cfg *cfg) ++{ ++ uint32_t tmp_reg; ++ uint16_t period_in_fm_clocks; ++ uint8_t remainder; ++ /**********************/ ++ /* Init QMI Registers */ ++ /**********************/ ++ /* Clear error interrupt events */ ++ ++ iowrite32be(QMI_ERR_INTR_EN_DOUBLE_ECC | QMI_ERR_INTR_EN_DEQ_FROM_DEF, ++ &qmi_rg->fmqm_eie); ++ tmp_reg = 0; ++ if (cfg->exceptions & FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID) ++ tmp_reg |= QMI_ERR_INTR_EN_DEQ_FROM_DEF; ++ if (cfg->exceptions & FMAN_EX_QMI_DOUBLE_ECC) ++ tmp_reg |= QMI_ERR_INTR_EN_DOUBLE_ECC; ++ /* enable events */ ++ iowrite32be(tmp_reg, &qmi_rg->fmqm_eien); ++ ++ if (cfg->tnum_aging_period) { ++ /* tnum_aging_period is in units of usec, p_FmClockFreq in Mhz */ ++ period_in_fm_clocks = (uint16_t) ++ (cfg->tnum_aging_period * cfg->clk_freq); ++ /* period_in_fm_clocks must be a 64 multiply */ ++ remainder = (uint8_t)(period_in_fm_clocks % 64); ++ if (remainder) ++ tmp_reg = (uint32_t)((period_in_fm_clocks / 64) + 1); ++ else{ ++ tmp_reg = (uint32_t)(period_in_fm_clocks / 64); ++ if (!tmp_reg) ++ tmp_reg = 1; ++ } ++ tmp_reg <<= QMI_TAPC_TAP; ++ iowrite32be(tmp_reg, &qmi_rg->fmqm_tapc); ++ } ++ tmp_reg = 0; ++ /* Clear interrupt events */ ++ iowrite32be(QMI_INTR_EN_SINGLE_ECC, &qmi_rg->fmqm_ie); ++ if (cfg->exceptions & FMAN_EX_QMI_SINGLE_ECC) ++ tmp_reg |= QMI_INTR_EN_SINGLE_ECC; ++ /* enable events */ ++ iowrite32be(tmp_reg, &qmi_rg->fmqm_ien); ++ ++ return 0; ++} ++ ++int fman_enable(struct fman_rg *fman_rg, struct fman_cfg *cfg) ++{ ++ uint32_t cfg_reg = 0; ++ ++ /**********************/ ++ /* Enable all modules */ ++ /**********************/ ++ /* clear & enable global counters - calculate reg and save for later, ++ because it's the same reg for QMI enable */ ++ cfg_reg = QMI_CFG_EN_COUNTERS; ++ if (cfg->qmi_deq_option_support) ++ cfg_reg |= (uint32_t)(((cfg->qmi_def_tnums_thresh) << 8) | ++ (uint32_t)cfg->qmi_def_tnums_thresh); ++ ++ iowrite32be(BMI_INIT_START, &fman_rg->bmi_rg->fmbm_init); ++ iowrite32be(cfg_reg | QMI_CFG_ENQ_EN | QMI_CFG_DEQ_EN, ++ &fman_rg->qmi_rg->fmqm_gc); ++ ++ return 0; ++} ++ ++void fman_free_resources(struct fman_rg *fman_rg) ++{ ++ /* disable BMI and QMI */ ++ iowrite32be(0, &fman_rg->bmi_rg->fmbm_init); ++ iowrite32be(0, &fman_rg->qmi_rg->fmqm_gc); ++ ++ /* release BMI resources */ ++ iowrite32be(0, &fman_rg->bmi_rg->fmbm_cfg2); ++ iowrite32be(0, &fman_rg->bmi_rg->fmbm_cfg1); ++ ++ /* disable ECC */ ++ iowrite32be(0, &fman_rg->fpm_rg->fm_rcr); ++} ++ ++/****************************************************/ ++/* API Run-time Control uint functions */ ++/****************************************************/ ++uint32_t fman_get_normal_pending(struct fman_fpm_regs *fpm_rg) ++{ ++ return ioread32be(&fpm_rg->fm_npi); ++} ++ ++uint32_t fman_get_controller_event(struct fman_fpm_regs *fpm_rg, uint8_t reg_id) ++{ ++ uint32_t event; ++ ++ event = ioread32be(&fpm_rg->fmfp_fcev[reg_id]) & ++ ioread32be(&fpm_rg->fmfp_cee[reg_id]); ++ iowrite32be(event, &fpm_rg->fmfp_cev[reg_id]); ++ ++ return event; ++} ++ ++uint32_t fman_get_error_pending(struct fman_fpm_regs *fpm_rg) ++{ ++ return ioread32be(&fpm_rg->fm_epi); ++} ++ ++void fman_set_ports_bandwidth(struct fman_bmi_regs *bmi_rg, uint8_t *weights) ++{ ++ int i; ++ uint8_t shift; ++ uint32_t tmp = 0; ++ ++ for (i = 0; i < 64; i++) { ++ if (weights[i] > 1) { /* no need to write 1 since it is 0 */ ++ /* Add this port to tmp_reg */ ++ /* (each 8 ports result in one register)*/ ++ shift = (uint8_t)(32 - 4 * ((i % 8) + 1)); ++ tmp |= ((weights[i] - 1) << shift); ++ } ++ if (i % 8 == 7) { /* last in this set */ ++ iowrite32be(tmp, &bmi_rg->fmbm_arb[i / 8]); ++ tmp = 0; ++ } ++ } ++} ++ ++void fman_enable_rams_ecc(struct fman_fpm_regs *fpm_rg) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(&fpm_rg->fm_rcr); ++ if (tmp & FPM_RAM_RAMS_ECC_EN_SRC_SEL) ++ iowrite32be(tmp | FPM_RAM_IRAM_ECC_EN, ++ &fpm_rg->fm_rcr); ++ else ++ iowrite32be(tmp | FPM_RAM_RAMS_ECC_EN | ++ FPM_RAM_IRAM_ECC_EN, ++ &fpm_rg->fm_rcr); ++} ++ ++void fman_disable_rams_ecc(struct fman_fpm_regs *fpm_rg) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(&fpm_rg->fm_rcr); ++ if (tmp & FPM_RAM_RAMS_ECC_EN_SRC_SEL) ++ iowrite32be(tmp & ~FPM_RAM_IRAM_ECC_EN, ++ &fpm_rg->fm_rcr); ++ else ++ iowrite32be(tmp & ~(FPM_RAM_RAMS_ECC_EN | FPM_RAM_IRAM_ECC_EN), ++ &fpm_rg->fm_rcr); ++} ++ ++int fman_set_exception(struct fman_rg *fman_rg, ++ enum fman_exceptions exception, ++ bool enable) ++{ ++ uint32_t tmp; ++ ++ switch (exception) { ++ case(E_FMAN_EX_DMA_BUS_ERROR): ++ tmp = ioread32be(&fman_rg->dma_rg->fmdmmr); ++ if (enable) ++ tmp |= DMA_MODE_BER; ++ else ++ tmp &= ~DMA_MODE_BER; ++ /* disable bus error */ ++ iowrite32be(tmp, &fman_rg->dma_rg->fmdmmr); ++ break; ++ case(E_FMAN_EX_DMA_READ_ECC): ++ case(E_FMAN_EX_DMA_SYSTEM_WRITE_ECC): ++ case(E_FMAN_EX_DMA_FM_WRITE_ECC): ++ tmp = ioread32be(&fman_rg->dma_rg->fmdmmr); ++ if (enable) ++ tmp |= DMA_MODE_ECC; ++ else ++ tmp &= ~DMA_MODE_ECC; ++ iowrite32be(tmp, &fman_rg->dma_rg->fmdmmr); ++ break; ++ case(E_FMAN_EX_FPM_STALL_ON_TASKS): ++ tmp = ioread32be(&fman_rg->fpm_rg->fmfp_ee); ++ if (enable) ++ tmp |= FPM_EV_MASK_STALL_EN; ++ else ++ tmp &= ~FPM_EV_MASK_STALL_EN; ++ iowrite32be(tmp, &fman_rg->fpm_rg->fmfp_ee); ++ break; ++ case(E_FMAN_EX_FPM_SINGLE_ECC): ++ tmp = ioread32be(&fman_rg->fpm_rg->fmfp_ee); ++ if (enable) ++ tmp |= FPM_EV_MASK_SINGLE_ECC_EN; ++ else ++ tmp &= ~FPM_EV_MASK_SINGLE_ECC_EN; ++ iowrite32be(tmp, &fman_rg->fpm_rg->fmfp_ee); ++ break; ++ case(E_FMAN_EX_FPM_DOUBLE_ECC): ++ tmp = ioread32be(&fman_rg->fpm_rg->fmfp_ee); ++ if (enable) ++ tmp |= FPM_EV_MASK_DOUBLE_ECC_EN; ++ else ++ tmp &= ~FPM_EV_MASK_DOUBLE_ECC_EN; ++ iowrite32be(tmp, &fman_rg->fpm_rg->fmfp_ee); ++ break; ++ case(E_FMAN_EX_QMI_SINGLE_ECC): ++ tmp = ioread32be(&fman_rg->qmi_rg->fmqm_ien); ++ if (enable) ++ tmp |= QMI_INTR_EN_SINGLE_ECC; ++ else ++ tmp &= ~QMI_INTR_EN_SINGLE_ECC; ++ iowrite32be(tmp, &fman_rg->qmi_rg->fmqm_ien); ++ break; ++ case(E_FMAN_EX_QMI_DOUBLE_ECC): ++ tmp = ioread32be(&fman_rg->qmi_rg->fmqm_eien); ++ if (enable) ++ tmp |= QMI_ERR_INTR_EN_DOUBLE_ECC; ++ else ++ tmp &= ~QMI_ERR_INTR_EN_DOUBLE_ECC; ++ iowrite32be(tmp, &fman_rg->qmi_rg->fmqm_eien); ++ break; ++ case(E_FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID): ++ tmp = ioread32be(&fman_rg->qmi_rg->fmqm_eien); ++ if (enable) ++ tmp |= QMI_ERR_INTR_EN_DEQ_FROM_DEF; ++ else ++ tmp &= ~QMI_ERR_INTR_EN_DEQ_FROM_DEF; ++ iowrite32be(tmp, &fman_rg->qmi_rg->fmqm_eien); ++ break; ++ case(E_FMAN_EX_BMI_LIST_RAM_ECC): ++ tmp = ioread32be(&fman_rg->bmi_rg->fmbm_ier); ++ if (enable) ++ tmp |= BMI_ERR_INTR_EN_LIST_RAM_ECC; ++ else ++ tmp &= ~BMI_ERR_INTR_EN_LIST_RAM_ECC; ++ iowrite32be(tmp, &fman_rg->bmi_rg->fmbm_ier); ++ break; ++ case(E_FMAN_EX_BMI_STORAGE_PROFILE_ECC): ++ tmp = ioread32be(&fman_rg->bmi_rg->fmbm_ier); ++ if (enable) ++ tmp |= BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC; ++ else ++ tmp &= ~BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC; ++ iowrite32be(tmp, &fman_rg->bmi_rg->fmbm_ier); ++ break; ++ case(E_FMAN_EX_BMI_STATISTICS_RAM_ECC): ++ tmp = ioread32be(&fman_rg->bmi_rg->fmbm_ier); ++ if (enable) ++ tmp |= BMI_ERR_INTR_EN_STATISTICS_RAM_ECC; ++ else ++ tmp &= ~BMI_ERR_INTR_EN_STATISTICS_RAM_ECC; ++ iowrite32be(tmp, &fman_rg->bmi_rg->fmbm_ier); ++ break; ++ case(E_FMAN_EX_BMI_DISPATCH_RAM_ECC): ++ tmp = ioread32be(&fman_rg->bmi_rg->fmbm_ier); ++ if (enable) ++ tmp |= BMI_ERR_INTR_EN_DISPATCH_RAM_ECC; ++ else ++ tmp &= ~BMI_ERR_INTR_EN_DISPATCH_RAM_ECC; ++ iowrite32be(tmp, &fman_rg->bmi_rg->fmbm_ier); ++ break; ++ case(E_FMAN_EX_IRAM_ECC): ++ tmp = ioread32be(&fman_rg->fpm_rg->fm_rie); ++ if (enable) { ++ /* enable ECC if not enabled */ ++ fman_enable_rams_ecc(fman_rg->fpm_rg); ++ /* enable ECC interrupts */ ++ tmp |= FPM_IRAM_ECC_ERR_EX_EN; ++ } else { ++ /* ECC mechanism may be disabled, ++ * depending on driver status */ ++ fman_disable_rams_ecc(fman_rg->fpm_rg); ++ tmp &= ~FPM_IRAM_ECC_ERR_EX_EN; ++ } ++ iowrite32be(tmp, &fman_rg->fpm_rg->fm_rie); ++ break; ++ case(E_FMAN_EX_MURAM_ECC): ++ tmp = ioread32be(&fman_rg->fpm_rg->fm_rie); ++ if (enable) { ++ /* enable ECC if not enabled */ ++ fman_enable_rams_ecc(fman_rg->fpm_rg); ++ /* enable ECC interrupts */ ++ tmp |= FPM_MURAM_ECC_ERR_EX_EN; ++ } else { ++ /* ECC mechanism may be disabled, ++ * depending on driver status */ ++ fman_disable_rams_ecc(fman_rg->fpm_rg); ++ tmp &= ~FPM_MURAM_ECC_ERR_EX_EN; ++ } ++ iowrite32be(tmp, &fman_rg->fpm_rg->fm_rie); ++ break; ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++void fman_get_revision(struct fman_fpm_regs *fpm_rg, ++ uint8_t *major, ++ uint8_t *minor) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(&fpm_rg->fm_ip_rev_1); ++ *major = (uint8_t)((tmp & FPM_REV1_MAJOR_MASK) >> FPM_REV1_MAJOR_SHIFT); ++ *minor = (uint8_t)((tmp & FPM_REV1_MINOR_MASK) >> FPM_REV1_MINOR_SHIFT); ++ ++} ++ ++uint32_t fman_get_counter(struct fman_rg *fman_rg, ++ enum fman_counters reg_name) ++{ ++ uint32_t ret_val; ++ ++ switch (reg_name) { ++ case(E_FMAN_COUNTERS_ENQ_TOTAL_FRAME): ++ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_etfc); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_TOTAL_FRAME): ++ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dtfc); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_0): ++ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dc0); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_1): ++ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dc1); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_2): ++ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dc2); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_3): ++ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dc3); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_FROM_DEFAULT): ++ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dfdc); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_FROM_CONTEXT): ++ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dfcc); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_FROM_FD): ++ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dffc); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_CONFIRM): ++ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dcc); ++ break; ++ default: ++ ret_val = 0; ++ } ++ return ret_val; ++} ++ ++int fman_modify_counter(struct fman_rg *fman_rg, ++ enum fman_counters reg_name, ++ uint32_t val) ++{ ++ /* When applicable (when there is an 'enable counters' bit, ++ * check that counters are enabled */ ++ switch (reg_name) { ++ case(E_FMAN_COUNTERS_ENQ_TOTAL_FRAME): ++ case(E_FMAN_COUNTERS_DEQ_TOTAL_FRAME): ++ case(E_FMAN_COUNTERS_DEQ_0): ++ case(E_FMAN_COUNTERS_DEQ_1): ++ case(E_FMAN_COUNTERS_DEQ_2): ++ case(E_FMAN_COUNTERS_DEQ_3): ++ case(E_FMAN_COUNTERS_DEQ_FROM_DEFAULT): ++ case(E_FMAN_COUNTERS_DEQ_FROM_CONTEXT): ++ case(E_FMAN_COUNTERS_DEQ_FROM_FD): ++ case(E_FMAN_COUNTERS_DEQ_CONFIRM): ++ if (!(ioread32be(&fman_rg->qmi_rg->fmqm_gc) & ++ QMI_CFG_EN_COUNTERS)) ++ return -EINVAL; ++ break; ++ default: ++ break; ++ } ++ /* Set counter */ ++ switch (reg_name) { ++ case(E_FMAN_COUNTERS_ENQ_TOTAL_FRAME): ++ iowrite32be(val, &fman_rg->qmi_rg->fmqm_etfc); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_TOTAL_FRAME): ++ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dtfc); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_0): ++ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dc0); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_1): ++ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dc1); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_2): ++ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dc2); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_3): ++ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dc3); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_FROM_DEFAULT): ++ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dfdc); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_FROM_CONTEXT): ++ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dfcc); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_FROM_FD): ++ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dffc); ++ break; ++ case(E_FMAN_COUNTERS_DEQ_CONFIRM): ++ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dcc); ++ break; ++ case(E_FMAN_COUNTERS_SEMAPHOR_ENTRY_FULL_REJECT): ++ iowrite32be(val, &fman_rg->dma_rg->fmdmsefrc); ++ break; ++ case(E_FMAN_COUNTERS_SEMAPHOR_QUEUE_FULL_REJECT): ++ iowrite32be(val, &fman_rg->dma_rg->fmdmsqfrc); ++ break; ++ case(E_FMAN_COUNTERS_SEMAPHOR_SYNC_REJECT): ++ iowrite32be(val, &fman_rg->dma_rg->fmdmssrc); ++ break; ++ default: ++ break; ++ } ++ return 0; ++} ++ ++void fman_set_dma_emergency(struct fman_dma_regs *dma_rg, ++ bool is_write, ++ bool enable) ++{ ++ uint32_t msk; ++ ++ msk = (uint32_t)(is_write ? DMA_MODE_EMER_WRITE : DMA_MODE_EMER_READ); ++ ++ if (enable) ++ iowrite32be(ioread32be(&dma_rg->fmdmmr) | msk, ++ &dma_rg->fmdmmr); ++ else /* disable */ ++ iowrite32be(ioread32be(&dma_rg->fmdmmr) & ~msk, ++ &dma_rg->fmdmmr); ++} ++ ++void fman_set_dma_ext_bus_pri(struct fman_dma_regs *dma_rg, uint32_t pri) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(&dma_rg->fmdmmr) | ++ (pri << DMA_MODE_BUS_PRI_SHIFT); ++ ++ iowrite32be(tmp, &dma_rg->fmdmmr); ++} ++ ++uint32_t fman_get_dma_status(struct fman_dma_regs *dma_rg) ++{ ++ return ioread32be(&dma_rg->fmdmsr); ++} ++ ++void fman_force_intr(struct fman_rg *fman_rg, ++ enum fman_exceptions exception) ++{ ++ switch (exception) { ++ case E_FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: ++ iowrite32be(QMI_ERR_INTR_EN_DEQ_FROM_DEF, ++ &fman_rg->qmi_rg->fmqm_eif); ++ break; ++ case E_FMAN_EX_QMI_SINGLE_ECC: ++ iowrite32be(QMI_INTR_EN_SINGLE_ECC, ++ &fman_rg->qmi_rg->fmqm_if); ++ break; ++ case E_FMAN_EX_QMI_DOUBLE_ECC: ++ iowrite32be(QMI_ERR_INTR_EN_DOUBLE_ECC, ++ &fman_rg->qmi_rg->fmqm_eif); ++ break; ++ case E_FMAN_EX_BMI_LIST_RAM_ECC: ++ iowrite32be(BMI_ERR_INTR_EN_LIST_RAM_ECC, ++ &fman_rg->bmi_rg->fmbm_ifr); ++ break; ++ case E_FMAN_EX_BMI_STORAGE_PROFILE_ECC: ++ iowrite32be(BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC, ++ &fman_rg->bmi_rg->fmbm_ifr); ++ break; ++ case E_FMAN_EX_BMI_STATISTICS_RAM_ECC: ++ iowrite32be(BMI_ERR_INTR_EN_STATISTICS_RAM_ECC, ++ &fman_rg->bmi_rg->fmbm_ifr); ++ break; ++ case E_FMAN_EX_BMI_DISPATCH_RAM_ECC: ++ iowrite32be(BMI_ERR_INTR_EN_DISPATCH_RAM_ECC, ++ &fman_rg->bmi_rg->fmbm_ifr); ++ break; ++ default: ++ break; ++ } ++} ++ ++bool fman_is_qmi_halt_not_busy_state(struct fman_qmi_regs *qmi_rg) ++{ ++ return (bool)!!(ioread32be(&qmi_rg->fmqm_gs) & QMI_GS_HALT_NOT_BUSY); ++} ++void fman_resume(struct fman_fpm_regs *fpm_rg) ++{ ++ uint32_t tmp; ++ ++ tmp = ioread32be(&fpm_rg->fmfp_ee); ++ /* clear tmp_reg event bits in order not to clear standing events */ ++ tmp &= ~(FPM_EV_MASK_DOUBLE_ECC | ++ FPM_EV_MASK_STALL | ++ FPM_EV_MASK_SINGLE_ECC); ++ tmp |= FPM_EV_MASK_RELEASE_FM; ++ ++ iowrite32be(tmp, &fpm_rg->fmfp_ee); ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc/fm_common.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc/fm_common.h +new file mode 100644 +index 0000000..eb153d9 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc/fm_common.h +@@ -0,0 +1,1203 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_common.h ++ ++ @Description FM internal structures and definitions. ++*//***************************************************************************/ ++#ifndef __FM_COMMON_H ++#define __FM_COMMON_H ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "fm_pcd_ext.h" ++#include "fm_ext.h" ++#include "fm_port_ext.h" ++ ++ ++#define e_FM_PORT_TYPE_OH_HOST_COMMAND e_FM_PORT_TYPE_DUMMY ++ ++#define CLS_PLAN_NUM_PER_GRP 8 ++ ++#define IP_OFFLOAD_PACKAGE_NUMBER 106 ++#define CAPWAP_OFFLOAD_PACKAGE_NUMBER 108 ++#define IS_OFFLOAD_PACKAGE(num) ((num == IP_OFFLOAD_PACKAGE_NUMBER) || (num == CAPWAP_OFFLOAD_PACKAGE_NUMBER)) ++ ++ ++ ++/**************************************************************************//** ++ @Description Modules registers offsets ++*//***************************************************************************/ ++#define FM_MM_MURAM 0x00000000 ++#define FM_MM_BMI 0x00080000 ++#define FM_MM_QMI 0x00080400 ++#define FM_MM_PRS 0x000c7000 ++#define FM_MM_KG 0x000C1000 ++#define FM_MM_DMA 0x000C2000 ++#define FM_MM_FPM 0x000C3000 ++#define FM_MM_PLCR 0x000C0000 ++#define FM_MM_IMEM 0x000C4000 ++#define FM_MM_CGP 0x000DB000 ++#define FM_MM_TRB(i) (0x000D0200 + 0x400 * (i)) ++#if (DPAA_VERSION >= 11) ++#define FM_MM_SP 0x000dc000 ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ ++/**************************************************************************//** ++ @Description Enum for inter-module interrupts registration ++*//***************************************************************************/ ++typedef enum e_FmEventModules{ ++ e_FM_MOD_PRS, /**< Parser event */ ++ e_FM_MOD_KG, /**< Keygen event */ ++ e_FM_MOD_PLCR, /**< Policer event */ ++ e_FM_MOD_10G_MAC, /**< 10G MAC event */ ++ e_FM_MOD_1G_MAC, /**< 1G MAC event */ ++ e_FM_MOD_TMR, /**< Timer event */ ++ e_FM_MOD_FMAN_CTRL, /**< FMAN Controller Timer event */ ++ e_FM_MOD_MACSEC, ++ e_FM_MOD_DUMMY_LAST ++} e_FmEventModules; ++ ++/**************************************************************************//** ++ @Description Enum for interrupts types ++*//***************************************************************************/ ++typedef enum e_FmIntrType { ++ e_FM_INTR_TYPE_ERR, ++ e_FM_INTR_TYPE_NORMAL ++} e_FmIntrType; ++ ++/**************************************************************************//** ++ @Description Enum for inter-module interrupts registration ++*//***************************************************************************/ ++typedef enum e_FmInterModuleEvent ++{ ++ e_FM_EV_PRS = 0, /**< Parser event */ ++ e_FM_EV_ERR_PRS, /**< Parser error event */ ++ e_FM_EV_KG, /**< Keygen event */ ++ e_FM_EV_ERR_KG, /**< Keygen error event */ ++ e_FM_EV_PLCR, /**< Policer event */ ++ e_FM_EV_ERR_PLCR, /**< Policer error event */ ++ e_FM_EV_ERR_10G_MAC0, /**< 10G MAC 0 error event */ ++ e_FM_EV_ERR_10G_MAC1, /**< 10G MAC 1 error event */ ++ e_FM_EV_ERR_1G_MAC0, /**< 1G MAC 0 error event */ ++ e_FM_EV_ERR_1G_MAC1, /**< 1G MAC 1 error event */ ++ e_FM_EV_ERR_1G_MAC2, /**< 1G MAC 2 error event */ ++ e_FM_EV_ERR_1G_MAC3, /**< 1G MAC 3 error event */ ++ e_FM_EV_ERR_1G_MAC4, /**< 1G MAC 4 error event */ ++ e_FM_EV_ERR_1G_MAC5, /**< 1G MAC 5 error event */ ++ e_FM_EV_ERR_1G_MAC6, /**< 1G MAC 6 error event */ ++ e_FM_EV_ERR_1G_MAC7, /**< 1G MAC 7 error event */ ++ e_FM_EV_ERR_MACSEC_MAC0, ++ e_FM_EV_TMR, /**< Timer event */ ++ e_FM_EV_10G_MAC0, /**< 10G MAC 0 event (Magic packet detection)*/ ++ e_FM_EV_10G_MAC1, /**< 10G MAC 1 event (Magic packet detection)*/ ++ e_FM_EV_1G_MAC0, /**< 1G MAC 0 event (Magic packet detection)*/ ++ e_FM_EV_1G_MAC1, /**< 1G MAC 1 event (Magic packet detection)*/ ++ e_FM_EV_1G_MAC2, /**< 1G MAC 2 (Magic packet detection)*/ ++ e_FM_EV_1G_MAC3, /**< 1G MAC 3 (Magic packet detection)*/ ++ e_FM_EV_1G_MAC4, /**< 1G MAC 4 (Magic packet detection)*/ ++ e_FM_EV_1G_MAC5, /**< 1G MAC 5 (Magic packet detection)*/ ++ e_FM_EV_1G_MAC6, /**< 1G MAC 6 (Magic packet detection)*/ ++ e_FM_EV_1G_MAC7, /**< 1G MAC 7 (Magic packet detection)*/ ++ e_FM_EV_MACSEC_MAC0, /**< MACSEC MAC 0 event */ ++ e_FM_EV_FMAN_CTRL_0, /**< Fman controller event 0 */ ++ e_FM_EV_FMAN_CTRL_1, /**< Fman controller event 1 */ ++ e_FM_EV_FMAN_CTRL_2, /**< Fman controller event 2 */ ++ e_FM_EV_FMAN_CTRL_3, /**< Fman controller event 3 */ ++ e_FM_EV_DUMMY_LAST ++} e_FmInterModuleEvent; ++ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/**************************************************************************//** ++ @Description PCD KG scheme registers ++*//***************************************************************************/ ++typedef _Packed struct t_FmPcdPlcrProfileRegs { ++ volatile uint32_t fmpl_pemode; /* 0x090 FMPL_PEMODE - FM Policer Profile Entry Mode*/ ++ volatile uint32_t fmpl_pegnia; /* 0x094 FMPL_PEGNIA - FM Policer Profile Entry GREEN Next Invoked Action*/ ++ volatile uint32_t fmpl_peynia; /* 0x098 FMPL_PEYNIA - FM Policer Profile Entry YELLOW Next Invoked Action*/ ++ volatile uint32_t fmpl_pernia; /* 0x09C FMPL_PERNIA - FM Policer Profile Entry RED Next Invoked Action*/ ++ volatile uint32_t fmpl_pecir; /* 0x0A0 FMPL_PECIR - FM Policer Profile Entry Committed Information Rate*/ ++ volatile uint32_t fmpl_pecbs; /* 0x0A4 FMPL_PECBS - FM Policer Profile Entry Committed Burst Size*/ ++ volatile uint32_t fmpl_pepepir_eir; /* 0x0A8 FMPL_PEPIR_EIR - FM Policer Profile Entry Peak/Excess Information Rate*/ ++ volatile uint32_t fmpl_pepbs_ebs; /* 0x0AC FMPL_PEPBS_EBS - FM Policer Profile Entry Peak/Excess Information Rate*/ ++ volatile uint32_t fmpl_pelts; /* 0x0B0 FMPL_PELTS - FM Policer Profile Entry Last TimeStamp*/ ++ volatile uint32_t fmpl_pects; /* 0x0B4 FMPL_PECTS - FM Policer Profile Entry Committed Token Status*/ ++ volatile uint32_t fmpl_pepts_ets; /* 0x0B8 FMPL_PEPTS_ETS - FM Policer Profile Entry Peak/Excess Token Status*/ ++ volatile uint32_t fmpl_pegpc; /* 0x0BC FMPL_PEGPC - FM Policer Profile Entry GREEN Packet Counter*/ ++ volatile uint32_t fmpl_peypc; /* 0x0C0 FMPL_PEYPC - FM Policer Profile Entry YELLOW Packet Counter*/ ++ volatile uint32_t fmpl_perpc; /* 0x0C4 FMPL_PERPC - FM Policer Profile Entry RED Packet Counter */ ++ volatile uint32_t fmpl_perypc; /* 0x0C8 FMPL_PERYPC - FM Policer Profile Entry Recolored YELLOW Packet Counter*/ ++ volatile uint32_t fmpl_perrpc; /* 0x0CC FMPL_PERRPC - FM Policer Profile Entry Recolored RED Packet Counter*/ ++ volatile uint32_t fmpl_res1[12]; /* 0x0D0-0x0FF Reserved */ ++} _PackedType t_FmPcdPlcrProfileRegs; ++ ++ ++typedef _Packed struct t_FmPcdCcCapwapReassmTimeoutParams { ++ volatile uint32_t portIdAndCapwapReassmTbl; ++ volatile uint32_t fqidForTimeOutFrames; ++ volatile uint32_t timeoutRequestTime; ++}_PackedType t_FmPcdCcCapwapReassmTimeoutParams; ++ ++/**************************************************************************//** ++ @Description PCD CTRL Parameters Page ++*//***************************************************************************/ ++typedef _Packed struct t_FmPcdCtrlParamsPage { ++ volatile uint8_t reserved0[16]; ++ volatile uint32_t iprIpv4Nia; ++ volatile uint32_t iprIpv6Nia; ++ volatile uint8_t reserved1[24]; ++ volatile uint32_t ipfOptionsCounter; ++ volatile uint8_t reserved2[12]; ++ volatile uint32_t misc; ++ volatile uint32_t errorsDiscardMask; ++ volatile uint32_t discardMask; ++ volatile uint8_t reserved3[4]; ++ volatile uint32_t postBmiFetchNia; ++ volatile uint8_t reserved4[172]; ++} _PackedType t_FmPcdCtrlParamsPage; ++ ++ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/*for UNDER_CONSTRUCTION_FM_RMU_USE_SEC its defined in fm_ext.h*/ ++typedef uint32_t t_FmFmanCtrl; ++ ++#define FPM_PORT_FM_CTL1 0x00000001 ++#define FPM_PORT_FM_CTL2 0x00000002 ++ ++ ++ ++typedef struct t_FmPcdCcFragScratchPoolCmdParams { ++ uint32_t numOfBuffers; ++ uint8_t bufferPoolId; ++} t_FmPcdCcFragScratchPoolCmdParams; ++ ++typedef struct t_FmPcdCcReassmTimeoutParams { ++ bool activate; ++ uint8_t tsbs; ++ uint32_t iprcpt; ++} t_FmPcdCcReassmTimeoutParams; ++ ++typedef struct { ++ uint8_t baseEntry; ++ uint16_t numOfClsPlanEntries; ++ uint32_t vectors[FM_PCD_MAX_NUM_OF_CLS_PLANS]; ++} t_FmPcdKgInterModuleClsPlanSet; ++ ++/**************************************************************************//** ++ @Description Structure for binding a port to keygen schemes. ++*//***************************************************************************/ ++typedef struct t_FmPcdKgInterModuleBindPortToSchemes { ++ uint8_t hardwarePortId; ++ uint8_t netEnvId; ++ bool useClsPlan; /**< TRUE if this port uses the clsPlan mechanism */ ++ uint8_t numOfSchemes; ++ uint8_t schemesIds[FM_PCD_KG_NUM_OF_SCHEMES]; ++} t_FmPcdKgInterModuleBindPortToSchemes; ++ ++typedef struct { ++ uint32_t nextCcNodeInfo; ++ t_List node; ++} t_CcNodeInfo; ++ ++typedef struct ++{ ++ t_Handle h_CcNode; ++ uint16_t index; ++ t_List node; ++}t_CcNodeInformation; ++#define CC_NODE_F_OBJECT(ptr) LIST_OBJECT(ptr, t_CcNodeInformation, node) ++ ++typedef enum e_ModifyState ++{ ++ e_MODIFY_STATE_ADD = 0, ++ e_MODIFY_STATE_REMOVE, ++ e_MODIFY_STATE_CHANGE ++} e_ModifyState; ++ ++typedef struct ++{ ++ t_Handle h_Manip; ++ t_List node; ++}t_ManipInfo; ++#define CC_NEXT_NODE_F_OBJECT(ptr) LIST_OBJECT(ptr, t_CcNodeInfo, node) ++ ++typedef struct { ++ uint32_t type; ++ uint8_t prOffset; ++ uint16_t dataOffset; ++ uint8_t internalBufferOffset; ++ uint8_t numOfTasks; ++ uint8_t numOfExtraTasks; ++ uint8_t hardwarePortId; ++ t_FmRevisionInfo revInfo; ++ uint32_t nia; ++ uint32_t discardMask; ++} t_GetCcParams; ++ ++typedef struct { ++ uint32_t type; ++ int psoSize; ++ uint32_t nia; ++ t_FmFmanCtrl orFmanCtrl; ++ bool overwrite; ++ uint8_t ofpDpde; ++} t_SetCcParams; ++ ++typedef struct { ++ t_GetCcParams getCcParams; ++ t_SetCcParams setCcParams; ++} t_FmPortGetSetCcParams; ++ ++typedef struct { ++ uint32_t type; ++ bool sleep; ++} t_FmSetParams; ++ ++typedef struct { ++ uint32_t type; ++ uint32_t fmqm_gs; ++ uint32_t fm_npi; ++ uint32_t fm_cld; ++ uint32_t fmfp_extc; ++} t_FmGetParams; ++ ++typedef struct { ++ t_FmSetParams setParams; ++ t_FmGetParams getParams; ++} t_FmGetSetParams; ++ ++t_Error FmGetSetParams(t_Handle h_Fm, t_FmGetSetParams *p_Params); ++ ++static __inline__ bool TRY_LOCK(t_Handle h_Spinlock, volatile bool *p_Flag) ++{ ++ uint32_t intFlags; ++ if (h_Spinlock) ++ intFlags = XX_LockIntrSpinlock(h_Spinlock); ++ else ++ intFlags = XX_DisableAllIntr(); ++ ++ if (*p_Flag) ++ { ++ if (h_Spinlock) ++ XX_UnlockIntrSpinlock(h_Spinlock, intFlags); ++ else ++ XX_RestoreAllIntr(intFlags); ++ return FALSE; ++ } ++ *p_Flag = TRUE; ++ ++ if (h_Spinlock) ++ XX_UnlockIntrSpinlock(h_Spinlock, intFlags); ++ else ++ XX_RestoreAllIntr(intFlags); ++ ++ return TRUE; ++} ++ ++#define RELEASE_LOCK(_flag) _flag = FALSE; ++ ++/**************************************************************************//** ++ @Collection Defines used for manipulation CC and BMI ++ @{ ++*//***************************************************************************/ ++#define INTERNAL_CONTEXT_OFFSET 0x80000000 ++#define OFFSET_OF_PR 0x40000000 ++#define MANIP_EXTRA_SPACE 0x20000000 ++#define NUM_OF_TASKS 0x10000000 ++#define OFFSET_OF_DATA 0x08000000 ++#define HW_PORT_ID 0x04000000 ++#define FM_REV 0x02000000 ++#define GET_NIA_FPNE 0x01000000 ++#define GET_NIA_PNDN 0x00800000 ++#define NUM_OF_EXTRA_TASKS 0x00400000 ++#define DISCARD_MASK 0x00200000 ++ ++#define UPDATE_NIA_PNEN 0x80000000 ++#define UPDATE_PSO 0x40000000 ++#define UPDATE_NIA_PNDN 0x20000000 ++#define UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY 0x10000000 ++#define UPDATE_OFP_DPTE 0x08000000 ++#define UPDATE_NIA_FENE 0x04000000 ++#define UPDATE_NIA_CMNE 0x02000000 ++#define UPDATE_NIA_FPNE 0x01000000 ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection Defines used for manipulation CC and CC ++ @{ ++*//***************************************************************************/ ++#define UPDATE_NIA_ENQ_WITHOUT_DMA 0x80000000 ++#define UPDATE_CC_WITH_TREE 0x40000000 ++#define UPDATE_CC_WITH_DELETE_TREE 0x20000000 ++#define UPDATE_KG_NIA_CC_WA 0x10000000 ++#define UPDATE_KG_OPT_MODE 0x08000000 ++#define UPDATE_KG_NIA 0x04000000 ++#define UPDATE_CC_SHADOW_CLEAR 0x02000000 ++/* @} */ ++ ++#define UPDATE_FPM_BRKC_SLP 0x80000000 ++#define UPDATE_FPM_EXTC 0x40000000 ++#define UPDATE_FPM_EXTC_CLEAR 0x20000000 ++#define GET_FMQM_GS 0x10000000 ++#define GET_FM_NPI 0x08000000 ++#define GET_FMFP_EXTC 0x04000000 ++#define CLEAR_IRAM_READY 0x02000000 ++#define UPDATE_FM_CLD 0x01000000 ++#define GET_FM_CLD 0x00800000 ++#define FM_MAX_NUM_OF_PORTS (FM_MAX_NUM_OF_OH_PORTS + \ ++ FM_MAX_NUM_OF_1G_RX_PORTS + \ ++ FM_MAX_NUM_OF_10G_RX_PORTS + \ ++ FM_MAX_NUM_OF_1G_TX_PORTS + \ ++ FM_MAX_NUM_OF_10G_TX_PORTS) ++ ++#define MODULE_NAME_SIZE 30 ++#define DUMMY_PORT_ID 0 ++ ++#define FM_LIODN_OFFSET_MASK 0x3FF ++ ++/**************************************************************************//** ++ @Description NIA Description ++*//***************************************************************************/ ++#define NIA_ENG_MASK 0x007C0000 ++#define NIA_AC_MASK 0x0003ffff ++ ++#define NIA_ORDER_RESTOR 0x00800000 ++#define NIA_ENG_FM_CTL 0x00000000 ++#define NIA_ENG_PRS 0x00440000 ++#define NIA_ENG_KG 0x00480000 ++#define NIA_ENG_PLCR 0x004C0000 ++#define NIA_ENG_BMI 0x00500000 ++#define NIA_ENG_QMI_ENQ 0x00540000 ++#define NIA_ENG_QMI_DEQ 0x00580000 ++ ++#define NIA_FM_CTL_AC_CC 0x00000006 ++#define NIA_FM_CTL_AC_HC 0x0000000C ++#define NIA_FM_CTL_AC_IND_MODE_TX 0x00000008 ++#define NIA_FM_CTL_AC_IND_MODE_RX 0x0000000A ++#define NIA_FM_CTL_AC_POP_TO_N_STEP 0x0000000e ++#define NIA_FM_CTL_AC_PRE_BMI_FETCH_HEADER 0x00000010 ++#define NIA_FM_CTL_AC_PRE_BMI_FETCH_FULL_FRAME 0x00000018 ++#define NIA_FM_CTL_AC_POST_BMI_FETCH 0x00000012 ++#define NIA_FM_CTL_AC_PRE_BMI_ENQ_FRAME 0x0000001A ++#define NIA_FM_CTL_AC_PRE_BMI_DISCARD_FRAME 0x0000001E ++#define NIA_FM_CTL_AC_POST_BMI_ENQ_ORR 0x00000014 ++#define NIA_FM_CTL_AC_POST_BMI_ENQ 0x00000022 ++#define NIA_FM_CTL_AC_PRE_CC 0x00000020 ++#define NIA_FM_CTL_AC_POST_TX 0x00000024 ++/* V3 only */ ++#define NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME 0x00000028 ++#define NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_DISCARD_FRAME 0x0000002A ++#define NIA_FM_CTL_AC_NO_IPACC_POP_TO_N_STEP 0x0000002C ++ ++#define NIA_BMI_AC_ENQ_FRAME 0x00000002 ++#define NIA_BMI_AC_TX_RELEASE 0x000002C0 ++#define NIA_BMI_AC_RELEASE 0x000000C0 ++#define NIA_BMI_AC_DISCARD 0x000000C1 ++#define NIA_BMI_AC_TX 0x00000274 ++#define NIA_BMI_AC_FETCH 0x00000208 ++#define NIA_BMI_AC_MASK 0x000003FF ++ ++#define NIA_KG_DIRECT 0x00000100 ++#define NIA_KG_CC_EN 0x00000200 ++#define NIA_PLCR_ABSOLUTE 0x00008000 ++ ++#define NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA 0x00000202 ++ ++#if defined(FM_OP_NO_VSP_NO_RELEASE_ERRATA_FMAN_A006675) || defined(FM_ERROR_VSP_NO_MATCH_SW006) ++#define GET_NIA_BMI_AC_ENQ_FRAME(h_FmPcd) \ ++ (uint32_t)((FmPcdIsAdvancedOffloadSupported(h_FmPcd)) ? \ ++ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_PRE_BMI_ENQ_FRAME) : \ ++ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME)) ++#define GET_NIA_BMI_AC_DISCARD_FRAME(h_FmPcd) \ ++ (uint32_t)((FmPcdIsAdvancedOffloadSupported(h_FmPcd)) ? \ ++ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_PRE_BMI_DISCARD_FRAME) : \ ++ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_DISCARD_FRAME)) ++#define GET_NO_PCD_NIA_BMI_AC_ENQ_FRAME() \ ++ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME) ++#else ++#define GET_NIA_BMI_AC_ENQ_FRAME(h_FmPcd) \ ++ (uint32_t)((FmPcdIsAdvancedOffloadSupported(h_FmPcd)) ? \ ++ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_PRE_BMI_ENQ_FRAME) : \ ++ (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)) ++#define GET_NIA_BMI_AC_DISCARD_FRAME(h_FmPcd) \ ++ (uint32_t)((FmPcdIsAdvancedOffloadSupported(h_FmPcd)) ? \ ++ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_PRE_BMI_DISCARD_FRAME) : \ ++ (NIA_ENG_BMI | NIA_BMI_AC_DISCARD)) ++#define GET_NO_PCD_NIA_BMI_AC_ENQ_FRAME() \ ++ (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME) ++#endif /* defined(FM_OP_NO_VSP_NO_RELEASE_ERRATA_FMAN_A006675) || ... */ ++ ++/**************************************************************************//** ++ @Description CTRL Parameters Page defines ++*//***************************************************************************/ ++#define FM_CTL_PARAMS_PAGE_OP_FIX_EN 0x80000000 ++#define FM_CTL_PARAMS_PAGE_OFFLOAD_SUPPORT_EN 0x40000000 ++#define FM_CTL_PARAMS_PAGE_ALWAYS_ON 0x00000100 ++ ++#define FM_CTL_PARAMS_PAGE_ERROR_VSP_MASK 0x0000003f ++ ++/**************************************************************************//** ++ @Description Port Id defines ++*//***************************************************************************/ ++#if (DPAA_VERSION == 10) ++#define BASE_OH_PORTID 1 ++#else ++#define BASE_OH_PORTID 2 ++#endif /* (DPAA_VERSION == 10) */ ++#define BASE_1G_RX_PORTID 8 ++#define BASE_10G_RX_PORTID 0x10 ++#define BASE_1G_TX_PORTID 0x28 ++#define BASE_10G_TX_PORTID 0x30 ++ ++#define FM_PCD_PORT_OH_BASE_INDX 0 ++#define FM_PCD_PORT_1G_RX_BASE_INDX (FM_PCD_PORT_OH_BASE_INDX+FM_MAX_NUM_OF_OH_PORTS) ++#define FM_PCD_PORT_10G_RX_BASE_INDX (FM_PCD_PORT_1G_RX_BASE_INDX+FM_MAX_NUM_OF_1G_RX_PORTS) ++#define FM_PCD_PORT_1G_TX_BASE_INDX (FM_PCD_PORT_10G_RX_BASE_INDX+FM_MAX_NUM_OF_10G_RX_PORTS) ++#define FM_PCD_PORT_10G_TX_BASE_INDX (FM_PCD_PORT_1G_TX_BASE_INDX+FM_MAX_NUM_OF_1G_TX_PORTS) ++ ++#if (FM_MAX_NUM_OF_OH_PORTS > 0) ++#define CHECK_PORT_ID_OH_PORTS(_relativePortId) \ ++ if ((_relativePortId) >= FM_MAX_NUM_OF_OH_PORTS) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal OH_PORT port id")) ++#else ++#define CHECK_PORT_ID_OH_PORTS(_relativePortId) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal OH_PORT port id")) ++#endif ++#if (FM_MAX_NUM_OF_1G_RX_PORTS > 0) ++#define CHECK_PORT_ID_1G_RX_PORTS(_relativePortId) \ ++ if ((_relativePortId) >= FM_MAX_NUM_OF_1G_RX_PORTS) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 1G_RX_PORT port id")) ++#else ++#define CHECK_PORT_ID_1G_RX_PORTS(_relativePortId) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 1G_RX_PORT port id")) ++#endif ++#if (FM_MAX_NUM_OF_10G_RX_PORTS > 0) ++#define CHECK_PORT_ID_10G_RX_PORTS(_relativePortId) \ ++ if ((_relativePortId) >= FM_MAX_NUM_OF_10G_RX_PORTS) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 10G_RX_PORT port id")) ++#else ++#define CHECK_PORT_ID_10G_RX_PORTS(_relativePortId) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 10G_RX_PORT port id")) ++#endif ++#if (FM_MAX_NUM_OF_1G_TX_PORTS > 0) ++#define CHECK_PORT_ID_1G_TX_PORTS(_relativePortId) \ ++ if ((_relativePortId) >= FM_MAX_NUM_OF_1G_TX_PORTS) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 1G_TX_PORT port id")) ++#else ++#define CHECK_PORT_ID_1G_TX_PORTS(_relativePortId) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 1G_TX_PORT port id")) ++#endif ++#if (FM_MAX_NUM_OF_10G_TX_PORTS > 0) ++#define CHECK_PORT_ID_10G_TX_PORTS(_relativePortId) \ ++ if ((_relativePortId) >= FM_MAX_NUM_OF_10G_TX_PORTS) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 10G_TX_PORT port id")) ++#else ++#define CHECK_PORT_ID_10G_TX_PORTS(_relativePortId) \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 10G_TX_PORT port id")) ++#endif ++ ++uint8_t SwPortIdToHwPortId(e_FmPortType type, uint8_t relativePortId, uint8_t majorRev, uint8_t minorRev); ++ ++#define HW_PORT_ID_TO_SW_PORT_ID(_relativePortId, hardwarePortId) \ ++{ if (((hardwarePortId) >= BASE_OH_PORTID) && \ ++ ((hardwarePortId) < BASE_OH_PORTID+FM_MAX_NUM_OF_OH_PORTS)) \ ++ _relativePortId = (uint8_t)((hardwarePortId)-BASE_OH_PORTID); \ ++ else if (((hardwarePortId) >= BASE_10G_TX_PORTID) && \ ++ ((hardwarePortId) < BASE_10G_TX_PORTID+FM_MAX_NUM_OF_10G_TX_PORTS)) \ ++ _relativePortId = (uint8_t)((hardwarePortId)-BASE_10G_TX_PORTID); \ ++ else if (((hardwarePortId) >= BASE_1G_TX_PORTID) && \ ++ ((hardwarePortId) < BASE_1G_TX_PORTID+FM_MAX_NUM_OF_1G_TX_PORTS)) \ ++ _relativePortId = (uint8_t)((hardwarePortId)-BASE_1G_TX_PORTID); \ ++ else if (((hardwarePortId) >= BASE_10G_RX_PORTID) && \ ++ ((hardwarePortId) < BASE_10G_RX_PORTID+FM_MAX_NUM_OF_10G_RX_PORTS)) \ ++ _relativePortId = (uint8_t)((hardwarePortId)-BASE_10G_RX_PORTID); \ ++ else if (((hardwarePortId) >= BASE_1G_RX_PORTID) && \ ++ ((hardwarePortId) < BASE_1G_RX_PORTID+FM_MAX_NUM_OF_1G_RX_PORTS)) \ ++ _relativePortId = (uint8_t)((hardwarePortId)-BASE_1G_RX_PORTID); \ ++ else { \ ++ _relativePortId = (uint8_t)DUMMY_PORT_ID; \ ++ ASSERT_COND(TRUE); \ ++ } \ ++} ++ ++#define HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId) \ ++do { \ ++ if (((hardwarePortId) >= BASE_OH_PORTID) && ((hardwarePortId) < BASE_OH_PORTID+FM_MAX_NUM_OF_OH_PORTS)) \ ++ swPortIndex = (uint8_t)((hardwarePortId)-BASE_OH_PORTID+FM_PCD_PORT_OH_BASE_INDX); \ ++ else if (((hardwarePortId) >= BASE_1G_RX_PORTID) && \ ++ ((hardwarePortId) < BASE_1G_RX_PORTID+FM_MAX_NUM_OF_1G_RX_PORTS)) \ ++ swPortIndex = (uint8_t)((hardwarePortId)-BASE_1G_RX_PORTID+FM_PCD_PORT_1G_RX_BASE_INDX); \ ++ else if (((hardwarePortId) >= BASE_10G_RX_PORTID) && \ ++ ((hardwarePortId) < BASE_10G_RX_PORTID+FM_MAX_NUM_OF_10G_RX_PORTS)) \ ++ swPortIndex = (uint8_t)((hardwarePortId)-BASE_10G_RX_PORTID+FM_PCD_PORT_10G_RX_BASE_INDX); \ ++ else if (((hardwarePortId) >= BASE_1G_TX_PORTID) && \ ++ ((hardwarePortId) < BASE_1G_TX_PORTID+FM_MAX_NUM_OF_1G_TX_PORTS)) \ ++ swPortIndex = (uint8_t)((hardwarePortId)-BASE_1G_TX_PORTID+FM_PCD_PORT_1G_TX_BASE_INDX); \ ++ else if (((hardwarePortId) >= BASE_10G_TX_PORTID) && \ ++ ((hardwarePortId) < BASE_10G_TX_PORTID+FM_MAX_NUM_OF_10G_TX_PORTS)) \ ++ swPortIndex = (uint8_t)((hardwarePortId)-BASE_10G_TX_PORTID+FM_PCD_PORT_10G_TX_BASE_INDX); \ ++ else ASSERT_COND(FALSE); \ ++} while (0) ++ ++#define SW_PORT_INDX_TO_HW_PORT_ID(hardwarePortId, swPortIndex) \ ++do { \ ++ if (((swPortIndex) >= FM_PCD_PORT_OH_BASE_INDX) && ((swPortIndex) < FM_PCD_PORT_1G_RX_BASE_INDX)) \ ++ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_OH_BASE_INDX+BASE_OH_PORTID); \ ++ else if (((swPortIndex) >= FM_PCD_PORT_1G_RX_BASE_INDX) && ((swPortIndex) < FM_PCD_PORT_10G_RX_BASE_INDX)) \ ++ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_1G_RX_BASE_INDX+BASE_1G_RX_PORTID); \ ++ else if (((swPortIndex) >= FM_PCD_PORT_10G_RX_BASE_INDX) && ((swPortIndex) < FM_MAX_NUM_OF_PORTS)) \ ++ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_10G_RX_BASE_INDX+BASE_10G_RX_PORTID); \ ++ else if (((swPortIndex) >= FM_PCD_PORT_1G_TX_BASE_INDX) && ((swPortIndex) < FM_PCD_PORT_10G_TX_BASE_INDX)) \ ++ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_1G_TX_BASE_INDX+BASE_1G_TX_PORTID); \ ++ else if (((swPortIndex) >= FM_PCD_PORT_10G_TX_BASE_INDX) && ((swPortIndex) < FM_MAX_NUM_OF_PORTS)) \ ++ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_10G_TX_BASE_INDX+BASE_10G_TX_PORTID); \ ++ else ASSERT_COND(FALSE); \ ++} while (0) ++ ++#define BMI_MAX_FIFO_SIZE (FM_MURAM_SIZE) ++#define BMI_FIFO_UNITS 0x100 ++ ++typedef struct { ++ void (*f_Isr) (t_Handle h_Arg); ++ t_Handle h_SrcHandle; ++ uint8_t guestId; ++} t_FmIntrSrc; ++ ++#define ILLEGAL_HDR_NUM 0xFF ++#define NO_HDR_NUM FM_PCD_PRS_NUM_OF_HDRS ++ ++#define IS_PRIVATE_HEADER(hdr) (((hdr) == HEADER_TYPE_USER_DEFINED_SHIM1) || \ ++ ((hdr) == HEADER_TYPE_USER_DEFINED_SHIM2)) ++#define IS_SPECIAL_HEADER(hdr) ((hdr) == HEADER_TYPE_MACSEC) ++ ++static __inline__ uint8_t GetPrsHdrNum(e_NetHeaderType hdr) ++{ ++ switch (hdr) ++ { case (HEADER_TYPE_ETH): return 0; ++ case (HEADER_TYPE_LLC_SNAP): return 1; ++ case (HEADER_TYPE_VLAN): return 2; ++ case (HEADER_TYPE_PPPoE): return 3; ++ case (HEADER_TYPE_PPP): return 3; ++ case (HEADER_TYPE_MPLS): return 4; ++ case (HEADER_TYPE_IPv4): return 5; ++ case (HEADER_TYPE_IPv6): return 6; ++ case (HEADER_TYPE_GRE): return 7; ++ case (HEADER_TYPE_MINENCAP): return 8; ++ case (HEADER_TYPE_USER_DEFINED_L3): return 9; ++ case (HEADER_TYPE_TCP): return 10; ++ case (HEADER_TYPE_UDP): return 11; ++ case (HEADER_TYPE_IPSEC_AH): ++ case (HEADER_TYPE_IPSEC_ESP): return 12; ++ case (HEADER_TYPE_SCTP): return 13; ++ case (HEADER_TYPE_DCCP): return 14; ++ case (HEADER_TYPE_USER_DEFINED_L4): return 15; ++ case (HEADER_TYPE_USER_DEFINED_SHIM1): ++ case (HEADER_TYPE_USER_DEFINED_SHIM2): ++ case (HEADER_TYPE_MACSEC): return NO_HDR_NUM; ++ default: ++ return ILLEGAL_HDR_NUM; ++ } ++} ++ ++#define FM_PCD_MAX_NUM_OF_OPTIONS(clsPlanEntries) ((clsPlanEntries==256)? 8:((clsPlanEntries==128)? 7: ((clsPlanEntries==64)? 6: ((clsPlanEntries==32)? 5:0)))) ++ ++ ++/**************************************************************************//** ++ @Description A structure for initializing a keygen classification plan group ++*//***************************************************************************/ ++typedef struct t_FmPcdKgInterModuleClsPlanGrpParams { ++ uint8_t netEnvId; /* IN */ ++ bool grpExists; /* OUT (unused in FmPcdKgBuildClsPlanGrp)*/ ++ uint8_t clsPlanGrpId; /* OUT */ ++ bool emptyClsPlanGrp; /* OUT */ ++ uint8_t numOfOptions; /* OUT in FmPcdGetSetClsPlanGrpParams IN in FmPcdKgBuildClsPlanGrp*/ ++ protocolOpt_t options[FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)]; ++ /* OUT in FmPcdGetSetClsPlanGrpParams IN in FmPcdKgBuildClsPlanGrp*/ ++ uint32_t optVectors[FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)]; ++ /* OUT in FmPcdGetSetClsPlanGrpParams IN in FmPcdKgBuildClsPlanGrp*/ ++} t_FmPcdKgInterModuleClsPlanGrpParams; ++ ++typedef struct t_FmPcdLock { ++ t_Handle h_Spinlock; ++ volatile bool flag; ++ t_List node; ++} t_FmPcdLock; ++#define FM_PCD_LOCK_OBJ(ptr) LIST_OBJECT(ptr, t_FmPcdLock, node) ++ ++ ++typedef t_Error (t_FmPortGetSetCcParamsCallback) (t_Handle h_FmPort, ++ t_FmPortGetSetCcParams *p_FmPortGetSetCcParams); ++ ++ ++/***********************************************************************/ ++/* Common API for FM-PCD module */ ++/***********************************************************************/ ++t_Handle FmPcdGetHcHandle(t_Handle h_FmPcd); ++uint32_t FmPcdGetSwPrsOffset(t_Handle h_FmPcd, e_NetHeaderType hdr, uint8_t indexPerHdr); ++uint32_t FmPcdGetLcv(t_Handle h_FmPcd, uint32_t netEnvId, uint8_t hdrNum); ++uint32_t FmPcdGetMacsecLcv(t_Handle h_FmPcd, uint32_t netEnvId); ++void FmPcdIncNetEnvOwners(t_Handle h_FmPcd, uint8_t netEnvId); ++void FmPcdDecNetEnvOwners(t_Handle h_FmPcd, uint8_t netEnvId); ++uint8_t FmPcdGetNetEnvId(t_Handle h_NetEnv); ++void FmPcdPortRegister(t_Handle h_FmPcd, t_Handle h_FmPort, uint8_t hardwarePortId); ++uint32_t FmPcdLock(t_Handle h_FmPcd); ++void FmPcdUnlock(t_Handle h_FmPcd, uint32_t intFlags); ++bool FmPcdNetEnvIsHdrExist(t_Handle h_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr); ++t_Error FmPcdFragHcScratchPoolInit(t_Handle h_FmPcd, uint8_t scratchBpid); ++t_Error FmPcdRegisterReassmPort(t_Handle h_FmPcd, t_Handle h_IpReasmCommonPramTbl); ++t_Error FmPcdUnregisterReassmPort(t_Handle h_FmPcd, t_Handle h_IpReasmCommonPramTbl); ++bool FmPcdIsAdvancedOffloadSupported(t_Handle h_FmPcd); ++bool FmPcdLockTryLockAll(t_Handle h_FmPcd); ++void FmPcdLockUnlockAll(t_Handle h_FmPcd); ++t_Error FmPcdHcSync(t_Handle h_FmPcd); ++t_Handle FmGetPcd(t_Handle h_Fm); ++/***********************************************************************/ ++/* Common API for FM-PCD KG module */ ++/***********************************************************************/ ++uint8_t FmPcdKgGetClsPlanGrpBase(t_Handle h_FmPcd, uint8_t clsPlanGrp); ++uint16_t FmPcdKgGetClsPlanGrpSize(t_Handle h_FmPcd, uint8_t clsPlanGrp); ++t_Error FmPcdKgBuildClsPlanGrp(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_Grp, t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet); ++ ++uint8_t FmPcdKgGetSchemeId(t_Handle h_Scheme); ++#if (DPAA_VERSION >= 11) ++bool FmPcdKgGetVspe(t_Handle h_Scheme); ++#endif /* (DPAA_VERSION >= 11) */ ++uint8_t FmPcdKgGetRelativeSchemeId(t_Handle h_FmPcd, uint8_t schemeId); ++void FmPcdKgDestroyClsPlanGrp(t_Handle h_FmPcd, uint8_t grpId); ++t_Error FmPcdKgCheckInvalidateSchemeSw(t_Handle h_Scheme); ++t_Error FmPcdKgBuildBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_BindPortToSchemes, uint32_t *p_SpReg, bool add); ++bool FmPcdKgHwSchemeIsValid(uint32_t schemeModeReg); ++uint32_t FmPcdKgBuildWriteSchemeActionReg(uint8_t schemeId, bool updateCounter); ++uint32_t FmPcdKgBuildReadSchemeActionReg(uint8_t schemeId); ++uint32_t FmPcdKgBuildWriteClsPlanBlockActionReg(uint8_t grpId); ++uint32_t FmPcdKgBuildWritePortSchemeBindActionReg(uint8_t hardwarePortId); ++uint32_t FmPcdKgBuildReadPortSchemeBindActionReg(uint8_t hardwarePortId); ++uint32_t FmPcdKgBuildWritePortClsPlanBindActionReg(uint8_t hardwarePortId); ++bool FmPcdKgIsSchemeValidSw(t_Handle h_Scheme); ++ ++t_Error FmPcdKgBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind); ++t_Error FmPcdKgUnbindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind); ++uint32_t FmPcdKgGetRequiredAction(t_Handle h_FmPcd, uint8_t schemeId); ++uint32_t FmPcdKgGetRequiredActionFlag(t_Handle h_FmPcd, uint8_t schemeId); ++e_FmPcdDoneAction FmPcdKgGetDoneAction(t_Handle h_FmPcd, uint8_t schemeId); ++e_FmPcdEngine FmPcdKgGetNextEngine(t_Handle h_FmPcd, uint8_t schemeId); ++void FmPcdKgUpdateRequiredAction(t_Handle h_Scheme, uint32_t requiredAction); ++bool FmPcdKgIsDirectPlcr(t_Handle h_FmPcd, uint8_t schemeId); ++bool FmPcdKgIsDistrOnPlcrProfile(t_Handle h_FmPcd, uint8_t schemeId); ++uint16_t FmPcdKgGetRelativeProfileId(t_Handle h_FmPcd, uint8_t schemeId); ++t_Handle FmPcdKgGetSchemeHandle(t_Handle h_FmPcd, uint8_t relativeSchemeId); ++bool FmPcdKgIsSchemeHasOwners(t_Handle h_Scheme); ++t_Error FmPcdKgCcGetSetParams(t_Handle h_FmPcd, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value); ++t_Error FmPcdKgSetOrBindToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t netEnvId, protocolOpt_t *p_OptArray, uint8_t *p_ClsPlanGrpId, bool *p_IsEmptyClsPlanGrp); ++t_Error FmPcdKgDeleteOrUnbindPortToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t clsPlanGrpId); ++ ++/***********************************************************************/ ++/* Common API for FM-PCD parser module */ ++/***********************************************************************/ ++t_Error FmPcdPrsIncludePortInStatistics(t_Handle p_FmPcd, uint8_t hardwarePortId, bool include); ++ ++/***********************************************************************/ ++/* Common API for FM-PCD policer module */ ++/***********************************************************************/ ++t_Error FmPcdPlcrAllocProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId, uint16_t numOfProfiles); ++t_Error FmPcdPlcrFreeProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId); ++bool FmPcdPlcrIsProfileValid(t_Handle h_FmPcd, uint16_t absoluteProfileId); ++uint16_t FmPcdPlcrGetPortProfilesBase(t_Handle h_FmPcd, uint8_t hardwarePortId); ++uint16_t FmPcdPlcrGetPortNumOfProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId); ++uint32_t FmPcdPlcrBuildWritePlcrActionRegs(uint16_t absoluteProfileId); ++uint32_t FmPcdPlcrBuildCounterProfileReg(e_FmPcdPlcrProfileCounters counter); ++uint32_t FmPcdPlcrBuildWritePlcrActionReg(uint16_t absoluteProfileId); ++uint32_t FmPcdPlcrBuildReadPlcrActionReg(uint16_t absoluteProfileId); ++uint16_t FmPcdPlcrProfileGetAbsoluteId(t_Handle h_Profile); ++t_Error FmPcdPlcrGetAbsoluteIdByProfileParams(t_Handle h_FmPcd, ++ e_FmPcdProfileTypeSelection profileType, ++ t_Handle h_FmPort, ++ uint16_t relativeProfile, ++ uint16_t *p_AbsoluteId); ++void FmPcdPlcrInvalidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId); ++void FmPcdPlcrValidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId); ++bool FmPcdPlcrHwProfileIsValid(uint32_t profileModeReg); ++uint32_t FmPcdPlcrGetRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId); ++uint32_t FmPcdPlcrGetRequiredActionFlag(t_Handle h_FmPcd, uint16_t absoluteProfileId); ++uint32_t FmPcdPlcrBuildNiaProfileReg(bool green, bool yellow, bool red); ++void FmPcdPlcrUpdateRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId, uint32_t requiredAction); ++t_Error FmPcdPlcrCcGetSetParams(t_Handle h_FmPcd, uint16_t profileIndx,uint32_t requiredAction); ++ ++/***********************************************************************/ ++/* Common API for FM-PCD CC module */ ++/***********************************************************************/ ++uint8_t FmPcdCcGetParseCode(t_Handle h_CcNode); ++uint8_t FmPcdCcGetOffset(t_Handle h_CcNode); ++t_Error FmPcdCcRemoveKey(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode, uint16_t keyIndex); ++t_Error FmPcdCcAddKey(t_Handle h_FmPcd, t_Handle h_CcNode, uint16_t keyIndex, uint8_t keySize, t_FmPcdCcKeyParams *p_FmPCdCcKeyParams); ++t_Error FmPcdCcModifyKey(t_Handle h_FmPcd, t_Handle h_CcNode, uint16_t keyIndex, uint8_t keySize, uint8_t *p_Key, uint8_t *p_Mask); ++t_Error FmPcdCcModifyKeyAndNextEngine(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode, uint16_t keyIndex, uint8_t keySize, t_FmPcdCcKeyParams *p_FmPcdCcKeyParams); ++t_Error FmPcdCcModifyMissNextEngineParamNode(t_Handle h_FmPcd,t_Handle h_FmPcdCcNode, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++t_Error FmPcdCcModifyNextEngineParamTree(t_Handle h_FmPcd, t_Handle h_FmPcdCcTree, uint8_t grpId, uint8_t index, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++uint32_t FmPcdCcGetNodeAddrOffsetFromNodeInfo(t_Handle h_FmPcd, t_Handle h_Pointer); ++t_Handle FmPcdCcTreeGetSavedManipParams(t_Handle h_FmTree); ++void FmPcdCcTreeSetSavedManipParams(t_Handle h_FmTree, t_Handle h_SavedManipParams); ++t_Error FmPcdCcTreeAddIPR(t_Handle h_FmPcd, t_Handle h_FmTree, t_Handle h_NetEnv, t_Handle h_ReassemblyManip, bool schemes); ++t_Error FmPcdCcTreeAddCPR(t_Handle h_FmPcd, t_Handle h_FmTree, t_Handle h_NetEnv, t_Handle h_ReassemblyManip, bool schemes); ++t_Error FmPcdCcBindTree(t_Handle h_FmPcd, t_Handle h_PcdParams, t_Handle h_CcTree, uint32_t *p_Offset,t_Handle h_FmPort); ++t_Error FmPcdCcUnbindTree(t_Handle h_FmPcd, t_Handle h_CcTree); ++ ++/***********************************************************************/ ++/* Common API for FM-PCD Manip module */ ++/***********************************************************************/ ++t_Error FmPcdManipUpdate(t_Handle h_FmPcd, t_Handle h_PcdParams, t_Handle h_FmPort, t_Handle h_Manip, t_Handle h_Ad, bool validate, int level, t_Handle h_FmTree, bool modify); ++ ++/***********************************************************************/ ++/* Common API for FM-Port module */ ++/***********************************************************************/ ++#if (DPAA_VERSION >= 11) ++typedef enum e_FmPortGprFuncType ++{ ++ e_FM_PORT_GPR_EMPTY = 0, ++ e_FM_PORT_GPR_MURAM_PAGE ++} e_FmPortGprFuncType; ++ ++t_Error FmPortSetGprFunc(t_Handle h_FmPort, e_FmPortGprFuncType gprFunc, void **p_Value); ++#endif /* DPAA_VERSION >= 11) */ ++t_Error FmGetSetParams(t_Handle h_Fm, t_FmGetSetParams *p_FmGetSetParams); ++t_Error FmPortGetSetCcParams(t_Handle h_FmPort, t_FmPortGetSetCcParams *p_FmPortGetSetCcParams); ++uint8_t FmPortGetNetEnvId(t_Handle h_FmPort); ++uint8_t FmPortGetHardwarePortId(t_Handle h_FmPort); ++uint32_t FmPortGetPcdEngines(t_Handle h_FmPort); ++void FmPortPcdKgSwUnbindClsPlanGrp (t_Handle h_FmPort); ++ ++ ++#if (DPAA_VERSION >= 11) ++t_Error FmPcdFrmReplicUpdate(t_Handle h_FmPcd, t_Handle h_FmPort, t_Handle h_FrmReplic); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Function FmRegisterIntr ++ ++ @Description Used to register an inter-module event handler to be processed by FM ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] mod The module that causes the event ++ @Param[in] modId Module id - if more than 1 instansiation of this ++ mode exists,0 otherwise. ++ @Param[in] intrType Interrupt type (error/normal) selection. ++ @Param[in] f_Isr The interrupt service routine. ++ @Param[in] h_Arg Argument to be passed to f_Isr. ++ ++ @Return None. ++*//***************************************************************************/ ++void FmRegisterIntr(t_Handle h_Fm, ++ e_FmEventModules mod, ++ uint8_t modId, ++ e_FmIntrType intrType, ++ void (*f_Isr) (t_Handle h_Arg), ++ t_Handle h_Arg); ++ ++/**************************************************************************//** ++ @Function FmUnregisterIntr ++ ++ @Description Used to un-register an inter-module event handler that was processed by FM ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] mod The module that causes the event ++ @Param[in] modId Module id - if more than 1 instansiation of this ++ mode exists,0 otherwise. ++ @Param[in] intrType Interrupt type (error/normal) selection. ++ ++ @Return None. ++*//***************************************************************************/ ++void FmUnregisterIntr(t_Handle h_Fm, ++ e_FmEventModules mod, ++ uint8_t modId, ++ e_FmIntrType intrType); ++ ++/**************************************************************************//** ++ @Function FmRegisterFmCtlIntr ++ ++ @Description Used to register to one of the fmCtl events in the FM module ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] eventRegId FmCtl event id (0-7). ++ @Param[in] f_Isr The interrupt service routine. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++void FmRegisterFmCtlIntr(t_Handle h_Fm, uint8_t eventRegId, void (*f_Isr) (t_Handle h_Fm, uint32_t event)); ++ ++ ++/**************************************************************************//** ++ @Description enum for defining MAC types ++*//***************************************************************************/ ++typedef enum e_FmMacType { ++ e_FM_MAC_10G = 0, /**< 10G MAC */ ++ e_FM_MAC_1G /**< 1G MAC */ ++} e_FmMacType; ++ ++/**************************************************************************//** ++ @Description Structure for port-FM communication during FM_PORT_Init. ++ Fields commented 'IN' are passed by the port module to be used ++ by the FM module. ++ Fields commented 'OUT' will be filled by FM before returning to port. ++ Some fields are optional (depending on configuration) and ++ will be analized by the port and FM modules accordingly. ++*//***************************************************************************/ ++typedef struct t_FmInterModulePortInitParams { ++ uint8_t hardwarePortId; /**< IN. port Id */ ++ e_FmPortType portType; /**< IN. Port type */ ++ bool independentMode; /**< IN. TRUE if FM Port operates in independent mode */ ++ uint16_t liodnOffset; /**< IN. Port's requested resource */ ++ uint8_t numOfTasks; /**< IN. Port's requested resource */ ++ uint8_t numOfExtraTasks; /**< IN. Port's requested resource */ ++ uint8_t numOfOpenDmas; /**< IN. Port's requested resource */ ++ uint8_t numOfExtraOpenDmas; /**< IN. Port's requested resource */ ++ uint32_t sizeOfFifo; /**< IN. Port's requested resource */ ++ uint32_t extraSizeOfFifo; /**< IN. Port's requested resource */ ++ uint8_t deqPipelineDepth; /**< IN. Port's requested resource */ ++ uint16_t maxFrameLength; /**< IN. Port's max frame length. */ ++ uint16_t liodnBase; /**< IN. Irrelevant for P4080 rev 1. ++ LIODN base for this port, to be ++ used together with LIODN offset. */ ++ t_FmPhysAddr fmMuramPhysBaseAddr;/**< OUT. FM-MURAM physical address*/ ++} t_FmInterModulePortInitParams; ++ ++/**************************************************************************//** ++ @Description Structure for port-FM communication during FM_PORT_Free. ++*//***************************************************************************/ ++typedef struct t_FmInterModulePortFreeParams { ++ uint8_t hardwarePortId; /**< IN. port Id */ ++ e_FmPortType portType; /**< IN. Port type */ ++ uint8_t deqPipelineDepth; /**< IN. Port's requested resource */ ++} t_FmInterModulePortFreeParams; ++ ++/**************************************************************************//** ++ @Function FmGetPcdPrsBaseAddr ++ ++ @Description Get the base address of the Parser from the FM module ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return Base address. ++*//***************************************************************************/ ++uintptr_t FmGetPcdPrsBaseAddr(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FmGetPcdKgBaseAddr ++ ++ @Description Get the base address of the Keygen from the FM module ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return Base address. ++*//***************************************************************************/ ++uintptr_t FmGetPcdKgBaseAddr(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FmGetPcdPlcrBaseAddr ++ ++ @Description Get the base address of the Policer from the FM module ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return Base address. ++*//***************************************************************************/ ++uintptr_t FmGetPcdPlcrBaseAddr(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FmGetMuramHandle ++ ++ @Description Get the handle of the MURAM from the FM module ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return MURAM module handle. ++*//***************************************************************************/ ++t_Handle FmGetMuramHandle(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FmGetPhysicalMuramBase ++ ++ @Description Get the physical base address of the MURAM from the FM module ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] fmPhysAddr Physical MURAM base ++ ++ @Return Physical base address. ++*//***************************************************************************/ ++void FmGetPhysicalMuramBase(t_Handle h_Fm, t_FmPhysAddr *fmPhysAddr); ++ ++/**************************************************************************//** ++ @Function FmGetTimeStampScale ++ ++ @Description Used internally by other modules in order to get the timeStamp ++ period as requested by the application. ++ ++ This function returns bit number that is incremented every 1 usec. ++ To calculate timestamp period in nsec, use ++ 1000 / (1 << FmGetTimeStampScale()). ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return Bit that counts 1 usec. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++uint32_t FmGetTimeStampScale(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FmResumeStalledPort ++ ++ @Description Used internally by FM port to release a stalled port. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] hardwarePortId HW port id. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FmResumeStalledPort(t_Handle h_Fm, uint8_t hardwarePortId); ++ ++/**************************************************************************//** ++ @Function FmIsPortStalled ++ ++ @Description Used internally by FM port to read the port's status. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] hardwarePortId HW port id. ++ @Param[in] p_IsStalled A pointer to the boolean port stalled state ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FmIsPortStalled(t_Handle h_Fm, uint8_t hardwarePortId, bool *p_IsStalled); ++ ++/**************************************************************************//** ++ @Function FmResetMac ++ ++ @Description Used by MAC driver to reset the MAC registers ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] type MAC type. ++ @Param[in] macId MAC id - according to type. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FmResetMac(t_Handle h_Fm, e_FmMacType type, uint8_t macId); ++ ++/**************************************************************************//** ++ @Function FmGetClockFreq ++ ++ @Description Used by MAC driver to get the FM clock frequency ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return clock-freq on success; 0 otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++uint16_t FmGetClockFreq(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FmGetMacClockFreq ++ ++ @Description Used by MAC driver to get the MAC clock frequency ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return clock-freq on success; 0 otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++uint16_t FmGetMacClockFreq(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FmGetId ++ ++ @Description Used by PCD driver to read rhe FM id ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++uint8_t FmGetId(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FmGetSetPortParams ++ ++ @Description Used by FM-PORT driver to pass and receive parameters between ++ PORT and FM modules. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in,out] p_PortParams A structure of FM Port parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FmGetSetPortParams(t_Handle h_Fm,t_FmInterModulePortInitParams *p_PortParams); ++ ++/**************************************************************************//** ++ @Function FmFreePortParams ++ ++ @Description Used by FM-PORT driver to free port's resources within the FM. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in,out] p_PortParams A structure of FM Port parameters. ++ ++ @Return None. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++void FmFreePortParams(t_Handle h_Fm,t_FmInterModulePortFreeParams *p_PortParams); ++ ++/**************************************************************************//** ++ @Function FmSetNumOfRiscsPerPort ++ ++ @Description Used by FM-PORT driver to pass parameter between ++ PORT and FM modules for working with number of RISC.. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] hardwarePortId hardware port Id. ++ @Param[in] numOfFmanCtrls number of Fman Controllers. ++ @Param[in] orFmanCtrl Fman Controller for order restoration. ++ ++ @Return None. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FmSetNumOfRiscsPerPort(t_Handle h_Fm, uint8_t hardwarePortId, uint8_t numOfFmanCtrls, t_FmFmanCtrl orFmanCtrl); ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++/**************************************************************************//* ++ @Function FmDumpPortRegs ++ ++ @Description Dumps FM port registers which are part of FM common registers ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] hardwarePortId HW port id. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only FM_Init(). ++*//***************************************************************************/ ++t_Error FmDumpPortRegs(t_Handle h_Fm,uint8_t hardwarePortId); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++void FmRegisterPcd(t_Handle h_Fm, t_Handle h_FmPcd); ++void FmUnregisterPcd(t_Handle h_Fm); ++t_Handle FmGetPcdHandle(t_Handle h_Fm); ++t_Error FmEnableRamsEcc(t_Handle h_Fm); ++t_Error FmDisableRamsEcc(t_Handle h_Fm); ++void FmGetRevision(t_Handle h_Fm, t_FmRevisionInfo *p_FmRevisionInfo); ++t_Error FmAllocFmanCtrlEventReg(t_Handle h_Fm, uint8_t *p_EventId); ++void FmFreeFmanCtrlEventReg(t_Handle h_Fm, uint8_t eventId); ++void FmSetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, uint32_t enableEvents); ++uint32_t FmGetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId); ++void FmRegisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, void (*f_Isr) (t_Handle h_Fm, uint32_t event), t_Handle h_Arg); ++void FmUnregisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId); ++t_Error FmSetMacMaxFrame(t_Handle h_Fm, e_FmMacType type, uint8_t macId, uint16_t mtu); ++bool FmIsMaster(t_Handle h_Fm); ++uint8_t FmGetGuestId(t_Handle h_Fm); ++uint16_t FmGetTnumAgingPeriod(t_Handle h_Fm); ++t_Error FmSetPortPreFetchConfiguration(t_Handle h_Fm, uint8_t portNum, bool preFetchConfigured); ++t_Error FmGetPortPreFetchConfiguration(t_Handle h_Fm, uint8_t portNum, bool *p_PortConfigured, bool *p_PreFetchConfigured); ++ ++ ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++t_Error Fm10GTxEccWorkaround(t_Handle h_Fm, uint8_t macId); ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++ ++void FmMuramClear(t_Handle h_FmMuram); ++t_Error FmSetNumOfOpenDmas(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint8_t *p_NumOfOpenDmas, ++ uint8_t *p_NumOfExtraOpenDmas, ++ bool initialConfig); ++t_Error FmSetNumOfTasks(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint8_t *p_NumOfTasks, ++ uint8_t *p_NumOfExtraTasks, ++ bool initialConfig); ++t_Error FmSetSizeOfFifo(t_Handle h_Fm, ++ uint8_t hardwarePortId, ++ uint32_t *p_SizeOfFifo, ++ uint32_t *p_ExtraSizeOfFifo, ++ bool initialConfig); ++ ++t_Error FmSetCongestionGroupPFCpriority(t_Handle h_Fm, ++ uint32_t congestionGroupId, ++ uint8_t priorityBitMap); ++ ++#if (DPAA_VERSION >= 11) ++t_Error FmVSPAllocForPort(t_Handle h_Fm, ++ e_FmPortType portType, ++ uint8_t portId, ++ uint8_t numOfStorageProfiles); ++ ++t_Error FmVSPFreeForPort(t_Handle h_Fm, ++ e_FmPortType portType, ++ uint8_t portId); ++ ++t_Error FmVSPGetAbsoluteProfileId(t_Handle h_Fm, ++ e_FmPortType portType, ++ uint8_t portId, ++ uint16_t relativeProfile, ++ uint16_t *p_AbsoluteId); ++t_Error FmVSPCheckRelativeProfile(t_Handle h_Fm, ++ e_FmPortType portType, ++ uint8_t portId, ++ uint16_t relativeProfile); ++ ++uintptr_t FmGetVSPBaseAddr(t_Handle h_Fm); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ ++#endif /* __FM_COMMON_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc/fm_hc.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc/fm_hc.h +new file mode 100644 +index 0000000..492aa8a +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc/fm_hc.h +@@ -0,0 +1,93 @@ ++/* ++ * Copyright 2008-2012 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 __FM_HC_H ++#define __FM_HC_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "fsl_fman_kg.h" ++ ++#define __ERR_MODULE__ MODULE_FM_PCD ++ ++ ++typedef struct t_FmHcParams { ++ t_Handle h_Fm; ++ t_Handle h_FmPcd; ++ t_FmPcdHcParams params; ++} t_FmHcParams; ++ ++ ++t_Handle FmHcConfigAndInit(t_FmHcParams *p_FmHcParams); ++void FmHcFree(t_Handle h_FmHc); ++t_Error FmHcSetFramesDataMemory(t_Handle h_FmHc, ++ uint8_t memId); ++t_Error FmHcDumpRegs(t_Handle h_FmHc); ++ ++void FmHcTxConf(t_Handle h_FmHc, t_DpaaFD *p_Fd); ++ ++t_Error FmHcPcdKgSetScheme(t_Handle h_FmHc, ++ t_Handle h_Scheme, ++ struct fman_kg_scheme_regs *p_SchemeRegs, ++ bool updateCounter); ++t_Error FmHcPcdKgDeleteScheme(t_Handle h_FmHc, t_Handle h_Scheme); ++t_Error FmHcPcdCcCapwapTimeoutReassm(t_Handle h_FmHc, t_FmPcdCcCapwapReassmTimeoutParams *p_CcCapwapReassmTimeoutParams ); ++t_Error FmHcPcdCcIpFragScratchPollCmd(t_Handle h_FmHc, bool fill, t_FmPcdCcFragScratchPoolCmdParams *p_FmPcdCcFragScratchPoolCmdParams); ++t_Error FmHcPcdCcTimeoutReassm(t_Handle h_FmHc, t_FmPcdCcReassmTimeoutParams *p_CcReassmTimeoutParams, uint8_t *p_Result); ++t_Error FmHcPcdKgSetClsPlan(t_Handle h_FmHc, t_FmPcdKgInterModuleClsPlanSet *p_Set); ++t_Error FmHcPcdKgDeleteClsPlan(t_Handle h_FmHc, uint8_t clsPlanGrpId); ++ ++t_Error FmHcPcdKgSetSchemeCounter(t_Handle h_FmHc, t_Handle h_Scheme, uint32_t value); ++uint32_t FmHcPcdKgGetSchemeCounter(t_Handle h_FmHc, t_Handle h_Scheme); ++ ++t_Error FmHcPcdCcDoDynamicChange(t_Handle h_FmHc, uint32_t oldAdAddrOffset, uint32_t newAdAddrOffset); ++ ++t_Error FmHcPcdPlcrSetProfile(t_Handle h_FmHc, t_Handle h_Profile, t_FmPcdPlcrProfileRegs *p_PlcrRegs); ++t_Error FmHcPcdPlcrDeleteProfile(t_Handle h_FmHc, t_Handle h_Profile); ++ ++t_Error FmHcPcdPlcrSetProfileCounter(t_Handle h_FmHc, t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter, uint32_t value); ++uint32_t FmHcPcdPlcrGetProfileCounter(t_Handle h_FmHc, t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter); ++ ++t_Error FmHcKgWriteSp(t_Handle h_FmHc, uint8_t hardwarePortId, uint32_t spReg, bool add); ++t_Error FmHcKgWriteCpp(t_Handle h_FmHc, uint8_t hardwarePortId, uint32_t cppReg); ++ ++t_Error FmHcPcdKgCcGetSetParams(t_Handle h_FmHc, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value); ++t_Error FmHcPcdPlcrCcGetSetParams(t_Handle h_FmHc,uint16_t absoluteProfileId, uint32_t requiredAction); ++ ++t_Error FmHcPcdSync(t_Handle h_FmHc); ++t_Handle FmHcGetPort(t_Handle h_FmHc); ++ ++ ++ ++ ++#endif /* __FM_HC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc/fm_sp_common.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc/fm_sp_common.h +new file mode 100644 +index 0000000..f9dd384 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc/fm_sp_common.h +@@ -0,0 +1,117 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_sp_common.h ++ ++ @Description FM SP ... ++*//***************************************************************************/ ++#ifndef __FM_SP_COMMON_H ++#define __FM_SP_COMMON_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++ ++#include "fm_ext.h" ++#include "fm_pcd_ext.h" ++#include "fsl_fman.h" ++ ++/**************************************************************************//** ++ @Description defaults ++*//***************************************************************************/ ++#define DEFAULT_FM_SP_bufferPrefixContent_privDataSize 0 ++#define DEFAULT_FM_SP_bufferPrefixContent_passPrsResult FALSE ++#define DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp FALSE ++#define DEFAULT_FM_SP_bufferPrefixContent_allOtherPCDInfo FALSE ++#define DEFAULT_FM_SP_bufferPrefixContent_dataAlign 64 ++ ++/**************************************************************************//** ++ @Description structure for defining internal context copying ++*//***************************************************************************/ ++typedef struct ++{ ++ uint16_t extBufOffset; /**< Offset in External buffer to which internal ++ context is copied to (Rx) or taken from (Tx, Op). */ ++ uint8_t intContextOffset; /**< Offset within internal context to copy from ++ (Rx) or to copy to (Tx, Op). */ ++ uint16_t size; /**< Internal offset size to be copied */ ++} t_FmSpIntContextDataCopy; ++ ++/**************************************************************************//** ++ @Description struct for defining external buffer margins ++*//***************************************************************************/ ++typedef struct { ++ uint16_t startMargins; /**< Number of bytes to be left at the beginning ++ of the external buffer (must be divisible by 16) */ ++ uint16_t endMargins; /**< number of bytes to be left at the end ++ of the external buffer(must be divisible by 16) */ ++} t_FmSpBufMargins; ++ ++typedef struct { ++ uint32_t dataOffset; ++ uint32_t prsResultOffset; ++ uint32_t timeStampOffset; ++ uint32_t hashResultOffset; ++ uint32_t pcdInfoOffset; ++ uint32_t manipOffset; ++} t_FmSpBufferOffsets; ++ ++ ++t_Error FmSpBuildBufferStructure(t_FmSpIntContextDataCopy *p_FmPortIntContextDataCopy, ++ t_FmBufferPrefixContent *p_BufferPrefixContent, ++ t_FmSpBufMargins *p_FmPortBufMargins, ++ t_FmSpBufferOffsets *p_FmPortBufferOffsets, ++ uint8_t *internalBufferOffset); ++ ++t_Error FmSpCheckIntContextParams(t_FmSpIntContextDataCopy *p_FmSpIntContextDataCopy); ++t_Error FmSpCheckBufPoolsParams(t_FmExtPools *p_FmExtPools, ++ t_FmBackupBmPools *p_FmBackupBmPools, ++ t_FmBufPoolDepletion *p_FmBufPoolDepletion); ++t_Error FmSpCheckBufMargins(t_FmSpBufMargins *p_FmSpBufMargins); ++void FmSpSetBufPoolsInAscOrderOfBufSizes(t_FmExtPools *p_FmExtPools, uint8_t *orderedArray, uint16_t *sizesArray); ++ ++t_Error FmPcdSpAllocProfiles(t_Handle h_FmPcd, ++ uint8_t hardwarePortId, ++ uint16_t numOfStorageProfiles, ++ uint16_t *base, ++ uint8_t *log2Num); ++t_Error FmPcdSpGetAbsoluteProfileId(t_Handle h_FmPcd, ++ t_Handle h_FmPort, ++ uint16_t relativeProfile, ++ uint16_t *p_AbsoluteId); ++void SpInvalidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId); ++void SpValidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId); ++ ++ ++#endif /* __FM_SP_COMMON_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/etc/Makefile b/drivers/net/ethernet/freescale/sdk_fman/etc/Makefile +new file mode 100644 +index 0000000..d03a519 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/etc/Makefile +@@ -0,0 +1,12 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++ccflags-y += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++ ++include $(srctree)/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk ++ ++obj-y += fsl-ncsw-etc.o ++ ++fsl-ncsw-etc-objs := mm.o memcpy.o sprint.o list.o error.o +diff --git a/drivers/net/ethernet/freescale/sdk_fman/etc/error.c b/drivers/net/ethernet/freescale/sdk_fman/etc/error.c +new file mode 100644 +index 0000000..fead7f5 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/etc/error.c +@@ -0,0 +1,95 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/* ++ ++ @File error.c ++ ++ @Description General errors and events reporting utilities. ++*//***************************************************************************/ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++#include "error_ext.h" ++ ++ ++const char *dbgLevelStrings[] = ++{ ++ "CRITICAL" ++ ,"MAJOR" ++ ,"MINOR" ++ ,"WARNING" ++ ,"INFO" ++ ,"TRACE" ++}; ++ ++ ++char * ErrTypeStrings (e_ErrorType err) ++{ ++ switch (err) ++ { ++ case (E_OK): return "OK"; ++ case (E_WRITE_FAILED): return "Write Access Failed"; ++ case (E_NO_DEVICE): return "No Device"; ++ case (E_NOT_AVAILABLE): return "Resource Is Unavailable"; ++ case (E_NO_MEMORY): return "Memory Allocation Failed"; ++ case (E_INVALID_ADDRESS): return "Invalid Address"; ++ case (E_BUSY): return "Resource Is Busy"; ++ case (E_ALREADY_EXISTS): return "Resource Already Exists"; ++ case (E_INVALID_OPERATION): return "Invalid Operation"; ++ case (E_INVALID_VALUE): return "Invalid Value"; ++ case (E_NOT_IN_RANGE): return "Value Out Of Range"; ++ case (E_NOT_SUPPORTED): return "Unsupported Operation"; ++ case (E_INVALID_STATE): return "Invalid State"; ++ case (E_INVALID_HANDLE): return "Invalid Handle"; ++ case (E_INVALID_ID): return "Invalid ID"; ++ case (E_NULL_POINTER): return "Unexpected NULL Pointer"; ++ case (E_INVALID_SELECTION): return "Invalid Selection"; ++ case (E_INVALID_COMM_MODE): return "Invalid Communication Mode"; ++ case (E_INVALID_MEMORY_TYPE): return "Invalid Memory Type"; ++ case (E_INVALID_CLOCK): return "Invalid Clock"; ++ case (E_CONFLICT): return "Conflict In Settings"; ++ case (E_NOT_ALIGNED): return "Incorrect Alignment"; ++ case (E_NOT_FOUND): return "Resource Not Found"; ++ case (E_FULL): return "Resource Is Full"; ++ case (E_EMPTY): return "Resource Is Empty"; ++ case (E_ALREADY_FREE): return "Resource Already Free"; ++ case (E_READ_FAILED): return "Read Access Failed"; ++ case (E_INVALID_FRAME): return "Invalid Frame"; ++ case (E_SEND_FAILED): return "Send Operation Failed"; ++ case (E_RECEIVE_FAILED): return "Receive Operation Failed"; ++ case (E_TIMEOUT): return "Operation Timed Out"; ++ default: ++ break; ++ } ++ return NULL; ++} ++#endif /* (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/etc/list.c b/drivers/net/ethernet/freescale/sdk_fman/etc/list.c +new file mode 100644 +index 0000000..2d044be +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/etc/list.c +@@ -0,0 +1,71 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/**************************************************************************//** ++ ++ @File list.c ++ ++ @Description Implementation of list. ++*//***************************************************************************/ ++#include "std_ext.h" ++#include "list_ext.h" ++ ++ ++void LIST_Append(t_List *p_NewList, t_List *p_Head) ++{ ++ t_List *p_First = LIST_FIRST(p_NewList); ++ ++ if (p_First != p_NewList) ++ { ++ t_List *p_Last = LIST_LAST(p_NewList); ++ t_List *p_Cur = LIST_NEXT(p_Head); ++ ++ LIST_PREV(p_First) = p_Head; ++ LIST_FIRST(p_Head) = p_First; ++ LIST_NEXT(p_Last) = p_Cur; ++ LIST_LAST(p_Cur) = p_Last; ++ } ++} ++ ++ ++int LIST_NumOfObjs(t_List *p_List) ++{ ++ t_List *p_Tmp; ++ int numOfObjs = 0; ++ ++ if (!LIST_IsEmpty(p_List)) ++ LIST_FOR_EACH(p_Tmp, p_List) ++ numOfObjs++; ++ ++ return numOfObjs; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/etc/memcpy.c b/drivers/net/ethernet/freescale/sdk_fman/etc/memcpy.c +new file mode 100644 +index 0000000..02973e5 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/etc/memcpy.c +@@ -0,0 +1,601 @@ ++/* ++ * Copyright 2008-2012 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 "std_ext.h" ++#include "xx_ext.h" ++#include "memcpy_ext.h" ++ ++ ++void * MemCpy32(void* pDst,void* pSrc, uint32_t size) ++{ ++ uint32_t leftAlign; ++ uint32_t rightAlign; ++ uint32_t lastWord; ++ uint32_t currWord; ++ uint32_t *p_Src32; ++ uint32_t *p_Dst32; ++ uint8_t *p_Src8; ++ uint8_t *p_Dst8; ++ ++ p_Src8 = (uint8_t*)(pSrc); ++ p_Dst8 = (uint8_t*)(pDst); ++ /* first copy byte by byte till the source first alignment ++ * this step is necessary to ensure we do not even try to access ++ * data which is before the source buffer, hence it is not ours. ++ */ ++ while((PTR_TO_UINT(p_Src8) & 3) && size) /* (pSrc mod 4) > 0 and size > 0 */ ++ { ++ *p_Dst8++ = *p_Src8++; ++ size--; ++ } ++ ++ /* align destination (possibly disaligning source)*/ ++ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */ ++ { ++ *p_Dst8++ = *p_Src8++; ++ size--; ++ } ++ ++ /* dest is aligned and source is not necessarily aligned */ ++ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 3) << 3); /* leftAlign = (pSrc mod 4)*8 */ ++ rightAlign = 32 - leftAlign; ++ ++ ++ if (leftAlign == 0) ++ { ++ /* source is also aligned */ ++ p_Src32 = (uint32_t*)(p_Src8); ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ while (size >> 2) /* size >= 4 */ ++ { ++ *p_Dst32++ = *p_Src32++; ++ size -= 4; ++ } ++ p_Src8 = (uint8_t*)(p_Src32); ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ } ++ else ++ { ++ /* source is not aligned (destination is aligned)*/ ++ p_Src32 = (uint32_t*)(p_Src8 - (leftAlign >> 3)); ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ lastWord = *p_Src32++; ++ while(size >> 3) /* size >= 8 */ ++ { ++ currWord = *p_Src32; ++ *p_Dst32 = (lastWord << leftAlign) | (currWord >> rightAlign); ++ lastWord = currWord; ++ p_Src32++; ++ p_Dst32++; ++ size -= 4; ++ } ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ p_Src8 = (uint8_t*)(p_Src32) - 4 + (leftAlign >> 3); ++ } ++ ++ /* complete the left overs */ ++ while (size--) ++ *p_Dst8++ = *p_Src8++; ++ ++ return pDst; ++} ++ ++void * IO2IOCpy32(void* pDst,void* pSrc, uint32_t size) ++{ ++ uint32_t leftAlign; ++ uint32_t rightAlign; ++ uint32_t lastWord; ++ uint32_t currWord; ++ uint32_t *p_Src32; ++ uint32_t *p_Dst32; ++ uint8_t *p_Src8; ++ uint8_t *p_Dst8; ++ ++ p_Src8 = (uint8_t*)(pSrc); ++ p_Dst8 = (uint8_t*)(pDst); ++ /* first copy byte by byte till the source first alignment ++ * this step is necessary to ensure we do not even try to access ++ * data which is before the source buffer, hence it is not ours. ++ */ ++ while((PTR_TO_UINT(p_Src8) & 3) && size) /* (pSrc mod 4) > 0 and size > 0 */ ++ { ++ WRITE_UINT8(*p_Dst8, GET_UINT8(*p_Src8)); ++ p_Dst8++;p_Src8++; ++ size--; ++ } ++ ++ /* align destination (possibly disaligning source)*/ ++ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */ ++ { ++ WRITE_UINT8(*p_Dst8, GET_UINT8(*p_Src8)); ++ p_Dst8++;p_Src8++; ++ size--; ++ } ++ ++ /* dest is aligned and source is not necessarily aligned */ ++ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 3) << 3); /* leftAlign = (pSrc mod 4)*8 */ ++ rightAlign = 32 - leftAlign; ++ ++ if (leftAlign == 0) ++ { ++ /* source is also aligned */ ++ p_Src32 = (uint32_t*)(p_Src8); ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ while (size >> 2) /* size >= 4 */ ++ { ++ WRITE_UINT32(*p_Dst32, GET_UINT32(*p_Src32)); ++ p_Dst32++;p_Src32++; ++ size -= 4; ++ } ++ p_Src8 = (uint8_t*)(p_Src32); ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ } ++ else ++ { ++ /* source is not aligned (destination is aligned)*/ ++ p_Src32 = (uint32_t*)(p_Src8 - (leftAlign >> 3)); ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ lastWord = GET_UINT32(*p_Src32); ++ p_Src32++; ++ while(size >> 3) /* size >= 8 */ ++ { ++ currWord = GET_UINT32(*p_Src32); ++ WRITE_UINT32(*p_Dst32, (lastWord << leftAlign) | (currWord >> rightAlign)); ++ lastWord = currWord; ++ p_Src32++;p_Dst32++; ++ size -= 4; ++ } ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ p_Src8 = (uint8_t*)(p_Src32) - 4 + (leftAlign >> 3); ++ } ++ ++ /* complete the left overs */ ++ while (size--) ++ { ++ WRITE_UINT8(*p_Dst8, GET_UINT8(*p_Src8)); ++ p_Dst8++;p_Src8++; ++ } ++ ++ return pDst; ++} ++ ++void * Mem2IOCpy32(void* pDst,void* pSrc, uint32_t size) ++{ ++ uint32_t leftAlign; ++ uint32_t rightAlign; ++ uint32_t lastWord; ++ uint32_t currWord; ++ uint32_t *p_Src32; ++ uint32_t *p_Dst32; ++ uint8_t *p_Src8; ++ uint8_t *p_Dst8; ++ ++ p_Src8 = (uint8_t*)(pSrc); ++ p_Dst8 = (uint8_t*)(pDst); ++ /* first copy byte by byte till the source first alignment ++ * this step is necessary to ensure we do not even try to access ++ * data which is before the source buffer, hence it is not ours. ++ */ ++ while((PTR_TO_UINT(p_Src8) & 3) && size) /* (pSrc mod 4) > 0 and size > 0 */ ++ { ++ WRITE_UINT8(*p_Dst8, *p_Src8); ++ p_Dst8++;p_Src8++; ++ size--; ++ } ++ ++ /* align destination (possibly disaligning source)*/ ++ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */ ++ { ++ WRITE_UINT8(*p_Dst8, *p_Src8); ++ p_Dst8++;p_Src8++; ++ size--; ++ } ++ ++ /* dest is aligned and source is not necessarily aligned */ ++ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 3) << 3); /* leftAlign = (pSrc mod 4)*8 */ ++ rightAlign = 32 - leftAlign; ++ ++ if (leftAlign == 0) ++ { ++ /* source is also aligned */ ++ p_Src32 = (uint32_t*)(p_Src8); ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ while (size >> 2) /* size >= 4 */ ++ { ++ WRITE_UINT32(*p_Dst32, *p_Src32); ++ p_Dst32++;p_Src32++; ++ size -= 4; ++ } ++ p_Src8 = (uint8_t*)(p_Src32); ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ } ++ else ++ { ++ /* source is not aligned (destination is aligned)*/ ++ p_Src32 = (uint32_t*)(p_Src8 - (leftAlign >> 3)); ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ lastWord = *p_Src32++; ++ while(size >> 3) /* size >= 8 */ ++ { ++ currWord = *p_Src32; ++ WRITE_UINT32(*p_Dst32, (lastWord << leftAlign) | (currWord >> rightAlign)); ++ lastWord = currWord; ++ p_Src32++;p_Dst32++; ++ size -= 4; ++ } ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ p_Src8 = (uint8_t*)(p_Src32) - 4 + (leftAlign >> 3); ++ } ++ ++ /* complete the left overs */ ++ while (size--) ++ { ++ WRITE_UINT8(*p_Dst8, *p_Src8); ++ p_Dst8++;p_Src8++; ++ } ++ ++ return pDst; ++} ++ ++void * IO2MemCpy32(void* pDst,void* pSrc, uint32_t size) ++{ ++ uint32_t leftAlign; ++ uint32_t rightAlign; ++ uint32_t lastWord; ++ uint32_t currWord; ++ uint32_t *p_Src32; ++ uint32_t *p_Dst32; ++ uint8_t *p_Src8; ++ uint8_t *p_Dst8; ++ ++ p_Src8 = (uint8_t*)(pSrc); ++ p_Dst8 = (uint8_t*)(pDst); ++ /* first copy byte by byte till the source first alignment ++ * this step is necessary to ensure we do not even try to access ++ * data which is before the source buffer, hence it is not ours. ++ */ ++ while((PTR_TO_UINT(p_Src8) & 3) && size) /* (pSrc mod 4) > 0 and size > 0 */ ++ { ++ *p_Dst8 = GET_UINT8(*p_Src8); ++ p_Dst8++;p_Src8++; ++ size--; ++ } ++ ++ /* align destination (possibly disaligning source)*/ ++ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */ ++ { ++ *p_Dst8 = GET_UINT8(*p_Src8); ++ p_Dst8++;p_Src8++; ++ size--; ++ } ++ ++ /* dest is aligned and source is not necessarily aligned */ ++ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 3) << 3); /* leftAlign = (pSrc mod 4)*8 */ ++ rightAlign = 32 - leftAlign; ++ ++ if (leftAlign == 0) ++ { ++ /* source is also aligned */ ++ p_Src32 = (uint32_t*)(p_Src8); ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ while (size >> 2) /* size >= 4 */ ++ { ++ *p_Dst32 = GET_UINT32(*p_Src32); ++ p_Dst32++;p_Src32++; ++ size -= 4; ++ } ++ p_Src8 = (uint8_t*)(p_Src32); ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ } ++ else ++ { ++ /* source is not aligned (destination is aligned)*/ ++ p_Src32 = (uint32_t*)(p_Src8 - (leftAlign >> 3)); ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ lastWord = GET_UINT32(*p_Src32); ++ p_Src32++; ++ while(size >> 3) /* size >= 8 */ ++ { ++ currWord = GET_UINT32(*p_Src32); ++ *p_Dst32 = (lastWord << leftAlign) | (currWord >> rightAlign); ++ lastWord = currWord; ++ p_Src32++;p_Dst32++; ++ size -= 4; ++ } ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ p_Src8 = (uint8_t*)(p_Src32) - 4 + (leftAlign >> 3); ++ } ++ ++ /* complete the left overs */ ++ while (size--) ++ { ++ *p_Dst8 = GET_UINT8(*p_Src8); ++ p_Dst8++;p_Src8++; ++ } ++ ++ return pDst; ++} ++ ++void * MemCpy64(void* pDst,void* pSrc, uint32_t size) ++{ ++ uint32_t leftAlign; ++ uint32_t rightAlign; ++ uint64_t lastWord; ++ uint64_t currWord; ++ uint64_t *pSrc64; ++ uint64_t *pDst64; ++ uint8_t *p_Src8; ++ uint8_t *p_Dst8; ++ ++ p_Src8 = (uint8_t*)(pSrc); ++ p_Dst8 = (uint8_t*)(pDst); ++ /* first copy byte by byte till the source first alignment ++ * this step is necessarily to ensure we do not even try to access ++ * data which is before the source buffer, hence it is not ours. ++ */ ++ while((PTR_TO_UINT(p_Src8) & 7) && size) /* (pSrc mod 8) > 0 and size > 0 */ ++ { ++ *p_Dst8++ = *p_Src8++; ++ size--; ++ } ++ ++ /* align destination (possibly disaligning source)*/ ++ while((PTR_TO_UINT(p_Dst8) & 7) && size) /* (pDst mod 8) > 0 and size > 0 */ ++ { ++ *p_Dst8++ = *p_Src8++; ++ size--; ++ } ++ ++ /* dest is aligned and source is not necessarily aligned */ ++ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 7) << 3); /* leftAlign = (pSrc mod 8)*8 */ ++ rightAlign = 64 - leftAlign; ++ ++ ++ if (leftAlign == 0) ++ { ++ /* source is also aligned */ ++ pSrc64 = (uint64_t*)(p_Src8); ++ pDst64 = (uint64_t*)(p_Dst8); ++ while (size >> 3) /* size >= 8 */ ++ { ++ *pDst64++ = *pSrc64++; ++ size -= 8; ++ } ++ p_Src8 = (uint8_t*)(pSrc64); ++ p_Dst8 = (uint8_t*)(pDst64); ++ } ++ else ++ { ++ /* source is not aligned (destination is aligned)*/ ++ pSrc64 = (uint64_t*)(p_Src8 - (leftAlign >> 3)); ++ pDst64 = (uint64_t*)(p_Dst8); ++ lastWord = *pSrc64++; ++ while(size >> 4) /* size >= 16 */ ++ { ++ currWord = *pSrc64; ++ *pDst64 = (lastWord << leftAlign) | (currWord >> rightAlign); ++ lastWord = currWord; ++ pSrc64++; ++ pDst64++; ++ size -= 8; ++ } ++ p_Dst8 = (uint8_t*)(pDst64); ++ p_Src8 = (uint8_t*)(pSrc64) - 8 + (leftAlign >> 3); ++ } ++ ++ /* complete the left overs */ ++ while (size--) ++ *p_Dst8++ = *p_Src8++; ++ ++ return pDst; ++} ++ ++void * MemSet32(void* pDst, uint8_t val, uint32_t size) ++{ ++ uint32_t val32; ++ uint32_t *p_Dst32; ++ uint8_t *p_Dst8; ++ ++ p_Dst8 = (uint8_t*)(pDst); ++ ++ /* generate four 8-bit val's in 32-bit container */ ++ val32 = (uint32_t) val; ++ val32 |= (val32 << 8); ++ val32 |= (val32 << 16); ++ ++ /* align destination to 32 */ ++ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */ ++ { ++ *p_Dst8++ = val; ++ size--; ++ } ++ ++ /* 32-bit chunks */ ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ while (size >> 2) /* size >= 4 */ ++ { ++ *p_Dst32++ = val32; ++ size -= 4; ++ } ++ ++ /* complete the leftovers */ ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ while (size--) ++ *p_Dst8++ = val; ++ ++ return pDst; ++} ++ ++void * IOMemSet32(void* pDst, uint8_t val, uint32_t size) ++{ ++ uint32_t val32; ++ uint32_t *p_Dst32; ++ uint8_t *p_Dst8; ++ ++ p_Dst8 = (uint8_t*)(pDst); ++ ++ /* generate four 8-bit val's in 32-bit container */ ++ val32 = (uint32_t) val; ++ val32 |= (val32 << 8); ++ val32 |= (val32 << 16); ++ ++ /* align destination to 32 */ ++ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */ ++ { ++ WRITE_UINT8(*p_Dst8, val); ++ p_Dst8++; ++ size--; ++ } ++ ++ /* 32-bit chunks */ ++ p_Dst32 = (uint32_t*)(p_Dst8); ++ while (size >> 2) /* size >= 4 */ ++ { ++ WRITE_UINT32(*p_Dst32, val32); ++ p_Dst32++; ++ size -= 4; ++ } ++ ++ /* complete the leftovers */ ++ p_Dst8 = (uint8_t*)(p_Dst32); ++ while (size--) ++ { ++ WRITE_UINT8(*p_Dst8, val); ++ p_Dst8++; ++ } ++ ++ return pDst; ++} ++ ++void * MemSet64(void* pDst, uint8_t val, uint32_t size) ++{ ++ uint64_t val64; ++ uint64_t *pDst64; ++ uint8_t *p_Dst8; ++ ++ p_Dst8 = (uint8_t*)(pDst); ++ ++ /* generate four 8-bit val's in 32-bit container */ ++ val64 = (uint64_t) val; ++ val64 |= (val64 << 8); ++ val64 |= (val64 << 16); ++ val64 |= (val64 << 24); ++ val64 |= (val64 << 32); ++ ++ /* align destination to 64 */ ++ while((PTR_TO_UINT(p_Dst8) & 7) && size) /* (pDst mod 8) > 0 and size > 0 */ ++ { ++ *p_Dst8++ = val; ++ size--; ++ } ++ ++ /* 64-bit chunks */ ++ pDst64 = (uint64_t*)(p_Dst8); ++ while (size >> 4) /* size >= 8 */ ++ { ++ *pDst64++ = val64; ++ size -= 8; ++ } ++ ++ /* complete the leftovers */ ++ p_Dst8 = (uint8_t*)(pDst64); ++ while (size--) ++ *p_Dst8++ = val; ++ ++ return pDst; ++} ++ ++void MemDisp(uint8_t *p, int size) ++{ ++ uint32_t space = (uint32_t)(PTR_TO_UINT(p) & 0x3); ++ uint8_t *p_Limit; ++ ++ if (space) ++ { ++ p_Limit = (p - space + 4); ++ ++ XX_Print("0x%08X: ", (p - space)); ++ ++ while (space--) ++ { ++ XX_Print("--"); ++ } ++ while (size && (p < p_Limit)) ++ { ++ XX_Print("%02x", *(uint8_t*)p); ++ size--; ++ p++; ++ } ++ ++ XX_Print(" "); ++ p_Limit += 12; ++ ++ while ((size > 3) && (p < p_Limit)) ++ { ++ XX_Print("%08x ", *(uint32_t*)p); ++ size -= 4; ++ p += 4; ++ } ++ XX_Print("\r\n"); ++ } ++ ++ while (size > 15) ++ { ++ XX_Print("0x%08X: %08x %08x %08x %08x\r\n", ++ p, *(uint32_t *)p, *(uint32_t *)(p + 4), ++ *(uint32_t *)(p + 8), *(uint32_t *)(p + 12)); ++ size -= 16; ++ p += 16; ++ } ++ ++ if (size) ++ { ++ XX_Print("0x%08X: ", p); ++ ++ while (size > 3) ++ { ++ XX_Print("%08x ", *(uint32_t *)p); ++ size -= 4; ++ p += 4; ++ } ++ while (size) ++ { ++ XX_Print("%02x", *(uint8_t *)p); ++ size--; ++ p++; ++ } ++ ++ XX_Print("\r\n"); ++ } ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/etc/mm.c b/drivers/net/ethernet/freescale/sdk_fman/etc/mm.c +new file mode 100644 +index 0000000..9fcc46e +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/etc/mm.c +@@ -0,0 +1,1155 @@ ++/* ++ * Copyright 2008-2012 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 "string_ext.h" ++#include "error_ext.h" ++#include "std_ext.h" ++#include "part_ext.h" ++#include "xx_ext.h" ++ ++#include "mm.h" ++ ++ ++ ++ ++/********************************************************************** ++ * MM internal routines set * ++ **********************************************************************/ ++ ++/**************************************************************** ++ * Routine: CreateBusyBlock ++ * ++ * Description: ++ * Initializes a new busy block of "size" bytes and started ++ * rom "base" address. Each busy block has a name that ++ * specified the purpose of the memory allocation. ++ * ++ * Arguments: ++ * base - base address of the busy block ++ * size - size of the busy block ++ * name - name that specified the busy block ++ * ++ * Return value: ++ * A pointer to new created structure returned on success; ++ * Otherwise, NULL. ++ ****************************************************************/ ++static t_BusyBlock * CreateBusyBlock(uint64_t base, uint64_t size, char *name) ++{ ++ t_BusyBlock *p_BusyBlock; ++ uint32_t n; ++ ++ p_BusyBlock = (t_BusyBlock *)XX_Malloc(sizeof(t_BusyBlock)); ++ if ( !p_BusyBlock ) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ return NULL; ++ } ++ ++ p_BusyBlock->base = base; ++ p_BusyBlock->end = base + size; ++ ++ n = strlen(name); ++ if (n >= MM_MAX_NAME_LEN) ++ n = MM_MAX_NAME_LEN - 1; ++ strncpy(p_BusyBlock->name, name, MM_MAX_NAME_LEN-1); ++ p_BusyBlock->name[n] = '\0'; ++ p_BusyBlock->p_Next = 0; ++ ++ return p_BusyBlock; ++} ++ ++/**************************************************************** ++ * Routine: CreateNewBlock ++ * ++ * Description: ++ * Initializes a new memory block of "size" bytes and started ++ * from "base" address. ++ * ++ * Arguments: ++ * base - base address of the memory block ++ * size - size of the memory block ++ * ++ * Return value: ++ * A pointer to new created structure returned on success; ++ * Otherwise, NULL. ++ ****************************************************************/ ++static t_MemBlock * CreateNewBlock(uint64_t base, uint64_t size) ++{ ++ t_MemBlock *p_MemBlock; ++ ++ p_MemBlock = (t_MemBlock *)XX_Malloc(sizeof(t_MemBlock)); ++ if ( !p_MemBlock ) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ return NULL; ++ } ++ ++ p_MemBlock->base = base; ++ p_MemBlock->end = base+size; ++ p_MemBlock->p_Next = 0; ++ ++ return p_MemBlock; ++} ++ ++/**************************************************************** ++ * Routine: CreateFreeBlock ++ * ++ * Description: ++ * Initializes a new free block of of "size" bytes and ++ * started from "base" address. ++ * ++ * Arguments: ++ * base - base address of the free block ++ * size - size of the free block ++ * ++ * Return value: ++ * A pointer to new created structure returned on success; ++ * Otherwise, NULL. ++ ****************************************************************/ ++static t_FreeBlock * CreateFreeBlock(uint64_t base, uint64_t size) ++{ ++ t_FreeBlock *p_FreeBlock; ++ ++ p_FreeBlock = (t_FreeBlock *)XX_Malloc(sizeof(t_FreeBlock)); ++ if ( !p_FreeBlock ) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ return NULL; ++ } ++ ++ p_FreeBlock->base = base; ++ p_FreeBlock->end = base + size; ++ p_FreeBlock->p_Next = 0; ++ ++ return p_FreeBlock; ++} ++ ++/**************************************************************** ++ * Routine: AddFree ++ * ++ * Description: ++ * Adds a new free block to the free lists. It updates each ++ * free list to include a new free block. ++ * Note, that all free block in each free list are ordered ++ * by their base address. ++ * ++ * Arguments: ++ * p_MM - pointer to the MM object ++ * base - base address of a given free block ++ * end - end address of a given free block ++ * ++ * Return value: ++ * ++ * ++ ****************************************************************/ ++static t_Error AddFree(t_MM *p_MM, uint64_t base, uint64_t end) ++{ ++ t_FreeBlock *p_PrevB, *p_CurrB, *p_NewB; ++ uint64_t alignment; ++ uint64_t alignBase; ++ int i; ++ ++ /* Updates free lists to include a just released block */ ++ for (i=0; i <= MM_MAX_ALIGNMENT; i++) ++ { ++ p_PrevB = p_NewB = 0; ++ p_CurrB = p_MM->freeBlocks[i]; ++ ++ alignment = (uint64_t)(0x1 << i); ++ alignBase = MAKE_ALIGNED(base, alignment); ++ ++ /* Goes to the next free list if there is no block to free */ ++ if (alignBase >= end) ++ continue; ++ ++ /* Looks for a free block that should be updated */ ++ while ( p_CurrB ) ++ { ++ if ( alignBase <= p_CurrB->end ) ++ { ++ if ( end > p_CurrB->end ) ++ { ++ t_FreeBlock *p_NextB; ++ while ( p_CurrB->p_Next && end > p_CurrB->p_Next->end ) ++ { ++ p_NextB = p_CurrB->p_Next; ++ p_CurrB->p_Next = p_CurrB->p_Next->p_Next; ++ XX_Free(p_NextB); ++ } ++ ++ p_NextB = p_CurrB->p_Next; ++ if ( !p_NextB || (p_NextB && end < p_NextB->base) ) ++ { ++ p_CurrB->end = end; ++ } ++ else ++ { ++ p_CurrB->end = p_NextB->end; ++ p_CurrB->p_Next = p_NextB->p_Next; ++ XX_Free(p_NextB); ++ } ++ } ++ else if ( (end < p_CurrB->base) && ((end-alignBase) >= alignment) ) ++ { ++ if ((p_NewB = CreateFreeBlock(alignBase, end-alignBase)) == NULL) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ ++ p_NewB->p_Next = p_CurrB; ++ if (p_PrevB) ++ p_PrevB->p_Next = p_NewB; ++ else ++ p_MM->freeBlocks[i] = p_NewB; ++ break; ++ } ++ ++ if ((alignBase < p_CurrB->base) && (end >= p_CurrB->base)) ++ { ++ p_CurrB->base = alignBase; ++ } ++ ++ /* if size of the free block is less then alignment ++ * deletes that free block from the free list. */ ++ if ( (p_CurrB->end - p_CurrB->base) < alignment) ++ { ++ if ( p_PrevB ) ++ p_PrevB->p_Next = p_CurrB->p_Next; ++ else ++ p_MM->freeBlocks[i] = p_CurrB->p_Next; ++ XX_Free(p_CurrB); ++ p_CurrB = NULL; ++ } ++ break; ++ } ++ else ++ { ++ p_PrevB = p_CurrB; ++ p_CurrB = p_CurrB->p_Next; ++ } ++ } ++ ++ /* If no free block found to be updated, insert a new free block ++ * to the end of the free list. ++ */ ++ if ( !p_CurrB && ((((uint64_t)(end-base)) & ((uint64_t)(alignment-1))) == 0) ) ++ { ++ if ((p_NewB = CreateFreeBlock(alignBase, end-base)) == NULL) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ ++ if (p_PrevB) ++ p_PrevB->p_Next = p_NewB; ++ else ++ p_MM->freeBlocks[i] = p_NewB; ++ } ++ ++ /* Update boundaries of the new free block */ ++ if ((alignment == 1) && !p_NewB) ++ { ++ if ( p_CurrB && base > p_CurrB->base ) ++ base = p_CurrB->base; ++ if ( p_CurrB && end < p_CurrB->end ) ++ end = p_CurrB->end; ++ } ++ } ++ ++ return (E_OK); ++} ++ ++/**************************************************************** ++ * Routine: CutFree ++ * ++ * Description: ++ * Cuts a free block from holdBase to holdEnd from the free lists. ++ * That is, it updates all free lists of the MM object do ++ * not include a block of memory from holdBase to holdEnd. ++ * For each free lists it seek for a free block that holds ++ * either holdBase or holdEnd. If such block is found it updates it. ++ * ++ * Arguments: ++ * p_MM - pointer to the MM object ++ * holdBase - base address of the allocated block ++ * holdEnd - end address of the allocated block ++ * ++ * Return value: ++ * E_OK is returned on success, ++ * otherwise returns an error code. ++ * ++ ****************************************************************/ ++static t_Error CutFree(t_MM *p_MM, uint64_t holdBase, uint64_t holdEnd) ++{ ++ t_FreeBlock *p_PrevB, *p_CurrB, *p_NewB; ++ uint64_t alignBase, base, end; ++ uint64_t alignment; ++ int i; ++ ++ for (i=0; i <= MM_MAX_ALIGNMENT; i++) ++ { ++ p_PrevB = p_NewB = 0; ++ p_CurrB = p_MM->freeBlocks[i]; ++ ++ alignment = (uint64_t)(0x1 << i); ++ alignBase = MAKE_ALIGNED(holdEnd, alignment); ++ ++ while ( p_CurrB ) ++ { ++ base = p_CurrB->base; ++ end = p_CurrB->end; ++ ++ if ( (holdBase <= base) && (holdEnd <= end) && (holdEnd > base) ) ++ { ++ if ( alignBase >= end || ++ (alignBase < end && ((end-alignBase) < alignment)) ) ++ { ++ if (p_PrevB) ++ p_PrevB->p_Next = p_CurrB->p_Next; ++ else ++ p_MM->freeBlocks[i] = p_CurrB->p_Next; ++ XX_Free(p_CurrB); ++ } ++ else ++ { ++ p_CurrB->base = alignBase; ++ } ++ break; ++ } ++ else if ( (holdBase > base) && (holdEnd <= end) ) ++ { ++ if ( (holdBase-base) >= alignment ) ++ { ++ if ( (alignBase < end) && ((end-alignBase) >= alignment) ) ++ { ++ if ((p_NewB = CreateFreeBlock(alignBase, end-alignBase)) == NULL) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ p_NewB->p_Next = p_CurrB->p_Next; ++ p_CurrB->p_Next = p_NewB; ++ } ++ p_CurrB->end = holdBase; ++ } ++ else if ( (alignBase < end) && ((end-alignBase) >= alignment) ) ++ { ++ p_CurrB->base = alignBase; ++ } ++ else ++ { ++ if (p_PrevB) ++ p_PrevB->p_Next = p_CurrB->p_Next; ++ else ++ p_MM->freeBlocks[i] = p_CurrB->p_Next; ++ XX_Free(p_CurrB); ++ } ++ break; ++ } ++ else ++ { ++ p_PrevB = p_CurrB; ++ p_CurrB = p_CurrB->p_Next; ++ } ++ } ++ } ++ ++ return (E_OK); ++} ++ ++/**************************************************************** ++ * Routine: AddBusy ++ * ++ * Description: ++ * Adds a new busy block to the list of busy blocks. Note, ++ * that all busy blocks are ordered by their base address in ++ * the busy list. ++ * ++ * Arguments: ++ * MM - handler to the MM object ++ * p_NewBusyB - pointer to the a busy block ++ * ++ * Return value: ++ * None. ++ * ++ ****************************************************************/ ++static void AddBusy(t_MM *p_MM, t_BusyBlock *p_NewBusyB) ++{ ++ t_BusyBlock *p_CurrBusyB, *p_PrevBusyB; ++ ++ /* finds a place of a new busy block in the list of busy blocks */ ++ p_PrevBusyB = 0; ++ p_CurrBusyB = p_MM->busyBlocks; ++ ++ while ( p_CurrBusyB && p_NewBusyB->base > p_CurrBusyB->base ) ++ { ++ p_PrevBusyB = p_CurrBusyB; ++ p_CurrBusyB = p_CurrBusyB->p_Next; ++ } ++ ++ /* insert the new busy block into the list of busy blocks */ ++ if ( p_CurrBusyB ) ++ p_NewBusyB->p_Next = p_CurrBusyB; ++ if ( p_PrevBusyB ) ++ p_PrevBusyB->p_Next = p_NewBusyB; ++ else ++ p_MM->busyBlocks = p_NewBusyB; ++} ++ ++/**************************************************************** ++ * Routine: CutBusy ++ * ++ * Description: ++ * Cuts a block from base to end from the list of busy blocks. ++ * This is done by updating the list of busy blocks do not ++ * include a given block, that block is going to be free. If a ++ * given block is a part of some other busy block, so that ++ * busy block is updated. If there are number of busy blocks ++ * included in the given block, so all that blocks are removed ++ * from the busy list and the end blocks are updated. ++ * If the given block devides some block into two parts, a new ++ * busy block is added to the busy list. ++ * ++ * Arguments: ++ * p_MM - pointer to the MM object ++ * base - base address of a given busy block ++ * end - end address of a given busy block ++ * ++ * Return value: ++ * E_OK on success, E_NOMEMORY otherwise. ++ * ++ ****************************************************************/ ++static t_Error CutBusy(t_MM *p_MM, uint64_t base, uint64_t end) ++{ ++ t_BusyBlock *p_CurrB, *p_PrevB, *p_NewB; ++ ++ p_CurrB = p_MM->busyBlocks; ++ p_PrevB = p_NewB = 0; ++ ++ while ( p_CurrB ) ++ { ++ if ( base < p_CurrB->end ) ++ { ++ if ( end > p_CurrB->end ) ++ { ++ t_BusyBlock *p_NextB; ++ while ( p_CurrB->p_Next && end >= p_CurrB->p_Next->end ) ++ { ++ p_NextB = p_CurrB->p_Next; ++ p_CurrB->p_Next = p_CurrB->p_Next->p_Next; ++ XX_Free(p_NextB); ++ } ++ ++ p_NextB = p_CurrB->p_Next; ++ if ( p_NextB && end > p_NextB->base ) ++ { ++ p_NextB->base = end; ++ } ++ } ++ ++ if ( base <= p_CurrB->base ) ++ { ++ if ( end < p_CurrB->end && end > p_CurrB->base ) ++ { ++ p_CurrB->base = end; ++ } ++ else if ( end >= p_CurrB->end ) ++ { ++ if ( p_PrevB ) ++ p_PrevB->p_Next = p_CurrB->p_Next; ++ else ++ p_MM->busyBlocks = p_CurrB->p_Next; ++ XX_Free(p_CurrB); ++ } ++ } ++ else ++ { ++ if ( end < p_CurrB->end && end > p_CurrB->base ) ++ { ++ if ((p_NewB = CreateBusyBlock(end, ++ p_CurrB->end-end, ++ p_CurrB->name)) == NULL) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ p_NewB->p_Next = p_CurrB->p_Next; ++ p_CurrB->p_Next = p_NewB; ++ } ++ p_CurrB->end = base; ++ } ++ break; ++ } ++ else ++ { ++ p_PrevB = p_CurrB; ++ p_CurrB = p_CurrB->p_Next; ++ } ++ } ++ ++ return (E_OK); ++} ++ ++/**************************************************************** ++ * Routine: MmGetGreaterAlignment ++ * ++ * Description: ++ * Allocates a block of memory according to the given size ++ * and the alignment. That routine is called from the MM_Get ++ * routine if the required alignment is greater then MM_MAX_ALIGNMENT. ++ * In that case, it goes over free blocks of 64 byte align list ++ * and checks if it has the required size of bytes of the required ++ * alignment. If no blocks found returns ILLEGAL_BASE. ++ * After the block is found and data is allocated, it calls ++ * the internal CutFree routine to update all free lists ++ * do not include a just allocated block. Of course, each ++ * free list contains a free blocks with the same alignment. ++ * It is also creates a busy block that holds ++ * information about an allocated block. ++ * ++ * Arguments: ++ * MM - handle to the MM object ++ * size - size of the MM ++ * alignment - index as a power of two defines ++ * a required alignment that is greater then 64. ++ * name - the name that specifies an allocated block. ++ * ++ * Return value: ++ * base address of an allocated block. ++ * ILLEGAL_BASE if can't allocate a block ++ * ++ ****************************************************************/ ++static uint64_t MmGetGreaterAlignment(t_MM *p_MM, uint64_t size, uint64_t alignment, char* name) ++{ ++ t_FreeBlock *p_FreeB; ++ t_BusyBlock *p_NewBusyB; ++ uint64_t holdBase, holdEnd, alignBase = 0; ++ ++ /* goes over free blocks of the 64 byte alignment list ++ and look for a block of the suitable size and ++ base address according to the alignment. */ ++ p_FreeB = p_MM->freeBlocks[MM_MAX_ALIGNMENT]; ++ ++ while ( p_FreeB ) ++ { ++ alignBase = MAKE_ALIGNED(p_FreeB->base, alignment); ++ ++ /* the block is found if the aligned base inside the block ++ * and has the anough size. */ ++ if ( alignBase >= p_FreeB->base && ++ alignBase < p_FreeB->end && ++ size <= (p_FreeB->end - alignBase) ) ++ break; ++ else ++ p_FreeB = p_FreeB->p_Next; ++ } ++ ++ /* If such block isn't found */ ++ if ( !p_FreeB ) ++ return (uint64_t)(ILLEGAL_BASE); ++ ++ holdBase = alignBase; ++ holdEnd = alignBase + size; ++ ++ /* init a new busy block */ ++ if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL) ++ return (uint64_t)(ILLEGAL_BASE); ++ ++ /* calls Update routine to update a lists of free blocks */ ++ if ( CutFree ( p_MM, holdBase, holdEnd ) != E_OK ) ++ { ++ XX_Free(p_NewBusyB); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* insert the new busy block into the list of busy blocks */ ++ AddBusy ( p_MM, p_NewBusyB ); ++ ++ return (holdBase); ++} ++ ++ ++/********************************************************************** ++ * MM API routines set * ++ **********************************************************************/ ++ ++/*****************************************************************************/ ++t_Error MM_Init(t_Handle *h_MM, uint64_t base, uint64_t size) ++{ ++ t_MM *p_MM; ++ uint64_t newBase, newSize; ++ int i; ++ ++ if (!size) ++ { ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Size (should be positive)")); ++ } ++ ++ /* Initializes a new MM object */ ++ p_MM = (t_MM *)XX_Malloc(sizeof(t_MM)); ++ if (!p_MM) ++ { ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ } ++ ++ p_MM->h_Spinlock = XX_InitSpinlock(); ++ if (!p_MM->h_Spinlock) ++ { ++ XX_Free(p_MM); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MM spinlock!")); ++ } ++ ++ /* Initializes counter of free memory to total size */ ++ p_MM->freeMemSize = size; ++ ++ /* A busy list is empty */ ++ p_MM->busyBlocks = 0; ++ ++ /* Initializes a new memory block */ ++ if ((p_MM->memBlocks = CreateNewBlock(base, size)) == NULL) ++ { ++ MM_Free(p_MM); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ } ++ ++ /* Initializes a new free block for each free list*/ ++ for (i=0; i <= MM_MAX_ALIGNMENT; i++) ++ { ++ newBase = MAKE_ALIGNED( base, (0x1 << i) ); ++ newSize = size - (newBase - base); ++ ++ if ((p_MM->freeBlocks[i] = CreateFreeBlock(newBase, newSize)) == NULL) ++ { ++ MM_Free(p_MM); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ } ++ } ++ ++ *h_MM = p_MM; ++ ++ return (E_OK); ++} ++ ++/*****************************************************************************/ ++void MM_Free(t_Handle h_MM) ++{ ++ t_MM *p_MM = (t_MM *)h_MM; ++ t_MemBlock *p_MemBlock; ++ t_BusyBlock *p_BusyBlock; ++ t_FreeBlock *p_FreeBlock; ++ void *p_Block; ++ int i; ++ ++ ASSERT_COND(p_MM); ++ ++ /* release memory allocated for busy blocks */ ++ p_BusyBlock = p_MM->busyBlocks; ++ while ( p_BusyBlock ) ++ { ++ p_Block = p_BusyBlock; ++ p_BusyBlock = p_BusyBlock->p_Next; ++ XX_Free(p_Block); ++ } ++ ++ /* release memory allocated for free blocks */ ++ for (i=0; i <= MM_MAX_ALIGNMENT; i++) ++ { ++ p_FreeBlock = p_MM->freeBlocks[i]; ++ while ( p_FreeBlock ) ++ { ++ p_Block = p_FreeBlock; ++ p_FreeBlock = p_FreeBlock->p_Next; ++ XX_Free(p_Block); ++ } ++ } ++ ++ /* release memory allocated for memory blocks */ ++ p_MemBlock = p_MM->memBlocks; ++ while ( p_MemBlock ) ++ { ++ p_Block = p_MemBlock; ++ p_MemBlock = p_MemBlock->p_Next; ++ XX_Free(p_Block); ++ } ++ ++ if (p_MM->h_Spinlock) ++ XX_FreeSpinlock(p_MM->h_Spinlock); ++ ++ /* release memory allocated for MM object itself */ ++ XX_Free(p_MM); ++} ++ ++/*****************************************************************************/ ++uint64_t MM_Get(t_Handle h_MM, uint64_t size, uint64_t alignment, char* name) ++{ ++ t_MM *p_MM = (t_MM *)h_MM; ++ t_FreeBlock *p_FreeB; ++ t_BusyBlock *p_NewBusyB; ++ uint64_t holdBase, holdEnd, j, i = 0; ++ uint32_t intFlags; ++ ++ SANITY_CHECK_RETURN_VALUE(p_MM, E_INVALID_HANDLE, (uint64_t)ILLEGAL_BASE); ++ ++ /* checks that alignment value is greater then zero */ ++ if (alignment == 0) ++ { ++ alignment = 1; ++ } ++ ++ j = alignment; ++ ++ /* checks if alignment is a power of two, if it correct and if the ++ required size is multiple of the given alignment. */ ++ while ((j & 0x1) == 0) ++ { ++ i++; ++ j = j >> 1; ++ } ++ ++ /* if the given alignment isn't power of two, returns an error */ ++ if (j != 1) ++ { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("alignment (should be power of 2)")); ++ return (uint64_t)ILLEGAL_BASE; ++ } ++ ++ if (i > MM_MAX_ALIGNMENT) ++ { ++ return (MmGetGreaterAlignment(p_MM, size, alignment, name)); ++ } ++ ++ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); ++ /* look for a block of the size greater or equal to the required size. */ ++ p_FreeB = p_MM->freeBlocks[i]; ++ while ( p_FreeB && (p_FreeB->end - p_FreeB->base) < size ) ++ p_FreeB = p_FreeB->p_Next; ++ ++ /* If such block is found */ ++ if ( !p_FreeB ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ holdBase = p_FreeB->base; ++ holdEnd = holdBase + size; ++ ++ /* init a new busy block */ ++ if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* calls Update routine to update a lists of free blocks */ ++ if ( CutFree ( p_MM, holdBase, holdEnd ) != E_OK ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ XX_Free(p_NewBusyB); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* Decreasing the allocated memory size from free memory size */ ++ p_MM->freeMemSize -= size; ++ ++ /* insert the new busy block into the list of busy blocks */ ++ AddBusy ( p_MM, p_NewBusyB ); ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ ++ return (holdBase); ++} ++ ++/*****************************************************************************/ ++uint64_t MM_GetForce(t_Handle h_MM, uint64_t base, uint64_t size, char* name) ++{ ++ t_MM *p_MM = (t_MM *)h_MM; ++ t_FreeBlock *p_FreeB; ++ t_BusyBlock *p_NewBusyB; ++ uint32_t intFlags; ++ bool blockIsFree = FALSE; ++ ++ ASSERT_COND(p_MM); ++ ++ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); ++ p_FreeB = p_MM->freeBlocks[0]; /* The biggest free blocks are in the ++ free list with alignment 1 */ ++ ++ while ( p_FreeB ) ++ { ++ if ( base >= p_FreeB->base && (base+size) <= p_FreeB->end ) ++ { ++ blockIsFree = TRUE; ++ break; ++ } ++ else ++ p_FreeB = p_FreeB->p_Next; ++ } ++ ++ if ( !blockIsFree ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* init a new busy block */ ++ if ((p_NewBusyB = CreateBusyBlock(base, size, name)) == NULL) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* calls Update routine to update a lists of free blocks */ ++ if ( CutFree ( p_MM, base, base+size ) != E_OK ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ XX_Free(p_NewBusyB); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* Decreasing the allocated memory size from free memory size */ ++ p_MM->freeMemSize -= size; ++ ++ /* insert the new busy block into the list of busy blocks */ ++ AddBusy ( p_MM, p_NewBusyB ); ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ ++ return (base); ++} ++ ++/*****************************************************************************/ ++uint64_t MM_GetForceMin(t_Handle h_MM, uint64_t size, uint64_t alignment, uint64_t min, char* name) ++{ ++ t_MM *p_MM = (t_MM *)h_MM; ++ t_FreeBlock *p_FreeB; ++ t_BusyBlock *p_NewBusyB; ++ uint64_t holdBase, holdEnd, j = alignment, i=0; ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_MM); ++ ++ /* checks if alignment is a power of two, if it correct and if the ++ required size is multiple of the given alignment. */ ++ while ((j & 0x1) == 0) ++ { ++ i++; ++ j = j >> 1; ++ } ++ ++ if ( (j != 1) || (i > MM_MAX_ALIGNMENT) ) ++ { ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); ++ p_FreeB = p_MM->freeBlocks[i]; ++ ++ /* look for the first block that contains the minimum ++ base address. If the whole required size may be fit ++ into it, use that block, otherwise look for the next ++ block of size greater or equal to the required size. */ ++ while ( p_FreeB && (min >= p_FreeB->end)) ++ p_FreeB = p_FreeB->p_Next; ++ ++ /* If such block is found */ ++ if ( !p_FreeB ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* if this block is large enough, use this block */ ++ holdBase = ( min <= p_FreeB->base ) ? p_FreeB->base : min; ++ if ((holdBase + size) <= p_FreeB->end ) ++ { ++ holdEnd = holdBase + size; ++ } ++ else ++ { ++ p_FreeB = p_FreeB->p_Next; ++ while ( p_FreeB && ((p_FreeB->end - p_FreeB->base) < size) ) ++ p_FreeB = p_FreeB->p_Next; ++ ++ /* If such block is found */ ++ if ( !p_FreeB ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ holdBase = p_FreeB->base; ++ holdEnd = holdBase + size; ++ } ++ ++ /* init a new busy block */ ++ if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* calls Update routine to update a lists of free blocks */ ++ if ( CutFree( p_MM, holdBase, holdEnd ) != E_OK ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ XX_Free(p_NewBusyB); ++ return (uint64_t)(ILLEGAL_BASE); ++ } ++ ++ /* Decreasing the allocated memory size from free memory size */ ++ p_MM->freeMemSize -= size; ++ ++ /* insert the new busy block into the list of busy blocks */ ++ AddBusy( p_MM, p_NewBusyB ); ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ ++ return (holdBase); ++} ++ ++/*****************************************************************************/ ++uint64_t MM_Put(t_Handle h_MM, uint64_t base) ++{ ++ t_MM *p_MM = (t_MM *)h_MM; ++ t_BusyBlock *p_BusyB, *p_PrevBusyB; ++ uint64_t size; ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_MM); ++ ++ /* Look for a busy block that have the given base value. ++ * That block will be returned back to the memory. ++ */ ++ p_PrevBusyB = 0; ++ ++ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); ++ p_BusyB = p_MM->busyBlocks; ++ while ( p_BusyB && base != p_BusyB->base ) ++ { ++ p_PrevBusyB = p_BusyB; ++ p_BusyB = p_BusyB->p_Next; ++ } ++ ++ if ( !p_BusyB ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(0); ++ } ++ ++ if ( AddFree( p_MM, p_BusyB->base, p_BusyB->end ) != E_OK ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(0); ++ } ++ ++ /* removes a busy block form the list of busy blocks */ ++ if ( p_PrevBusyB ) ++ p_PrevBusyB->p_Next = p_BusyB->p_Next; ++ else ++ p_MM->busyBlocks = p_BusyB->p_Next; ++ ++ size = p_BusyB->end - p_BusyB->base; ++ ++ /* Adding the deallocated memory size to free memory size */ ++ p_MM->freeMemSize += size; ++ ++ XX_Free(p_BusyB); ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ ++ return (size); ++} ++ ++/*****************************************************************************/ ++uint64_t MM_PutForce(t_Handle h_MM, uint64_t base, uint64_t size) ++{ ++ t_MM *p_MM = (t_MM *)h_MM; ++ uint64_t end = base + size; ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_MM); ++ ++ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); ++ ++ if ( CutBusy( p_MM, base, end ) != E_OK ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(0); ++ } ++ ++ if ( AddFree ( p_MM, base, end ) != E_OK ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ return (uint64_t)(0); ++ } ++ ++ /* Adding the deallocated memory size to free memory size */ ++ p_MM->freeMemSize += size; ++ ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ ++ return (size); ++} ++ ++/*****************************************************************************/ ++t_Error MM_Add(t_Handle h_MM, uint64_t base, uint64_t size) ++{ ++ t_MM *p_MM = (t_MM *)h_MM; ++ t_MemBlock *p_MemB, *p_NewMemB; ++ t_Error errCode; ++ uint32_t intFlags; ++ ++ ASSERT_COND(p_MM); ++ ++ /* find a last block in the list of memory blocks to insert a new ++ * memory block ++ */ ++ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock); ++ ++ p_MemB = p_MM->memBlocks; ++ while ( p_MemB->p_Next ) ++ { ++ if ( base >= p_MemB->base && base < p_MemB->end ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG); ++ } ++ p_MemB = p_MemB->p_Next; ++ } ++ /* check for a last memory block */ ++ if ( base >= p_MemB->base && base < p_MemB->end ) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG); ++ } ++ ++ /* create a new memory block */ ++ if ((p_NewMemB = CreateNewBlock(base, size)) == NULL) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ } ++ ++ /* append a new memory block to the end of the list of memory blocks */ ++ p_MemB->p_Next = p_NewMemB; ++ ++ /* add a new free block to the free lists */ ++ errCode = AddFree(p_MM, base, base+size); ++ if (errCode) ++ { ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ p_MemB->p_Next = 0; ++ XX_Free(p_NewMemB); ++ return ((t_Error)errCode); ++ } ++ ++ /* Adding the new block size to free memory size */ ++ p_MM->freeMemSize += size; ++ ++ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags); ++ ++ return (E_OK); ++} ++ ++/*****************************************************************************/ ++uint64_t MM_GetMemBlock(t_Handle h_MM, int index) ++{ ++ t_MM *p_MM = (t_MM*)h_MM; ++ t_MemBlock *p_MemBlock; ++ int i; ++ ++ ASSERT_COND(p_MM); ++ ++ p_MemBlock = p_MM->memBlocks; ++ for (i=0; i < index; i++) ++ p_MemBlock = p_MemBlock->p_Next; ++ ++ if ( p_MemBlock ) ++ return (p_MemBlock->base); ++ else ++ return (uint64_t)ILLEGAL_BASE; ++} ++ ++/*****************************************************************************/ ++uint64_t MM_GetBase(t_Handle h_MM) ++{ ++ t_MM *p_MM = (t_MM*)h_MM; ++ t_MemBlock *p_MemBlock; ++ ++ ASSERT_COND(p_MM); ++ ++ p_MemBlock = p_MM->memBlocks; ++ return p_MemBlock->base; ++} ++ ++/*****************************************************************************/ ++bool MM_InRange(t_Handle h_MM, uint64_t addr) ++{ ++ t_MM *p_MM = (t_MM*)h_MM; ++ t_MemBlock *p_MemBlock; ++ ++ ASSERT_COND(p_MM); ++ ++ p_MemBlock = p_MM->memBlocks; ++ ++ if ((addr >= p_MemBlock->base) && (addr < p_MemBlock->end)) ++ return TRUE; ++ else ++ return FALSE; ++} ++ ++/*****************************************************************************/ ++uint64_t MM_GetFreeMemSize(t_Handle h_MM) ++{ ++ t_MM *p_MM = (t_MM*)h_MM; ++ ++ ASSERT_COND(p_MM); ++ ++ return p_MM->freeMemSize; ++} ++ ++/*****************************************************************************/ ++void MM_Dump(t_Handle h_MM) ++{ ++ t_MM *p_MM = (t_MM *)h_MM; ++ t_FreeBlock *p_FreeB; ++ t_BusyBlock *p_BusyB; ++ int i; ++ ++ p_BusyB = p_MM->busyBlocks; ++ XX_Print("List of busy blocks:\n"); ++ while (p_BusyB) ++ { ++ XX_Print("\t0x%p: (%s: b=0x%llx, e=0x%llx)\n", p_BusyB, p_BusyB->name, p_BusyB->base, p_BusyB->end ); ++ p_BusyB = p_BusyB->p_Next; ++ } ++ ++ XX_Print("\nLists of free blocks according to alignment:\n"); ++ for (i=0; i <= MM_MAX_ALIGNMENT; i++) ++ { ++ XX_Print("%d alignment:\n", (0x1 << i)); ++ p_FreeB = p_MM->freeBlocks[i]; ++ while (p_FreeB) ++ { ++ XX_Print("\t0x%p: (b=0x%llx, e=0x%llx)\n", p_FreeB, p_FreeB->base, p_FreeB->end); ++ p_FreeB = p_FreeB->p_Next; ++ } ++ XX_Print("\n"); ++ } ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/etc/mm.h b/drivers/net/ethernet/freescale/sdk_fman/etc/mm.h +new file mode 100644 +index 0000000..43b2298 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/etc/mm.h +@@ -0,0 +1,105 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/**************************************************************** ++ * ++ * File: mm.h ++ * ++ * ++ * Description: ++ * MM (Memory Management) object definitions. ++ * It also includes definitions of the Free Block, Busy Block ++ * and Memory Block structures used by the MM object. ++ * ++ ****************************************************************/ ++ ++#ifndef __MM_H ++#define __MM_H ++ ++ ++#include "mm_ext.h" ++ ++#define __ERR_MODULE__ MODULE_MM ++ ++ ++#define MAKE_ALIGNED(addr, align) \ ++ (((uint64_t)(addr) + ((align) - 1)) & (~(((uint64_t)align) - 1))) ++ ++ ++/* t_MemBlock data structure defines parameters of the Memory Block */ ++typedef struct t_MemBlock ++{ ++ struct t_MemBlock *p_Next; /* Pointer to the next memory block */ ++ ++ uint64_t base; /* Base address of the memory block */ ++ uint64_t end; /* End address of the memory block */ ++} t_MemBlock; ++ ++ ++/* t_FreeBlock data structure defines parameters of the Free Block */ ++typedef struct t_FreeBlock ++{ ++ struct t_FreeBlock *p_Next; /* Pointer to the next free block */ ++ ++ uint64_t base; /* Base address of the block */ ++ uint64_t end; /* End address of the block */ ++} t_FreeBlock; ++ ++ ++/* t_BusyBlock data structure defines parameters of the Busy Block */ ++typedef struct t_BusyBlock ++{ ++ struct t_BusyBlock *p_Next; /* Pointer to the next free block */ ++ ++ uint64_t base; /* Base address of the block */ ++ uint64_t end; /* End address of the block */ ++ char name[MM_MAX_NAME_LEN]; /* That block of memory was allocated for ++ something specified by the Name */ ++} t_BusyBlock; ++ ++ ++/* t_MM data structure defines parameters of the MM object */ ++typedef struct t_MM ++{ ++ t_Handle h_Spinlock; ++ ++ t_MemBlock *memBlocks; /* List of memory blocks (Memory list) */ ++ t_BusyBlock *busyBlocks; /* List of busy blocks (Busy list) */ ++ t_FreeBlock *freeBlocks[MM_MAX_ALIGNMENT + 1]; ++ /* Alignment lists of free blocks (Free lists) */ ++ ++ uint64_t freeMemSize; /* Total size of free memory (in bytes) */ ++} t_MM; ++ ++ ++#endif /* __MM_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/etc/sprint.c b/drivers/net/ethernet/freescale/sdk_fman/etc/sprint.c +new file mode 100644 +index 0000000..46d2956 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/etc/sprint.c +@@ -0,0 +1,81 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/*------------------------------------------------------*/ ++/* File: sprint.c */ ++/* */ ++/* Description: */ ++/* Debug routines (externals) */ ++/*------------------------------------------------------*/ ++#include "string_ext.h" ++#include "stdlib_ext.h" ++#include "stdarg_ext.h" ++#include "sprint_ext.h" ++#include "std_ext.h" ++#include "xx_ext.h" ++ ++ ++int Sprint(char * buf, const char *fmt, ...) ++{ ++ va_list args; ++ int i; ++ ++ va_start(args, fmt); ++ i=vsprintf(buf,fmt,args); ++ va_end(args); ++ return i; ++} ++ ++int Snprint(char * buf, uint32_t size, const char *fmt, ...) ++{ ++ va_list args; ++ int i; ++ ++ va_start(args, fmt); ++ i=vsnprintf(buf,size,fmt,args); ++ va_end(args); ++ return i; ++} ++ ++#ifndef NCSW_VXWORKS ++int Sscan(const char * buf, const char * fmt, ...) ++{ ++ va_list args; ++ int i; ++ ++ va_start(args,fmt); ++ i = vsscanf(buf,fmt,args); ++ va_end(args); ++ return i; ++} ++#endif /* NCSW_VXWORKS */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/fmanv3h_dflags.h b/drivers/net/ethernet/freescale/sdk_fman/fmanv3h_dflags.h +new file mode 100644 +index 0000000..435b0d2 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/fmanv3h_dflags.h +@@ -0,0 +1,57 @@ ++/* ++ * Copyright 2012 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 __dflags_h ++#define __dflags_h ++ ++ ++#define NCSW_LINUX ++ ++#define T4240 ++#define NCSW_PPC_CORE ++ ++#define DEBUG_ERRORS 1 ++ ++#if defined(DEBUG) ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_INFO ++ ++#define DEBUG_XX_MALLOC ++#define DEBUG_MEM_LEAKS ++ ++#else ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_WARNING ++#endif /* (DEBUG) */ ++ ++#define REPORT_EVENTS 1 ++#define EVENT_GLOBAL_LEVEL REPORT_LEVEL_MINOR ++ ++#endif /* __dflags_h */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/fmanv3l_dflags.h b/drivers/net/ethernet/freescale/sdk_fman/fmanv3l_dflags.h +new file mode 100644 +index 0000000..789eb87 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/fmanv3l_dflags.h +@@ -0,0 +1,56 @@ ++/* ++ * Copyright 2012 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 __dflags_h ++#define __dflags_h ++ ++ ++#define NCSW_LINUX ++ ++#define NCSW_PPC_CORE ++ ++#define DEBUG_ERRORS 1 ++ ++#if defined(DEBUG) ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_INFO ++ ++#define DEBUG_XX_MALLOC ++#define DEBUG_MEM_LEAKS ++ ++#else ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_WARNING ++#endif /* (DEBUG) */ ++ ++#define REPORT_EVENTS 1 ++#define EVENT_GLOBAL_LEVEL REPORT_LEVEL_MINOR ++ ++#endif /* __dflags_h */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/crc_mac_addr_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/crc_mac_addr_ext.h +new file mode 100644 +index 0000000..a84d563 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/crc_mac_addr_ext.h +@@ -0,0 +1,364 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/*------------------------------------------------------*/ ++/* */ ++/* File: crc_mac_addr_ext.h */ ++/* */ ++/* Description: */ ++/* Define a macro that calculate the crc value of */ ++/* an Ethernet MAC address (48 bitd address */ ++/*------------------------------------------------------*/ ++ ++#ifndef __crc_mac_addr_ext_h ++#define __crc_mac_addr_ext_h ++ ++#include "std_ext.h" ++ ++ ++static uint32_t crc_table[256] = ++{ ++ 0x00000000, ++ 0x77073096, ++ 0xee0e612c, ++ 0x990951ba, ++ 0x076dc419, ++ 0x706af48f, ++ 0xe963a535, ++ 0x9e6495a3, ++ 0x0edb8832, ++ 0x79dcb8a4, ++ 0xe0d5e91e, ++ 0x97d2d988, ++ 0x09b64c2b, ++ 0x7eb17cbd, ++ 0xe7b82d07, ++ 0x90bf1d91, ++ 0x1db71064, ++ 0x6ab020f2, ++ 0xf3b97148, ++ 0x84be41de, ++ 0x1adad47d, ++ 0x6ddde4eb, ++ 0xf4d4b551, ++ 0x83d385c7, ++ 0x136c9856, ++ 0x646ba8c0, ++ 0xfd62f97a, ++ 0x8a65c9ec, ++ 0x14015c4f, ++ 0x63066cd9, ++ 0xfa0f3d63, ++ 0x8d080df5, ++ 0x3b6e20c8, ++ 0x4c69105e, ++ 0xd56041e4, ++ 0xa2677172, ++ 0x3c03e4d1, ++ 0x4b04d447, ++ 0xd20d85fd, ++ 0xa50ab56b, ++ 0x35b5a8fa, ++ 0x42b2986c, ++ 0xdbbbc9d6, ++ 0xacbcf940, ++ 0x32d86ce3, ++ 0x45df5c75, ++ 0xdcd60dcf, ++ 0xabd13d59, ++ 0x26d930ac, ++ 0x51de003a, ++ 0xc8d75180, ++ 0xbfd06116, ++ 0x21b4f4b5, ++ 0x56b3c423, ++ 0xcfba9599, ++ 0xb8bda50f, ++ 0x2802b89e, ++ 0x5f058808, ++ 0xc60cd9b2, ++ 0xb10be924, ++ 0x2f6f7c87, ++ 0x58684c11, ++ 0xc1611dab, ++ 0xb6662d3d, ++ 0x76dc4190, ++ 0x01db7106, ++ 0x98d220bc, ++ 0xefd5102a, ++ 0x71b18589, ++ 0x06b6b51f, ++ 0x9fbfe4a5, ++ 0xe8b8d433, ++ 0x7807c9a2, ++ 0x0f00f934, ++ 0x9609a88e, ++ 0xe10e9818, ++ 0x7f6a0dbb, ++ 0x086d3d2d, ++ 0x91646c97, ++ 0xe6635c01, ++ 0x6b6b51f4, ++ 0x1c6c6162, ++ 0x856530d8, ++ 0xf262004e, ++ 0x6c0695ed, ++ 0x1b01a57b, ++ 0x8208f4c1, ++ 0xf50fc457, ++ 0x65b0d9c6, ++ 0x12b7e950, ++ 0x8bbeb8ea, ++ 0xfcb9887c, ++ 0x62dd1ddf, ++ 0x15da2d49, ++ 0x8cd37cf3, ++ 0xfbd44c65, ++ 0x4db26158, ++ 0x3ab551ce, ++ 0xa3bc0074, ++ 0xd4bb30e2, ++ 0x4adfa541, ++ 0x3dd895d7, ++ 0xa4d1c46d, ++ 0xd3d6f4fb, ++ 0x4369e96a, ++ 0x346ed9fc, ++ 0xad678846, ++ 0xda60b8d0, ++ 0x44042d73, ++ 0x33031de5, ++ 0xaa0a4c5f, ++ 0xdd0d7cc9, ++ 0x5005713c, ++ 0x270241aa, ++ 0xbe0b1010, ++ 0xc90c2086, ++ 0x5768b525, ++ 0x206f85b3, ++ 0xb966d409, ++ 0xce61e49f, ++ 0x5edef90e, ++ 0x29d9c998, ++ 0xb0d09822, ++ 0xc7d7a8b4, ++ 0x59b33d17, ++ 0x2eb40d81, ++ 0xb7bd5c3b, ++ 0xc0ba6cad, ++ 0xedb88320, ++ 0x9abfb3b6, ++ 0x03b6e20c, ++ 0x74b1d29a, ++ 0xead54739, ++ 0x9dd277af, ++ 0x04db2615, ++ 0x73dc1683, ++ 0xe3630b12, ++ 0x94643b84, ++ 0x0d6d6a3e, ++ 0x7a6a5aa8, ++ 0xe40ecf0b, ++ 0x9309ff9d, ++ 0x0a00ae27, ++ 0x7d079eb1, ++ 0xf00f9344, ++ 0x8708a3d2, ++ 0x1e01f268, ++ 0x6906c2fe, ++ 0xf762575d, ++ 0x806567cb, ++ 0x196c3671, ++ 0x6e6b06e7, ++ 0xfed41b76, ++ 0x89d32be0, ++ 0x10da7a5a, ++ 0x67dd4acc, ++ 0xf9b9df6f, ++ 0x8ebeeff9, ++ 0x17b7be43, ++ 0x60b08ed5, ++ 0xd6d6a3e8, ++ 0xa1d1937e, ++ 0x38d8c2c4, ++ 0x4fdff252, ++ 0xd1bb67f1, ++ 0xa6bc5767, ++ 0x3fb506dd, ++ 0x48b2364b, ++ 0xd80d2bda, ++ 0xaf0a1b4c, ++ 0x36034af6, ++ 0x41047a60, ++ 0xdf60efc3, ++ 0xa867df55, ++ 0x316e8eef, ++ 0x4669be79, ++ 0xcb61b38c, ++ 0xbc66831a, ++ 0x256fd2a0, ++ 0x5268e236, ++ 0xcc0c7795, ++ 0xbb0b4703, ++ 0x220216b9, ++ 0x5505262f, ++ 0xc5ba3bbe, ++ 0xb2bd0b28, ++ 0x2bb45a92, ++ 0x5cb36a04, ++ 0xc2d7ffa7, ++ 0xb5d0cf31, ++ 0x2cd99e8b, ++ 0x5bdeae1d, ++ 0x9b64c2b0, ++ 0xec63f226, ++ 0x756aa39c, ++ 0x026d930a, ++ 0x9c0906a9, ++ 0xeb0e363f, ++ 0x72076785, ++ 0x05005713, ++ 0x95bf4a82, ++ 0xe2b87a14, ++ 0x7bb12bae, ++ 0x0cb61b38, ++ 0x92d28e9b, ++ 0xe5d5be0d, ++ 0x7cdcefb7, ++ 0x0bdbdf21, ++ 0x86d3d2d4, ++ 0xf1d4e242, ++ 0x68ddb3f8, ++ 0x1fda836e, ++ 0x81be16cd, ++ 0xf6b9265b, ++ 0x6fb077e1, ++ 0x18b74777, ++ 0x88085ae6, ++ 0xff0f6a70, ++ 0x66063bca, ++ 0x11010b5c, ++ 0x8f659eff, ++ 0xf862ae69, ++ 0x616bffd3, ++ 0x166ccf45, ++ 0xa00ae278, ++ 0xd70dd2ee, ++ 0x4e048354, ++ 0x3903b3c2, ++ 0xa7672661, ++ 0xd06016f7, ++ 0x4969474d, ++ 0x3e6e77db, ++ 0xaed16a4a, ++ 0xd9d65adc, ++ 0x40df0b66, ++ 0x37d83bf0, ++ 0xa9bcae53, ++ 0xdebb9ec5, ++ 0x47b2cf7f, ++ 0x30b5ffe9, ++ 0xbdbdf21c, ++ 0xcabac28a, ++ 0x53b39330, ++ 0x24b4a3a6, ++ 0xbad03605, ++ 0xcdd70693, ++ 0x54de5729, ++ 0x23d967bf, ++ 0xb3667a2e, ++ 0xc4614ab8, ++ 0x5d681b02, ++ 0x2a6f2b94, ++ 0xb40bbe37, ++ 0xc30c8ea1, ++ 0x5a05df1b, ++ 0x2d02ef8d ++}; ++ ++ ++#define GET_MAC_ADDR_CRC(addr, crc) \ ++{ \ ++ uint32_t i; \ ++ uint8_t data; \ ++ \ ++ /* CRC calculation */ \ ++ crc = 0xffffffff; \ ++ for (i=0; i < 6; i++) \ ++ { \ ++ data = (uint8_t)(addr >> ((5-i)*8)); \ ++ crc = crc^data; \ ++ crc = crc_table[crc&0xff] ^ (crc>>8); \ ++ } \ ++} \ ++ ++/* Define a macro for getting the mirrored value of */ ++/* a byte size number. (0x11010011 --> 0x11001011) */ ++/* Sometimes the mirrored value of the CRC is required */ ++static __inline__ uint8_t GetMirror(uint8_t n) ++{ ++ uint8_t mirror[16] = ++ { ++ 0x00, ++ 0x08, ++ 0x04, ++ 0x0c, ++ 0x02, ++ 0x0a, ++ 0x06, ++ 0x0e, ++ 0x01, ++ 0x09, ++ 0x05, ++ 0x0d, ++ 0x03, ++ 0x0b, ++ 0x07, ++ 0x0f ++ }; ++ return ((uint8_t)(((mirror[n & 0x0f] << 4) | (mirror[n >> 4])))); ++} ++ ++static __inline__ uint32_t GetMirror32(uint32_t n) ++{ ++ return (((uint32_t)GetMirror((uint8_t)(n))<<24) | ++ ((uint32_t)GetMirror((uint8_t)(n>>8))<<16) | ++ ((uint32_t)GetMirror((uint8_t)(n>>16))<<8) | ++ ((uint32_t)GetMirror((uint8_t)(n>>24)))); ++} ++ ++#define MIRROR GetMirror ++#define MIRROR_32 GetMirror32 ++ ++ ++#endif /* __crc_mac_addr_ext_h */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/dpaa_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/dpaa_ext.h +new file mode 100644 +index 0000000..66fa760 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/dpaa_ext.h +@@ -0,0 +1,207 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File dpaa_ext.h ++ ++ @Description DPAA Application Programming Interface. ++*//***************************************************************************/ ++#ifndef __DPAA_EXT_H ++#define __DPAA_EXT_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group DPAA_grp Data Path Acceleration Architecture API ++ ++ @Description DPAA API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/**************************************************************************//** ++ @Description Frame descriptor ++*//***************************************************************************/ ++typedef _Packed struct t_DpaaFD { ++ volatile uint32_t id; /**< FD id */ ++ volatile uint32_t addrl; /**< Data Address */ ++ volatile uint32_t length; /**< Frame length */ ++ volatile uint32_t status; /**< FD status */ ++} _PackedType t_DpaaFD; ++ ++/**************************************************************************//** ++ @Description enum for defining frame format ++*//***************************************************************************/ ++typedef enum e_DpaaFDFormatType { ++ e_DPAA_FD_FORMAT_TYPE_SHORT_SBSF = 0x0, /**< Simple frame Single buffer; Offset and ++ small length (9b OFFSET, 20b LENGTH) */ ++ e_DPAA_FD_FORMAT_TYPE_LONG_SBSF = 0x2, /**< Simple frame, single buffer; big length ++ (29b LENGTH ,No OFFSET) */ ++ e_DPAA_FD_FORMAT_TYPE_SHORT_MBSF = 0x4, /**< Simple frame, Scatter Gather table; Offset ++ and small length (9b OFFSET, 20b LENGTH) */ ++ e_DPAA_FD_FORMAT_TYPE_LONG_MBSF = 0x6, /**< Simple frame, Scatter Gather table; ++ big length (29b LENGTH ,No OFFSET) */ ++ e_DPAA_FD_FORMAT_TYPE_COMPOUND = 0x1, /**< Compound Frame (29b CONGESTION-WEIGHT ++ No LENGTH or OFFSET) */ ++ e_DPAA_FD_FORMAT_TYPE_DUMMY ++} e_DpaaFDFormatType; ++ ++/**************************************************************************//** ++ @Collection Frame descriptor macros ++*//***************************************************************************/ ++#define DPAA_FD_DD_MASK 0xc0000000 /**< FD DD field mask */ ++#define DPAA_FD_PID_MASK 0x3f000000 /**< FD PID field mask */ ++#define DPAA_FD_ELIODN_MASK 0x0000f000 /**< FD ELIODN field mask */ ++#define DPAA_FD_BPID_MASK 0x00ff0000 /**< FD BPID field mask */ ++#define DPAA_FD_ADDRH_MASK 0x000000ff /**< FD ADDRH field mask */ ++#define DPAA_FD_ADDRL_MASK 0xffffffff /**< FD ADDRL field mask */ ++#define DPAA_FD_FORMAT_MASK 0xe0000000 /**< FD FORMAT field mask */ ++#define DPAA_FD_OFFSET_MASK 0x1ff00000 /**< FD OFFSET field mask */ ++#define DPAA_FD_LENGTH_MASK 0x000fffff /**< FD LENGTH field mask */ ++ ++#define DPAA_FD_GET_DD(fd) ((((t_DpaaFD *)fd)->id & DPAA_FD_DD_MASK) >> (31-1)) /**< Macro to get FD DD field */ ++#define DPAA_FD_GET_PID(fd) (((((t_DpaaFD *)fd)->id & DPAA_FD_PID_MASK) >> (31-7)) | \ ++ ((((t_DpaaFD *)fd)->id & DPAA_FD_ELIODN_MASK) >> (31-19-6))) /**< Macro to get FD PID field */ ++#define DPAA_FD_GET_BPID(fd) ((((t_DpaaFD *)fd)->id & DPAA_FD_BPID_MASK) >> (31-15)) /**< Macro to get FD BPID field */ ++#define DPAA_FD_GET_ADDRH(fd) (((t_DpaaFD *)fd)->id & DPAA_FD_ADDRH_MASK) /**< Macro to get FD ADDRH field */ ++#define DPAA_FD_GET_ADDRL(fd) ((t_DpaaFD *)fd)->addrl /**< Macro to get FD ADDRL field */ ++#define DPAA_FD_GET_PHYS_ADDR(fd) ((physAddress_t)(((uint64_t)DPAA_FD_GET_ADDRH(fd) << 32) | (uint64_t)DPAA_FD_GET_ADDRL(fd))) /**< Macro to get FD ADDR field */ ++#define DPAA_FD_GET_FORMAT(fd) ((((t_DpaaFD *)fd)->length & DPAA_FD_FORMAT_MASK) >> (31-2)) /**< Macro to get FD FORMAT field */ ++#define DPAA_FD_GET_OFFSET(fd) ((((t_DpaaFD *)fd)->length & DPAA_FD_OFFSET_MASK) >> (31-11)) /**< Macro to get FD OFFSET field */ ++#define DPAA_FD_GET_LENGTH(fd) (((t_DpaaFD *)fd)->length & DPAA_FD_LENGTH_MASK) /**< Macro to get FD LENGTH field */ ++#define DPAA_FD_GET_STATUS(fd) ((t_DpaaFD *)fd)->status /**< Macro to get FD STATUS field */ ++#define DPAA_FD_GET_ADDR(fd) XX_PhysToVirt(DPAA_FD_GET_PHYS_ADDR(fd)) /**< Macro to get FD ADDR (virtual) */ ++ ++#define DPAA_FD_SET_DD(fd,val) (((t_DpaaFD *)fd)->id = ((((t_DpaaFD *)fd)->id & ~DPAA_FD_DD_MASK) | (((val) << (31-1)) & DPAA_FD_DD_MASK ))) /**< Macro to set FD DD field */ ++ /**< Macro to set FD PID field or LIODN offset*/ ++#define DPAA_FD_SET_PID(fd,val) (((t_DpaaFD *)fd)->id = ((((t_DpaaFD *)fd)->id & ~(DPAA_FD_PID_MASK|DPAA_FD_ELIODN_MASK)) | ((((val) << (31-7)) & DPAA_FD_PID_MASK) | ((((val)>>6) << (31-19)) & DPAA_FD_ELIODN_MASK)))) ++#define DPAA_FD_SET_BPID(fd,val) (((t_DpaaFD *)fd)->id = ((((t_DpaaFD *)fd)->id & ~DPAA_FD_BPID_MASK) | (((val) << (31-15)) & DPAA_FD_BPID_MASK))) /**< Macro to set FD BPID field */ ++#define DPAA_FD_SET_ADDRH(fd,val) (((t_DpaaFD *)fd)->id = ((((t_DpaaFD *)fd)->id & ~DPAA_FD_ADDRH_MASK) | ((val) & DPAA_FD_ADDRH_MASK))) /**< Macro to set FD ADDRH field */ ++#define DPAA_FD_SET_ADDRL(fd,val) ((t_DpaaFD *)fd)->addrl = (val) /**< Macro to set FD ADDRL field */ ++#define DPAA_FD_SET_ADDR(fd,val) \ ++do { \ ++ uint64_t physAddr = (uint64_t)(XX_VirtToPhys(val)); \ ++ DPAA_FD_SET_ADDRH(fd, ((uint32_t)(physAddr >> 32))); \ ++ DPAA_FD_SET_ADDRL(fd, (uint32_t)physAddr); \ ++} while (0) /**< Macro to set FD ADDR field */ ++#define DPAA_FD_SET_FORMAT(fd,val) (((t_DpaaFD *)fd)->length = ((((t_DpaaFD *)fd)->length & ~DPAA_FD_FORMAT_MASK) | (((val) << (31-2))& DPAA_FD_FORMAT_MASK))) /**< Macro to set FD FORMAT field */ ++#define DPAA_FD_SET_OFFSET(fd,val) (((t_DpaaFD *)fd)->length = ((((t_DpaaFD *)fd)->length & ~DPAA_FD_OFFSET_MASK) | (((val) << (31-11))& DPAA_FD_OFFSET_MASK) )) /**< Macro to set FD OFFSET field */ ++#define DPAA_FD_SET_LENGTH(fd,val) (((t_DpaaFD *)fd)->length = (((t_DpaaFD *)fd)->length & ~DPAA_FD_LENGTH_MASK) | ((val) & DPAA_FD_LENGTH_MASK)) /**< Macro to set FD LENGTH field */ ++#define DPAA_FD_SET_STATUS(fd,val) ((t_DpaaFD *)fd)->status = (val) /**< Macro to set FD STATUS field */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Description Frame Scatter/Gather Table Entry ++*//***************************************************************************/ ++typedef _Packed struct t_DpaaSGTE { ++ volatile uint32_t addrh; /**< Buffer Address high */ ++ volatile uint32_t addrl; /**< Buffer Address low */ ++ volatile uint32_t length; /**< Buffer length */ ++ volatile uint32_t offset; /**< SGTE offset */ ++} _PackedType t_DpaaSGTE; ++ ++#define DPAA_NUM_OF_SG_TABLE_ENTRY 16 ++ ++/**************************************************************************//** ++ @Description Frame Scatter/Gather Table ++*//***************************************************************************/ ++typedef _Packed struct t_DpaaSGT { ++ t_DpaaSGTE tableEntry[DPAA_NUM_OF_SG_TABLE_ENTRY]; ++ /**< Structure that holds information about ++ a single S/G entry. */ ++} _PackedType t_DpaaSGT; ++ ++/**************************************************************************//** ++ @Description Compound Frame Table ++*//***************************************************************************/ ++typedef _Packed struct t_DpaaCompTbl { ++ t_DpaaSGTE outputBuffInfo; /**< Structure that holds information about ++ the compound-frame output buffer; ++ NOTE: this may point to a S/G table */ ++ t_DpaaSGTE inputBuffInfo; /**< Structure that holds information about ++ the compound-frame input buffer; ++ NOTE: this may point to a S/G table */ ++} _PackedType t_DpaaCompTbl; ++ ++/**************************************************************************//** ++ @Collection Frame Scatter/Gather Table Entry macros ++*//***************************************************************************/ ++#define DPAA_SGTE_ADDRH_MASK 0x000000ff /**< SGTE ADDRH field mask */ ++#define DPAA_SGTE_ADDRL_MASK 0xffffffff /**< SGTE ADDRL field mask */ ++#define DPAA_SGTE_E_MASK 0x80000000 /**< SGTE Extension field mask */ ++#define DPAA_SGTE_F_MASK 0x40000000 /**< SGTE Final field mask */ ++#define DPAA_SGTE_LENGTH_MASK 0x3fffffff /**< SGTE LENGTH field mask */ ++#define DPAA_SGTE_BPID_MASK 0x00ff0000 /**< SGTE BPID field mask */ ++#define DPAA_SGTE_OFFSET_MASK 0x00001fff /**< SGTE OFFSET field mask */ ++ ++#define DPAA_SGTE_GET_ADDRH(sgte) (((t_DpaaSGTE *)sgte)->addrh & DPAA_SGTE_ADDRH_MASK) /**< Macro to get SGTE ADDRH field */ ++#define DPAA_SGTE_GET_ADDRL(sgte) ((t_DpaaSGTE *)sgte)->addrl /**< Macro to get SGTE ADDRL field */ ++#define DPAA_SGTE_GET_PHYS_ADDR(sgte) ((physAddress_t)(((uint64_t)DPAA_SGTE_GET_ADDRH(sgte) << 32) | (uint64_t)DPAA_SGTE_GET_ADDRL(sgte))) /**< Macro to get FD ADDR field */ ++#define DPAA_SGTE_GET_EXTENSION(sgte) ((((t_DpaaSGTE *)sgte)->length & DPAA_SGTE_E_MASK) >> (31-0)) /**< Macro to get SGTE EXTENSION field */ ++#define DPAA_SGTE_GET_FINAL(sgte) ((((t_DpaaSGTE *)sgte)->length & DPAA_SGTE_F_MASK) >> (31-1)) /**< Macro to get SGTE FINAL field */ ++#define DPAA_SGTE_GET_LENGTH(sgte) (((t_DpaaSGTE *)sgte)->length & DPAA_SGTE_LENGTH_MASK) /**< Macro to get SGTE LENGTH field */ ++#define DPAA_SGTE_GET_BPID(sgte) ((((t_DpaaSGTE *)sgte)->offset & DPAA_SGTE_BPID_MASK) >> (31-15)) /**< Macro to get SGTE BPID field */ ++#define DPAA_SGTE_GET_OFFSET(sgte) (((t_DpaaSGTE *)sgte)->offset & DPAA_SGTE_OFFSET_MASK) /**< Macro to get SGTE OFFSET field */ ++#define DPAA_SGTE_GET_ADDR(sgte) XX_PhysToVirt(DPAA_SGTE_GET_PHYS_ADDR(sgte)) ++ ++#define DPAA_SGTE_SET_ADDRH(sgte,val) (((t_DpaaSGTE *)sgte)->addrh = ((((t_DpaaSGTE *)sgte)->addrh & ~DPAA_SGTE_ADDRH_MASK) | ((val) & DPAA_SGTE_ADDRH_MASK))) /**< Macro to set SGTE ADDRH field */ ++#define DPAA_SGTE_SET_ADDRL(sgte,val) ((t_DpaaSGTE *)sgte)->addrl = (val) /**< Macro to set SGTE ADDRL field */ ++#define DPAA_SGTE_SET_ADDR(sgte,val) \ ++do { \ ++ uint64_t physAddr = (uint64_t)(XX_VirtToPhys(val)); \ ++ DPAA_SGTE_SET_ADDRH(sgte, ((uint32_t)(physAddr >> 32))); \ ++ DPAA_SGTE_SET_ADDRL(sgte, (uint32_t)physAddr); \ ++} while (0) /**< Macro to set SGTE ADDR field */ ++#define DPAA_SGTE_SET_EXTENSION(sgte,val) (((t_DpaaSGTE *)sgte)->length = ((((t_DpaaSGTE *)sgte)->length & ~DPAA_SGTE_E_MASK) | (((val) << (31-0))& DPAA_SGTE_E_MASK))) /**< Macro to set SGTE EXTENSION field */ ++#define DPAA_SGTE_SET_FINAL(sgte,val) (((t_DpaaSGTE *)sgte)->length = ((((t_DpaaSGTE *)sgte)->length & ~DPAA_SGTE_F_MASK) | (((val) << (31-1))& DPAA_SGTE_F_MASK))) /**< Macro to set SGTE FINAL field */ ++#define DPAA_SGTE_SET_LENGTH(sgte,val) (((t_DpaaSGTE *)sgte)->length = (((t_DpaaSGTE *)sgte)->length & ~DPAA_SGTE_LENGTH_MASK) | ((val) & DPAA_SGTE_LENGTH_MASK)) /**< Macro to set SGTE LENGTH field */ ++#define DPAA_SGTE_SET_BPID(sgte,val) (((t_DpaaSGTE *)sgte)->offset = ((((t_DpaaSGTE *)sgte)->offset & ~DPAA_SGTE_BPID_MASK) | (((val) << (31-15))& DPAA_SGTE_BPID_MASK))) /**< Macro to set SGTE BPID field */ ++#define DPAA_SGTE_SET_OFFSET(sgte,val) (((t_DpaaSGTE *)sgte)->offset = ((((t_DpaaSGTE *)sgte)->offset & ~DPAA_SGTE_OFFSET_MASK) | (((val) << (31-31))& DPAA_SGTE_OFFSET_MASK) )) /**< Macro to set SGTE OFFSET field */ ++/* @} */ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++#define DPAA_LIODN_DONT_OVERRIDE (-1) ++ ++/** @} */ /* end of DPAA_grp group */ ++ ++ ++#endif /* __DPAA_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_ext.h +new file mode 100644 +index 0000000..efbe6d3 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_ext.h +@@ -0,0 +1,1705 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File fm_ext.h ++ ++ @Description FM Application Programming Interface. ++*//***************************************************************************/ ++#ifndef __FM_EXT ++#define __FM_EXT ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "dpaa_ext.h" ++#include "fsl_fman_sp.h" ++ ++/**************************************************************************//** ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_lib_grp FM library ++ ++ @Description FM API functions, definitions and enums. ++ ++ The FM module is the main driver module and is a mandatory module ++ for FM driver users. This module must be initialized first prior ++ to any other drivers modules. ++ The FM is a "singleton" module. It is responsible of the common ++ HW modules: FPM, DMA, common QMI and common BMI initializations and ++ run-time control routines. This module must be initialized always ++ when working with any of the FM modules. ++ NOTE - We assume that the FM library will be initialized only by core No. 0! ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Enum for defining port types ++*//***************************************************************************/ ++typedef enum e_FmPortType { ++ e_FM_PORT_TYPE_OH_OFFLINE_PARSING = 0, /**< Offline parsing port */ ++ e_FM_PORT_TYPE_RX, /**< 1G Rx port */ ++ e_FM_PORT_TYPE_RX_10G, /**< 10G Rx port */ ++ e_FM_PORT_TYPE_TX, /**< 1G Tx port */ ++ e_FM_PORT_TYPE_TX_10G, /**< 10G Tx port */ ++ e_FM_PORT_TYPE_DUMMY ++} e_FmPortType; ++ ++/**************************************************************************//** ++ @Collection General FM defines ++*//***************************************************************************/ ++#define FM_MAX_NUM_OF_PARTITIONS 64 /**< Maximum number of partitions */ ++#define FM_PHYS_ADDRESS_SIZE 6 /**< FM Physical address size */ ++/* @} */ ++ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ ++/**************************************************************************//** ++ @Description FM physical Address ++*//***************************************************************************/ ++typedef _Packed struct t_FmPhysAddr { ++ volatile uint8_t high; /**< High part of the physical address */ ++ volatile uint32_t low; /**< Low part of the physical address */ ++} _PackedType t_FmPhysAddr; ++ ++/**************************************************************************//** ++ @Description Parse results memory layout ++*//***************************************************************************/ ++typedef _Packed struct t_FmPrsResult { ++ volatile uint8_t lpid; /**< Logical port id */ ++ volatile uint8_t shimr; /**< Shim header result */ ++ volatile uint16_t l2r; /**< Layer 2 result */ ++ volatile uint16_t l3r; /**< Layer 3 result */ ++ volatile uint8_t l4r; /**< Layer 4 result */ ++ volatile uint8_t cplan; /**< Classification plan id */ ++ volatile uint16_t nxthdr; /**< Next Header */ ++ volatile uint16_t cksum; /**< Running-sum */ ++ volatile uint16_t flags_frag_off; /**< Flags & fragment-offset field of the last IP-header */ ++ volatile uint8_t route_type; /**< Routing type field of a IPv6 routing extension header */ ++ volatile uint8_t rhp_ip_valid; /**< Routing Extension Header Present; last bit is IP valid */ ++ volatile uint8_t shim_off[2]; /**< Shim offset */ ++ volatile uint8_t ip_pid_off; /**< IP PID (last IP-proto) offset */ ++ volatile uint8_t eth_off; /**< ETH offset */ ++ volatile uint8_t llc_snap_off; /**< LLC_SNAP offset */ ++ volatile uint8_t vlan_off[2]; /**< VLAN offset */ ++ volatile uint8_t etype_off; /**< ETYPE offset */ ++ volatile uint8_t pppoe_off; /**< PPP offset */ ++ volatile uint8_t mpls_off[2]; /**< MPLS offset */ ++ volatile uint8_t ip_off[2]; /**< IP offset */ ++ volatile uint8_t gre_off; /**< GRE offset */ ++ volatile uint8_t l4_off; /**< Layer 4 offset */ ++ volatile uint8_t nxthdr_off; /**< Parser end point */ ++} _PackedType t_FmPrsResult; ++ ++/**************************************************************************//** ++ @Collection FM Parser results ++*//***************************************************************************/ ++#define FM_PR_L2_VLAN_STACK 0x00000100 /**< Parse Result: VLAN stack */ ++#define FM_PR_L2_ETHERNET 0x00008000 /**< Parse Result: Ethernet*/ ++#define FM_PR_L2_VLAN 0x00004000 /**< Parse Result: VLAN */ ++#define FM_PR_L2_LLC_SNAP 0x00002000 /**< Parse Result: LLC_SNAP */ ++#define FM_PR_L2_MPLS 0x00001000 /**< Parse Result: MPLS */ ++#define FM_PR_L2_PPPoE 0x00000800 /**< Parse Result: PPPoE */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection FM Frame descriptor macros ++*//***************************************************************************/ ++#define FM_FD_CMD_FCO 0x80000000 /**< Frame queue Context Override */ ++#define FM_FD_CMD_RPD 0x40000000 /**< Read Prepended Data */ ++#define FM_FD_CMD_UPD 0x20000000 /**< Update Prepended Data */ ++#define FM_FD_CMD_DTC 0x10000000 /**< Do L4 Checksum */ ++#define FM_FD_CMD_DCL4C 0x10000000 /**< Didn't calculate L4 Checksum */ ++#define FM_FD_CMD_CFQ 0x00ffffff /**< Confirmation Frame Queue */ ++ ++#define FM_FD_ERR_UNSUPPORTED_FORMAT 0x04000000 /**< Not for Rx-Port! Unsupported Format */ ++#define FM_FD_ERR_LENGTH 0x02000000 /**< Not for Rx-Port! Length Error */ ++#define FM_FD_ERR_DMA 0x01000000 /**< DMA Data error */ ++ ++#define FM_FD_IPR 0x00000001 /**< IPR frame (not error) */ ++ ++#define FM_FD_ERR_IPR_NCSP (0x00100000 | FM_FD_IPR) /**< IPR non-consistent-sp */ ++#define FM_FD_ERR_IPR (0x00200000 | FM_FD_IPR) /**< IPR error */ ++#define FM_FD_ERR_IPR_TO (0x00300000 | FM_FD_IPR) /**< IPR timeout */ ++ ++#ifdef FM_CAPWAP_SUPPORT ++#define FM_FD_ERR_CRE 0x00200000 ++#define FM_FD_ERR_CHE 0x00100000 ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++#define FM_FD_ERR_PHYSICAL 0x00080000 /**< Rx FIFO overflow, FCS error, code error, running disparity ++ error (SGMII and TBI modes), FIFO parity error. PHY ++ Sequence error, PHY error control character detected. */ ++#define FM_FD_ERR_SIZE 0x00040000 /**< Frame too long OR Frame size exceeds max_length_frame */ ++#define FM_FD_ERR_CLS_DISCARD 0x00020000 /**< classification discard */ ++#define FM_FD_ERR_EXTRACTION 0x00008000 /**< Extract Out of Frame */ ++#define FM_FD_ERR_NO_SCHEME 0x00004000 /**< No Scheme Selected */ ++#define FM_FD_ERR_KEYSIZE_OVERFLOW 0x00002000 /**< Keysize Overflow */ ++#define FM_FD_ERR_COLOR_RED 0x00000800 /**< Frame color is red */ ++#define FM_FD_ERR_COLOR_YELLOW 0x00000400 /**< Frame color is yellow */ ++#define FM_FD_ERR_ILL_PLCR 0x00000200 /**< Illegal Policer Profile selected */ ++#define FM_FD_ERR_PLCR_FRAME_LEN 0x00000100 /**< Policer frame length error */ ++#define FM_FD_ERR_PRS_TIMEOUT 0x00000080 /**< Parser Time out Exceed */ ++#define FM_FD_ERR_PRS_ILL_INSTRUCT 0x00000040 /**< Invalid Soft Parser instruction */ ++#define FM_FD_ERR_PRS_HDR_ERR 0x00000020 /**< Header error was identified during parsing */ ++#define FM_FD_ERR_BLOCK_LIMIT_EXCEEDED 0x00000008 /**< Frame parsed beyind 256 first bytes */ ++ ++#define FM_FD_TX_STATUS_ERR_MASK (FM_FD_ERR_UNSUPPORTED_FORMAT | \ ++ FM_FD_ERR_LENGTH | \ ++ FM_FD_ERR_DMA) /**< TX Error FD bits */ ++ ++#define FM_FD_RX_STATUS_ERR_MASK (FM_FD_ERR_UNSUPPORTED_FORMAT | \ ++ FM_FD_ERR_LENGTH | \ ++ FM_FD_ERR_DMA | \ ++ FM_FD_ERR_IPR | \ ++ FM_FD_ERR_IPR_TO | \ ++ FM_FD_ERR_IPR_NCSP | \ ++ FM_FD_ERR_PHYSICAL | \ ++ FM_FD_ERR_SIZE | \ ++ FM_FD_ERR_CLS_DISCARD | \ ++ FM_FD_ERR_COLOR_RED | \ ++ FM_FD_ERR_COLOR_YELLOW | \ ++ FM_FD_ERR_ILL_PLCR | \ ++ FM_FD_ERR_PLCR_FRAME_LEN | \ ++ FM_FD_ERR_EXTRACTION | \ ++ FM_FD_ERR_NO_SCHEME | \ ++ FM_FD_ERR_KEYSIZE_OVERFLOW | \ ++ FM_FD_ERR_PRS_TIMEOUT | \ ++ FM_FD_ERR_PRS_ILL_INSTRUCT | \ ++ FM_FD_ERR_PRS_HDR_ERR | \ ++ FM_FD_ERR_BLOCK_LIMIT_EXCEEDED) /**< RX Error FD bits */ ++ ++#define FM_FD_RX_STATUS_ERR_NON_FM 0x00400000 /**< non Frame-Manager error */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Description Context A ++*//***************************************************************************/ ++typedef _Packed struct t_FmContextA { ++ volatile uint32_t command; /**< ContextA Command */ ++ volatile uint8_t res0[4]; /**< ContextA Reserved bits */ ++} _PackedType t_FmContextA; ++ ++/**************************************************************************//** ++ @Description Context B ++*//***************************************************************************/ ++typedef uint32_t t_FmContextB; ++ ++/**************************************************************************//** ++ @Collection Special Operation options ++*//***************************************************************************/ ++typedef uint32_t fmSpecialOperations_t; /**< typedef for defining Special Operation options */ ++ ++#define FM_SP_OP_IPSEC 0x80000000 /**< activate features that related to IPSec (e.g fix Eth-type) */ ++#define FM_SP_OP_IPSEC_UPDATE_UDP_LEN 0x40000000 /**< update the UDP-Len after Encryption */ ++#define FM_SP_OP_IPSEC_MANIP 0x20000000 /**< handle the IPSec-manip options */ ++#define FM_SP_OP_RPD 0x10000000 /**< Set the RPD bit */ ++#define FM_SP_OP_DCL4C 0x08000000 /**< Set the DCL4C bit */ ++#define FM_SP_OP_CHECK_SEC_ERRORS 0x04000000 /**< Check SEC errors */ ++#define FM_SP_OP_CLEAR_RPD 0x02000000 /**< Clear the RPD bit */ ++#define FM_SP_OP_CAPWAP_DTLS_ENC 0x01000000 /**< activate features that related to CAPWAP-DTLS post Encryption */ ++#define FM_SP_OP_CAPWAP_DTLS_DEC 0x00800000 /**< activate features that related to CAPWAP-DTLS post Decryption */ ++#define FM_SP_OP_IPSEC_NO_ETH_HDR 0x00400000 /**< activate features that related to IPSec without Eth hdr */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection Context A macros ++*//***************************************************************************/ ++#define FM_CONTEXTA_OVERRIDE_MASK 0x80000000 ++#define FM_CONTEXTA_ICMD_MASK 0x40000000 ++#define FM_CONTEXTA_A1_VALID_MASK 0x20000000 ++#define FM_CONTEXTA_MACCMD_MASK 0x00ff0000 ++#define FM_CONTEXTA_MACCMD_VALID_MASK 0x00800000 ++#define FM_CONTEXTA_MACCMD_SECURED_MASK 0x00100000 ++#define FM_CONTEXTA_MACCMD_SC_MASK 0x000f0000 ++#define FM_CONTEXTA_A1_MASK 0x0000ffff ++ ++#define FM_CONTEXTA_GET_OVERRIDE(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_OVERRIDE_MASK) >> (31-0)) ++#define FM_CONTEXTA_GET_ICMD(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_ICMD_MASK) >> (31-1)) ++#define FM_CONTEXTA_GET_A1_VALID(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_A1_VALID_MASK) >> (31-2)) ++#define FM_CONTEXTA_GET_A1(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_A1_MASK) >> (31-31)) ++#define FM_CONTEXTA_GET_MACCMD(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_MACCMD_MASK) >> (31-15)) ++#define FM_CONTEXTA_GET_MACCMD_VALID(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_MACCMD_VALID_MASK) >> (31-8)) ++#define FM_CONTEXTA_GET_MACCMD_SECURED(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_MACCMD_SECURED_MASK) >> (31-11)) ++#define FM_CONTEXTA_GET_MACCMD_SECURE_CHANNEL(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_MACCMD_SC_MASK) >> (31-15)) ++ ++#define FM_CONTEXTA_SET_OVERRIDE(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_OVERRIDE_MASK) | (((uint32_t)(val) << (31-0)) & FM_CONTEXTA_OVERRIDE_MASK) )) ++#define FM_CONTEXTA_SET_ICMD(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_ICMD_MASK) | (((val) << (31-1)) & FM_CONTEXTA_ICMD_MASK) )) ++#define FM_CONTEXTA_SET_A1_VALID(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_A1_VALID_MASK) | (((val) << (31-2)) & FM_CONTEXTA_A1_VALID_MASK) )) ++#define FM_CONTEXTA_SET_A1(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_A1_MASK) | (((val) << (31-31)) & FM_CONTEXTA_A1_MASK) )) ++#define FM_CONTEXTA_SET_MACCMD(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_MACCMD_MASK) | (((val) << (31-15)) & FM_CONTEXTA_MACCMD_MASK) )) ++#define FM_CONTEXTA_SET_MACCMD_VALID(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_MACCMD_VALID_MASK) | (((val) << (31-8)) & FM_CONTEXTA_MACCMD_VALID_MASK) )) ++#define FM_CONTEXTA_SET_MACCMD_SECURED(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_MACCMD_SECURED_MASK) | (((val) << (31-11)) & FM_CONTEXTA_MACCMD_SECURED_MASK) )) ++#define FM_CONTEXTA_SET_MACCMD_SECURE_CHANNEL(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_MACCMD_SC_MASK) | (((val) << (31-15)) & FM_CONTEXTA_MACCMD_SC_MASK) )) ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection Context B macros ++*//***************************************************************************/ ++#define FM_CONTEXTB_FQID_MASK 0x00ffffff ++ ++#define FM_CONTEXTB_GET_FQID(contextB) (*((t_FmContextB *)contextB) & FM_CONTEXTB_FQID_MASK) ++#define FM_CONTEXTB_SET_FQID(contextB,val) (*((t_FmContextB *)contextB) = ((*((t_FmContextB *)contextB) & ~FM_CONTEXTB_FQID_MASK) | ((val) & FM_CONTEXTB_FQID_MASK))) ++/* @} */ ++ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ ++ ++/**************************************************************************//** ++ @Description FM Exceptions ++*//***************************************************************************/ ++typedef enum e_FmExceptions { ++ e_FM_EX_DMA_BUS_ERROR = 0, /**< DMA bus error. */ ++ e_FM_EX_DMA_READ_ECC, /**< Read Buffer ECC error (Valid for FM rev < 6)*/ ++ e_FM_EX_DMA_SYSTEM_WRITE_ECC, /**< Write Buffer ECC error on system side (Valid for FM rev < 6)*/ ++ e_FM_EX_DMA_FM_WRITE_ECC, /**< Write Buffer ECC error on FM side (Valid for FM rev < 6)*/ ++ e_FM_EX_DMA_SINGLE_PORT_ECC, /**< Single Port ECC error on FM side (Valid for FM rev > 6)*/ ++ e_FM_EX_FPM_STALL_ON_TASKS, /**< Stall of tasks on FPM */ ++ e_FM_EX_FPM_SINGLE_ECC, /**< Single ECC on FPM. */ ++ e_FM_EX_FPM_DOUBLE_ECC, /**< Double ECC error on FPM ram access */ ++ e_FM_EX_QMI_SINGLE_ECC, /**< Single ECC on QMI. */ ++ e_FM_EX_QMI_DOUBLE_ECC, /**< Double bit ECC occurred on QMI */ ++ e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID,/**< Dequeue from unknown port id */ ++ e_FM_EX_BMI_LIST_RAM_ECC, /**< Linked List RAM ECC error */ ++ e_FM_EX_BMI_STORAGE_PROFILE_ECC, /**< Storage Profile ECC Error */ ++ e_FM_EX_BMI_STATISTICS_RAM_ECC, /**< Statistics Count RAM ECC Error Enable */ ++ e_FM_EX_BMI_DISPATCH_RAM_ECC, /**< Dispatch RAM ECC Error Enable */ ++ e_FM_EX_IRAM_ECC, /**< Double bit ECC occurred on IRAM*/ ++ e_FM_EX_MURAM_ECC /**< Double bit ECC occurred on MURAM*/ ++} e_FmExceptions; ++ ++/**************************************************************************//** ++ @Description Enum for defining port DMA swap mode ++*//***************************************************************************/ ++typedef enum e_FmDmaSwapOption { ++ e_FM_DMA_NO_SWP = FMAN_DMA_NO_SWP, /**< No swap, transfer data as is.*/ ++ e_FM_DMA_SWP_PPC_LE = FMAN_DMA_SWP_PPC_LE, /**< The transferred data should be swapped ++ in PowerPc Little Endian mode. */ ++ e_FM_DMA_SWP_BE = FMAN_DMA_SWP_BE /**< The transferred data should be swapped ++ in Big Endian mode */ ++} e_FmDmaSwapOption; ++ ++/**************************************************************************//** ++ @Description Enum for defining port DMA cache attributes ++*//***************************************************************************/ ++typedef enum e_FmDmaCacheOption { ++ e_FM_DMA_NO_STASH = FMAN_DMA_NO_STASH, /**< Cacheable, no Allocate (No Stashing) */ ++ e_FM_DMA_STASH = FMAN_DMA_STASH /**< Cacheable and Allocate (Stashing on) */ ++} e_FmDmaCacheOption; ++ ++ ++/**************************************************************************//** ++ @Group FM_init_grp FM Initialization Unit ++ ++ @Description FM Initialization Unit ++ ++ Initialization Flow ++ Initialization of the FM Module will be carried out by the application ++ according to the following sequence: ++ - Calling the configuration routine with basic parameters. ++ - Calling the advance initialization routines to change driver's defaults. ++ - Calling the initialization routine. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function t_FmExceptionsCallback ++ ++ @Description Exceptions user callback routine, will be called upon an ++ exception passing the exception identification. ++ ++ @Param[in] h_App - User's application descriptor. ++ @Param[in] exception - The exception. ++*//***************************************************************************/ ++typedef void (t_FmExceptionsCallback)(t_Handle h_App, ++ e_FmExceptions exception); ++ ++ ++/**************************************************************************//** ++ @Function t_FmBusErrorCallback ++ ++ @Description Bus error user callback routine, will be called upon a ++ bus error, passing parameters describing the errors and the owner. ++ ++ @Param[in] h_App - User's application descriptor. ++ @Param[in] portType - Port type (e_FmPortType) ++ @Param[in] portId - Port id - relative to type. ++ @Param[in] addr - Address that caused the error ++ @Param[in] tnum - Owner of error ++ @Param[in] liodn - Logical IO device number ++*//***************************************************************************/ ++typedef void (t_FmBusErrorCallback) (t_Handle h_App, ++ e_FmPortType portType, ++ uint8_t portId, ++ uint64_t addr, ++ uint8_t tnum, ++ uint16_t liodn); ++ ++/**************************************************************************//** ++ @Description A structure for defining buffer prefix area content. ++*//***************************************************************************/ ++typedef struct t_FmBufferPrefixContent { ++ uint16_t privDataSize; /**< Number of bytes to be left at the beginning ++ of the external buffer; Note that the private-area will ++ start from the base of the buffer address. */ ++ bool passPrsResult; /**< TRUE to pass the parse result to/from the FM; ++ User may use FM_PORT_GetBufferPrsResult() in order to ++ get the parser-result from a buffer. */ ++ bool passTimeStamp; /**< TRUE to pass the timeStamp to/from the FM ++ User may use FM_PORT_GetBufferTimeStamp() in order to ++ get the parser-result from a buffer. */ ++ bool passHashResult; /**< TRUE to pass the KG hash result to/from the FM ++ User may use FM_PORT_GetBufferHashResult() in order to ++ get the parser-result from a buffer. */ ++ bool passAllOtherPCDInfo;/**< Add all other Internal-Context information: ++ AD, hash-result, key, etc. */ ++ uint16_t dataAlign; /**< 0 to use driver's default alignment [DEFAULT_FM_SP_bufferPrefixContent_dataAlign], ++ other value for selecting a data alignment (must be a power of 2); ++ if write optimization is used, must be >= 16. */ ++ uint8_t manipExtraSpace; /**< Maximum extra size needed (insertion-size minus removal-size); ++ Note that this field impacts the size of the buffer-prefix ++ (i.e. it pushes the data offset); ++ This field is irrelevant if DPAA_VERSION==10 */ ++} t_FmBufferPrefixContent; ++ ++/**************************************************************************//** ++ @Description A structure of information about each of the external ++ buffer pools used by a port or storage-profile. ++*//***************************************************************************/ ++typedef struct t_FmExtPoolParams { ++ uint8_t id; /**< External buffer pool id */ ++ uint16_t size; /**< External buffer pool buffer size */ ++} t_FmExtPoolParams; ++ ++/**************************************************************************//** ++ @Description A structure for informing the driver about the external ++ buffer pools allocated in the BM and used by a port or a ++ storage-profile. ++*//***************************************************************************/ ++typedef struct t_FmExtPools { ++ uint8_t numOfPoolsUsed; /**< Number of pools use by this port */ ++ t_FmExtPoolParams extBufPool[FM_PORT_MAX_NUM_OF_EXT_POOLS]; ++ /**< Parameters for each port */ ++} t_FmExtPools; ++ ++/**************************************************************************//** ++ @Description A structure for defining backup BM Pools. ++*//***************************************************************************/ ++typedef struct t_FmBackupBmPools { ++ uint8_t numOfBackupPools; /**< Number of BM backup pools - ++ must be smaller than the total number of ++ pools defined for the specified port.*/ ++ uint8_t poolIds[FM_PORT_MAX_NUM_OF_EXT_POOLS]; ++ /**< numOfBackupPools pool id's, specifying which ++ pools should be used only as backup. Pool ++ id's specified here must be a subset of the ++ pools used by the specified port.*/ ++} t_FmBackupBmPools; ++ ++/**************************************************************************//** ++ @Description A structure for defining BM pool depletion criteria ++*//***************************************************************************/ ++typedef struct t_FmBufPoolDepletion { ++ bool poolsGrpModeEnable; /**< select mode in which pause frames will be sent after ++ a number of pools (all together!) are depleted */ ++ uint8_t numOfPools; /**< the number of depleted pools that will invoke ++ pause frames transmission. */ ++ bool poolsToConsider[BM_MAX_NUM_OF_POOLS]; ++ /**< For each pool, TRUE if it should be considered for ++ depletion (Note - this pool must be used by this port!). */ ++ bool singlePoolModeEnable; /**< select mode in which pause frames will be sent after ++ a single-pool is depleted; */ ++ bool poolsToConsiderForSingleMode[BM_MAX_NUM_OF_POOLS]; ++ /**< For each pool, TRUE if it should be considered for ++ depletion (Note - this pool must be used by this port!) */ ++#if (DPAA_VERSION >= 11) ++ bool pfcPrioritiesEn[FM_MAX_NUM_OF_PFC_PRIORITIES]; ++ /**< This field is used by the MAC as the Priority Enable Vector in the PFC frame which is transmitted */ ++#endif /* (DPAA_VERSION >= 11) */ ++} t_FmBufPoolDepletion; ++ ++/**************************************************************************//** ++ @Description A Structure for defining Ucode patch for loading. ++*//***************************************************************************/ ++typedef struct t_FmFirmwareParams { ++ uint32_t size; /**< Size of uCode */ ++ uint32_t *p_Code; /**< A pointer to the uCode */ ++} t_FmFirmwareParams; ++ ++/**************************************************************************//** ++ @Description A Structure for defining FM initialization parameters ++*//***************************************************************************/ ++typedef struct t_FmParams { ++ uint8_t fmId; /**< Index of the FM */ ++ uint8_t guestId; /**< FM Partition Id */ ++ uintptr_t baseAddr; /**< A pointer to base of memory mapped FM registers (virtual); ++ this field is optional when the FM runs in "guest-mode" ++ (i.e. guestId != NCSW_MASTER_ID); in that case, the driver will ++ use the memory-map instead of calling the IPC where possible; ++ NOTE that this should include ALL common registers of the FM including ++ the PCD registers area (i.e. until the VSP pages - 880KB). */ ++ t_Handle h_FmMuram; /**< A handle of an initialized MURAM object, ++ to be used by the FM. */ ++ uint16_t fmClkFreq; /**< In Mhz; ++ Relevant when FM not runs in "guest-mode". */ ++ uint16_t fmMacClkRatio; /**< FM MAC Clock ratio, for backward comparability: ++ when fmMacClkRatio = 0, ratio is 2:1 ++ when fmMacClkRatio = 1, ratio is 1:1 */ ++ t_FmExceptionsCallback *f_Exception; /**< An application callback routine to handle exceptions; ++ Relevant when FM not runs in "guest-mode". */ ++ t_FmBusErrorCallback *f_BusError; /**< An application callback routine to handle exceptions; ++ Relevant when FM not runs in "guest-mode". */ ++ t_Handle h_App; /**< A handle to an application layer object; This handle will ++ be passed by the driver upon calling the above callbacks; ++ Relevant when FM not runs in "guest-mode". */ ++ int irq; /**< FM interrupt source for normal events; ++ Relevant when FM not runs in "guest-mode". */ ++ int errIrq; /**< FM interrupt source for errors; ++ Relevant when FM not runs in "guest-mode". */ ++ t_FmFirmwareParams firmware; /**< The firmware parameters structure; ++ Relevant when FM not runs in "guest-mode". */ ++ ++#if (DPAA_VERSION >= 11) ++ uintptr_t vspBaseAddr; /**< A pointer to base of memory mapped FM VSP registers (virtual); ++ i.e. up to 24KB, depending on the specific chip. */ ++ uint8_t partVSPBase; /**< The first Virtual-Storage-Profile-id dedicated to this partition. ++ NOTE: this parameter relevant only when working with multiple partitions. */ ++ uint8_t partNumOfVSPs; /**< Number of VSPs dedicated to this partition. ++ NOTE: this parameter relevant only when working with multiple partitions. */ ++#endif /* (DPAA_VERSION >= 11) */ ++} t_FmParams; ++ ++ ++/**************************************************************************//** ++ @Function FM_Config ++ ++ @Description Creates the FM module and returns its handle (descriptor). ++ This descriptor must be passed as first parameter to all other ++ FM function calls. ++ ++ No actual initialization or configuration of FM hardware is ++ done by this routine. All FM parameters get default values that ++ may be changed by calling one or more of the advance config routines. ++ ++ @Param[in] p_FmParams - A pointer to a data structure of mandatory FM parameters ++ ++ @Return A handle to the FM object, or NULL for Failure. ++*//***************************************************************************/ ++t_Handle FM_Config(t_FmParams *p_FmParams); ++ ++/**************************************************************************//** ++ @Function FM_Init ++ ++ @Description Initializes the FM module by defining the software structure ++ and configuring the hardware registers. ++ ++ @Param[in] h_Fm - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_Init(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_Free ++ ++ @Description Frees all resources that were assigned to FM module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_Fm - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_Free(t_Handle h_Fm); ++ ++ ++/**************************************************************************//** ++ @Group FM_advanced_init_grp FM Advanced Configuration Unit ++ ++ @Description Advanced configuration routines are optional routines that may ++ be called in order to change the default driver settings. ++ ++ Note: Advanced configuration routines are not available for guest partition. ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Enum for selecting DMA debug mode ++*//***************************************************************************/ ++typedef enum e_FmDmaDbgCntMode { ++ e_FM_DMA_DBG_NO_CNT = 0, /**< No counting */ ++ e_FM_DMA_DBG_CNT_DONE, /**< Count DONE commands */ ++ e_FM_DMA_DBG_CNT_COMM_Q_EM, /**< count command queue emergency signals */ ++ e_FM_DMA_DBG_CNT_INT_READ_EM, /**< Count Internal Read buffer emergency signal */ ++ e_FM_DMA_DBG_CNT_INT_WRITE_EM, /**< Count Internal Write buffer emergency signal */ ++ e_FM_DMA_DBG_CNT_FPM_WAIT, /**< Count FPM WAIT signal */ ++ e_FM_DMA_DBG_CNT_SIGLE_BIT_ECC, /**< Single bit ECC errors. */ ++ e_FM_DMA_DBG_CNT_RAW_WAR_PROT /**< Number of times there was a need for RAW & WAR protection. */ ++} e_FmDmaDbgCntMode; ++ ++/**************************************************************************//** ++ @Description Enum for selecting DMA Cache Override ++*//***************************************************************************/ ++typedef enum e_FmDmaCacheOverride { ++ e_FM_DMA_NO_CACHE_OR = 0, /**< No override of the Cache field */ ++ e_FM_DMA_NO_STASH_DATA, /**< Data should not be stashed in system level cache */ ++ e_FM_DMA_MAY_STASH_DATA, /**< Data may be stashed in system level cache */ ++ e_FM_DMA_STASH_DATA /**< Data should be stashed in system level cache */ ++} e_FmDmaCacheOverride; ++ ++/**************************************************************************//** ++ @Description Enum for selecting DMA External Bus Priority ++*//***************************************************************************/ ++typedef enum e_FmDmaExtBusPri { ++ e_FM_DMA_EXT_BUS_NORMAL = 0, /**< Normal priority */ ++ e_FM_DMA_EXT_BUS_EBS, /**< AXI extended bus service priority */ ++ e_FM_DMA_EXT_BUS_SOS, /**< AXI sos priority */ ++ e_FM_DMA_EXT_BUS_EBS_AND_SOS /**< AXI ebs + sos priority */ ++} e_FmDmaExtBusPri; ++ ++/**************************************************************************//** ++ @Description Enum for choosing the field that will be output on AID ++*//***************************************************************************/ ++typedef enum e_FmDmaAidMode { ++ e_FM_DMA_AID_OUT_PORT_ID = 0, /**< 4 LSB of PORT_ID */ ++ e_FM_DMA_AID_OUT_TNUM /**< 4 LSB of TNUM */ ++} e_FmDmaAidMode; ++ ++/**************************************************************************//** ++ @Description Enum for selecting FPM Catastrophic error behavior ++*//***************************************************************************/ ++typedef enum e_FmCatastrophicErr { ++ e_FM_CATASTROPHIC_ERR_STALL_PORT = 0, /**< Port_ID is stalled (only reset can release it) */ ++ e_FM_CATASTROPHIC_ERR_STALL_TASK /**< Only erroneous task is stalled */ ++} e_FmCatastrophicErr; ++ ++/**************************************************************************//** ++ @Description Enum for selecting FPM DMA Error behavior ++*//***************************************************************************/ ++typedef enum e_FmDmaErr { ++ e_FM_DMA_ERR_CATASTROPHIC = 0, /**< Dma error is treated as a catastrophic ++ error (e_FmCatastrophicErr)*/ ++ e_FM_DMA_ERR_REPORT /**< Dma error is just reported */ ++} e_FmDmaErr; ++ ++/**************************************************************************//** ++ @Description Enum for selecting DMA Emergency level by BMI emergency signal ++*//***************************************************************************/ ++typedef enum e_FmDmaEmergencyLevel { ++ e_FM_DMA_EM_EBS = 0, /**< EBS emergency */ ++ e_FM_DMA_EM_SOS /**< SOS emergency */ ++} e_FmDmaEmergencyLevel; ++ ++/**************************************************************************//** ++ @Collection Enum for selecting DMA Emergency options ++*//***************************************************************************/ ++typedef uint32_t fmEmergencyBus_t; /**< DMA emergency options */ ++ ++#define FM_DMA_MURAM_READ_EMERGENCY 0x00800000 /**< Enable emergency for MURAM1 */ ++#define FM_DMA_MURAM_WRITE_EMERGENCY 0x00400000 /**< Enable emergency for MURAM2 */ ++#define FM_DMA_EXT_BUS_EMERGENCY 0x00100000 /**< Enable emergency for external bus */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Description A structure for defining DMA emergency level ++*//***************************************************************************/ ++typedef struct t_FmDmaEmergency { ++ fmEmergencyBus_t emergencyBusSelect; /**< An OR of the busses where emergency ++ should be enabled */ ++ e_FmDmaEmergencyLevel emergencyLevel; /**< EBS/SOS */ ++} t_FmDmaEmergency; ++ ++/**************************************************************************//* ++ @Description structure for defining FM threshold ++*//***************************************************************************/ ++typedef struct t_FmThresholds { ++ uint8_t dispLimit; /**< The number of times a frames may ++ be passed in the FM before assumed to ++ be looping. */ ++ uint8_t prsDispTh; /**< This is the number pf packets that may be ++ queued in the parser dispatch queue*/ ++ uint8_t plcrDispTh; /**< This is the number pf packets that may be ++ queued in the policer dispatch queue*/ ++ uint8_t kgDispTh; /**< This is the number pf packets that may be ++ queued in the keygen dispatch queue*/ ++ uint8_t bmiDispTh; /**< This is the number pf packets that may be ++ queued in the BMI dispatch queue*/ ++ uint8_t qmiEnqDispTh; /**< This is the number pf packets that may be ++ queued in the QMI enqueue dispatch queue*/ ++ uint8_t qmiDeqDispTh; /**< This is the number pf packets that may be ++ queued in the QMI dequeue dispatch queue*/ ++ uint8_t fmCtl1DispTh; /**< This is the number pf packets that may be ++ queued in fmCtl1 dispatch queue*/ ++ uint8_t fmCtl2DispTh; /**< This is the number pf packets that may be ++ queued in fmCtl2 dispatch queue*/ ++} t_FmThresholds; ++ ++/**************************************************************************//* ++ @Description structure for defining DMA thresholds ++*//***************************************************************************/ ++typedef struct t_FmDmaThresholds { ++ uint8_t assertEmergency; /**< When this value is reached, ++ assert emergency (Threshold)*/ ++ uint8_t clearEmergency; /**< After emergency is asserted, it is held ++ until this value is reached (Hystheresis) */ ++} t_FmDmaThresholds; ++ ++ ++/**************************************************************************//** ++ @Function FM_ConfigResetOnInit ++ ++ @Description Define whether to reset the FM before initialization. ++ Change the default configuration [DEFAULT_resetOnInit]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] enable When TRUE, FM will be reset before any initialization. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigResetOnInit(t_Handle h_Fm, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_ConfigTotalFifoSize ++ ++ @Description Define Total FIFO size for the whole FM. ++ Calling this routine changes the total Fifo size in the internal driver ++ data base from its default configuration [DEFAULT_totalFifoSize] ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] totalFifoSize The selected new value. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigTotalFifoSize(t_Handle h_Fm, uint32_t totalFifoSize); ++ ++ /**************************************************************************//** ++ @Function FM_ConfigDmaCacheOverride ++ ++ @Description Define cache override mode. ++ Calling this routine changes the cache override mode ++ in the internal driver data base from its default configuration [DEFAULT_cacheOverride] ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] cacheOverride The selected new value. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaCacheOverride(t_Handle h_Fm, e_FmDmaCacheOverride cacheOverride); ++ ++/**************************************************************************//** ++ @Function FM_ConfigDmaAidOverride ++ ++ @Description Define DMA AID override mode. ++ Calling this routine changes the AID override mode ++ in the internal driver data base from its default configuration [DEFAULT_aidOverride] ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] aidOverride The selected new value. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaAidOverride(t_Handle h_Fm, bool aidOverride); ++ ++/**************************************************************************//** ++ @Function FM_ConfigDmaAidMode ++ ++ @Description Define DMA AID mode. ++ Calling this routine changes the AID mode in the internal ++ driver data base from its default configuration [DEFAULT_aidMode] ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] aidMode The selected new value. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaAidMode(t_Handle h_Fm, e_FmDmaAidMode aidMode); ++ ++/**************************************************************************//** ++ @Function FM_ConfigDmaAxiDbgNumOfBeats ++ ++ @Description Define DMA AXI number of beats. ++ Calling this routine changes the AXI number of beats in the internal ++ driver data base from its default configuration [DEFAULT_axiDbgNumOfBeats] ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] axiDbgNumOfBeats The selected new value. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaAxiDbgNumOfBeats(t_Handle h_Fm, uint8_t axiDbgNumOfBeats); ++ ++/**************************************************************************//** ++ @Function FM_ConfigDmaCamNumOfEntries ++ ++ @Description Define number of CAM entries. ++ Calling this routine changes the number of CAM entries in the internal ++ driver data base from its default configuration [DEFAULT_dmaCamNumOfEntries]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] numOfEntries The selected new value. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaCamNumOfEntries(t_Handle h_Fm, uint8_t numOfEntries); ++ ++/**************************************************************************//** ++ @Function FM_ConfigEnableCounters ++ ++ @Description Obsolete, always return E_OK. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_ConfigEnableCounters(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_ConfigDmaDbgCounter ++ ++ @Description Define DMA debug counter. ++ Calling this routine changes the number of the DMA debug counter in the internal ++ driver data base from its default configuration [DEFAULT_dmaDbgCntMode]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] fmDmaDbgCntMode An enum selecting the debug counter mode. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaDbgCounter(t_Handle h_Fm, e_FmDmaDbgCntMode fmDmaDbgCntMode); ++ ++/**************************************************************************//** ++ @Function FM_ConfigDmaStopOnBusErr ++ ++ @Description Define bus error behavior. ++ Calling this routine changes the bus error behavior definition ++ in the internal driver data base from its default ++ configuration [DEFAULT_dmaStopOnBusError]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] stop TRUE to stop on bus error, FALSE to continue. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ Only if bus error is enabled. ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaStopOnBusErr(t_Handle h_Fm, bool stop); ++ ++/**************************************************************************//** ++ @Function FM_ConfigDmaEmergency ++ ++ @Description Define DMA emergency. ++ Calling this routine changes the DMA emergency definition ++ in the internal driver data base from its default ++ configuration where's it's disabled. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] p_Emergency An OR mask of all required options. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaEmergency(t_Handle h_Fm, t_FmDmaEmergency *p_Emergency); ++ ++/**************************************************************************//** ++ @Function FM_ConfigDmaErr ++ ++ @Description DMA error treatment. ++ Calling this routine changes the DMA error treatment ++ in the internal driver data base from its default ++ configuration [DEFAULT_dmaErr]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] dmaErr The selected new choice. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaErr(t_Handle h_Fm, e_FmDmaErr dmaErr); ++ ++/**************************************************************************//** ++ @Function FM_ConfigCatastrophicErr ++ ++ @Description Define FM behavior on catastrophic error. ++ Calling this routine changes the FM behavior on catastrophic ++ error in the internal driver data base from its default ++ [DEFAULT_catastrophicErr]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] catastrophicErr The selected new choice. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigCatastrophicErr(t_Handle h_Fm, e_FmCatastrophicErr catastrophicErr); ++ ++/**************************************************************************//** ++ @Function FM_ConfigEnableMuramTestMode ++ ++ @Description Enable MURAM test mode. ++ Calling this routine changes the internal driver data base ++ from its default selection of test mode where it's disabled. ++ This routine is only avaiable on old FM revisions (FMan v2). ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigEnableMuramTestMode(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_ConfigEnableIramTestMode ++ ++ @Description Enable IRAM test mode. ++ Calling this routine changes the internal driver data base ++ from its default selection of test mode where it's disabled. ++ This routine is only avaiable on old FM revisions (FMan v2). ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigEnableIramTestMode(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_ConfigHaltOnExternalActivation ++ ++ @Description Define FM behavior on external halt activation. ++ Calling this routine changes the FM behavior on external halt ++ activation in the internal driver data base from its default ++ [DEFAULT_haltOnExternalActivation]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] enable TRUE to enable halt on external halt ++ activation. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigHaltOnExternalActivation(t_Handle h_Fm, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_ConfigHaltOnUnrecoverableEccError ++ ++ @Description Define FM behavior on external halt activation. ++ Calling this routine changes the FM behavior on unrecoverable ++ ECC error in the internal driver data base from its default ++ [DEFAULT_haltOnUnrecoverableEccError]. ++ This routine is only avaiable on old FM revisions (FMan v2). ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] enable TRUE to enable halt on unrecoverable Ecc error ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigHaltOnUnrecoverableEccError(t_Handle h_Fm, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_ConfigException ++ ++ @Description Define FM exceptions. ++ Calling this routine changes the exceptions defaults in the ++ internal driver data base where all exceptions are enabled. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] exception The exception to be selected. ++ @Param[in] enable TRUE to enable interrupt, FALSE to mask it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigException(t_Handle h_Fm, e_FmExceptions exception, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_ConfigExternalEccRamsEnable ++ ++ @Description Select external ECC enabling. ++ Calling this routine changes the ECC enabling control in the internal ++ driver data base from its default [DEFAULT_externalEccRamsEnable]. ++ When this option is enabled Rams ECC enabling is not effected ++ by FM_EnableRamsEcc/FM_DisableRamsEcc, but by a JTAG. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] enable TRUE to enable this option. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigExternalEccRamsEnable(t_Handle h_Fm, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_ConfigTnumAgingPeriod ++ ++ @Description Define Tnum aging period. ++ Calling this routine changes the Tnum aging of dequeue TNUMs ++ in the QMI in the internal driver data base from its default ++ [DEFAULT_tnumAgingPeriod]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] tnumAgingPeriod Tnum Aging Period in microseconds. ++ Note that period is recalculated in units of ++ 64 FM clocks. Driver will pick the closest ++ possible period. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++ NOTE that if some MAC is configured for PFC, '0' value is NOT ++ allowed. ++*//***************************************************************************/ ++t_Error FM_ConfigTnumAgingPeriod(t_Handle h_Fm, uint16_t tnumAgingPeriod); ++ ++/**************************************************************************//* ++ @Function FM_ConfigDmaEmergencySmoother ++ ++ @Description Define DMA emergency smoother. ++ Calling this routine changes the definition of the minimum ++ amount of DATA beats transferred on the AXI READ and WRITE ++ ports before lowering the emergency level. ++ By default smoother is disabled. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] emergencyCnt emergency switching counter. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaEmergencySmoother(t_Handle h_Fm, uint32_t emergencyCnt); ++ ++/**************************************************************************//* ++ @Function FM_ConfigThresholds ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default FM threshold configuration: ++ dispLimit: [DEFAULT_dispLimit] ++ prsDispTh: [DEFAULT_prsDispTh] ++ plcrDispTh: [DEFAULT_plcrDispTh] ++ kgDispTh: [DEFAULT_kgDispTh] ++ bmiDispTh: [DEFAULT_bmiDispTh] ++ qmiEnqDispTh: [DEFAULT_qmiEnqDispTh] ++ qmiDeqDispTh: [DEFAULT_qmiDeqDispTh] ++ fmCtl1DispTh: [DEFAULT_fmCtl1DispTh] ++ fmCtl2DispTh: [DEFAULT_fmCtl2DispTh] ++ ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] p_FmThresholds A structure of threshold parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigThresholds(t_Handle h_Fm, t_FmThresholds *p_FmThresholds); ++ ++/**************************************************************************//* ++ @Function FM_ConfigDmaSosEmergencyThreshold ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default dma SOS emergency configuration [DEFAULT_dmaSosEmergency] ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] dmaSosEmergency The selected new value. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaSosEmergencyThreshold(t_Handle h_Fm, uint32_t dmaSosEmergency); ++ ++/**************************************************************************//* ++ @Function FM_ConfigDmaWriteBufThresholds ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default configuration of DMA write buffer threshold ++ assertEmergency: [DEFAULT_dmaWriteIntBufLow] ++ clearEmergency: [DEFAULT_dmaWriteIntBufHigh] ++ This routine is only avaiable on old FM revisions (FMan v2). ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] p_FmDmaThresholds A structure of thresholds to define emergency behavior - ++ When 'assertEmergency' value is reached, emergency is asserted, ++ then it is held until 'clearEmergency' value is reached. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaWriteBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds); ++ ++ /**************************************************************************//* ++ @Function FM_ConfigDmaCommQThresholds ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default configuration of DMA command queue threshold ++ assertEmergency: [DEFAULT_dmaCommQLow] ++ clearEmergency: [DEFAULT_dmaCommQHigh] ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] p_FmDmaThresholds A structure of thresholds to define emergency behavior - ++ When 'assertEmergency' value is reached, emergency is asserted, ++ then it is held until 'clearEmergency' value is reached.. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaCommQThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds); ++ ++/**************************************************************************//* ++ @Function FM_ConfigDmaReadBufThresholds ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default configuration of DMA read buffer threshold ++ assertEmergency: [DEFAULT_dmaReadIntBufLow] ++ clearEmergency: [DEFAULT_dmaReadIntBufHigh] ++ This routine is only avaiable on old FM revisions (FMan v2). ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] p_FmDmaThresholds A structure of thresholds to define emergency behavior - ++ When 'assertEmergency' value is reached, emergency is asserted, ++ then it is held until 'clearEmergency' value is reached.. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaReadBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds); ++ ++/**************************************************************************//* ++ @Function FM_ConfigDmaWatchdog ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default watchdog configuration, which is disabled ++ [DEFAULT_dmaWatchdog]. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] watchDogValue The selected new value - in microseconds. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ConfigDmaWatchdog(t_Handle h_Fm, uint32_t watchDogValue); ++ ++/** @} */ /* end of FM_advanced_init_grp group */ ++/** @} */ /* end of FM_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_runtime_control_grp FM Runtime Control Unit ++ ++ @Description FM Runtime control unit API functions, definitions and enums. ++ The FM driver provides a set of control routines. ++ These routines may only be called after the module was fully ++ initialized (both configuration and initialization routines were ++ called). They are typically used to get information from hardware ++ (status, counters/statistics, revision etc.), to modify a current ++ state or to force/enable a required action. Run-time control may ++ be called whenever necessary and as many times as needed. ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Collection General FM defines. ++*//***************************************************************************/ ++#define FM_MAX_NUM_OF_VALID_PORTS (FM_MAX_NUM_OF_OH_PORTS + \ ++ FM_MAX_NUM_OF_1G_RX_PORTS + \ ++ FM_MAX_NUM_OF_10G_RX_PORTS + \ ++ FM_MAX_NUM_OF_1G_TX_PORTS + \ ++ FM_MAX_NUM_OF_10G_TX_PORTS) /**< Number of available FM ports */ ++/* @} */ ++ ++/**************************************************************************//* ++ @Description A Structure for Port bandwidth requirement. Port is identified ++ by type and relative id. ++*//***************************************************************************/ ++typedef struct t_FmPortBandwidth { ++ e_FmPortType type; /**< FM port type */ ++ uint8_t relativePortId; /**< Type relative port id */ ++ uint8_t bandwidth; /**< bandwidth - (in term of percents) */ ++} t_FmPortBandwidth; ++ ++/**************************************************************************//* ++ @Description A Structure containing an array of Port bandwidth requirements. ++ The user should state the ports requiring bandwidth in terms of ++ percentage - i.e. all port's bandwidths in the array must add ++ up to 100. ++*//***************************************************************************/ ++typedef struct t_FmPortsBandwidthParams { ++ uint8_t numOfPorts; /**< The number of relevant ports, which is the ++ number of valid entries in the array below */ ++ t_FmPortBandwidth portsBandwidths[FM_MAX_NUM_OF_VALID_PORTS]; ++ /**< for each port, it's bandwidth (all port's ++ bandwidths must add up to 100.*/ ++} t_FmPortsBandwidthParams; ++ ++/**************************************************************************//** ++ @Description DMA Emergency control on MURAM ++*//***************************************************************************/ ++typedef enum e_FmDmaMuramPort { ++ e_FM_DMA_MURAM_PORT_WRITE, /**< MURAM write port */ ++ e_FM_DMA_MURAM_PORT_READ /**< MURAM read port */ ++} e_FmDmaMuramPort; ++ ++/**************************************************************************//** ++ @Description Enum for defining FM counters ++*//***************************************************************************/ ++typedef enum e_FmCounters { ++ e_FM_COUNTERS_ENQ_TOTAL_FRAME = 0, /**< QMI total enqueued frames counter */ ++ e_FM_COUNTERS_DEQ_TOTAL_FRAME, /**< QMI total dequeued frames counter */ ++ e_FM_COUNTERS_DEQ_0, /**< QMI 0 frames from QMan counter */ ++ e_FM_COUNTERS_DEQ_1, /**< QMI 1 frames from QMan counter */ ++ e_FM_COUNTERS_DEQ_2, /**< QMI 2 frames from QMan counter */ ++ e_FM_COUNTERS_DEQ_3, /**< QMI 3 frames from QMan counter */ ++ e_FM_COUNTERS_DEQ_FROM_DEFAULT, /**< QMI dequeue from default queue counter */ ++ e_FM_COUNTERS_DEQ_FROM_CONTEXT, /**< QMI dequeue from FQ context counter */ ++ e_FM_COUNTERS_DEQ_FROM_FD, /**< QMI dequeue from FD command field counter */ ++ e_FM_COUNTERS_DEQ_CONFIRM /**< QMI dequeue confirm counter */ ++} e_FmCounters; ++ ++/**************************************************************************//** ++ @Description A Structure for returning FM revision information ++*//***************************************************************************/ ++typedef struct t_FmRevisionInfo { ++ uint8_t majorRev; /**< Major revision */ ++ uint8_t minorRev; /**< Minor revision */ ++} t_FmRevisionInfo; ++ ++/**************************************************************************//** ++ @Description A Structure for returning FM ctrl code revision information ++*//***************************************************************************/ ++typedef struct t_FmCtrlCodeRevisionInfo { ++ uint16_t packageRev; /**< Package revision */ ++ uint8_t majorRev; /**< Major revision */ ++ uint8_t minorRev; /**< Minor revision */ ++} t_FmCtrlCodeRevisionInfo; ++ ++/**************************************************************************//** ++ @Description A Structure for defining DMA status ++*//***************************************************************************/ ++typedef struct t_FmDmaStatus { ++ bool cmqNotEmpty; /**< Command queue is not empty */ ++ bool busError; /**< Bus error occurred */ ++ bool readBufEccError; /**< Double ECC error on buffer Read (Valid for FM rev < 6)*/ ++ bool writeBufEccSysError; /**< Double ECC error on buffer write from system side (Valid for FM rev < 6)*/ ++ bool writeBufEccFmError; /**< Double ECC error on buffer write from FM side (Valid for FM rev < 6) */ ++ bool singlePortEccError; /**< Single Port ECC error from FM side (Valid for FM rev >= 6)*/ ++} t_FmDmaStatus; ++ ++/**************************************************************************//** ++ @Description A Structure for obtaining FM controller monitor values ++*//***************************************************************************/ ++typedef struct t_FmCtrlMon { ++ uint8_t percentCnt[2]; /**< Percentage value */ ++} t_FmCtrlMon; ++ ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++/**************************************************************************//** ++ @Function FM_DumpRegs ++ ++ @Description Dumps all FM registers ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FM_DumpRegs(t_Handle h_Fm); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++/**************************************************************************//** ++ @Function FM_SetException ++ ++ @Description Calling this routine enables/disables the specified exception. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] exception The exception to be selected. ++ @Param[in] enable TRUE to enable interrupt, FALSE to mask it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_SetException(t_Handle h_Fm, e_FmExceptions exception, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_EnableRamsEcc ++ ++ @Description Enables ECC mechanism for all the different FM RAM's; E.g. IRAM, ++ MURAM, Parser, Keygen, Policer, etc. ++ Note: ++ If FM_ConfigExternalEccRamsEnable was called to enable external ++ setting of ECC, this routine effects IRAM ECC only. ++ This routine is also called by the driver if an ECC exception is ++ enabled. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_EnableRamsEcc(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_DisableRamsEcc ++ ++ @Description Disables ECC mechanism for all the different FM RAM's; E.g. IRAM, ++ MURAM, Parser, Keygen, Policer, etc. ++ Note: ++ If FM_ConfigExternalEccRamsEnable was called to enable external ++ setting of ECC, this routine effects IRAM ECC only. ++ In opposed to FM_EnableRamsEcc, this routine must be called ++ explicitly to disable all Rams ECC. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Config() and before FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_DisableRamsEcc(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_GetRevision ++ ++ @Description Returns the FM revision ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[out] p_FmRevisionInfo A structure of revision information parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FM_GetRevision(t_Handle h_Fm, t_FmRevisionInfo *p_FmRevisionInfo); ++ ++/**************************************************************************//** ++ @Function FM_GetFmanCtrlCodeRevision ++ ++ @Description Returns the Fman controller code revision ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[out] p_RevisionInfo A structure of revision information parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FM_GetFmanCtrlCodeRevision(t_Handle h_Fm, t_FmCtrlCodeRevisionInfo *p_RevisionInfo); ++ ++/**************************************************************************//** ++ @Function FM_GetCounter ++ ++ @Description Reads one of the FM counters. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] counter The requested counter. ++ ++ @Return Counter's current value. ++ ++ @Cautions Allowed only following FM_Init(). ++ Note that it is user's responsibility to call this routine only ++ for enabled counters, and there will be no indication if a ++ disabled counter is accessed. ++*//***************************************************************************/ ++uint32_t FM_GetCounter(t_Handle h_Fm, e_FmCounters counter); ++ ++/**************************************************************************//** ++ @Function FM_ModifyCounter ++ ++ @Description Sets a value to an enabled counter. Use "0" to reset the counter. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] counter The requested counter. ++ @Param[in] val The requested value to be written into the counter. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ModifyCounter(t_Handle h_Fm, e_FmCounters counter, uint32_t val); ++ ++/**************************************************************************//** ++ @Function FM_Resume ++ ++ @Description Release FM after halt FM command or after unrecoverable ECC error. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++void FM_Resume(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_SetDmaEmergency ++ ++ @Description Manual emergency set ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] muramPort MURAM direction select. ++ @Param[in] enable TRUE to manually enable emergency, FALSE to disable. ++ ++ @Return None. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++void FM_SetDmaEmergency(t_Handle h_Fm, e_FmDmaMuramPort muramPort, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_SetDmaExtBusPri ++ ++ @Description Set the DMA external bus priority ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] pri External bus priority select ++ ++ @Return None. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++void FM_SetDmaExtBusPri(t_Handle h_Fm, e_FmDmaExtBusPri pri); ++ ++/**************************************************************************//** ++ @Function FM_GetDmaStatus ++ ++ @Description Reads the DMA current status ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[out] p_FmDmaStatus A structure of DMA status parameters. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++void FM_GetDmaStatus(t_Handle h_Fm, t_FmDmaStatus *p_FmDmaStatus); ++ ++/**************************************************************************//** ++ @Function FM_ErrorIsr ++ ++ @Description FM interrupt-service-routine for errors. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; E_EMPTY if no errors found in register, other ++ error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ErrorIsr(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_EventIsr ++ ++ @Description FM interrupt-service-routine for normal events. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++void FM_EventIsr(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_GetSpecialOperationCoding ++ ++ @Description Return a specific coding according to the input mask. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] spOper special operation mask. ++ @Param[out] p_SpOperCoding special operation code. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FM_GetSpecialOperationCoding(t_Handle h_Fm, ++ fmSpecialOperations_t spOper, ++ uint8_t *p_SpOperCoding); ++ ++/**************************************************************************//** ++ @Function FM_CtrlMonStart ++ ++ @Description Start monitoring utilization of all available FM controllers. ++ ++ In order to obtain FM controllers utilization the following sequence ++ should be used: ++ -# FM_CtrlMonStart() ++ -# FM_CtrlMonStop() ++ -# FM_CtrlMonGetCounters() - issued for each FM controller ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID). ++*//***************************************************************************/ ++t_Error FM_CtrlMonStart(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_CtrlMonStop ++ ++ @Description Stop monitoring utilization of all available FM controllers. ++ ++ In order to obtain FM controllers utilization the following sequence ++ should be used: ++ -# FM_CtrlMonStart() ++ -# FM_CtrlMonStop() ++ -# FM_CtrlMonGetCounters() - issued for each FM controller ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID). ++*//***************************************************************************/ ++t_Error FM_CtrlMonStop(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_CtrlMonGetCounters ++ ++ @Description Obtain FM controller utilization parameters. ++ ++ In order to obtain FM controllers utilization the following sequence ++ should be used: ++ -# FM_CtrlMonStart() ++ -# FM_CtrlMonStop() ++ -# FM_CtrlMonGetCounters() - issued for each FM controller ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] fmCtrlIndex FM Controller index for that utilization results ++ are requested. ++ @Param[in] p_Mon Pointer to utilization results structure. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID). ++*//***************************************************************************/ ++t_Error FM_CtrlMonGetCounters(t_Handle h_Fm, uint8_t fmCtrlIndex, t_FmCtrlMon *p_Mon); ++ ++ ++/**************************************************************************//* ++ @Function FM_ForceIntr ++ ++ @Description Causes an interrupt event on the requested source. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] exception An exception to be forced. ++ ++ @Return E_OK on success; Error code if the exception is not enabled, ++ or is not able to create interrupt. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_ForceIntr (t_Handle h_Fm, e_FmExceptions exception); ++ ++/**************************************************************************//* ++ @Function FM_SetPortsBandwidth ++ ++ @Description Sets relative weights between ports when accessing common resources. ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ @Param[in] p_PortsBandwidth A structure of ports bandwidths in percentage, i.e. ++ total must equal 100. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_SetPortsBandwidth(t_Handle h_Fm, t_FmPortsBandwidthParams *p_PortsBandwidth); ++ ++/**************************************************************************//* ++ @Function FM_GetMuramHandle ++ ++ @Description Gets the corresponding MURAM handle ++ ++ @Param[in] h_Fm A handle to an FM Module. ++ ++ @Return MURAM handle; NULL otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Handle FM_GetMuramHandle(t_Handle h_Fm); ++ ++/** @} */ /* end of FM_runtime_control_grp group */ ++/** @} */ /* end of FM_lib_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++#ifdef NCSW_BACKWARD_COMPATIBLE_API ++typedef t_FmFirmwareParams t_FmPcdFirmwareParams; ++typedef t_FmBufferPrefixContent t_FmPortBufferPrefixContent; ++typedef t_FmExtPoolParams t_FmPortExtPoolParams; ++typedef t_FmExtPools t_FmPortExtPools; ++typedef t_FmBackupBmPools t_FmPortBackupBmPools; ++typedef t_FmBufPoolDepletion t_FmPortBufPoolDepletion; ++typedef e_FmDmaSwapOption e_FmPortDmaSwapOption; ++typedef e_FmDmaCacheOption e_FmPortDmaCacheOption; ++ ++#define FM_CONTEXTA_GET_OVVERIDE FM_CONTEXTA_GET_OVERRIDE ++#define FM_CONTEXTA_SET_OVVERIDE FM_CONTEXTA_SET_OVERRIDE ++ ++#define e_FM_EX_BMI_PIPELINE_ECC e_FM_EX_BMI_STORAGE_PROFILE_ECC ++#define e_FM_PORT_DMA_NO_SWP e_FM_DMA_NO_SWP ++#define e_FM_PORT_DMA_SWP_PPC_LE e_FM_DMA_SWP_PPC_LE ++#define e_FM_PORT_DMA_SWP_BE e_FM_DMA_SWP_BE ++#define e_FM_PORT_DMA_NO_STASH e_FM_DMA_NO_STASH ++#define e_FM_PORT_DMA_STASH e_FM_DMA_STASH ++#endif /* NCSW_BACKWARD_COMPATIBLE_API */ ++ ++ ++#endif /* __FM_EXT */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_mac_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_mac_ext.h +new file mode 100644 +index 0000000..f90f2a7 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_mac_ext.h +@@ -0,0 +1,846 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File fm_mac_ext.h ++ ++ @Description FM MAC ... ++*//***************************************************************************/ ++#ifndef __FM_MAC_EXT_H ++#define __FM_MAC_EXT_H ++ ++#include "std_ext.h" ++#include "enet_ext.h" ++ ++ ++/**************************************************************************//** ++ ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_mac_grp FM MAC ++ ++ @Description FM MAC API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++#define FM_MAC_NO_PFC 0xff ++ ++ ++/**************************************************************************//** ++ @Description FM MAC Exceptions ++*//***************************************************************************/ ++typedef enum e_FmMacExceptions { ++ e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO = 0 /**< 10GEC MDIO scan event interrupt */ ++ ,e_FM_MAC_EX_10G_MDIO_CMD_CMPL /**< 10GEC MDIO command completion interrupt */ ++ ,e_FM_MAC_EX_10G_REM_FAULT /**< 10GEC, mEMAC Remote fault interrupt */ ++ ,e_FM_MAC_EX_10G_LOC_FAULT /**< 10GEC, mEMAC Local fault interrupt */ ++ ,e_FM_MAC_EX_10G_1TX_ECC_ER /**< 10GEC, mEMAC Transmit frame ECC error interrupt */ ++ ,e_FM_MAC_EX_10G_TX_FIFO_UNFL /**< 10GEC, mEMAC Transmit FIFO underflow interrupt */ ++ ,e_FM_MAC_EX_10G_TX_FIFO_OVFL /**< 10GEC, mEMAC Transmit FIFO overflow interrupt */ ++ ,e_FM_MAC_EX_10G_TX_ER /**< 10GEC Transmit frame error interrupt */ ++ ,e_FM_MAC_EX_10G_RX_FIFO_OVFL /**< 10GEC, mEMAC Receive FIFO overflow interrupt */ ++ ,e_FM_MAC_EX_10G_RX_ECC_ER /**< 10GEC, mEMAC Receive frame ECC error interrupt */ ++ ,e_FM_MAC_EX_10G_RX_JAB_FRM /**< 10GEC Receive jabber frame interrupt */ ++ ,e_FM_MAC_EX_10G_RX_OVRSZ_FRM /**< 10GEC Receive oversized frame interrupt */ ++ ,e_FM_MAC_EX_10G_RX_RUNT_FRM /**< 10GEC Receive runt frame interrupt */ ++ ,e_FM_MAC_EX_10G_RX_FRAG_FRM /**< 10GEC Receive fragment frame interrupt */ ++ ,e_FM_MAC_EX_10G_RX_LEN_ER /**< 10GEC Receive payload length error interrupt */ ++ ,e_FM_MAC_EX_10G_RX_CRC_ER /**< 10GEC Receive CRC error interrupt */ ++ ,e_FM_MAC_EX_10G_RX_ALIGN_ER /**< 10GEC Receive alignment error interrupt */ ++ ,e_FM_MAC_EX_1G_BAB_RX /**< dTSEC Babbling receive error */ ++ ,e_FM_MAC_EX_1G_RX_CTL /**< dTSEC Receive control (pause frame) interrupt */ ++ ,e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET /**< dTSEC Graceful transmit stop complete */ ++ ,e_FM_MAC_EX_1G_BAB_TX /**< dTSEC Babbling transmit error */ ++ ,e_FM_MAC_EX_1G_TX_CTL /**< dTSEC Transmit control (pause frame) interrupt */ ++ ,e_FM_MAC_EX_1G_TX_ERR /**< dTSEC Transmit error */ ++ ,e_FM_MAC_EX_1G_LATE_COL /**< dTSEC Late collision */ ++ ,e_FM_MAC_EX_1G_COL_RET_LMT /**< dTSEC Collision retry limit */ ++ ,e_FM_MAC_EX_1G_TX_FIFO_UNDRN /**< dTSEC Transmit FIFO underrun */ ++ ,e_FM_MAC_EX_1G_MAG_PCKT /**< dTSEC Magic Packet detection */ ++ ,e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET /**< dTSEC MII management read completion */ ++ ,e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET /**< dTSEC MII management write completion */ ++ ,e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET /**< dTSEC Graceful receive stop complete */ ++ ,e_FM_MAC_EX_1G_TX_DATA_ERR /**< dTSEC Internal data error on transmit */ ++ ,e_FM_MAC_EX_1G_RX_DATA_ERR /**< dTSEC Internal data error on receive */ ++ ,e_FM_MAC_EX_1G_1588_TS_RX_ERR /**< dTSEC Time-Stamp Receive Error */ ++ ,e_FM_MAC_EX_1G_RX_MIB_CNT_OVFL /**< dTSEC MIB counter overflow */ ++ ,e_FM_MAC_EX_TS_FIFO_ECC_ERR /**< mEMAC Time-stamp FIFO ECC error interrupt; ++ not supported on T4240/B4860 rev1 chips */ ++ ,e_FM_MAC_EX_MAGIC_PACKET_INDICATION = e_FM_MAC_EX_1G_MAG_PCKT ++ /**< mEMAC Magic Packet Indication Interrupt */ ++} e_FmMacExceptions; ++ ++/**************************************************************************//** ++ @Description TM MAC statistics level ++*//***************************************************************************/ ++typedef enum e_FmMacStatisticsLevel { ++ e_FM_MAC_NONE_STATISTICS = 0, /**< No statistics */ ++ e_FM_MAC_PARTIAL_STATISTICS, /**< Only error counters are available; Optimized for performance */ ++ e_FM_MAC_FULL_STATISTICS /**< All counters available; Not optimized for performance */ ++} e_FmMacStatisticsLevel; ++ ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description Priority Flow Control Parameters ++*//***************************************************************************/ ++typedef struct t_FmMacPfcParams { ++ bool pfcEnable; /**< Enable/Disable PFC */ ++ ++ uint16_t pauseQuanta[FM_MAX_NUM_OF_PFC_PRIORITIES]; /**< Pause Quanta per priority to be sent in a pause frame. Each quanta represents a 512 bit-times*/ ++ ++ uint16_t pauseThresholdQuanta[FM_MAX_NUM_OF_PFC_PRIORITIES];/**< Pause threshold per priority, when timer passes this threshold time a PFC frames is sent again if the port is still congested or BM pool in depletion*/ ++ ++ ++} t_FmMacPfcParams; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Function t_FmMacExceptionCallback ++ ++ @Description Fm Mac Exception Callback from FM MAC to the user ++ ++ @Param[in] h_App - Handle to the upper layer handler ++ ++ @Param[in] exceptions - The exception that occurred ++ ++ @Return void. ++*//***************************************************************************/ ++typedef void (t_FmMacExceptionCallback)(t_Handle h_App, e_FmMacExceptions exceptions); ++ ++ ++/**************************************************************************//** ++ @Description TM MAC statistics rfc3635 ++*//***************************************************************************/ ++typedef struct t_FmMacStatistics { ++/* RMON */ ++ uint64_t eStatPkts64; /**< r-10G tr-DT 64 byte frame counter */ ++ uint64_t eStatPkts65to127; /**< r-10G 65 to 127 byte frame counter */ ++ uint64_t eStatPkts128to255; /**< r-10G 128 to 255 byte frame counter */ ++ uint64_t eStatPkts256to511; /**< r-10G 256 to 511 byte frame counter */ ++ uint64_t eStatPkts512to1023; /**< r-10G 512 to 1023 byte frame counter */ ++ uint64_t eStatPkts1024to1518; /**< r-10G 1024 to 1518 byte frame counter */ ++ uint64_t eStatPkts1519to1522; /**< r-10G 1519 to 1522 byte good frame count */ ++/* */ ++ uint64_t eStatFragments; /**< Total number of packets that were less than 64 octets long with a wrong CRC.*/ ++ uint64_t eStatJabbers; /**< Total number of packets longer than valid maximum length octets */ ++ uint64_t eStatsDropEvents; /**< number of dropped packets due to internal errors of the MAC Client (during receive). */ ++ uint64_t eStatCRCAlignErrors; /**< Incremented when frames of correct length but with CRC error are received.*/ ++ uint64_t eStatUndersizePkts; /**< Incremented for frames under 64 bytes with a valid FCS and otherwise well formed; ++ This count does not include range length errors */ ++ uint64_t eStatOversizePkts; /**< Incremented for frames which exceed 1518 (non VLAN) or 1522 (VLAN) and contains ++ a valid FCS and otherwise well formed */ ++/* Pause */ ++ uint64_t teStatPause; /**< Pause MAC Control received */ ++ uint64_t reStatPause; /**< Pause MAC Control sent */ ++/* MIB II */ ++ uint64_t ifInOctets; /**< Total number of byte received. */ ++ uint64_t ifInPkts; /**< Total number of packets received.*/ ++ uint64_t ifInUcastPkts; /**< Total number of unicast frame received; ++ NOTE: this counter is not supported on dTSEC MAC */ ++ uint64_t ifInMcastPkts; /**< Total number of multicast frame received*/ ++ uint64_t ifInBcastPkts; /**< Total number of broadcast frame received */ ++ uint64_t ifInDiscards; /**< Frames received, but discarded due to problems within the MAC RX. */ ++ uint64_t ifInErrors; /**< Number of frames received with error: ++ - FIFO Overflow Error ++ - CRC Error ++ - Frame Too Long Error ++ - Alignment Error ++ - The dedicated Error Code (0xfe, not a code error) was received */ ++ uint64_t ifOutOctets; /**< Total number of byte sent. */ ++ uint64_t ifOutPkts; /**< Total number of packets sent .*/ ++ uint64_t ifOutUcastPkts; /**< Total number of unicast frame sent; ++ NOTE: this counter is not supported on dTSEC MAC */ ++ uint64_t ifOutMcastPkts; /**< Total number of multicast frame sent */ ++ uint64_t ifOutBcastPkts; /**< Total number of multicast frame sent */ ++ uint64_t ifOutDiscards; /**< Frames received, but discarded due to problems within the MAC TX N/A!.*/ ++ uint64_t ifOutErrors; /**< Number of frames transmitted with error: ++ - FIFO Overflow Error ++ - FIFO Underflow Error ++ - Other */ ++} t_FmMacStatistics; ++ ++ ++/**************************************************************************//** ++ @Group FM_mac_init_grp FM MAC Initialization Unit ++ ++ @Description FM MAC Initialization Unit ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description FM MAC config input ++*//***************************************************************************/ ++typedef struct t_FmMacParams { ++ uintptr_t baseAddr; /**< Base of memory mapped FM MAC registers */ ++ t_EnetAddr addr; /**< MAC address of device; First octet is sent first */ ++ uint8_t macId; /**< MAC ID; ++ numbering of dTSEC and 1G-mEMAC: ++ 0 - FM_MAX_NUM_OF_1G_MACS; ++ numbering of 10G-MAC (TGEC) and 10G-mEMAC: ++ 0 - FM_MAX_NUM_OF_10G_MACS */ ++ e_EnetMode enetMode; /**< Ethernet operation mode (MAC-PHY interface and speed); ++ Note that the speed should indicate the maximum rate that ++ this MAC should support rather than the actual speed; ++ i.e. user should use the FM_MAC_AdjustLink() routine to ++ provide accurate speed; ++ In case of mEMAC RGMII mode, the MAC is configured to RGMII ++ automatic mode, where actual speed/duplex mode information ++ is provided by PHY automatically in-band; FM_MAC_AdjustLink() ++ function should be used to switch to manual RGMII speed/duplex mode ++ configuration if RGMII PHY doesn't support in-band status signaling; ++ In addition, in mEMAC, in case where user is using the higher MACs ++ (i.e. the MACs that should support 10G), user should pass here ++ speed=10000 even if the interface is not allowing that (e.g. SGMII). */ ++ t_Handle h_Fm; /**< A handle to the FM object this port related to */ ++ int mdioIrq; /**< MDIO exceptions interrupt source - not valid for all ++ MACs; MUST be set to 'NO_IRQ' for MACs that don't have ++ mdio-irq, or for polling */ ++ t_FmMacExceptionCallback *f_Event; /**< MDIO Events Callback Routine */ ++ t_FmMacExceptionCallback *f_Exception; /**< Exception Callback Routine */ ++ t_Handle h_App; /**< A handle to an application layer object; This handle will ++ be passed by the driver upon calling the above callbacks */ ++} t_FmMacParams; ++ ++ ++/**************************************************************************//** ++ @Function FM_MAC_Config ++ ++ @Description Creates descriptor for the FM MAC module. ++ ++ The routine returns a handle (descriptor) to the FM MAC object. ++ This descriptor must be passed as first parameter to all other ++ FM MAC function calls. ++ ++ No actual initialization or configuration of FM MAC hardware is ++ done by this routine. ++ ++ @Param[in] p_FmMacParam - Pointer to data structure of parameters ++ ++ @Retval Handle to FM MAC object, or NULL for Failure. ++*//***************************************************************************/ ++t_Handle FM_MAC_Config(t_FmMacParams *p_FmMacParam); ++ ++/**************************************************************************//** ++ @Function FM_MAC_Init ++ ++ @Description Initializes the FM MAC module ++ ++ @Param[in] h_FmMac - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_MAC_Init(t_Handle h_FmMac); ++ ++/**************************************************************************//** ++ @Function FM_Free ++ ++ @Description Frees all resources that were assigned to FM MAC module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmMac - FM module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_MAC_Free(t_Handle h_FmMac); ++ ++ ++/**************************************************************************//** ++ @Group FM_mac_advanced_init_grp FM MAC Advanced Configuration Unit ++ ++ @Description Configuration functions used to change default values. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigResetOnInit ++ ++ @Description Tell the driver whether to reset the FM MAC before initialization or ++ not. It changes the default configuration [DEFAULT_resetOnInit]. ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] enable When TRUE, FM will be reset before any initialization. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigResetOnInit(t_Handle h_FmMac, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigLoopback ++ ++ @Description Enable/Disable internal loopback mode ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] enable TRUE to enable or FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigLoopback(t_Handle h_FmMac, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigMaxFrameLength ++ ++ @Description Setup maximum Rx Frame Length (in 1G MAC, effects also Tx) ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] newVal MAX Frame length ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigMaxFrameLength(t_Handle h_FmMac, uint16_t newVal); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigWan ++ ++ @Description ENABLE WAN mode in 10G-MAC ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] enable TRUE to enable or FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigWan(t_Handle h_FmMac, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigPadAndCrc ++ ++ @Description Config PAD and CRC mode ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] enable TRUE to enable or FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++ Not supported on 10G-MAC (i.e. CRC & PAD are added automatically ++ by HW); on mEMAC, this routine supports only PAD (i.e. CRC is ++ added automatically by HW). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigPadAndCrc(t_Handle h_FmMac, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigHalfDuplex ++ ++ @Description Config Half Duplex Mode ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] enable TRUE to enable or FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigHalfDuplex(t_Handle h_FmMac, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigTbiPhyAddr ++ ++ @Description Configures the address of internal TBI PHY. ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] newVal TBI PHY address (1-31). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigTbiPhyAddr(t_Handle h_FmMac, uint8_t newVal); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigLengthCheck ++ ++ @Description Configure the frame length checking. ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] enable TRUE to enable or FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigLengthCheck(t_Handle h_FmMac, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ConfigException ++ ++ @Description Change Exception selection from default ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] ex Type of the desired exceptions ++ @Param[in] enable TRUE to enable the specified exception, FALSE to disable it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ConfigException(t_Handle h_FmMac, e_FmMacExceptions ex, bool enable); ++ ++#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++t_Error FM_MAC_ConfigSkipFman11Workaround (t_Handle h_FmMac); ++#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ ++/** @} */ /* end of FM_mac_advanced_init_grp group */ ++/** @} */ /* end of FM_mac_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_mac_runtime_control_grp FM MAC Runtime Control Unit ++ ++ @Description FM MAC Runtime control unit API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_MAC_Enable ++ ++ @Description Enable the MAC ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] mode Mode of operation (RX, TX, Both) ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_Enable(t_Handle h_FmMac, e_CommMode mode); ++ ++/**************************************************************************//** ++ @Function FM_MAC_Disable ++ ++ @Description DISABLE the MAC ++ ++ @Param[in] h_FmMac A handle to a FM MAC Module. ++ @Param[in] mode Define what part to Disable (RX, TX or BOTH) ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_Disable(t_Handle h_FmMac, e_CommMode mode); ++ ++/**************************************************************************//** ++ @Function FM_MAC_Enable1588TimeStamp ++ ++ @Description Enables the TSU operation. ++ ++ @Param[in] h_Fm - Handle to the PTP as returned from the FM_MAC_PtpConfig. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_Enable1588TimeStamp(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_MAC_Disable1588TimeStamp ++ ++ @Description Disables the TSU operation. ++ ++ @Param[in] h_Fm - Handle to the PTP as returned from the FM_MAC_PtpConfig. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_Disable1588TimeStamp(t_Handle h_Fm); ++ ++/**************************************************************************//** ++ @Function FM_MAC_SetTxAutoPauseFrames ++ ++ @Description Enable/Disable transmission of Pause-Frames. ++ The routine changes the default configuration [DEFAULT_TX_PAUSE_TIME]. ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ @Param[in] pauseTime - Pause quanta value used with transmitted pause frames. ++ Each quanta represents a 512 bit-times; Note that '0' ++ as an input here will be used as disabling the ++ transmission of the pause-frames. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_SetTxAutoPauseFrames(t_Handle h_FmMac, ++ uint16_t pauseTime); ++ ++ /**************************************************************************//** ++ @Function FM_MAC_SetTxPauseFrames ++ ++ @Description Enable/Disable transmission of Pause-Frames. ++ The routine changes the default configuration: ++ pause-time - [DEFAULT_TX_PAUSE_TIME] ++ threshold-time - [0] ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ @Param[in] priority - the PFC class of service; use 'FM_MAC_NO_PFC' ++ to indicate legacy pause support (i.e. no PFC). ++ @Param[in] pauseTime - Pause quanta value used with transmitted pause frames. ++ Each quanta represents a 512 bit-times; ++ Note that '0' as an input here will be used as disabling the ++ transmission of the pause-frames. ++ @Param[in] threshTime - Pause Threshold equanta value used by the MAC to retransmit pause frame. ++ if the situation causing a pause frame to be sent didn't finish when the timer ++ reached the threshold quanta, the MAC will retransmit the pause frame. ++ Each quanta represents a 512 bit-times. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++ In order for PFC to work properly the user must configure ++ TNUM-aging in the tx-port it is recommended that pre-fetch and ++ rate limit in the tx port should be disabled; ++ PFC is supported only on new mEMAC; i.e. in MACs that don't have ++ PFC support (10G-MAC and dTSEC), user should use 'FM_MAC_NO_PFC' ++ in the 'priority' field. ++*//***************************************************************************/ ++t_Error FM_MAC_SetTxPauseFrames(t_Handle h_FmMac, ++ uint8_t priority, ++ uint16_t pauseTime, ++ uint16_t threshTime); ++ ++/**************************************************************************//** ++ @Function FM_MAC_SetRxIgnorePauseFrames ++ ++ @Description Enable/Disable ignoring of Pause-Frames. ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ @Param[in] en - boolean indicates whether to ignore the incoming pause ++ frames or not. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_SetRxIgnorePauseFrames(t_Handle h_FmMac, bool en); ++ ++/**************************************************************************//** ++ @Function FM_MAC_SetWakeOnLan ++ ++ @Description Enable/Disable Wake On Lan support ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ @Param[in] en - boolean indicates whether to enable Wake On Lan ++ support or not. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_SetWakeOnLan(t_Handle h_FmMac, bool en); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ResetCounters ++ ++ @Description reset all statistics counters ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ResetCounters(t_Handle h_FmMac); ++ ++/**************************************************************************//** ++ @Function FM_MAC_SetException ++ ++ @Description Enable/Disable a specific Exception ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ @Param[in] ex - Type of the desired exceptions ++ @Param[in] enable - TRUE to enable the specified exception, FALSE to disable it. ++ ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_SetException(t_Handle h_FmMac, e_FmMacExceptions ex, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MAC_SetStatistics ++ ++ @Description Define Statistics level. ++ Where applicable, the routine also enables the MIB counters ++ overflow interrupt in order to keep counters accurate ++ and account for overflows. ++ This routine is relevant only for dTSEC. ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ @Param[in] statisticsLevel - Full statistics level provides all standard counters but may ++ reduce performance. Partial statistics provides only special ++ event counters (errors etc.). If selected, regular counters (such as ++ byte/packet) will be invalid and will return -1. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_SetStatistics(t_Handle h_FmMac, e_FmMacStatisticsLevel statisticsLevel); ++ ++/**************************************************************************//** ++ @Function FM_MAC_GetStatistics ++ ++ @Description get all statistics counters ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ @Param[in] p_Statistics - Structure with statistics ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_GetStatistics(t_Handle h_FmMac, t_FmMacStatistics *p_Statistics); ++ ++/**************************************************************************//** ++ @Function FM_MAC_ModifyMacAddr ++ ++ @Description Replace the main MAC Address ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[in] p_EnetAddr - Ethernet Mac address ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_ModifyMacAddr(t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ ++/**************************************************************************//** ++ @Function FM_MAC_AddHashMacAddr ++ ++ @Description Add an Address to the hash table. This is for filter purpose only. ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[in] p_EnetAddr - Ethernet Mac address ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). It is a filter only address. ++ @Cautions Some address need to be filterd out in upper FM blocks. ++*//***************************************************************************/ ++t_Error FM_MAC_AddHashMacAddr(t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ ++/**************************************************************************//** ++ @Function FM_MAC_RemoveHashMacAddr ++ ++ @Description Delete an Address to the hash table. This is for filter purpose only. ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[in] p_EnetAddr - Ethernet Mac address ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_RemoveHashMacAddr(t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ ++/**************************************************************************//** ++ @Function FM_MAC_AddExactMatchMacAddr ++ ++ @Description Add a unicast or multicast mac address for exact-match filtering ++ (8 on dTSEC, 2 for 10G-MAC) ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[in] p_EnetAddr - MAC Address to ADD ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_AddExactMatchMacAddr(t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ ++/**************************************************************************//** ++ @Function FM_MAC_RemovelExactMatchMacAddr ++ ++ @Description Remove a uni cast or multi cast mac address. ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[in] p_EnetAddr - MAC Address to remove ++ ++ @Return E_OK on success; Error code otherwise.. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_RemovelExactMatchMacAddr(t_Handle h_FmMac, t_EnetAddr *p_EnetAddr); ++ ++/**************************************************************************//** ++ @Function FM_MAC_SetPromiscuous ++ ++ @Description Enable/Disable MAC Promiscuous mode for ALL mac addresses. ++ ++ @Param[in] h_FmMac - A handle to a FM MAC Module. ++ @Param[in] enable - TRUE to enable or FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_SetPromiscuous(t_Handle h_FmMac, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MAC_AdjustLink ++ ++ @Description Adjusts the Ethernet link with new speed/duplex setup. ++ This routine is relevant for dTSEC and mEMAC. ++ In case of mEMAC, this routine is also used for manual ++ re-configuration of RGMII speed and duplex mode for ++ RGMII PHYs not supporting in-band status information ++ to MAC. ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[in] speed - Ethernet speed. ++ @Param[in] fullDuplex - TRUE for full-duplex mode; ++ FALSE for half-duplex mode. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_MAC_AdjustLink(t_Handle h_FmMac, e_EnetSpeed speed, bool fullDuplex); ++ ++/**************************************************************************//** ++ @Function FM_MAC_RestartAutoneg ++ ++ @Description Restarts the auto-negotiation process. ++ When auto-negotiation process is invoked under traffic the ++ auto-negotiation process between the internal SGMII PHY and the ++ external PHY does not always complete successfully. Calling this ++ function will restart the auto-negotiation process that will end ++ successfully. It is recommended to call this function after issuing ++ auto-negotiation restart command to the Eth Phy. ++ This routine is relevant only for dTSEC. ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_MAC_RestartAutoneg(t_Handle h_FmMac); ++ ++/**************************************************************************//** ++ @Function FM_MAC_GetId ++ ++ @Description Return the MAC ID ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[out] p_MacId - MAC ID of device ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_GetId(t_Handle h_FmMac, uint32_t *p_MacId); ++ ++/**************************************************************************//** ++ @Function FM_MAC_GetVesrion ++ ++ @Description Return Mac HW chip version ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[out] p_MacVresion - Mac version as defined by the chip ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_GetVesrion(t_Handle h_FmMac, uint32_t *p_MacVresion); ++ ++/**************************************************************************//** ++ @Function FM_MAC_MII_WritePhyReg ++ ++ @Description Write data into Phy Register ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[in] phyAddr - Phy Address on the MII bus ++ @Param[in] reg - Register Number. ++ @Param[in] data - Data to write. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_MII_WritePhyReg(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t data); ++ ++/**************************************************************************//** ++ @Function FM_MAC_MII_ReadPhyReg ++ ++ @Description Read data from Phy Register ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ @Param[in] phyAddr - Phy Address on the MII bus ++ @Param[in] reg - Register Number. ++ @Param[out] p_Data - Data from PHY. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_MII_ReadPhyReg(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data); ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++/**************************************************************************//** ++ @Function FM_MAC_DumpRegs ++ ++ @Description Dump internal registers ++ ++ @Param[in] h_FmMac - A handle to a FM Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MAC_Init(). ++*//***************************************************************************/ ++t_Error FM_MAC_DumpRegs(t_Handle h_FmMac); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++/** @} */ /* end of FM_mac_runtime_control_grp group */ ++/** @} */ /* end of FM_mac_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++#endif /* __FM_MAC_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_macsec_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_macsec_ext.h +new file mode 100644 +index 0000000..57925f1 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_macsec_ext.h +@@ -0,0 +1,1271 @@ ++/* ++ * Copyright 2008-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. ++ */ ++ ++/**************************************************************************//** ++ @File fm_macsec_ext.h ++ ++ @Description FM MACSEC ... ++*//***************************************************************************/ ++#ifndef __FM_MACSEC_EXT_H ++#define __FM_MACSEC_EXT_H ++ ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_MACSEC_grp FM MACSEC ++ ++ @Description FM MACSEC API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description MACSEC Exceptions ++*//***************************************************************************/ ++typedef enum e_FmMacsecExceptions { ++ e_FM_MACSEC_EX_SINGLE_BIT_ECC, /**< Single bit ECC error */ ++ e_FM_MACSEC_EX_MULTI_BIT_ECC /**< Multi bit ECC error */ ++} e_FmMacsecExceptions; ++ ++ ++/**************************************************************************//** ++ @Group FM_MACSEC_init_grp FM-MACSEC Initialization Unit ++ ++ @Description FM MACSEC Initialization Unit ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function t_FmMacsecExceptionsCallback ++ ++ @Description Exceptions user callback routine, will be called upon an ++ exception passing the exception identification. ++ ++ @Param[in] h_App A handle to an application layer object; This handle ++ will be passed by the driver upon calling this callback. ++ @Param[in] exception The exception. ++*//***************************************************************************/ ++typedef void (t_FmMacsecExceptionsCallback) ( t_Handle h_App, ++ e_FmMacsecExceptions exception); ++ ++ ++/**************************************************************************//** ++ @Description FM MACSEC config input ++*//***************************************************************************/ ++typedef struct t_FmMacsecParams { ++ t_Handle h_Fm; /**< A handle to the FM object related to */ ++ bool guestMode; /**< Partition-id */ ++ union { ++ struct { ++ uint8_t fmMacId; /**< FM MAC id */ ++ } guestParams; ++ ++ struct { ++ uintptr_t baseAddr; /**< Base of memory mapped FM MACSEC registers */ ++ t_Handle h_FmMac; /**< A handle to the FM MAC object related to */ ++ t_FmMacsecExceptionsCallback *f_Exception; /**< Exception Callback Routine */ ++ t_Handle h_App; /**< A handle to an application layer object; This handle will ++ be passed by the driver upon calling the above callbacks */ ++ } nonGuestParams; ++ }; ++} t_FmMacsecParams; ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_Config ++ ++ @Description Creates descriptor for the FM MACSEC module; ++ ++ The routine returns a handle (descriptor) to the FM MACSEC object; ++ This descriptor must be passed as first parameter to all other ++ FM MACSEC function calls; ++ ++ No actual initialization or configuration of FM MACSEC hardware is ++ done by this routine. ++ ++ @Param[in] p_FmMacsecParam Pointer to data structure of parameters. ++ ++ @Retval Handle to FM MACSEC object, or NULL for Failure. ++*//***************************************************************************/ ++t_Handle FM_MACSEC_Config(t_FmMacsecParams *p_FmMacsecParam); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_Init ++ ++ @Description Initializes the FM MACSEC module. ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_MACSEC_Init(t_Handle h_FmMacsec); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_Free ++ ++ @Description Frees all resources that were assigned to FM MACSEC module; ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_MACSEC_Free(t_Handle h_FmMacsec); ++ ++ ++/**************************************************************************//** ++ @Group FM_MACSEC_advanced_init_grp FM-MACSEC Advanced Configuration Unit ++ ++ @Description Configuration functions used to change default values. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description enum for unknown sci frame treatment ++*//***************************************************************************/ ++typedef enum e_FmMacsecUnknownSciFrameTreatment { ++ e_FM_MACSEC_UNKNOWN_SCI_FRAME_TREATMENT_DISCARD_BOTH = 0, /**< Controlled port - Strict mode */ ++ e_FM_MACSEC_UNKNOWN_SCI_FRAME_TREATMENT_DISCARD_UNCONTROLLED_DELIVER_OR_DISCARD_CONTROLLED, /**< If C bit clear deliver on controlled port, else discard ++ Controlled port - Check or Disable mode */ ++ e_FM_MACSEC_UNKNOWN_SCI_FRAME_TREATMENT_DELIVER_UNCONTROLLED_DISCARD_CONTROLLED, /**< Controlled port - Strict mode */ ++ e_FM_MACSEC_UNKNOWN_SCI_FRAME_TREATMENT_DELIVER_OR_DISCARD_UNCONTROLLED_DELIVER_OR_DISCARD_CONTROLLED /**< If C bit set deliver on uncontrolled port and discard on controlled port, ++ else discard on uncontrolled port and deliver on controlled port ++ Controlled port - Check or Disable mode */ ++} e_FmMacsecUnknownSciFrameTreatment; ++ ++/**************************************************************************//** ++ @Description enum for untag frame treatment ++*//***************************************************************************/ ++typedef enum e_FmMacsecUntagFrameTreatment { ++ e_FM_MACSEC_UNTAG_FRAME_TREATMENT_DELIVER_UNCONTROLLED_DISCARD_CONTROLLED = 0, /**< Controlled port - Strict mode */ ++ e_FM_MACSEC_UNTAG_FRAME_TREATMENT_DISCARD_BOTH, /**< Controlled port - Strict mode */ ++ e_FM_MACSEC_UNTAG_FRAME_TREATMENT_DISCARD_UNCONTROLLED_DELIVER_CONTROLLED_UNMODIFIED /**< Controlled port - Strict mode */ ++} e_FmMacsecUntagFrameTreatment; ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_ConfigUnknownSciFrameTreatment ++ ++ @Description Change the treatment for received frames with unknown sci from its default ++ configuration [DEFAULT_unknownSciFrameTreatment]. ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ @Param[in] treatMode The selected mode. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_Config() and before FM_MACSEC_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_ConfigUnknownSciFrameTreatment(t_Handle h_FmMacsec, e_FmMacsecUnknownSciFrameTreatment treatMode); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_ConfigInvalidTagsFrameTreatment ++ ++ @Description Change the treatment for received frames with invalid tags or ++ a zero value PN or an invalid ICV from its default configuration ++ [DEFAULT_invalidTagsFrameTreatment]. ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ @Param[in] deliverUncontrolled If True deliver on the uncontrolled port, else discard; ++ In both cases discard on the controlled port; ++ this provide Strict, Check or Disable mode. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_Config() and before FM_MACSEC_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_ConfigInvalidTagsFrameTreatment(t_Handle h_FmMacsec, bool deliverUncontrolled); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_ConfigEncryptWithNoChangedTextFrameTreatment ++ ++ @Description Change the treatment for received frames with the Encryption bit ++ set and the Changed Text bit clear from its default configuration ++ [DEFAULT_encryptWithNoChangedTextFrameTreatment]. ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ @Param[in] discardUncontrolled If True discard on the uncontrolled port, else deliver; ++ In both cases discard on the controlled port; ++ this provide Strict, Check or Disable mode. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_Config() and before FM_MACSEC_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_ConfigEncryptWithNoChangedTextFrameTreatment(t_Handle h_FmMacsec, bool discardUncontrolled); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_ConfigChangedTextWithNoEncryptFrameTreatment ++ ++ @Description Change the treatment for received frames with the Encryption bit ++ clear and the Changed Text bit set from its default configuration ++ [DEFAULT_changedTextWithNoEncryptFrameTreatment]. ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ @Param[in] deliverUncontrolled If True deliver on the uncontrolled port, else discard; ++ In both cases discard on the controlled port; ++ this provide Strict, Check or Disable mode. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_Config() and before FM_MACSEC_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_ConfigChangedTextWithNoEncryptFrameTreatment(t_Handle h_FmMacsec, bool deliverUncontrolled); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_ConfigUntagFrameTreatment ++ ++ @Description Change the treatment for received frames without the MAC security tag (SecTAG) ++ from its default configuration [DEFAULT_untagFrameTreatment]. ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ @Param[in] treatMode The selected mode. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_Config() and before FM_MACSEC_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_ConfigUntagFrameTreatment(t_Handle h_FmMacsec, e_FmMacsecUntagFrameTreatment treatMode); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_ConfigOnlyScbIsSetFrameTreatment ++ ++ @Description Change the treatment for received frames with only SCB bit set ++ from its default configuration [DEFAULT_onlyScbIsSetFrameTreatment]. ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ @Param[in] deliverUncontrolled If True deliver on the uncontrolled port, else discard; ++ In both cases discard on the controlled port; ++ this provide Strict, Check or Disable mode. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_Config() and before FM_MACSEC_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_ConfigOnlyScbIsSetFrameTreatment(t_Handle h_FmMacsec, bool deliverUncontrolled); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_ConfigPnExhaustionThreshold ++ ++ @Description It's provide the ability to configure a PN exhaustion threshold; ++ When the NextPn crosses this value an interrupt event ++ is asserted to warn that the active SA should re-key. ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ @Param[in] pnExhThr If the threshold is reached, an interrupt event ++ is asserted to re-key. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_Config() and before FM_MACSEC_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_ConfigPnExhaustionThreshold(t_Handle h_FmMacsec, uint32_t pnExhThr); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_ConfigKeysUnreadable ++ ++ @Description Turn on privacy mode; All the keys and their hash values can't be read any more; ++ Can not be cleared unless hard reset. ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_Config() and before FM_MACSEC_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_ConfigKeysUnreadable(t_Handle h_FmMacsec); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_ConfigSectagWithoutSCI ++ ++ @Description Promise that all generated Sectag will be without SCI included. ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_Config() and before FM_MACSEC_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_ConfigSectagWithoutSCI(t_Handle h_FmMacsec); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_ConfigException ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default selection of exceptions enablement; ++ By default all exceptions are enabled. ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ @Param[in] exception The exception to be selected. ++ @Param[in] enable TRUE to enable interrupt, FALSE to mask it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_Config() and before FM_MACSEC_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_ConfigException(t_Handle h_FmMacsec, e_FmMacsecExceptions exception, bool enable); ++ ++/** @} */ /* end of FM_MACSEC_advanced_init_grp group */ ++/** @} */ /* end of FM_MACSEC_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_MACSEC_runtime_control_grp FM-MACSEC Runtime Control Data Unit ++ ++ @Description FM MACSEC runtime control data unit API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_GetRevision ++ ++ @Description Return MACSEC HW chip revision ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ @Param[out] p_MacsecRevision MACSEC revision as defined by the chip. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MACSEC_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_GetRevision(t_Handle h_FmMacsec, uint32_t *p_MacsecRevision); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_Enable ++ ++ @Description This routine should be called after MACSEC is initialized for enabling all ++ MACSEC engines according to their existing configuration. ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_Init() and when MACSEC is disabled. ++*//***************************************************************************/ ++t_Error FM_MACSEC_Enable(t_Handle h_FmMacsec); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_Disable ++ ++ @Description This routine may be called when MACSEC is enabled in order to ++ disable all MACSEC engines; The MACSEC is working in bypass mode. ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_Init() and when MACSEC is enabled. ++*//***************************************************************************/ ++t_Error FM_MACSEC_Disable(t_Handle h_FmMacsec); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SetException ++ ++ @Description Calling this routine enables/disables the specified exception. ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ @Param[in] exception The exception to be selected. ++ @Param[in] enable TRUE to enable interrupt, FALSE to mask it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SetException(t_Handle h_FmMacsec, e_FmMacsecExceptions exception, bool enable); ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++/**************************************************************************//** ++ @Function FM_MACSEC_DumpRegs ++ ++ @Description Dump internal registers. ++ ++ @Param[in] h_FmMacsec - FM MACSEC module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_MACSEC_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_DumpRegs(t_Handle h_FmMacsec); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++#ifdef VERIFICATION_SUPPORT ++/********************* VERIFICATION ONLY ********************************/ ++/**************************************************************************//** ++ @Function FM_MACSEC_BackdoorSet ++ ++ @Description Set register of the MACSEC memory map ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ @Param[out] offset Register offset. ++ @Param[out] value Value to write. ++ ++ ++ @Return None ++ ++ @Cautions Allowed only following FM_MACSEC_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_BackdoorSet(t_Handle h_FmMacsec, uint32_t offset, uint32_t value); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_BackdoorGet ++ ++ @Description Read from register of the MACSEC memory map. ++ ++ @Param[in] h_FmMacsec FM MACSEC module descriptor. ++ @Param[out] offset Register offset. ++ ++ @Return Value read ++ ++ @Cautions Allowed only following FM_MACSEC_Init(). ++*//***************************************************************************/ ++uint32_t FM_MACSEC_BackdoorGet(t_Handle h_FmMacsec, uint32_t offset); ++#endif /* VERIFICATION_SUPPORT */ ++ ++/** @} */ /* end of FM_MACSEC_runtime_control_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_MACSEC_SECY_grp FM-MACSEC SecY ++ ++ @Description FM-MACSEC SecY API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++typedef uint8_t macsecSAKey_t[32]; ++typedef uint64_t macsecSCI_t; ++typedef uint8_t macsecAN_t; ++ ++/**************************************************************************//** ++ at Description MACSEC SECY Cipher Suite ++*//***************************************************************************/ ++typedef enum e_FmMacsecSecYCipherSuite { ++ e_FM_MACSEC_SECY_GCM_AES_128 = 0, /**< GCM-AES-128 */ ++#if (DPAA_VERSION >= 11) ++ e_FM_MACSEC_SECY_GCM_AES_256 /**< GCM-AES-256 */ ++#endif /* (DPAA_VERSION >= 11) */ ++} e_FmMacsecSecYCipherSuite; ++ ++/**************************************************************************//** ++ @Description MACSEC SECY Exceptions ++*//***************************************************************************/ ++typedef enum e_FmMacsecSecYExceptions { ++ e_FM_MACSEC_SECY_EX_FRAME_DISCARDED /**< Frame Discarded */ ++} e_FmMacsecSecYExceptions; ++ ++/**************************************************************************//** ++ @Description MACSEC SECY Events ++*//***************************************************************************/ ++typedef enum e_FmMacsecSecYEvents { ++ e_FM_MACSEC_SECY_EV_NEXT_PN /**< Next Packet Number exhaustion threshold reached */ ++} e_FmMacsecSecYEvents; ++ ++/**************************************************************************//** ++ @Collection MACSEC SECY Frame Discarded Descriptor error ++*//***************************************************************************/ ++typedef uint8_t macsecTxScFrameDiscardedErrSelect_t; /**< typedef for defining Frame Discarded Descriptor errors */ ++ ++#define FM_MACSEC_SECY_TX_SC_FRM_DISCAR_ERR_NEXT_PN_ZERO 0x8000 /**< NextPn == 0 */ ++#define FM_MACSEC_SECY_TX_SC_FRM_DISCAR_ERR_SC_DISBALE 0x4000 /**< SC is disable */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Function t_FmMacsecSecYExceptionsCallback ++ ++ @Description Exceptions user callback routine, will be called upon an ++ exception passing the exception identification. ++ ++ @Param[in] h_App A handle to an application layer object; This handle ++ will be passed by the driver upon calling this callback. ++ @Param[in] exception The exception. ++*//***************************************************************************/ ++typedef void (t_FmMacsecSecYExceptionsCallback) ( t_Handle h_App, ++ e_FmMacsecSecYExceptions exception); ++ ++/**************************************************************************//** ++ @Function t_FmMacsecSecYEventsCallback ++ ++ @Description Events user callback routine, will be called upon an ++ event passing the event identification. ++ ++ @Param[in] h_App A handle to an application layer object; This handle ++ will be passed by the driver upon calling this callback. ++ @Param[in] event The event. ++*//***************************************************************************/ ++typedef void (t_FmMacsecSecYEventsCallback) ( t_Handle h_App, ++ e_FmMacsecSecYEvents event); ++ ++/**************************************************************************//** ++ @Description RFC2863 MIB ++*//***************************************************************************/ ++typedef struct t_MIBStatistics { ++ uint64_t ifInOctets; /**< Total number of byte received */ ++ uint64_t ifInPkts; /**< Total number of packets received */ ++ uint64_t ifInMcastPkts; /**< Total number of multicast frame received */ ++ uint64_t ifInBcastPkts; /**< Total number of broadcast frame received */ ++ uint64_t ifInDiscards; /**< Frames received, but discarded due to problems within the MAC RX : ++ - InPktsNoTag, ++ - InPktsLate, ++ - InPktsOverrun */ ++ uint64_t ifInErrors; /**< Number of frames received with error: ++ - InPktsBadTag, ++ - InPktsNoSCI, ++ - InPktsNotUsingSA ++ - InPktsNotValid */ ++ uint64_t ifOutOctets; /**< Total number of byte sent */ ++ uint64_t ifOutPkts; /**< Total number of packets sent */ ++ uint64_t ifOutMcastPkts; /**< Total number of multicast frame sent */ ++ uint64_t ifOutBcastPkts; /**< Total number of multicast frame sent */ ++ uint64_t ifOutDiscards; /**< Frames received, but discarded due to problems within the MAC TX N/A! */ ++ uint64_t ifOutErrors; /**< Number of frames transmitted with error: ++ - FIFO Overflow Error ++ - FIFO Underflow Error ++ - Other */ ++} t_MIBStatistics; ++ ++/**************************************************************************//** ++ @Description MACSEC SecY Rx SA Statistics ++*//***************************************************************************/ ++typedef struct t_FmMacsecSecYRxSaStatistics { ++ uint32_t inPktsOK; /**< The number of frames with resolved SCI, have passed all ++ frame validation frame validation with the validateFrame not set to disable */ ++ uint32_t inPktsInvalid; /**< The number of frames with resolved SCI, that have failed frame ++ validation with the validateFrame set to check */ ++ uint32_t inPktsNotValid; /**< The number of frames with resolved SCI, discarded on the controlled port, ++ that have failed frame validation with the validateFrame set to strict or the c bit is set */ ++ uint32_t inPktsNotUsingSA; /**< The number of frames received with resolved SCI and discarded on disabled or ++ not provisioned SA with validateFrame in the strict mode or the C bit is set */ ++ uint32_t inPktsUnusedSA; /**< The number of frames received with resolved SCI on disabled or not provisioned SA ++ with validateFrame not in the strict mode and the C bit is cleared */ ++} t_FmMacsecSecYRxSaStatistics; ++ ++/**************************************************************************//** ++ @Description MACSEC SecY Tx SA Statistics ++*//***************************************************************************/ ++typedef struct t_FmMacsecSecYTxSaStatistics { ++ uint64_t outPktsProtected; /**< The number of frames, that the user of the controlled port requested to ++ be transmitted, which were integrity protected */ ++ uint64_t outPktsEncrypted; /**< The number of frames, that the user of the controlled port requested to ++ be transmitted, which were confidentiality protected */ ++} t_FmMacsecSecYTxSaStatistics; ++ ++/**************************************************************************//** ++ @Description MACSEC SecY Rx SC Statistics ++*//***************************************************************************/ ++typedef struct t_FmMacsecSecYRxScStatistics { ++ uint64_t inPktsUnchecked; /**< The number of frames with resolved SCI, delivered to the user of a controlled port, ++ that are not validated with the validateFrame set to disable */ ++ uint64_t inPktsDelayed; /**< The number of frames with resolved SCI, delivered to the user of a controlled port, ++ that have their PN smaller than the lowest_PN with the validateFrame set to ++ disable or replayProtect disabled */ ++ uint64_t inPktsLate; /**< The number of frames with resolved SCI, discarded on the controlled port, ++ that have their PN smaller than the lowest_PN with the validateFrame set to ++ Check or Strict and replayProtect enabled */ ++ uint64_t inPktsOK; /**< The number of frames with resolved SCI, have passed all ++ frame validation frame validation with the validateFrame not set to disable */ ++ uint64_t inPktsInvalid; /**< The number of frames with resolved SCI, that have failed frame ++ validation with the validateFrame set to check */ ++ uint64_t inPktsNotValid; /**< The number of frames with resolved SCI, discarded on the controlled port, ++ that have failed frame validation with the validateFrame set to strict or the c bit is set */ ++ uint64_t inPktsNotUsingSA; /**< The number of frames received with resolved SCI and discarded on disabled or ++ not provisioned SA with validateFrame in the strict mode or the C bit is set */ ++ uint64_t inPktsUnusedSA; /**< The number of frames received with resolved SCI on disabled or not provisioned SA ++ with validateFrame not in the strict mode and the C bit is cleared */ ++} t_FmMacsecSecYRxScStatistics; ++ ++/**************************************************************************//** ++ @Description MACSEC SecY Tx SC Statistics ++*//***************************************************************************/ ++typedef struct t_FmMacsecSecYTxScStatistics { ++ uint64_t outPktsProtected; /**< The number of frames, that the user of the controlled port requested to ++ be transmitted, which were integrity protected */ ++ uint64_t outPktsEncrypted; /**< The number of frames, that the user of the controlled port requested to ++ be transmitted, which were confidentiality protected */ ++} t_FmMacsecSecYTxScStatistics; ++ ++/**************************************************************************//** ++ @Description MACSEC SecY Statistics ++*//***************************************************************************/ ++typedef struct t_FmMacsecSecYStatistics { ++ t_MIBStatistics mibCtrlStatistics; /**< Controlled port MIB statistics */ ++ t_MIBStatistics mibNonCtrlStatistics; /**< Uncontrolled port MIB statistics */ ++/* Frame verification statistics */ ++ uint64_t inPktsUntagged; /**< The number of received packets without the MAC security tag ++ (SecTAG) with validateFrames which is not in the strict mode */ ++ uint64_t inPktsNoTag; /**< The number of received packets discarded without the ++ MAC security tag (SecTAG) with validateFrames which is in the strict mode */ ++ uint64_t inPktsBadTag; /**< The number of received packets discarded with an invalid ++ SecTAG or a zero value PN or an invalid ICV */ ++ uint64_t inPktsUnknownSCI; /**< The number of received packets with unknown SCI with the ++ condition : validateFrames is not in the strict mode and the ++ C bit in the SecTAG is not set */ ++ uint64_t inPktsNoSCI; /**< The number of received packets discarded with unknown SCI ++ information with the condition : validateFrames is in the strict mode ++ or the C bit in the SecTAG is set */ ++ uint64_t inPktsOverrun; /**< The number of packets discarded because the number of ++ received packets exceeded the cryptographic performance capabilities */ ++/* Frame validation statistics */ ++ uint64_t inOctetsValidated; /**< The number of octets of plaintext recovered from received frames with ++ resolved SCI that were integrity protected but not encrypted */ ++ uint64_t inOctetsDecrypted; /**< The number of octets of plaintext recovered from received frames with ++ resolved SCI that were integrity protected and encrypted */ ++/* Frame generation statistics */ ++ uint64_t outPktsUntagged; /**< The number of frames, that the user of the controlled port requested to ++ be transmitted, with protectFrame false */ ++ uint64_t outPktsTooLong; /**< The number of frames, that the user of the controlled port requested to ++ be transmitted, discarded due to length being larger than Maximum Frame Length (MACSEC_MFL) */ ++/* Frame protection statistics */ ++ uint64_t outOctetsProtected; /**< The number of octets of User Data in transmitted frames that were ++ integrity protected but not encrypted */ ++ uint64_t outOctetsEncrypted; /**< The number of octets of User Data in transmitted frames that were ++ both integrity protected and encrypted */ ++} t_FmMacsecSecYStatistics; ++ ++ ++/**************************************************************************//** ++ @Description MACSEC SecY SC Params ++*//***************************************************************************/ ++typedef struct t_FmMacsecSecYSCParams { ++ macsecSCI_t sci; /**< The secure channel identification of the SC */ ++ e_FmMacsecSecYCipherSuite cipherSuite; /**< Cipher suite to be used for the SC */ ++} t_FmMacsecSecYSCParams; ++ ++/**************************************************************************//** ++ @Group FM_MACSEC_SECY_init_grp FM-MACSEC SecY Initialization Unit ++ ++ @Description FM-MACSEC SecY Initialization Unit ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description enum for validate frames ++*//***************************************************************************/ ++typedef enum e_FmMacsecValidFrameBehavior { ++ e_FM_MACSEC_VALID_FRAME_BEHAVIOR_DISABLE = 0, /**< disable the validation function */ ++ e_FM_MACSEC_VALID_FRAME_BEHAVIOR_CHECK, /**< enable the validation function but only for checking ++ without filtering out invalid frames */ ++ e_FM_MACSEC_VALID_FRAME_BEHAVIOR_STRICT /**< enable the validation function and also strictly filter ++ out those invalid frames */ ++} e_FmMacsecValidFrameBehavior; ++ ++/**************************************************************************//** ++ @Description enum for sci insertion ++*//***************************************************************************/ ++typedef enum e_FmMacsecSciInsertionMode { ++ e_FM_MACSEC_SCI_INSERTION_MODE_EXPLICIT_SECTAG = 0, /**< explicit sci in the sectag */ ++ e_FM_MACSEC_SCI_INSERTION_MODE_EXPLICIT_MAC_SA, /**< mac sa is overwritten with the sci*/ ++ e_FM_MACSEC_SCI_INSERTION_MODE_IMPLICT_PTP /**< implicit point-to-point sci (pre-shared) */ ++} e_FmMacsecSciInsertionMode; ++ ++/**************************************************************************//** ++ @Description FM MACSEC SecY config input ++*//***************************************************************************/ ++typedef struct t_FmMacsecSecYParams { ++ t_Handle h_FmMacsec; /**< A handle to the FM MACSEC object */ ++ t_FmMacsecSecYSCParams txScParams; /**< Tx SC Params */ ++ uint32_t numReceiveChannels; /**< Number of receive channels dedicated to this SecY */ ++ t_FmMacsecSecYExceptionsCallback *f_Exception; /**< Callback routine to be called by the driver upon SecY exception */ ++ t_FmMacsecSecYEventsCallback *f_Event; /**< Callback routine to be called by the driver upon SecY event */ ++ t_Handle h_App; /**< A handle to an application layer object; This handle will ++ be passed by the driver upon calling the above callbacks */ ++} t_FmMacsecSecYParams; ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_Config ++ ++ @Description Creates descriptor for the FM MACSEC SECY module; ++ ++ The routine returns a handle (descriptor) to the FM MACSEC SECY object; ++ This descriptor must be passed as first parameter to all other ++ FM MACSEC SECY function calls; ++ No actual initialization or configuration of FM MACSEC SecY hardware is ++ done by this routine. ++ ++ @Param[in] p_FmMacsecSecYParam Pointer to data structure of parameters. ++ ++ @Return Handle to FM MACSEC SECY object, or NULL for Failure. ++*//***************************************************************************/ ++t_Handle FM_MACSEC_SECY_Config(t_FmMacsecSecYParams *p_FmMacsecSecYParam); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_Init ++ ++ @Description Initializes the FM MACSEC SECY module. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_Init(t_Handle h_FmMacsecSecY); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_Free ++ ++ @Description Frees all resources that were assigned to FM MACSEC SECY module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_Free(t_Handle h_FmMacsecSecY); ++ ++/**************************************************************************//** ++ @Group FM_MACSEC_SECY_advanced_init_grp FM-MACSEC SecY Advanced Configuration Unit ++ ++ @Description Configuration functions used to change default values. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_ConfigSciInsertionMode ++ ++ @Description Calling this routine changes the SCI-insertion-mode in the ++ internal driver data base from its default configuration ++ [DEFAULT_sciInsertionMode] ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] sciInsertionMode Sci insertion mode ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Config() and before FM_MACSEC_SECY_Init(); ++ ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_ConfigSciInsertionMode(t_Handle h_FmMacsecSecY, e_FmMacsecSciInsertionMode sciInsertionMode); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_ConfigProtectFrames ++ ++ @Description Calling this routine changes the protect-frame mode in the ++ internal driver data base from its default configuration ++ [DEFAULT_protectFrames] ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] protectFrames If FALSE, frames are transmitted without modification ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Config() and before FM_MACSEC_SECY_Init(); ++ ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_ConfigProtectFrames(t_Handle h_FmMacsecSecY, bool protectFrames); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_ConfigReplayWindow ++ ++ @Description Calling this routine changes the replay-window settings in the ++ internal driver data base from its default configuration ++ [DEFAULT_replayEnable], [DEFAULT_replayWindow] ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] replayProtect; Replay protection function mode ++ @Param[in] replayWindow; The size of the replay window ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Config() and before FM_MACSEC_SECY_Init(); ++ ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_ConfigReplayWindow(t_Handle h_FmMacsecSecY, bool replayProtect, uint32_t replayWindow); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_ConfigValidationMode ++ ++ @Description Calling this routine changes the frame-validation-behavior mode ++ in the internal driver data base from its default configuration ++ [DEFAULT_validateFrames] ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] validateFrames Validation function mode ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Config() and before FM_MACSEC_SECY_Init(); ++ ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_ConfigValidationMode(t_Handle h_FmMacsecSecY, e_FmMacsecValidFrameBehavior validateFrames); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_ConfigConfidentiality ++ ++ @Description Calling this routine changes the confidentiality settings in the ++ internal driver data base from its default configuration ++ [DEFAULT_confidentialityEnable], [DEFAULT_confidentialityOffset] ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] confidentialityEnable TRUE - confidentiality protection and integrity protection ++ FALSE - no confidentiality protection, only integrity protection ++ @Param[in] confidentialityOffset The number of initial octets of each MSDU without confidentiality protection ++ common values are 0, 30, and 50 ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Config() and before FM_MACSEC_SECY_Init(); ++ ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_ConfigConfidentiality(t_Handle h_FmMacsecSecY, bool confidentialityEnable, uint16_t confidentialityOffset); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_ConfigPointToPoint ++ ++ @Description configure this SecY to work in point-to-point mode, means that ++ it will have only one rx sc; ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Config() and before FM_MACSEC_SECY_Init(); ++ Can be called only once in a system; only the first secY that will call this ++ routine will be able to operate in Point-To-Point mode. ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_ConfigPointToPoint(t_Handle h_FmMacsecSecY); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_ConfigException ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default selection of exceptions enablement; ++ By default all exceptions are enabled. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] exception The exception to be selected. ++ @Param[in] enable TRUE to enable interrupt, FALSE to mask it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Config() and before FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_ConfigException(t_Handle h_FmMacsecSecY, e_FmMacsecSecYExceptions exception, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_ConfigEvent ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default selection of events enablement; ++ By default all events are enabled. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] event The event to be selected. ++ @Param[in] enable TRUE to enable interrupt, FALSE to mask it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Config() and before FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_ConfigEvent(t_Handle h_FmMacsecSecY, e_FmMacsecSecYEvents event, bool enable); ++ ++/** @} */ /* end of FM_MACSEC_SECY_advanced_init_grp group */ ++/** @} */ /* end of FM_MACSEC_SECY_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_MACSEC_SECY_runtime_control_grp FM-MACSEC SecY Runtime Control Unit ++ ++ @Description FM MACSEC SECY Runtime control unit API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_CreateRxSc ++ ++ @Description Create a receive secure channel. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] scParams secure channel params. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Handle FM_MACSEC_SECY_CreateRxSc(t_Handle h_FmMacsecSecY, t_FmMacsecSecYSCParams *p_ScParams); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_DeleteRxSc ++ ++ @Description Deleting an initialized secure channel. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] h_Sc SC handle as returned by FM_MACSEC_SECY_CreateRxSc. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_CreateRxSc(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_DeleteRxSc(t_Handle h_FmMacsecSecY, t_Handle h_Sc); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_CreateRxSa ++ ++ @Description Create a receive secure association for the secure channel; ++ the SA cannot be used to receive frames until FM_MACSEC_SECY_RxSaEnableReceive is called. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] h_Sc SC handle as returned by FM_MACSEC_SECY_CreateRxSc. ++ @Param[in] an association number represent the SA. ++ @Param[in] lowestPn the lowest acceptable PN value for a received frame. ++ @Param[in] key the desired key for this SA. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_CreateRxSc(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_CreateRxSa(t_Handle h_FmMacsecSecY, t_Handle h_Sc, macsecAN_t an, uint32_t lowestPn, macsecSAKey_t key); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_DeleteRxSa ++ ++ @Description Deleting an initialized secure association. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] h_Sc SC handle as returned by FM_MACSEC_SECY_CreateRxSc. ++ @Param[in] an association number represent the SA. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_DeleteRxSa(t_Handle h_FmMacsecSecY, t_Handle h_Sc, macsecAN_t an); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_RxSaEnableReceive ++ ++ @Description Enabling the SA to receive frames. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] h_Sc SC handle as returned by FM_MACSEC_SECY_CreateRxSc. ++ @Param[in] an association number represent the SA. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_CreateRxSa(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_RxSaEnableReceive(t_Handle h_FmMacsecSecY, t_Handle h_Sc, macsecAN_t an); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_RxSaDisableReceive ++ ++ @Description Disabling the SA from receive frames. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] h_Sc SC handle as returned by FM_MACSEC_SECY_CreateRxSc. ++ @Param[in] an association number represent the SA. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_CreateRxSa(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_RxSaDisableReceive(t_Handle h_FmMacsecSecY, t_Handle h_Sc, macsecAN_t an); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_RxSaUpdateNextPn ++ ++ @Description Update the next packet number expected on RX; ++ The value of nextPN shall be set to the greater of its existing value and the ++ supplied of updtNextPN (802.1AE-2006 10.7.15). ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] h_Sc SC handle as returned by FM_MACSEC_SECY_CreateRxSc. ++ @Param[in] an association number represent the SA. ++ @Param[in] updtNextPN the next PN value for a received frame. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_CreateRxSa(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_RxSaUpdateNextPn(t_Handle h_FmMacsecSecY, t_Handle h_Sc, macsecAN_t an, uint32_t updtNextPN); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_RxSaUpdateLowestPn ++ ++ @Description Update the lowest packet number expected on RX; ++ The value of lowestPN shall be set to the greater of its existing value and the ++ supplied of updtLowestPN (802.1AE-2006 10.7.15). ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] h_Sc SC handle as returned by FM_MACSEC_SECY_CreateRxSc. ++ @Param[in] an association number represent the SA. ++ @Param[in] updtLowestPN the lowest PN acceptable value for a received frame. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_CreateRxSa(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_RxSaUpdateLowestPn(t_Handle h_FmMacsecSecY, t_Handle h_Sc, macsecAN_t an, uint32_t updtLowestPN); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_RxSaModifyKey ++ ++ @Description Modify the current key of the SA with a new one. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] h_Sc SC handle as returned by FM_MACSEC_SECY_CreateRxSc. ++ @Param[in] an association number represent the SA. ++ @Param[in] key new key to replace the current key. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_CreateRxSa(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_RxSaModifyKey(t_Handle h_FmMacsecSecY, t_Handle h_Sc, macsecAN_t an, macsecSAKey_t key); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_CreateTxSa ++ ++ @Description Create a transmit secure association for the secure channel; ++ the SA cannot be used to transmit frames until FM_MACSEC_SECY_TxSaSetActivate is called; ++ Only one SA can be active at a time. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] an association number represent the SA. ++ @Param[in] key the desired key for this SA. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_CreateTxSa(t_Handle h_FmMacsecSecY, macsecAN_t an, macsecSAKey_t key); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_DeleteTxSa ++ ++ @Description Deleting an initialized secure association. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] an association number represent the SA. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_DeleteTxSa(t_Handle h_FmMacsecSecY, macsecAN_t an); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_TxSaModifyKey ++ ++ @Description Modify the key of the inactive SA with a new one. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] nextActiveAn association number represent the next SA to be activated. ++ @Param[in] key new key to replace the current key. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_TxSaModifyKey(t_Handle h_FmMacsecSecY, macsecAN_t nextActiveAn, macsecSAKey_t key); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_TxSaSetActive ++ ++ @Description Set this SA to the active SA to be used on TX for SC; ++ only one SA can be active at a time. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] an association number represent the SA. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_TxSaSetActive(t_Handle h_FmMacsecSecY, macsecAN_t an); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_TxSaGetActive ++ ++ @Description Get the active SA that being used for TX. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[out] p_An the active an. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_TxSaGetActive(t_Handle h_FmMacsecSecY, macsecAN_t *p_An); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_GetStatistics ++ ++ @Description get all statistics counters. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] p_Statistics Structure with statistics. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_GetStatistics(t_Handle h_FmMacsecSecY, t_FmMacsecSecYStatistics *p_Statistics); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_RxScGetStatistics ++ ++ @Description get all statistics counters. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] h_Sc Rx Sc handle. ++ @Param[in] p_Statistics Structure with statistics. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_RxScGetStatistics(t_Handle h_FmMacsecSecY, t_Handle h_Sc, t_FmMacsecSecYRxScStatistics *p_Statistics); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_RxSaGetStatistics ++ ++ @Description get all statistics counters ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] h_Sc Rx Sc handle. ++ @Param[in] an association number represent the SA. ++ @Param[in] p_Statistics Structure with statistics. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_RxSaGetStatistics(t_Handle h_FmMacsecSecY, t_Handle h_Sc, macsecAN_t an, t_FmMacsecSecYRxSaStatistics *p_Statistics); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_TxScGetStatistics ++ ++ @Description get all statistics counters. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] p_Statistics Structure with statistics. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_TxScGetStatistics(t_Handle h_FmMacsecSecY, t_FmMacsecSecYTxScStatistics *p_Statistics); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_TxSaGetStatistics ++ ++ @Description get all statistics counters. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] an association number represent the SA. ++ @Param[in] p_Statistics Structure with statistics. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_TxSaGetStatistics(t_Handle h_FmMacsecSecY, macsecAN_t an, t_FmMacsecSecYTxSaStatistics *p_Statistics); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_SetException ++ ++ @Description Calling this routine enables/disables the specified exception. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] exception The exception to be selected. ++ @Param[in] enable TRUE to enable interrupt, FALSE to mask it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_SetException(t_Handle h_FmMacsecSecY, e_FmMacsecExceptions exception, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_SetEvent ++ ++ @Description Calling this routine enables/disables the specified event. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] event The event to be selected. ++ @Param[in] enable TRUE to enable interrupt, FALSE to mask it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Config() and before FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_SetEvent(t_Handle h_FmMacsecSecY, e_FmMacsecSecYEvents event, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_GetRxScPhysId ++ ++ @Description return the physical id of the Secure Channel. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[in] h_Sc SC handle as returned by FM_MACSEC_SECY_CreateRxSc. ++ @Param[out] p_ScPhysId the SC physical id. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_CreateRxSc(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_GetRxScPhysId(t_Handle h_FmMacsecSecY, t_Handle h_Sc, uint32_t *p_ScPhysId); ++ ++/**************************************************************************//** ++ @Function FM_MACSEC_SECY_GetTxScPhysId ++ ++ @Description return the physical id of the Secure Channel. ++ ++ @Param[in] h_FmMacsecSecY FM MACSEC SECY module descriptor. ++ @Param[out] p_ScPhysId the SC physical id. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MACSEC_SECY_Init(). ++*//***************************************************************************/ ++t_Error FM_MACSEC_SECY_GetTxScPhysId(t_Handle h_FmMacsecSecY, uint32_t *p_ScPhysId); ++ ++/** @} */ /* end of FM_MACSEC_SECY_runtime_control_grp group */ ++/** @} */ /* end of FM_MACSEC_SECY_grp group */ ++/** @} */ /* end of FM_MACSEC_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++#endif /* __FM_MACSEC_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_muram_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_muram_ext.h +new file mode 100644 +index 0000000..ef62c8e +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_muram_ext.h +@@ -0,0 +1,170 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File fm_muram_ext.h ++ ++ @Description FM MURAM Application Programming Interface. ++*//***************************************************************************/ ++#ifndef __FM_MURAM_EXT ++#define __FM_MURAM_EXT ++ ++#include "error_ext.h" ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_muram_grp FM MURAM ++ ++ @Description FM MURAM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_muram_init_grp FM MURAM Initialization Unit ++ ++ @Description FM MURAM initialization API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_MURAM_ConfigAndInit ++ ++ @Description Creates partition in the MURAM. ++ ++ The routine returns a handle (descriptor) to the MURAM partition. ++ This descriptor must be passed as first parameter to all other ++ FM-MURAM function calls. ++ ++ No actual initialization or configuration of FM_MURAM hardware is ++ done by this routine. ++ ++ @Param[in] baseAddress - Pointer to base of memory mapped FM-MURAM. ++ @Param[in] size - Size of the FM-MURAM partition. ++ ++ @Return Handle to FM-MURAM object, or NULL for Failure. ++*//***************************************************************************/ ++t_Handle FM_MURAM_ConfigAndInit(uintptr_t baseAddress, uint32_t size); ++ ++/**************************************************************************//** ++ @Function FM_MURAM_Free ++ ++ @Description Frees all resources that were assigned to FM-MURAM module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmMuram - FM-MURAM module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_MURAM_Free(t_Handle h_FmMuram); ++ ++/** @} */ /* end of FM_muram_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_muram_ctrl_grp FM MURAM Control Unit ++ ++ @Description FM MURAM control API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_MURAM_AllocMem ++ ++ @Description Allocate some memory from FM-MURAM partition. ++ ++ @Param[in] h_FmMuram - FM-MURAM module descriptor. ++ @Param[in] size - size of the memory to be allocated. ++ @Param[in] align - Alignment of the memory. ++ ++ @Return address of the allocated memory; NULL otherwise. ++*//***************************************************************************/ ++void * FM_MURAM_AllocMem(t_Handle h_FmMuram, uint32_t size, uint32_t align); ++ ++/**************************************************************************//** ++ @Function FM_MURAM_AllocMemForce ++ ++ @Description Allocate some specific memory from FM-MURAM partition (according ++ to base). ++ ++ @Param[in] h_FmMuram - FM-MURAM module descriptor. ++ @Param[in] base - the desired base-address to be allocated. ++ @Param[in] size - size of the memory to be allocated. ++ ++ @Return address of the allocated memory; NULL otherwise. ++*//***************************************************************************/ ++void * FM_MURAM_AllocMemForce(t_Handle h_FmMuram, uint64_t base, uint32_t size); ++ ++/**************************************************************************//** ++ @Function FM_MURAM_FreeMem ++ ++ @Description Free an allocated memory from FM-MURAM partition. ++ ++ @Param[in] h_FmMuram - FM-MURAM module descriptor. ++ @Param[in] ptr - A pointer to an allocated memory. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_MURAM_FreeMem(t_Handle h_FmMuram, void *ptr); ++ ++/**************************************************************************//** ++ @Function FM_MURAM_GetFreeMemSize ++ ++ @Description Returns the size (in bytes) of free MURAM memory. ++ ++ @Param[in] h_FmMuram - FM-MURAM module descriptor. ++ ++ @Return Free MURAM memory size in bytes. ++*//***************************************************************************/ ++uint64_t FM_MURAM_GetFreeMemSize(t_Handle h_FmMuram); ++ ++/** @} */ /* end of FM_muram_ctrl_grp group */ ++/** @} */ /* end of FM_muram_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++ ++#endif /* __FM_MURAM_EXT */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_pcd_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_pcd_ext.h +new file mode 100644 +index 0000000..a9e4a24 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_pcd_ext.h +@@ -0,0 +1,3972 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File fm_pcd_ext.h ++ ++ @Description FM PCD API definitions ++*//***************************************************************************/ ++#ifndef __FM_PCD_EXT ++#define __FM_PCD_EXT ++ ++#include "std_ext.h" ++#include "net_ext.h" ++#include "list_ext.h" ++#include "fm_ext.h" ++#include "fsl_fman_kg.h" ++ ++ ++/**************************************************************************//** ++ @Group FM_grp Frame Manager API ++ ++ @Description Frame Manager Application Programming Interface ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_PCD_grp FM PCD ++ ++ @Description Frame Manager PCD (Parse-Classify-Distribute) API. ++ ++ The FM PCD module is responsible for the initialization of all ++ global classifying FM modules. This includes the parser general and ++ common registers, the key generator global and common registers, ++ and the policer global and common registers. ++ In addition, the FM PCD SW module will initialize all required ++ key generator schemes, coarse classification flows, and policer ++ profiles. When FM module is configured to work with one of these ++ entities, it will register to it using the FM PORT API. The PCD ++ module will manage the PCD resources - i.e. resource management of ++ KeyGen schemes, etc. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Collection General PCD defines ++*//***************************************************************************/ ++#define FM_PCD_MAX_NUM_OF_PRIVATE_HDRS 2 /**< Number of units/headers saved for user */ ++ ++#define FM_PCD_PRS_NUM_OF_HDRS 16 /**< Number of headers supported by HW parser */ ++#define FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS (32 - FM_PCD_MAX_NUM_OF_PRIVATE_HDRS) ++ /**< Number of distinction units is limited by ++ register size (32 bits) minus reserved bits ++ for private headers. */ ++#define FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS 4 /**< Maximum number of interchangeable headers ++ in a distinction unit */ ++#define FM_PCD_KG_NUM_OF_GENERIC_REGS FM_KG_NUM_OF_GENERIC_REGS /**< Total number of generic KeyGen registers */ ++#define FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY 35 /**< Max number allowed on any configuration; ++ For HW implementation reasons, in most ++ cases less than this will be allowed; The ++ driver will return an initialization error ++ if resource is unavailable. */ ++#define FM_PCD_KG_NUM_OF_EXTRACT_MASKS 4 /**< Total number of masks allowed on KeyGen extractions. */ ++#define FM_PCD_KG_NUM_OF_DEFAULT_GROUPS 16 /**< Number of default value logical groups */ ++ ++#define FM_PCD_PRS_NUM_OF_LABELS 32 /**< Maximum number of SW parser labels */ ++#define FM_SW_PRS_MAX_IMAGE_SIZE (FM_PCD_SW_PRS_SIZE /*- FM_PCD_PRS_SW_OFFSET -FM_PCD_PRS_SW_TAIL_SIZE*/-FM_PCD_PRS_SW_PATCHES_SIZE) ++ /**< Maximum size of SW parser code */ ++ ++#define FM_PCD_MAX_MANIP_INSRT_TEMPLATE_SIZE 128 /**< Maximum size of insertion template for ++ insert manipulation */ ++ ++#if (DPAA_VERSION >= 11) ++#define FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES 64 /**< Maximum possible entries for frame replicator group */ ++#endif /* (DPAA_VERSION >= 11) */ ++/* @} */ ++ ++ ++/**************************************************************************//** ++ @Group FM_PCD_init_grp FM PCD Initialization Unit ++ ++ @Description Frame Manager PCD Initialization Unit API ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description PCD counters ++*//***************************************************************************/ ++typedef enum e_FmPcdCounters { ++ e_FM_PCD_KG_COUNTERS_TOTAL, /**< KeyGen counter */ ++ e_FM_PCD_PLCR_COUNTERS_RED, /**< Policer counter - counts the total number of RED packets that exit the Policer. */ ++ e_FM_PCD_PLCR_COUNTERS_YELLOW, /**< Policer counter - counts the total number of YELLOW packets that exit the Policer. */ ++ e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED, /**< Policer counter - counts the number of packets that changed color to RED by the Policer; ++ This is a subset of e_FM_PCD_PLCR_COUNTERS_RED packet count, indicating active color changes. */ ++ e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW, /**< Policer counter - counts the number of packets that changed color to YELLOW by the Policer; ++ This is a subset of e_FM_PCD_PLCR_COUNTERS_YELLOW packet count, indicating active color changes. */ ++ e_FM_PCD_PLCR_COUNTERS_TOTAL, /**< Policer counter - counts the total number of packets passed in the Policer. */ ++ e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH, /**< Policer counter - counts the number of packets with length mismatch. */ ++ e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH, /**< Parser counter - counts the number of times the parser block is dispatched. */ ++ e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED, /**< Parser counter - counts the number of times L2 parse result is returned (including errors). */ ++ e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED, /**< Parser counter - counts the number of times L3 parse result is returned (including errors). */ ++ e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED, /**< Parser counter - counts the number of times L4 parse result is returned (including errors). */ ++ e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED, /**< Parser counter - counts the number of times SHIM parse result is returned (including errors). */ ++ e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR, /**< Parser counter - counts the number of times L2 parse result is returned with errors. */ ++ e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR, /**< Parser counter - counts the number of times L3 parse result is returned with errors. */ ++ e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR, /**< Parser counter - counts the number of times L4 parse result is returned with errors. */ ++ e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR, /**< Parser counter - counts the number of times SHIM parse result is returned with errors. */ ++ e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES, /**< Parser counter - counts the number of cycles spent executing soft parser instruction (including stall cycles). */ ++ e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES, /**< Parser counter - counts the number of cycles stalled waiting for parser internal memory reads while executing soft parser instruction. */ ++ e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES, /**< Parser counter - counts the number of cycles spent executing hard parser (including stall cycles). */ ++ e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES, /**< MURAM counter - counts the number of cycles while performing FMan Memory read. */ ++ e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES, /**< MURAM counter - counts the number of cycles stalled while performing FMan Memory read. */ ++ e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES, /**< MURAM counter - counts the number of cycles while performing FMan Memory write. */ ++ e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES, /**< MURAM counter - counts the number of cycles stalled while performing FMan Memory write. */ ++ e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES /**< FPM counter - counts the number of cycles stalled while performing a FPM Command. */ ++} e_FmPcdCounters; ++ ++/**************************************************************************//** ++ @Description PCD interrupts ++*//***************************************************************************/ ++typedef enum e_FmPcdExceptions { ++ e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC, /**< KeyGen double-bit ECC error is detected on internal memory read access. */ ++ e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW, /**< KeyGen scheme configuration error indicating a key size larger than 56 bytes. */ ++ e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC, /**< Policer double-bit ECC error has been detected on PRAM read access. */ ++ e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR, /**< Policer access to a non-initialized profile has been detected. */ ++ e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE, /**< Policer RAM self-initialization complete */ ++ e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE, /**< Policer atomic action complete */ ++ e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC, /**< Parser double-bit ECC error */ ++ e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC /**< Parser single-bit ECC error */ ++} e_FmPcdExceptions; ++ ++ ++/**************************************************************************//** ++ @Description Exceptions user callback routine, will be called upon an ++ exception passing the exception identification. ++ ++ @Param[in] h_App - User's application descriptor. ++ @Param[in] exception - The exception. ++ *//***************************************************************************/ ++typedef void (t_FmPcdExceptionCallback) (t_Handle h_App, e_FmPcdExceptions exception); ++ ++/**************************************************************************//** ++ @Description Exceptions user callback routine, will be called upon an exception ++ passing the exception identification. ++ ++ @Param[in] h_App - User's application descriptor. ++ @Param[in] exception - The exception. ++ @Param[in] index - id of the relevant source (may be scheme or profile id). ++ *//***************************************************************************/ ++typedef void (t_FmPcdIdExceptionCallback) ( t_Handle h_App, ++ e_FmPcdExceptions exception, ++ uint16_t index); ++ ++/**************************************************************************//** ++ @Description A callback for enqueuing frame onto a QM queue. ++ ++ @Param[in] h_QmArg - Application's handle passed to QM module on enqueue. ++ @Param[in] p_Fd - Frame descriptor for the frame. ++ ++ @Return E_OK on success; Error code otherwise. ++ *//***************************************************************************/ ++typedef t_Error (t_FmPcdQmEnqueueCallback) (t_Handle h_QmArg, void *p_Fd); ++ ++/**************************************************************************//** ++ @Description Host-Command parameters structure. ++ ++ When using Host command for PCD functionalities, a dedicated port ++ must be used. If this routine is called for a PCD in a single partition ++ environment, or it is the Master partition in a Multi-partition ++ environment, The port will be initialized by the PCD driver ++ initialization routine. ++ *//***************************************************************************/ ++typedef struct t_FmPcdHcParams { ++ uintptr_t portBaseAddr; /**< Virtual Address of Host-Command Port memory mapped registers.*/ ++ uint8_t portId; /**< Port Id (0-6 relative to Host-Command/Offline-Parsing ports); ++ NOTE: When configuring Host Command port for ++ FMANv3 devices (DPAA_VERSION 11 and higher), ++ portId=0 MUST be used. */ ++ uint16_t liodnBase; /**< LIODN base for this port, to be used together with LIODN offset ++ (irrelevant for P4080 revision 1.0) */ ++ uint32_t errFqid; /**< Host-Command Port error queue Id. */ ++ uint32_t confFqid; /**< Host-Command Port confirmation queue Id. */ ++ uint32_t qmChannel; /**< QM channel dedicated to this Host-Command port; ++ will be used by the FM for dequeue. */ ++ t_FmPcdQmEnqueueCallback *f_QmEnqueue; /**< Callback routine for enqueuing a frame to the QM */ ++ t_Handle h_QmArg; /**< Application's handle passed to QM module on enqueue */ ++} t_FmPcdHcParams; ++ ++/**************************************************************************//** ++ @Description The main structure for PCD initialization ++ *//***************************************************************************/ ++typedef struct t_FmPcdParams { ++ bool prsSupport; /**< TRUE if Parser will be used for any of the FM ports. */ ++ bool ccSupport; /**< TRUE if Coarse Classification will be used for any ++ of the FM ports. */ ++ bool kgSupport; /**< TRUE if KeyGen will be used for any of the FM ports. */ ++ bool plcrSupport; /**< TRUE if Policer will be used for any of the FM ports. */ ++ t_Handle h_Fm; /**< A handle to the FM module. */ ++ uint8_t numOfSchemes; /**< Number of schemes dedicated to this partition. ++ this parameter is relevant if 'kgSupport'=TRUE. */ ++ bool useHostCommand; /**< Optional for single partition, Mandatory for Multi partition */ ++ t_FmPcdHcParams hc; /**< Host Command parameters, relevant only if 'useHostCommand'=TRUE; ++ Relevant when FM not runs in "guest-mode". */ ++ ++ t_FmPcdExceptionCallback *f_Exception; /**< Callback routine for general PCD exceptions; ++ Relevant when FM not runs in "guest-mode". */ ++ t_FmPcdIdExceptionCallback *f_ExceptionId; /**< Callback routine for specific KeyGen scheme or ++ Policer profile exceptions; ++ Relevant when FM not runs in "guest-mode". */ ++ t_Handle h_App; /**< A handle to an application layer object; This handle will ++ be passed by the driver upon calling the above callbacks; ++ Relevant when FM not runs in "guest-mode". */ ++ uint8_t partPlcrProfilesBase; /**< The first policer-profile-id dedicated to this partition. ++ this parameter is relevant if 'plcrSupport'=TRUE. ++ NOTE: this parameter relevant only when working with multiple partitions. */ ++ uint16_t partNumOfPlcrProfiles; /**< Number of policer-profiles dedicated to this partition. ++ this parameter is relevant if 'plcrSupport'=TRUE. ++ NOTE: this parameter relevant only when working with multiple partitions. */ ++} t_FmPcdParams; ++ ++ ++/**************************************************************************//** ++ @Function FM_PCD_Config ++ ++ @Description Basic configuration of the PCD module. ++ Creates descriptor for the FM PCD module. ++ ++ @Param[in] p_FmPcdParams A structure of parameters for the initialization of PCD. ++ ++ @Return A handle to the initialized module. ++*//***************************************************************************/ ++t_Handle FM_PCD_Config(t_FmPcdParams *p_FmPcdParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_Init ++ ++ @Description Initialization of the PCD module. ++ ++ @Param[in] h_FmPcd - FM PCD module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PCD_Init(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_Free ++ ++ @Description Frees all resources that were assigned to FM module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmPcd - FM PCD module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PCD_Free(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Group FM_PCD_advanced_cfg_grp FM PCD Advanced Configuration Unit ++ ++ @Description Frame Manager PCD Advanced Configuration API. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_PCD_ConfigException ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default selection of exceptions enabling. ++ [DEFAULT_numOfSharedPlcrProfiles]. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] exception The exception to be selected. ++ @Param[in] enable TRUE to enable interrupt, FALSE to mask it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_ConfigException(t_Handle h_FmPcd, e_FmPcdExceptions exception, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ConfigHcFramesDataMemory ++ ++ @Description Configures memory-partition-id for FMan-Controller Host-Command ++ frames. Calling this routine changes the internal driver data ++ base from its default configuration [0]. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] memId Memory partition ID. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions This routine may be called only if 'useHostCommand' was TRUE ++ when FM_PCD_Config() routine was called. ++*//***************************************************************************/ ++t_Error FM_PCD_ConfigHcFramesDataMemory(t_Handle h_FmPcd, uint8_t memId); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ConfigPlcrNumOfSharedProfiles ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default selection of exceptions enablement. ++ [DEFAULT_numOfSharedPlcrProfiles]. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] numOfSharedPlcrProfiles Number of profiles to ++ be shared between ports on this partition ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PCD_ConfigPlcrNumOfSharedProfiles(t_Handle h_FmPcd, uint16_t numOfSharedPlcrProfiles); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ConfigPlcrAutoRefreshMode ++ ++ @Description Calling this routine changes the internal driver data base ++ from its default selection of exceptions enablement. ++ By default auto-refresh is [DEFAULT_plcrAutoRefresh]. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] enable TRUE to enable, FALSE to disable ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_ConfigPlcrAutoRefreshMode(t_Handle h_FmPcd, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ConfigPrsMaxCycleLimit ++ ++ @Description Calling this routine changes the internal data structure for ++ the maximum parsing time from its default value ++ [DEFAULT_MAX_PRS_CYC_LIM]. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] value 0 to disable the mechanism, or new ++ maximum parsing time. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_ConfigPrsMaxCycleLimit(t_Handle h_FmPcd,uint16_t value); ++ ++/** @} */ /* end of FM_PCD_advanced_cfg_grp group */ ++/** @} */ /* end of FM_PCD_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_PCD_Runtime_grp FM PCD Runtime Unit ++ ++ @Description Frame Manager PCD Runtime Unit API ++ ++ The runtime control allows creation of PCD infrastructure modules ++ such as Network Environment Characteristics, Classification Plan ++ Groups and Coarse Classification Trees. ++ It also allows on-the-fly initialization, modification and removal ++ of PCD modules such as KeyGen schemes, coarse classification nodes ++ and Policer profiles. ++ ++ In order to explain the programming model of the PCD driver interface ++ a few terms should be explained, and will be used below. ++ - Distinction Header - One of the 16 protocols supported by the FM parser, ++ or one of the SHIM headers (1 or 2). May be a header with a special ++ option (see below). ++ - Interchangeable Headers Group - This is a group of Headers recognized ++ by either one of them. For example, if in a specific context the user ++ chooses to treat IPv4 and IPV6 in the same way, they may create an ++ interchangeable Headers Unit consisting of these 2 headers. ++ - A Distinction Unit - a Distinction Header or an Interchangeable Headers ++ Group. ++ - Header with special option - applies to Ethernet, MPLS, VLAN, IPv4 and ++ IPv6, includes multicast, broadcast and other protocol specific options. ++ In terms of hardware it relates to the options available in the classification ++ plan. ++ - Network Environment Characteristics - a set of Distinction Units that define ++ the total recognizable header selection for a certain environment. This is ++ NOT the list of all headers that will ever appear in a flow, but rather ++ everything that needs distinction in a flow, where distinction is made by KeyGen ++ schemes and coarse classification action descriptors. ++ ++ The PCD runtime modules initialization is done in stages. The first stage after ++ initializing the PCD module itself is to establish a Network Flows Environment ++ Definition. The application may choose to establish one or more such environments. ++ Later, when needed, the application will have to state, for some of its modules, ++ to which single environment it belongs. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description A structure for SW parser labels ++ *//***************************************************************************/ ++typedef struct t_FmPcdPrsLabelParams { ++ uint32_t instructionOffset; /**< SW parser label instruction offset (2 bytes ++ resolution), relative to Parser RAM. */ ++ e_NetHeaderType hdr; /**< The existence of this header will invoke ++ the SW parser code; Use HEADER_TYPE_NONE ++ to indicate that sw parser is to run ++ independent of the existence of any protocol ++ (run before HW parser). */ ++ uint8_t indexPerHdr; /**< Normally 0, if more than one SW parser ++ attachments for the same header, use this ++ index to distinguish between them. */ ++} t_FmPcdPrsLabelParams; ++ ++/**************************************************************************//** ++ @Description A structure for SW parser ++ *//***************************************************************************/ ++typedef struct t_FmPcdPrsSwParams { ++ bool override; /**< FALSE to invoke a check that nothing else ++ was loaded to this address, including ++ internal patches. ++ TRUE to override any existing code.*/ ++ uint32_t size; /**< SW parser code size */ ++ uint16_t base; /**< SW parser base (in instruction counts! ++ must be larger than 0x20)*/ ++ uint8_t *p_Code; /**< SW parser code */ ++ uint32_t swPrsDataParams[FM_PCD_PRS_NUM_OF_HDRS]; ++ /**< SW parser data (parameters) */ ++ uint8_t numOfLabels; /**< Number of labels for SW parser. */ ++ t_FmPcdPrsLabelParams labelsTable[FM_PCD_PRS_NUM_OF_LABELS]; ++ /**< SW parser labels table, containing ++ numOfLabels entries */ ++} t_FmPcdPrsSwParams; ++ ++ ++/**************************************************************************//** ++ @Function FM_PCD_Enable ++ ++ @Description This routine should be called after PCD is initialized for enabling all ++ PCD engines according to their existing configuration. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init() and when PCD is disabled. ++*//***************************************************************************/ ++t_Error FM_PCD_Enable(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_Disable ++ ++ @Description This routine may be called when PCD is enabled in order to ++ disable all PCD engines. It may be called ++ only when none of the ports in the system are using the PCD. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init() and when PCD is enabled. ++*//***************************************************************************/ ++t_Error FM_PCD_Disable(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_GetCounter ++ ++ @Description Reads one of the FM PCD counters. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] counter The requested counter. ++ ++ @Return Counter's current value. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ Note that it is user's responsibility to call this routine only ++ for enabled counters, and there will be no indication if a ++ disabled counter is accessed. ++*//***************************************************************************/ ++uint32_t FM_PCD_GetCounter(t_Handle h_FmPcd, e_FmPcdCounters counter); ++ ++/**************************************************************************//** ++ at Function FM_PCD_PrsLoadSw ++ ++ at Description This routine may be called in order to load software parsing code. ++ ++ ++ at Param[in] h_FmPcd FM PCD module descriptor. ++ at Param[in] p_SwPrs A pointer to a structure of software ++ parser parameters, including the software ++ parser image. ++ ++ at Return E_OK on success; Error code otherwise. ++ ++ at Cautions Allowed only following FM_PCD_Init() and when PCD is disabled. ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_PrsLoadSw(t_Handle h_FmPcd, t_FmPcdPrsSwParams *p_SwPrs); ++ ++/**************************************************************************//** ++ at Function FM_PCD_SetAdvancedOffloadSupport ++ ++ at Description This routine must be called in order to support the following features: ++ IP-fragmentation, IP-reassembly, IPsec, Header-manipulation, frame-replicator. ++ ++ at Param[in] h_FmPcd FM PCD module descriptor. ++ ++ at Return E_OK on success; Error code otherwise. ++ ++ at Cautions Allowed only following FM_PCD_Init() and when PCD is disabled. ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_SetAdvancedOffloadSupport(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgSetDfltValue ++ ++ @Description Calling this routine sets a global default value to be used ++ by the KeyGen when parser does not recognize a required ++ field/header. ++ By default default values are 0. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] valueId 0,1 - one of 2 global default values. ++ @Param[in] value The requested default value. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init() and when PCD is disabled. ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_KgSetDfltValue(t_Handle h_FmPcd, uint8_t valueId, uint32_t value); ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgSetAdditionalDataAfterParsing ++ ++ @Description Calling this routine allows the KeyGen to access data past ++ the parser finishing point. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] payloadOffset the number of bytes beyond the parser location. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init() and when PCD is disabled. ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_KgSetAdditionalDataAfterParsing(t_Handle h_FmPcd, uint8_t payloadOffset); ++ ++/**************************************************************************//** ++ @Function FM_PCD_SetException ++ ++ @Description Calling this routine enables/disables PCD interrupts. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] exception The exception to be selected. ++ @Param[in] enable TRUE to enable interrupt, FALSE to mask it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_SetException(t_Handle h_FmPcd, e_FmPcdExceptions exception, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ModifyCounter ++ ++ @Description Sets a value to an enabled counter. Use "0" to reset the counter. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] counter The requested counter. ++ @Param[in] value The requested value to be written into the counter. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_ModifyCounter(t_Handle h_FmPcd, e_FmPcdCounters counter, uint32_t value); ++ ++/**************************************************************************//** ++ @Function FM_PCD_SetPlcrStatistics ++ ++ @Description This routine may be used to enable/disable policer statistics ++ counter. By default the statistics is enabled. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor ++ @Param[in] enable TRUE to enable, FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_SetPlcrStatistics(t_Handle h_FmPcd, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_PCD_SetPrsStatistics ++ ++ @Description Defines whether to gather parser statistics including all ports. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] enable TRUE to enable, FALSE to disable. ++ ++ @Return None ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++void FM_PCD_SetPrsStatistics(t_Handle h_FmPcd, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HcTxConf ++ ++ @Description This routine should be called to confirm frames that were ++ received on the HC confirmation queue. ++ ++ @Param[in] h_FmPcd A handle to an FM PCD Module. ++ @Param[in] p_Fd Frame descriptor of the received frame. ++ ++ @Cautions Allowed only following FM_PCD_Init(). Allowed only if 'useHostCommand' ++ option was selected in the initialization. ++*//***************************************************************************/ ++void FM_PCD_HcTxConf(t_Handle h_FmPcd, t_DpaaFD *p_Fd); ++ ++/**************************************************************************//* ++ @Function FM_PCD_ForceIntr ++ ++ @Description Causes an interrupt event on the requested source. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] exception An exception to be forced. ++ ++ @Return E_OK on success; Error code if the exception is not enabled, ++ or is not able to create interrupt. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PCD_ForceIntr (t_Handle h_FmPcd, e_FmPcdExceptions exception); ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++/**************************************************************************//** ++ @Function FM_PCD_DumpRegs ++ ++ @Description Dumps all PCD registers ++ ++ @Param[in] h_FmPcd A handle to an FM PCD Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ NOTE: this routine may be called only for FM in master mode ++ (i.e. 'guestId'=NCSW_MASTER_ID) or in a case that the registers ++ are mapped. ++*//***************************************************************************/ ++t_Error FM_PCD_DumpRegs(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgDumpRegs ++ ++ @Description Dumps all PCD KG registers ++ ++ @Param[in] h_FmPcd A handle to an FM PCD Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ NOTE: this routine may be called only for FM in master mode ++ (i.e. 'guestId'=NCSW_MASTER_ID) or in a case that the registers ++ are mapped. ++*//***************************************************************************/ ++t_Error FM_PCD_KgDumpRegs(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_PlcrDumpRegs ++ ++ @Description Dumps all PCD Policer registers ++ ++ @Param[in] h_FmPcd A handle to an FM PCD Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ NOTE: this routine may be called only for FM in master mode ++ (i.e. 'guestId'=NCSW_MASTER_ID) or in a case that the registers ++ are mapped. ++*//***************************************************************************/ ++t_Error FM_PCD_PlcrDumpRegs(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_PlcrProfileDumpRegs ++ ++ @Description Dumps all PCD Policer profile registers ++ ++ @Param[in] h_Profile A handle to a Policer profile. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ NOTE: this routine may be called only for FM in master mode ++ (i.e. 'guestId'=NCSW_MASTER_ID) or in a case that the registers ++ are mapped. ++*//***************************************************************************/ ++t_Error FM_PCD_PlcrProfileDumpRegs(t_Handle h_Profile); ++ ++/**************************************************************************//** ++ @Function FM_PCD_PrsDumpRegs ++ ++ @Description Dumps all PCD Parser registers ++ ++ @Param[in] h_FmPcd A handle to an FM PCD Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ NOTE: this routine may be called only for FM in master mode ++ (i.e. 'guestId'=NCSW_MASTER_ID) or in a case that the registers ++ are mapped. ++*//***************************************************************************/ ++t_Error FM_PCD_PrsDumpRegs(t_Handle h_FmPcd); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HcDumpRegs ++ ++ @Description Dumps HC Port registers ++ ++ @Param[in] h_FmPcd A handle to an FM PCD Module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++ NOTE: this routine may be called only for FM in master mode ++ (i.e. 'guestId'=NCSW_MASTER_ID). ++*//***************************************************************************/ ++t_Error FM_PCD_HcDumpRegs(t_Handle h_FmPcd); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ ++ ++/**************************************************************************//** ++ KeyGen FM_PCD_Runtime_build_grp FM PCD Runtime Building Unit ++ ++ @Description Frame Manager PCD Runtime Building API ++ ++ This group contains routines for setting, deleting and modifying ++ PCD resources, for defining the total PCD tree. ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Collection Definitions of coarse classification ++ parameters as required by KeyGen (when coarse classification ++ is the next engine after this scheme). ++*//***************************************************************************/ ++#define FM_PCD_MAX_NUM_OF_CC_TREES 8 ++#define FM_PCD_MAX_NUM_OF_CC_GROUPS 16 ++#define FM_PCD_MAX_NUM_OF_CC_UNITS 4 ++#define FM_PCD_MAX_NUM_OF_KEYS 256 ++#define FM_PCD_MAX_NUM_OF_FLOWS (4*KILOBYTE) ++#define FM_PCD_MAX_SIZE_OF_KEY 56 ++#define FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP 16 ++#define FM_PCD_LAST_KEY_INDEX 0xffff ++ ++#define FM_PCD_MAX_NUM_OF_CC_NODES 255 /* Obsolete, not used - will be removed in the future */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection A set of definitions to allow protocol ++ special option description. ++*//***************************************************************************/ ++typedef uint32_t protocolOpt_t; /**< A general type to define a protocol option. */ ++ ++typedef protocolOpt_t ethProtocolOpt_t; /**< Ethernet protocol options. */ ++#define ETH_BROADCAST 0x80000000 /**< Ethernet Broadcast. */ ++#define ETH_MULTICAST 0x40000000 /**< Ethernet Multicast. */ ++ ++typedef protocolOpt_t vlanProtocolOpt_t; /**< VLAN protocol options. */ ++#define VLAN_STACKED 0x20000000 /**< Stacked VLAN. */ ++ ++typedef protocolOpt_t mplsProtocolOpt_t; /**< MPLS protocol options. */ ++#define MPLS_STACKED 0x10000000 /**< Stacked MPLS. */ ++ ++typedef protocolOpt_t ipv4ProtocolOpt_t; /**< IPv4 protocol options. */ ++#define IPV4_BROADCAST_1 0x08000000 /**< IPv4 Broadcast. */ ++#define IPV4_MULTICAST_1 0x04000000 /**< IPv4 Multicast. */ ++#define IPV4_UNICAST_2 0x02000000 /**< Tunneled IPv4 - Unicast. */ ++#define IPV4_MULTICAST_BROADCAST_2 0x01000000 /**< Tunneled IPv4 - Broadcast/Multicast. */ ++ ++#define IPV4_FRAG_1 0x00000008 /**< IPV4 reassembly option. ++ IPV4 Reassembly manipulation requires network ++ environment with IPV4 header and IPV4_FRAG_1 option */ ++ ++typedef protocolOpt_t ipv6ProtocolOpt_t; /**< IPv6 protocol options. */ ++#define IPV6_MULTICAST_1 0x00800000 /**< IPv6 Multicast. */ ++#define IPV6_UNICAST_2 0x00400000 /**< Tunneled IPv6 - Unicast. */ ++#define IPV6_MULTICAST_2 0x00200000 /**< Tunneled IPv6 - Multicast. */ ++ ++#define IPV6_FRAG_1 0x00000004 /**< IPV6 reassembly option. ++ IPV6 Reassembly manipulation requires network ++ environment with IPV6 header and IPV6_FRAG_1 option; ++ in case where fragment found, the fragment-extension offset ++ may be found at 'shim2' (in parser-result). */ ++#if (DPAA_VERSION >= 11) ++typedef protocolOpt_t capwapProtocolOpt_t; /**< CAPWAP protocol options. */ ++#define CAPWAP_FRAG_1 0x00000008 /**< CAPWAP reassembly option. ++ CAPWAP Reassembly manipulation requires network ++ environment with CAPWAP header and CAPWAP_FRAG_1 option; ++ in case where fragment found, the fragment-extension offset ++ may be found at 'shim2' (in parser-result). */ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ ++/* @} */ ++ ++#define FM_PCD_MANIP_MAX_HDR_SIZE 256 ++#define FM_PCD_MANIP_DSCP_TO_VLAN_TRANS 64 ++ ++/**************************************************************************//** ++ @Collection A set of definitions to support Header Manipulation selection. ++*//***************************************************************************/ ++typedef uint32_t hdrManipFlags_t; /**< A general type to define a HMan update command flags. */ ++ ++typedef hdrManipFlags_t ipv4HdrManipUpdateFlags_t; /**< IPv4 protocol HMan update command flags. */ ++ ++#define HDR_MANIP_IPV4_TOS 0x80000000 /**< update TOS with the given value ('tos' field ++ of t_FmPcdManipHdrFieldUpdateIpv4) */ ++#define HDR_MANIP_IPV4_ID 0x40000000 /**< update IP ID with the given value ('id' field ++ of t_FmPcdManipHdrFieldUpdateIpv4) */ ++#define HDR_MANIP_IPV4_TTL 0x20000000 /**< Decrement TTL by 1 */ ++#define HDR_MANIP_IPV4_SRC 0x10000000 /**< update IP source address with the given value ++ ('src' field of t_FmPcdManipHdrFieldUpdateIpv4) */ ++#define HDR_MANIP_IPV4_DST 0x08000000 /**< update IP destination address with the given value ++ ('dst' field of t_FmPcdManipHdrFieldUpdateIpv4) */ ++ ++typedef hdrManipFlags_t ipv6HdrManipUpdateFlags_t; /**< IPv6 protocol HMan update command flags. */ ++ ++#define HDR_MANIP_IPV6_TC 0x80000000 /**< update Traffic Class address with the given value ++ ('trafficClass' field of t_FmPcdManipHdrFieldUpdateIpv6) */ ++#define HDR_MANIP_IPV6_HL 0x40000000 /**< Decrement Hop Limit by 1 */ ++#define HDR_MANIP_IPV6_SRC 0x20000000 /**< update IP source address with the given value ++ ('src' field of t_FmPcdManipHdrFieldUpdateIpv6) */ ++#define HDR_MANIP_IPV6_DST 0x10000000 /**< update IP destination address with the given value ++ ('dst' field of t_FmPcdManipHdrFieldUpdateIpv6) */ ++ ++typedef hdrManipFlags_t tcpUdpHdrManipUpdateFlags_t;/**< TCP/UDP protocol HMan update command flags. */ ++ ++#define HDR_MANIP_TCP_UDP_SRC 0x80000000 /**< update TCP/UDP source address with the given value ++ ('src' field of t_FmPcdManipHdrFieldUpdateTcpUdp) */ ++#define HDR_MANIP_TCP_UDP_DST 0x40000000 /**< update TCP/UDP destination address with the given value ++ ('dst' field of t_FmPcdManipHdrFieldUpdateTcpUdp) */ ++#define HDR_MANIP_TCP_UDP_CHECKSUM 0x20000000 /**< update TCP/UDP checksum */ ++ ++/* @} */ ++ ++/**************************************************************************//** ++ @Description A type used for returning the order of the key extraction. ++ each value in this array represents the index of the extraction ++ command as defined by the user in the initialization extraction array. ++ The valid size of this array is the user define number of extractions ++ required (also marked by the second '0' in this array). ++*//***************************************************************************/ ++typedef uint8_t t_FmPcdKgKeyOrder [FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY]; ++ ++/**************************************************************************//** ++ @Description All PCD engines ++*//***************************************************************************/ ++typedef enum e_FmPcdEngine { ++ e_FM_PCD_INVALID = 0, /**< Invalid PCD engine */ ++ e_FM_PCD_DONE, /**< No PCD Engine indicated */ ++ e_FM_PCD_KG, /**< KeyGen */ ++ e_FM_PCD_CC, /**< Coarse classifier */ ++ e_FM_PCD_PLCR, /**< Policer */ ++ e_FM_PCD_PRS, /**< Parser */ ++#if (DPAA_VERSION >= 11) ++ e_FM_PCD_FR, /**< Frame-Replicator */ ++#endif /* (DPAA_VERSION >= 11) */ ++ e_FM_PCD_HASH /**< Hash table */ ++} e_FmPcdEngine; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting extraction by header types ++*//***************************************************************************/ ++typedef enum e_FmPcdExtractByHdrType { ++ e_FM_PCD_EXTRACT_FROM_HDR, /**< Extract bytes from header */ ++ e_FM_PCD_EXTRACT_FROM_FIELD, /**< Extract bytes from header field */ ++ e_FM_PCD_EXTRACT_FULL_FIELD /**< Extract a full field */ ++} e_FmPcdExtractByHdrType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting extraction source ++ (when it is not the header) ++*//***************************************************************************/ ++typedef enum e_FmPcdExtractFrom { ++ e_FM_PCD_EXTRACT_FROM_FRAME_START, /**< KG & CC: Extract from beginning of frame */ ++ e_FM_PCD_EXTRACT_FROM_DFLT_VALUE, /**< KG only: Extract from a default value */ ++ e_FM_PCD_EXTRACT_FROM_CURR_END_OF_PARSE, /**< KG & CC: Extract from the point where parsing had finished */ ++ e_FM_PCD_EXTRACT_FROM_KEY, /**< CC only: Field where saved KEY */ ++ e_FM_PCD_EXTRACT_FROM_HASH, /**< CC only: Field where saved HASH */ ++ e_FM_PCD_EXTRACT_FROM_PARSE_RESULT, /**< KG only: Extract from the parser result */ ++ e_FM_PCD_EXTRACT_FROM_ENQ_FQID, /**< KG & CC: Extract from enqueue FQID */ ++ e_FM_PCD_EXTRACT_FROM_FLOW_ID /**< CC only: Field where saved Dequeue FQID */ ++} e_FmPcdExtractFrom; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting extraction type ++*//***************************************************************************/ ++typedef enum e_FmPcdExtractType { ++ e_FM_PCD_EXTRACT_BY_HDR, /**< Extract according to header */ ++ e_FM_PCD_EXTRACT_NON_HDR, /**< Extract from data that is not the header */ ++ e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO /**< Extract private info as specified by user */ ++} e_FmPcdExtractType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting default extraction value ++*//***************************************************************************/ ++typedef enum e_FmPcdKgExtractDfltSelect { ++ e_FM_PCD_KG_DFLT_GBL_0, /**< Default selection is KG register 0 */ ++ e_FM_PCD_KG_DFLT_GBL_1, /**< Default selection is KG register 1 */ ++ e_FM_PCD_KG_DFLT_PRIVATE_0, /**< Default selection is a per scheme register 0 */ ++ e_FM_PCD_KG_DFLT_PRIVATE_1, /**< Default selection is a per scheme register 1 */ ++ e_FM_PCD_KG_DFLT_ILLEGAL /**< Illegal selection */ ++} e_FmPcdKgExtractDfltSelect; ++ ++/**************************************************************************//** ++ @Description Enumeration type defining all default groups - each group shares ++ a default value, one of four user-initialized values. ++*//***************************************************************************/ ++typedef enum e_FmPcdKgKnownFieldsDfltTypes { ++ e_FM_PCD_KG_MAC_ADDR, /**< MAC Address */ ++ e_FM_PCD_KG_TCI, /**< TCI field */ ++ e_FM_PCD_KG_ENET_TYPE, /**< ENET Type */ ++ e_FM_PCD_KG_PPP_SESSION_ID, /**< PPP Session id */ ++ e_FM_PCD_KG_PPP_PROTOCOL_ID, /**< PPP Protocol id */ ++ e_FM_PCD_KG_MPLS_LABEL, /**< MPLS label */ ++ e_FM_PCD_KG_IP_ADDR, /**< IP address */ ++ e_FM_PCD_KG_PROTOCOL_TYPE, /**< Protocol type */ ++ e_FM_PCD_KG_IP_TOS_TC, /**< TOS or TC */ ++ e_FM_PCD_KG_IPV6_FLOW_LABEL, /**< IPV6 flow label */ ++ e_FM_PCD_KG_IPSEC_SPI, /**< IPSEC SPI */ ++ e_FM_PCD_KG_L4_PORT, /**< L4 Port */ ++ e_FM_PCD_KG_TCP_FLAG, /**< TCP Flag */ ++ e_FM_PCD_KG_GENERIC_FROM_DATA, /**< grouping implemented by SW, ++ any data extraction that is not the full ++ field described above */ ++ e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V, /**< grouping implemented by SW, ++ any data extraction without validation */ ++ e_FM_PCD_KG_GENERIC_NOT_FROM_DATA /**< grouping implemented by SW, ++ extraction from parser result or ++ direct use of default value */ ++} e_FmPcdKgKnownFieldsDfltTypes; ++ ++/**************************************************************************//** ++ @Description Enumeration type for defining header index for scenarios with ++ multiple (tunneled) headers ++*//***************************************************************************/ ++typedef enum e_FmPcdHdrIndex { ++ e_FM_PCD_HDR_INDEX_NONE = 0, /**< used when multiple headers not used, also ++ to specify regular IP (not tunneled). */ ++ e_FM_PCD_HDR_INDEX_1, /**< may be used for VLAN, MPLS, tunneled IP */ ++ e_FM_PCD_HDR_INDEX_2, /**< may be used for MPLS, tunneled IP */ ++ e_FM_PCD_HDR_INDEX_3, /**< may be used for MPLS */ ++ e_FM_PCD_HDR_INDEX_LAST = 0xFF /**< may be used for VLAN, MPLS */ ++} e_FmPcdHdrIndex; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the policer profile functional type ++*//***************************************************************************/ ++typedef enum e_FmPcdProfileTypeSelection { ++ e_FM_PCD_PLCR_PORT_PRIVATE, /**< Port dedicated profile */ ++ e_FM_PCD_PLCR_SHARED /**< Shared profile (shared within partition) */ ++} e_FmPcdProfileTypeSelection; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the policer profile algorithm ++*//***************************************************************************/ ++typedef enum e_FmPcdPlcrAlgorithmSelection { ++ e_FM_PCD_PLCR_PASS_THROUGH, /**< Policer pass through */ ++ e_FM_PCD_PLCR_RFC_2698, /**< Policer algorithm RFC 2698 */ ++ e_FM_PCD_PLCR_RFC_4115 /**< Policer algorithm RFC 4115 */ ++} e_FmPcdPlcrAlgorithmSelection; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting a policer profile color mode ++*//***************************************************************************/ ++typedef enum e_FmPcdPlcrColorMode { ++ e_FM_PCD_PLCR_COLOR_BLIND, /**< Color blind */ ++ e_FM_PCD_PLCR_COLOR_AWARE /**< Color aware */ ++} e_FmPcdPlcrColorMode; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting a policer profile color ++*//***************************************************************************/ ++typedef enum e_FmPcdPlcrColor { ++ e_FM_PCD_PLCR_GREEN, /**< Green color code */ ++ e_FM_PCD_PLCR_YELLOW, /**< Yellow color code */ ++ e_FM_PCD_PLCR_RED, /**< Red color code */ ++ e_FM_PCD_PLCR_OVERRIDE /**< Color override code */ ++} e_FmPcdPlcrColor; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the policer profile packet frame length selector ++*//***************************************************************************/ ++typedef enum e_FmPcdPlcrFrameLengthSelect { ++ e_FM_PCD_PLCR_L2_FRM_LEN, /**< L2 frame length */ ++ e_FM_PCD_PLCR_L3_FRM_LEN, /**< L3 frame length */ ++ e_FM_PCD_PLCR_L4_FRM_LEN, /**< L4 frame length */ ++ e_FM_PCD_PLCR_FULL_FRM_LEN /**< Full frame length */ ++} e_FmPcdPlcrFrameLengthSelect; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting roll-back frame ++*//***************************************************************************/ ++typedef enum e_FmPcdPlcrRollBackFrameSelect { ++ e_FM_PCD_PLCR_ROLLBACK_L2_FRM_LEN, /**< Roll-back L2 frame length */ ++ e_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN /**< Roll-back Full frame length */ ++} e_FmPcdPlcrRollBackFrameSelect; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the policer profile packet or byte mode ++*//***************************************************************************/ ++typedef enum e_FmPcdPlcrRateMode { ++ e_FM_PCD_PLCR_BYTE_MODE, /**< Byte mode */ ++ e_FM_PCD_PLCR_PACKET_MODE /**< Packet mode */ ++} e_FmPcdPlcrRateMode; ++ ++/**************************************************************************//** ++ @Description Enumeration type for defining action of frame ++*//***************************************************************************/ ++typedef enum e_FmPcdDoneAction { ++ e_FM_PCD_ENQ_FRAME = 0, /**< Enqueue frame */ ++ e_FM_PCD_DROP_FRAME /**< Mark this frame as error frame and continue ++ to error flow; 'FM_PORT_FRM_ERR_CLS_DISCARD' ++ flag will be set for this frame. */ ++} e_FmPcdDoneAction; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the policer counter ++*//***************************************************************************/ ++typedef enum e_FmPcdPlcrProfileCounters { ++ e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER, /**< Green packets counter */ ++ e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER, /**< Yellow packets counter */ ++ e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER, /**< Red packets counter */ ++ e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER, /**< Recolored yellow packets counter */ ++ e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER /**< Recolored red packets counter */ ++} e_FmPcdPlcrProfileCounters; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the PCD action after extraction ++*//***************************************************************************/ ++typedef enum e_FmPcdAction { ++ e_FM_PCD_ACTION_NONE, /**< NONE */ ++ e_FM_PCD_ACTION_EXACT_MATCH, /**< Exact match on the selected extraction */ ++ e_FM_PCD_ACTION_INDEXED_LOOKUP /**< Indexed lookup on the selected extraction */ ++} e_FmPcdAction; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of insert manipulation ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrInsrtType { ++ e_FM_PCD_MANIP_INSRT_GENERIC, /**< Insert according to offset & size */ ++ e_FM_PCD_MANIP_INSRT_BY_HDR, /**< Insert according to protocol */ ++#if ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++ e_FM_PCD_MANIP_INSRT_BY_TEMPLATE /**< Insert template to start of frame */ ++#endif /* ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) */ ++} e_FmPcdManipHdrInsrtType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of remove manipulation ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrRmvType { ++ e_FM_PCD_MANIP_RMV_GENERIC, /**< Remove according to offset & size */ ++ e_FM_PCD_MANIP_RMV_BY_HDR /**< Remove according to offset & size */ ++} e_FmPcdManipHdrRmvType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting specific L2 fields removal ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrRmvSpecificL2 { ++ e_FM_PCD_MANIP_HDR_RMV_ETHERNET, /**< Ethernet/802.3 MAC */ ++ e_FM_PCD_MANIP_HDR_RMV_STACKED_QTAGS, /**< stacked QTags */ ++ e_FM_PCD_MANIP_HDR_RMV_ETHERNET_AND_MPLS, /**< MPLS and Ethernet/802.3 MAC header until ++ the header which follows the MPLS header */ ++ e_FM_PCD_MANIP_HDR_RMV_MPLS /**< Remove MPLS header (Unlimited MPLS labels) */ ++} e_FmPcdManipHdrRmvSpecificL2; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting specific fields updates ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrFieldUpdateType { ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN, /**< VLAN updates */ ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4, /**< IPV4 updates */ ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6, /**< IPV6 updates */ ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP, /**< TCP_UDP updates */ ++} e_FmPcdManipHdrFieldUpdateType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting VLAN updates ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrFieldUpdateVlan { ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_VPRI, /**< Replace VPri of outer most VLAN tag. */ ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN /**< DSCP to VLAN priority bits translation */ ++} e_FmPcdManipHdrFieldUpdateVlan; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting specific L2 header insertion ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrInsrtSpecificL2 { ++ e_FM_PCD_MANIP_HDR_INSRT_MPLS /**< Insert MPLS header (Unlimited MPLS labels) */ ++} e_FmPcdManipHdrInsrtSpecificL2; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description Enumeration type for selecting QoS mapping mode ++ ++ Note: In all cases except 'e_FM_PCD_MANIP_HDR_QOS_MAPPING_NONE' ++ User should instruct the port to read the hash-result ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrQosMappingMode { ++ e_FM_PCD_MANIP_HDR_QOS_MAPPING_NONE = 0, /**< No mapping, QoS field will not be changed */ ++ e_FM_PCD_MANIP_HDR_QOS_MAPPING_AS_IS, /**< QoS field will be overwritten by the last byte in the hash-result. */ ++} e_FmPcdManipHdrQosMappingMode; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting QoS source ++ ++ Note: In all cases except 'e_FM_PCD_MANIP_HDR_QOS_SRC_NONE' ++ User should left room for the hash-result on input/output buffer ++ and instruct the port to read/write the hash-result to the buffer (RPD should be set) ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrQosSrc { ++ e_FM_PCD_MANIP_HDR_QOS_SRC_NONE = 0, /**< TODO */ ++ e_FM_PCD_MANIP_HDR_QOS_SRC_USER_DEFINED, /**< QoS will be taken from the last byte in the hash-result. */ ++} e_FmPcdManipHdrQosSrc; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of header insertion ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrInsrtByHdrType { ++ e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2, /**< Specific L2 fields insertion */ ++#if (DPAA_VERSION >= 11) ++ e_FM_PCD_MANIP_INSRT_BY_HDR_IP, /**< IP insertion */ ++ e_FM_PCD_MANIP_INSRT_BY_HDR_UDP, /**< UDP insertion */ ++ e_FM_PCD_MANIP_INSRT_BY_HDR_UDP_LITE, /**< UDP lite insertion */ ++ e_FM_PCD_MANIP_INSRT_BY_HDR_CAPWAP /**< CAPWAP insertion */ ++#endif /* (DPAA_VERSION >= 11) */ ++} e_FmPcdManipHdrInsrtByHdrType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting specific customCommand ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrCustomType { ++ e_FM_PCD_MANIP_HDR_CUSTOM_IP_REPLACE, /**< Replace IPv4/IPv6 */ ++ e_FM_PCD_MANIP_HDR_CUSTOM_GEN_FIELD_REPLACE, /**< Replace IPv4/IPv6 */ ++} e_FmPcdManipHdrCustomType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting specific customCommand ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrCustomIpReplace { ++ e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV4_BY_IPV6, /**< Replace IPv4 by IPv6 */ ++ e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4 /**< Replace IPv6 by IPv4 */ ++} e_FmPcdManipHdrCustomIpReplace; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of header removal ++*//***************************************************************************/ ++typedef enum e_FmPcdManipHdrRmvByHdrType { ++ e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2 = 0, /**< Specific L2 fields removal */ ++#if (DPAA_VERSION >= 11) ++ e_FM_PCD_MANIP_RMV_BY_HDR_CAPWAP, /**< CAPWAP removal */ ++#endif /* (DPAA_VERSION >= 11) */ ++#if (DPAA_VERSION >= 11) || ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++ e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START, /**< Locate from data that is not the header */ ++#endif /* (DPAA_VERSION >= 11) || ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) */ ++} e_FmPcdManipHdrRmvByHdrType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of timeout mode ++*//***************************************************************************/ ++typedef enum e_FmPcdManipReassemTimeOutMode { ++ e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAMES, /**< Limits the time of the reassembly process ++ from the first fragment to the last */ ++ e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAG /**< Limits the time of receiving the fragment */ ++} e_FmPcdManipReassemTimeOutMode; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of WaysNumber mode ++*//***************************************************************************/ ++typedef enum e_FmPcdManipReassemWaysNumber { ++ e_FM_PCD_MANIP_ONE_WAY_HASH = 1, /**< One way hash */ ++ e_FM_PCD_MANIP_TWO_WAYS_HASH, /**< Two ways hash */ ++ e_FM_PCD_MANIP_THREE_WAYS_HASH, /**< Three ways hash */ ++ e_FM_PCD_MANIP_FOUR_WAYS_HASH, /**< Four ways hash */ ++ e_FM_PCD_MANIP_FIVE_WAYS_HASH, /**< Five ways hash */ ++ e_FM_PCD_MANIP_SIX_WAYS_HASH, /**< Six ways hash */ ++ e_FM_PCD_MANIP_SEVEN_WAYS_HASH, /**< Seven ways hash */ ++ e_FM_PCD_MANIP_EIGHT_WAYS_HASH /**< Eight ways hash */ ++} e_FmPcdManipReassemWaysNumber; ++ ++#if ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of statistics mode ++*//***************************************************************************/ ++typedef enum e_FmPcdStatsType { ++ e_FM_PCD_STATS_PER_FLOWID = 0 /**< Flow ID is used as index for getting statistics */ ++} e_FmPcdStatsType; ++#endif /* ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) */ ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting manipulation type ++*//***************************************************************************/ ++typedef enum e_FmPcdManipType { ++ e_FM_PCD_MANIP_HDR = 0, /**< Header manipulation */ ++ e_FM_PCD_MANIP_REASSEM, /**< Reassembly */ ++ e_FM_PCD_MANIP_FRAG, /**< Fragmentation */ ++ e_FM_PCD_MANIP_SPECIAL_OFFLOAD /**< Special Offloading */ ++} e_FmPcdManipType; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of statistics mode ++*//***************************************************************************/ ++typedef enum e_FmPcdCcStatsMode { ++ e_FM_PCD_CC_STATS_MODE_NONE = 0, /**< No statistics support */ ++ e_FM_PCD_CC_STATS_MODE_FRAME, /**< Frame count statistics */ ++ e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME, /**< Byte and frame count statistics */ ++#if (DPAA_VERSION >= 11) ++ e_FM_PCD_CC_STATS_MODE_RMON, /**< Byte and frame length range count statistics; ++ This mode is supported only on B4860 device */ ++#endif /* (DPAA_VERSION >= 11) */ ++} e_FmPcdCcStatsMode; ++ ++/**************************************************************************//** ++ @Description Enumeration type for determining the action in case an IP packet ++ is larger than MTU but its DF (Don't Fragment) bit is set. ++*//***************************************************************************/ ++typedef enum e_FmPcdManipDontFragAction { ++ e_FM_PCD_MANIP_DISCARD_PACKET = 0, /**< Discard packet */ ++ e_FM_PCD_MANIP_ENQ_TO_ERR_Q_OR_DISCARD_PACKET = e_FM_PCD_MANIP_DISCARD_PACKET, ++ /**< Obsolete, cannot enqueue to error queue; ++ In practice, selects to discard packets; ++ Will be removed in the future */ ++ e_FM_PCD_MANIP_FRAGMENT_PACKET, /**< Fragment packet and continue normal processing */ ++ e_FM_PCD_MANIP_CONTINUE_WITHOUT_FRAG /**< Continue normal processing without fragmenting the packet */ ++} e_FmPcdManipDontFragAction; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of special offload manipulation ++*//***************************************************************************/ ++typedef enum e_FmPcdManipSpecialOffloadType { ++ e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC, /**< IPSec offload manipulation */ ++#if (DPAA_VERSION >= 11) ++ e_FM_PCD_MANIP_SPECIAL_OFFLOAD_CAPWAP /**< CAPWAP offload manipulation */ ++#endif /* (DPAA_VERSION >= 11) */ ++} e_FmPcdManipSpecialOffloadType; ++ ++ ++/**************************************************************************//** ++ @Description A Union of protocol dependent special options ++*//***************************************************************************/ ++typedef union u_FmPcdHdrProtocolOpt { ++ ethProtocolOpt_t ethOpt; /**< Ethernet options */ ++ vlanProtocolOpt_t vlanOpt; /**< VLAN options */ ++ mplsProtocolOpt_t mplsOpt; /**< MPLS options */ ++ ipv4ProtocolOpt_t ipv4Opt; /**< IPv4 options */ ++ ipv6ProtocolOpt_t ipv6Opt; /**< IPv6 options */ ++#if (DPAA_VERSION >= 11) ++ capwapProtocolOpt_t capwapOpt; /**< CAPWAP options */ ++#endif /* (DPAA_VERSION >= 11) */ ++} u_FmPcdHdrProtocolOpt; ++ ++/**************************************************************************//** ++ @Description A union holding protocol fields ++ ++ ++ Fields supported as "full fields": ++ HEADER_TYPE_ETH: ++ NET_HEADER_FIELD_ETH_DA ++ NET_HEADER_FIELD_ETH_SA ++ NET_HEADER_FIELD_ETH_TYPE ++ ++ HEADER_TYPE_LLC_SNAP: ++ NET_HEADER_FIELD_LLC_SNAP_TYPE ++ ++ HEADER_TYPE_VLAN: ++ NET_HEADER_FIELD_VLAN_TCI ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1, ++ e_FM_PCD_HDR_INDEX_LAST) ++ ++ HEADER_TYPE_MPLS: ++ NET_HEADER_FIELD_MPLS_LABEL_STACK ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1, ++ e_FM_PCD_HDR_INDEX_2, ++ e_FM_PCD_HDR_INDEX_LAST) ++ ++ HEADER_TYPE_IPv4: ++ NET_HEADER_FIELD_IPv4_SRC_IP ++ NET_HEADER_FIELD_IPv4_DST_IP ++ NET_HEADER_FIELD_IPv4_PROTO ++ NET_HEADER_FIELD_IPv4_TOS ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1, ++ e_FM_PCD_HDR_INDEX_2/e_FM_PCD_HDR_INDEX_LAST) ++ ++ HEADER_TYPE_IPv6: ++ NET_HEADER_FIELD_IPv6_SRC_IP ++ NET_HEADER_FIELD_IPv6_DST_IP ++ NET_HEADER_FIELD_IPv6_NEXT_HDR ++ NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL | NET_HEADER_FIELD_IPv6_TC (must come together!) ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1, ++ e_FM_PCD_HDR_INDEX_2/e_FM_PCD_HDR_INDEX_LAST) ++ ++ (Note that starting from DPAA 1-1, NET_HEADER_FIELD_IPv6_NEXT_HDR applies to ++ the last next header indication, meaning the next L4, which may be ++ present at the Ipv6 last extension. On earlier revisions this field ++ applies to the Next-Header field of the main IPv6 header) ++ ++ HEADER_TYPE_IP: ++ NET_HEADER_FIELD_IP_PROTO ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_LAST) ++ NET_HEADER_FIELD_IP_DSCP ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1) ++ HEADER_TYPE_GRE: ++ NET_HEADER_FIELD_GRE_TYPE ++ ++ HEADER_TYPE_MINENCAP ++ NET_HEADER_FIELD_MINENCAP_SRC_IP ++ NET_HEADER_FIELD_MINENCAP_DST_IP ++ NET_HEADER_FIELD_MINENCAP_TYPE ++ ++ HEADER_TYPE_TCP: ++ NET_HEADER_FIELD_TCP_PORT_SRC ++ NET_HEADER_FIELD_TCP_PORT_DST ++ NET_HEADER_FIELD_TCP_FLAGS ++ ++ HEADER_TYPE_UDP: ++ NET_HEADER_FIELD_UDP_PORT_SRC ++ NET_HEADER_FIELD_UDP_PORT_DST ++ ++ HEADER_TYPE_UDP_LITE: ++ NET_HEADER_FIELD_UDP_LITE_PORT_SRC ++ NET_HEADER_FIELD_UDP_LITE_PORT_DST ++ ++ HEADER_TYPE_IPSEC_AH: ++ NET_HEADER_FIELD_IPSEC_AH_SPI ++ NET_HEADER_FIELD_IPSEC_AH_NH ++ ++ HEADER_TYPE_IPSEC_ESP: ++ NET_HEADER_FIELD_IPSEC_ESP_SPI ++ ++ HEADER_TYPE_SCTP: ++ NET_HEADER_FIELD_SCTP_PORT_SRC ++ NET_HEADER_FIELD_SCTP_PORT_DST ++ ++ HEADER_TYPE_DCCP: ++ NET_HEADER_FIELD_DCCP_PORT_SRC ++ NET_HEADER_FIELD_DCCP_PORT_DST ++ ++ HEADER_TYPE_PPPoE: ++ NET_HEADER_FIELD_PPPoE_PID ++ NET_HEADER_FIELD_PPPoE_SID ++ ++ ***************************************************************** ++ Fields supported as "from fields": ++ HEADER_TYPE_ETH (with or without validation): ++ NET_HEADER_FIELD_ETH_TYPE ++ ++ HEADER_TYPE_VLAN (with or without validation): ++ NET_HEADER_FIELD_VLAN_TCI ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1, ++ e_FM_PCD_HDR_INDEX_LAST) ++ ++ HEADER_TYPE_IPv4 (without validation): ++ NET_HEADER_FIELD_IPv4_PROTO ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1, ++ e_FM_PCD_HDR_INDEX_2/e_FM_PCD_HDR_INDEX_LAST) ++ ++ HEADER_TYPE_IPv6 (without validation): ++ NET_HEADER_FIELD_IPv6_NEXT_HDR ++ (index may apply: ++ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1, ++ e_FM_PCD_HDR_INDEX_2/e_FM_PCD_HDR_INDEX_LAST) ++ ++*//***************************************************************************/ ++typedef union t_FmPcdFields { ++ headerFieldEth_t eth; /**< Ethernet */ ++ headerFieldVlan_t vlan; /**< VLAN */ ++ headerFieldLlcSnap_t llcSnap; /**< LLC SNAP */ ++ headerFieldPppoe_t pppoe; /**< PPPoE */ ++ headerFieldMpls_t mpls; /**< MPLS */ ++ headerFieldIp_t ip; /**< IP */ ++ headerFieldIpv4_t ipv4; /**< IPv4 */ ++ headerFieldIpv6_t ipv6; /**< IPv6 */ ++ headerFieldUdp_t udp; /**< UDP */ ++ headerFieldUdpLite_t udpLite; /**< UDP Lite */ ++ headerFieldTcp_t tcp; /**< TCP */ ++ headerFieldSctp_t sctp; /**< SCTP */ ++ headerFieldDccp_t dccp; /**< DCCP */ ++ headerFieldGre_t gre; /**< GRE */ ++ headerFieldMinencap_t minencap; /**< Minimal Encapsulation */ ++ headerFieldIpsecAh_t ipsecAh; /**< IPSec AH */ ++ headerFieldIpsecEsp_t ipsecEsp; /**< IPSec ESP */ ++ headerFieldUdpEncapEsp_t udpEncapEsp; /**< UDP Encapsulation ESP */ ++} t_FmPcdFields; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header extraction for key generation ++*//***************************************************************************/ ++typedef struct t_FmPcdFromHdr { ++ uint8_t size; /**< Size in byte */ ++ uint8_t offset; /**< Byte offset */ ++} t_FmPcdFromHdr; ++ ++/**************************************************************************//** ++ @Description Parameters for defining field extraction for key generation ++*//***************************************************************************/ ++typedef struct t_FmPcdFromField { ++ t_FmPcdFields field; /**< Field selection */ ++ uint8_t size; /**< Size in byte */ ++ uint8_t offset; /**< Byte offset */ ++} t_FmPcdFromField; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a single network environment unit ++ ++ A distinction unit should be defined if it will later be used ++ by one or more PCD engines to distinguish between flows. ++*//***************************************************************************/ ++typedef struct t_FmPcdDistinctionUnit { ++ struct { ++ e_NetHeaderType hdr; /**< One of the headers supported by the FM */ ++ u_FmPcdHdrProtocolOpt opt; /**< Select only one option ! */ ++ } hdrs[FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS]; ++} t_FmPcdDistinctionUnit; ++ ++/**************************************************************************//** ++ @Description Parameters for defining all different distinction units supported ++ by a specific PCD Network Environment Characteristics module. ++ ++ Each unit represent a protocol or a group of protocols that may ++ be used later by the different PCD engines to distinguish ++ between flows. ++*//***************************************************************************/ ++typedef struct t_FmPcdNetEnvParams { ++ uint8_t numOfDistinctionUnits; /**< Number of different units to be identified */ ++ t_FmPcdDistinctionUnit units[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; /**< An array of numOfDistinctionUnits of the ++ different units to be identified */ ++} t_FmPcdNetEnvParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a single extraction action when ++ creating a key ++*//***************************************************************************/ ++typedef struct t_FmPcdExtractEntry { ++ e_FmPcdExtractType type; /**< Extraction type select */ ++ union { ++ struct { ++ e_NetHeaderType hdr; /**< Header selection */ ++ bool ignoreProtocolValidation; ++ /**< Ignore protocol validation */ ++ e_FmPcdHdrIndex hdrIndex; /**< Relevant only for MPLS, VLAN and tunneled ++ IP. Otherwise should be cleared. */ ++ e_FmPcdExtractByHdrType type; /**< Header extraction type select */ ++ union { ++ t_FmPcdFromHdr fromHdr; /**< Extract bytes from header parameters */ ++ t_FmPcdFromField fromField; /**< Extract bytes from field parameters */ ++ t_FmPcdFields fullField; /**< Extract full filed parameters */ ++ } extractByHdrType; ++ } extractByHdr; /**< used when type = e_FM_PCD_KG_EXTRACT_BY_HDR */ ++ struct { ++ e_FmPcdExtractFrom src; /**< Non-header extraction source */ ++ e_FmPcdAction action; /**< Relevant for CC Only */ ++ uint16_t icIndxMask; /**< Relevant only for CC when ++ action = e_FM_PCD_ACTION_INDEXED_LOOKUP; ++ Note that the number of bits that are set within ++ this mask must be log2 of the CC-node 'numOfKeys'. ++ Note that the mask cannot be set on the lower bits. */ ++ uint8_t offset; /**< Byte offset */ ++ uint8_t size; /**< Size in byte */ ++ } extractNonHdr; /**< used when type = e_FM_PCD_KG_EXTRACT_NON_HDR */ ++ }; ++} t_FmPcdExtractEntry; ++ ++/**************************************************************************//** ++ @Description Parameters for defining masks for each extracted field in the key. ++*//***************************************************************************/ ++typedef struct t_FmPcdKgExtractMask { ++ uint8_t extractArrayIndex; /**< Index in the extraction array, as initialized by user */ ++ uint8_t offset; /**< Byte offset */ ++ uint8_t mask; /**< A byte mask (selected bits will be used) */ ++} t_FmPcdKgExtractMask; ++ ++/**************************************************************************//** ++ @Description Parameters for defining default selection per groups of fields ++*//***************************************************************************/ ++typedef struct t_FmPcdKgExtractDflt { ++ e_FmPcdKgKnownFieldsDfltTypes type; /**< Default type select */ ++ e_FmPcdKgExtractDfltSelect dfltSelect; /**< Default register select */ ++} t_FmPcdKgExtractDflt; ++ ++/**************************************************************************//** ++ @Description Parameters for defining key extraction and hashing ++*//***************************************************************************/ ++typedef struct t_FmPcdKgKeyExtractAndHashParams { ++ uint32_t privateDflt0; /**< Scheme default register 0 */ ++ uint32_t privateDflt1; /**< Scheme default register 1 */ ++ uint8_t numOfUsedExtracts; /**< defines the valid size of the following array */ ++ t_FmPcdExtractEntry extractArray [FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY]; /**< An array of extractions definition. */ ++ uint8_t numOfUsedDflts; /**< defines the valid size of the following array */ ++ t_FmPcdKgExtractDflt dflts[FM_PCD_KG_NUM_OF_DEFAULT_GROUPS]; ++ /**< For each extraction used in this scheme, specify the required ++ default register to be used when header is not found. ++ types not specified in this array will get undefined value. */ ++ uint8_t numOfUsedMasks; /**< defines the valid size of the following array */ ++ t_FmPcdKgExtractMask masks[FM_PCD_KG_NUM_OF_EXTRACT_MASKS]; ++ uint8_t hashShift; /**< hash result right shift. Select the 24 bits out of the 64 hash ++ result. 0 means using the 24 LSB's, otherwise use the ++ 24 LSB's after shifting right.*/ ++ uint32_t hashDistributionNumOfFqids; /**< must be > 1 and a power of 2. Represents the range ++ of queues for the key and hash functionality */ ++ uint8_t hashDistributionFqidsShift; /**< selects the FQID bits that will be effected by the hash */ ++ bool symmetricHash; /**< TRUE to generate the same hash for frames with swapped source and ++ destination fields on all layers; If TRUE, driver will check that for ++ all layers, if SRC extraction is selected, DST extraction must also be ++ selected, and vice versa. */ ++} t_FmPcdKgKeyExtractAndHashParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a single FQID mask (extracted OR). ++*//***************************************************************************/ ++typedef struct t_FmPcdKgExtractedOrParams { ++ e_FmPcdExtractType type; /**< Extraction type select */ ++ union { ++ struct { /**< used when type = e_FM_PCD_KG_EXTRACT_BY_HDR */ ++ e_NetHeaderType hdr; ++ e_FmPcdHdrIndex hdrIndex; /**< Relevant only for MPLS, VLAN and tunneled ++ IP. Otherwise should be cleared.*/ ++ bool ignoreProtocolValidation; ++ /**< continue extraction even if protocol is not recognized */ ++ } extractByHdr; /**< Header to extract by */ ++ e_FmPcdExtractFrom src; /**< used when type = e_FM_PCD_KG_EXTRACT_NON_HDR */ ++ }; ++ uint8_t extractionOffset; /**< Offset for extraction (in bytes). */ ++ e_FmPcdKgExtractDfltSelect dfltValue; /**< Select register from which extraction is taken if ++ field not found */ ++ uint8_t mask; /**< Extraction mask (specified bits are used) */ ++ uint8_t bitOffsetInFqid; /**< 0-31, Selects which bits of the 24 FQID bits to effect using ++ the extracted byte; Assume byte is placed as the 8 MSB's in ++ a 32 bit word where the lower bits ++ are the FQID; i.e if bitOffsetInFqid=1 than its LSB ++ will effect the FQID MSB, if bitOffsetInFqid=24 than the ++ extracted byte will effect the 8 LSB's of the FQID, ++ if bitOffsetInFqid=31 than the byte's MSB will effect ++ the FQID's LSB; 0 means - no effect on FQID; ++ Note that one, and only one of ++ bitOffsetInFqid or bitOffsetInPlcrProfile must be set (i.e, ++ extracted byte must effect either FQID or Policer profile).*/ ++ uint8_t bitOffsetInPlcrProfile; ++ /**< 0-15, Selects which bits of the 8 policer profile id bits to ++ effect using the extracted byte; Assume byte is placed ++ as the 8 MSB's in a 16 bit word where the lower bits ++ are the policer profile id; i.e if bitOffsetInPlcrProfile=1 ++ than its LSB will effect the profile MSB, if bitOffsetInFqid=8 ++ than the extracted byte will effect the whole policer profile id, ++ if bitOffsetInFqid=15 than the byte's MSB will effect ++ the Policer Profile id's LSB; ++ 0 means - no effect on policer profile; Note that one, and only one of ++ bitOffsetInFqid or bitOffsetInPlcrProfile must be set (i.e, ++ extracted byte must effect either FQID or Policer profile).*/ ++} t_FmPcdKgExtractedOrParams; ++ ++/**************************************************************************//** ++ @Description Parameters for configuring a scheme counter ++*//***************************************************************************/ ++typedef struct t_FmPcdKgSchemeCounter { ++ bool update; /**< FALSE to keep the current counter state ++ and continue from that point, TRUE to update/reset ++ the counter when the scheme is written. */ ++ uint32_t value; /**< If update=TRUE, this value will be written into the ++ counter. clear this field to reset the counter. */ ++} t_FmPcdKgSchemeCounter; ++ ++/**************************************************************************//** ++ @Description Parameters for configuring a policer profile for a KeyGen scheme ++ (when policer is the next engine after this scheme). ++*//***************************************************************************/ ++typedef struct t_FmPcdKgPlcrProfile { ++ bool sharedProfile; /**< TRUE if this profile is shared between ports ++ (managed by master partition); Must not be TRUE ++ if profile is after Coarse Classification*/ ++ bool direct; /**< if TRUE, directRelativeProfileId only selects the profile ++ id, if FALSE fqidOffsetRelativeProfileIdBase is used ++ together with fqidOffsetShift and numOfProfiles ++ parameters, to define a range of profiles from ++ which the KeyGen result will determine the ++ destination policer profile. */ ++ union { ++ uint16_t directRelativeProfileId; /**< Used if 'direct' is TRUE, to select policer profile. ++ should indicate the policer profile offset within the ++ port's policer profiles or shared window. */ ++ struct { ++ uint8_t fqidOffsetShift; /**< Shift on the KeyGen create FQID offset (i.e. not the ++ final FQID - without the FQID base). */ ++ uint8_t fqidOffsetRelativeProfileIdBase; ++ /**< The base of the FMan Port's relative Storage-Profile ID; ++ this value will be "OR'ed" with the KeyGen create FQID ++ offset (i.e. not the final FQID - without the FQID base); ++ the final result should indicate the Storage-Profile offset ++ within the FMan Port's relative Storage-Profiles window/ ++ (or the SHARED window depends on 'sharedProfile'). */ ++ uint8_t numOfProfiles; /**< Range of profiles starting at base */ ++ } indirectProfile; /**< Indirect profile parameters */ ++ } profileSelect; /**< Direct/indirect profile selection and parameters */ ++} t_FmPcdKgPlcrProfile; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description Parameters for configuring a storage profile for a KeyGen scheme. ++*//***************************************************************************/ ++typedef struct t_FmPcdKgStorageProfile { ++ bool direct; /**< If TRUE, directRelativeProfileId only selects the ++ profile id; ++ If FALSE, fqidOffsetRelativeProfileIdBase is used ++ together with fqidOffsetShift and numOfProfiles ++ parameters to define a range of profiles from which ++ the KeyGen result will determine the destination ++ storage profile. */ ++ union { ++ uint16_t directRelativeProfileId; /**< Used when 'direct' is TRUE, to select a storage profile; ++ should indicate the storage profile offset within the ++ port's storage profiles window. */ ++ struct { ++ uint8_t fqidOffsetShift; /**< Shift on the KeyGen create FQID offset (i.e. not the ++ final FQID - without the FQID base). */ ++ uint8_t fqidOffsetRelativeProfileIdBase; ++ /**< The base of the FMan Port's relative Storage-Profile ID; ++ this value will be "OR'ed" with the KeyGen create FQID ++ offset (i.e. not the final FQID - without the FQID base); ++ the final result should indicate the Storage-Profile offset ++ within the FMan Port's relative Storage-Profiles window. */ ++ uint8_t numOfProfiles; /**< Range of profiles starting at base. */ ++ } indirectProfile; /**< Indirect profile parameters. */ ++ } profileSelect; /**< Direct/indirect profile selection and parameters. */ ++} t_FmPcdKgStorageProfile; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Description Parameters for defining CC as the next engine after KeyGen ++*//***************************************************************************/ ++typedef struct t_FmPcdKgCc { ++ t_Handle h_CcTree; /**< A handle to a CC Tree */ ++ uint8_t grpId; /**< CC group id within the CC tree */ ++ bool plcrNext; /**< TRUE if after CC, in case of data frame, ++ policing is required. */ ++ bool bypassPlcrProfileGeneration; /**< TRUE to bypass KeyGen policer profile generation; ++ selected profile is the one set at port initialization. */ ++ t_FmPcdKgPlcrProfile plcrProfile; /**< Valid only if plcrNext = TRUE and ++ bypassPlcrProfileGeneration = FALSE */ ++} t_FmPcdKgCc; ++ ++/**************************************************************************//** ++ @Description Parameters for defining initializing a KeyGen scheme ++*//***************************************************************************/ ++typedef struct t_FmPcdKgSchemeParams { ++ bool modify; /**< TRUE to change an existing scheme */ ++ union ++ { ++ uint8_t relativeSchemeId; /**< if modify=FALSE:Partition relative scheme id */ ++ t_Handle h_Scheme; /**< if modify=TRUE: a handle of the existing scheme */ ++ } id; ++ bool alwaysDirect; /**< This scheme is reached only directly, i.e. no need ++ for match vector; KeyGen will ignore it when matching */ ++ struct { /**< HL Relevant only if alwaysDirect = FALSE */ ++ t_Handle h_NetEnv; /**< A handle to the Network environment as returned ++ by FM_PCD_NetEnvCharacteristicsSet() */ ++ uint8_t numOfDistinctionUnits; /**< Number of NetEnv units listed in unitIds array */ ++ uint8_t unitIds[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; ++ /**< Indexes as passed to SetNetEnvCharacteristics array*/ ++ } netEnvParams; ++ bool useHash; /**< use the KeyGen Hash functionality */ ++ t_FmPcdKgKeyExtractAndHashParams keyExtractAndHashParams; ++ /**< used only if useHash = TRUE */ ++ bool bypassFqidGeneration; /**< Normally - FALSE, TRUE to avoid FQID update in the IC; ++ In such a case FQID after KeyGen will be the default FQID ++ defined for the relevant port, or the FQID defined by CC ++ in cases where CC was the previous engine. */ ++ uint32_t baseFqid; /**< Base FQID; Relevant only if bypassFqidGeneration = FALSE; ++ If hash is used and an even distribution is expected ++ according to hashDistributionNumOfFqids, baseFqid must be aligned to ++ hashDistributionNumOfFqids. */ ++ uint8_t numOfUsedExtractedOrs; /**< Number of FQID masks listed in extractedOrs array */ ++ t_FmPcdKgExtractedOrParams extractedOrs[FM_PCD_KG_NUM_OF_GENERIC_REGS]; ++ /**< FM_PCD_KG_NUM_OF_GENERIC_REGS ++ registers are shared between qidMasks ++ functionality and some of the extraction ++ actions; Normally only some will be used ++ for qidMask. Driver will return error if ++ resource is full at initialization time. */ ++ ++#if (DPAA_VERSION >= 11) ++ bool overrideStorageProfile; /**< TRUE if KeyGen override previously decided storage profile */ ++ t_FmPcdKgStorageProfile storageProfile; /**< Used when overrideStorageProfile TRUE */ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ e_FmPcdEngine nextEngine; /**< may be BMI, PLCR or CC */ ++ union { /**< depends on nextEngine */ ++ e_FmPcdDoneAction doneAction; /**< Used when next engine is BMI (done) */ ++ t_FmPcdKgPlcrProfile plcrProfile; /**< Used when next engine is PLCR */ ++ t_FmPcdKgCc cc; /**< Used when next engine is CC */ ++ } kgNextEngineParams; ++ t_FmPcdKgSchemeCounter schemeCounter; /**< A structure of parameters for updating ++ the scheme counter */ ++} t_FmPcdKgSchemeParams; ++ ++/**************************************************************************//** ++ @Collection Definitions for CC statistics ++*//***************************************************************************/ ++#if (DPAA_VERSION >= 11) ++#define FM_PCD_CC_STATS_MAX_NUM_OF_FLR 10 /* Maximal supported number of frame length ranges */ ++#define FM_PCD_CC_STATS_FLR_SIZE 2 /* Size in bytes of a frame length range limit */ ++#endif /* (DPAA_VERSION >= 11) */ ++#define FM_PCD_CC_STATS_COUNTER_SIZE 4 /* Size in bytes of a frame length range counter */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Description Parameters for defining CC as the next engine after a CC node. ++*//***************************************************************************/ ++typedef struct t_FmPcdCcNextCcParams { ++ t_Handle h_CcNode; /**< A handle of the next CC node */ ++} t_FmPcdCcNextCcParams; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description Parameters for defining Frame replicator as the next engine after a CC node. ++*//***************************************************************************/ ++typedef struct t_FmPcdCcNextFrParams { ++ t_Handle h_FrmReplic; /**< A handle of the next frame replicator group */ ++} t_FmPcdCcNextFrParams; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Description Parameters for defining Policer as the next engine after a CC node. ++*//***************************************************************************/ ++typedef struct t_FmPcdCcNextPlcrParams { ++ bool overrideParams; /**< TRUE if CC override previously decided parameters*/ ++ bool sharedProfile; /**< Relevant only if overrideParams=TRUE: ++ TRUE if this profile is shared between ports */ ++ uint16_t newRelativeProfileId; /**< Relevant only if overrideParams=TRUE: ++ (otherwise profile id is taken from KeyGen); ++ This parameter should indicate the policer ++ profile offset within the port's ++ policer profiles or from SHARED window.*/ ++ uint32_t newFqid; /**< Relevant only if overrideParams=TRUE: ++ FQID for enqueuing the frame; ++ In earlier chips if policer next engine is KEYGEN, ++ this parameter can be 0, because the KEYGEN ++ always decides the enqueue FQID.*/ ++#if (DPAA_VERSION >= 11) ++ uint8_t newRelativeStorageProfileId; ++ /**< Indicates the relative storage profile offset within ++ the port's storage profiles window; ++ Relevant only if the port was configured with VSP. */ ++#endif /* (DPAA_VERSION >= 11) */ ++} t_FmPcdCcNextPlcrParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining enqueue as the next action after a CC node. ++*//***************************************************************************/ ++typedef struct t_FmPcdCcNextEnqueueParams { ++ e_FmPcdDoneAction action; /**< Action - when next engine is BMI (done) */ ++ bool overrideFqid; /**< TRUE if CC override previously decided fqid and vspid, ++ relevant if action = e_FM_PCD_ENQ_FRAME */ ++ uint32_t newFqid; /**< Valid if overrideFqid=TRUE, FQID for enqueuing the frame ++ (otherwise FQID is taken from KeyGen), ++ relevant if action = e_FM_PCD_ENQ_FRAME */ ++#if (DPAA_VERSION >= 11) ++ uint8_t newRelativeStorageProfileId; ++ /**< Valid if overrideFqid=TRUE, Indicates the relative virtual ++ storage profile offset within the port's storage profiles ++ window; Relevant only if the port was configured with VSP. */ ++#endif /* (DPAA_VERSION >= 11) */ ++} t_FmPcdCcNextEnqueueParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining KeyGen as the next engine after a CC node. ++*//***************************************************************************/ ++typedef struct t_FmPcdCcNextKgParams { ++ bool overrideFqid; /**< TRUE if CC override previously decided fqid and vspid, ++ Note - this parameters irrelevant for earlier chips */ ++ uint32_t newFqid; /**< Valid if overrideFqid=TRUE, FQID for enqueuing the frame ++ (otherwise FQID is taken from KeyGen), ++ Note - this parameters irrelevant for earlier chips */ ++#if (DPAA_VERSION >= 11) ++ uint8_t newRelativeStorageProfileId; ++ /**< Valid if overrideFqid=TRUE, Indicates the relative virtual ++ storage profile offset within the port's storage profiles ++ window; Relevant only if the port was configured with VSP. */ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ t_Handle h_DirectScheme; /**< Direct scheme handle to go to. */ ++} t_FmPcdCcNextKgParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining the next engine after a CC node. ++*//***************************************************************************/ ++typedef struct t_FmPcdCcNextEngineParams { ++ e_FmPcdEngine nextEngine; /**< User has to initialize parameters ++ according to nextEngine definition */ ++ union { ++ t_FmPcdCcNextCcParams ccParams; /**< Parameters in case next engine is CC */ ++ t_FmPcdCcNextPlcrParams plcrParams; /**< Parameters in case next engine is PLCR */ ++ t_FmPcdCcNextEnqueueParams enqueueParams; /**< Parameters in case next engine is BMI */ ++ t_FmPcdCcNextKgParams kgParams; /**< Parameters in case next engine is KG */ ++#if (DPAA_VERSION >= 11) ++ t_FmPcdCcNextFrParams frParams; /**< Parameters in case next engine is FR */ ++#endif /* (DPAA_VERSION >= 11) */ ++ } params; /**< union used for all the next-engine parameters options */ ++ ++ t_Handle h_Manip; /**< Handle to Manipulation object. ++ Relevant if next engine is of type result ++ (e_FM_PCD_PLCR, e_FM_PCD_KG, e_FM_PCD_DONE) */ ++ ++ bool statisticsEn; /**< If TRUE, statistics counters are incremented ++ for each frame passing through this ++ Coarse Classification entry. */ ++} t_FmPcdCcNextEngineParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a single CC key ++*//***************************************************************************/ ++typedef struct t_FmPcdCcKeyParams { ++ uint8_t *p_Key; /**< Relevant only if 'action' = e_FM_PCD_ACTION_EXACT_MATCH; ++ pointer to the key of the size defined in keySize */ ++ uint8_t *p_Mask; /**< Relevant only if 'action' = e_FM_PCD_ACTION_EXACT_MATCH; ++ pointer to the Mask per key of the size defined ++ in keySize. p_Key and p_Mask (if defined) has to be ++ of the same size defined in the keySize; ++ NOTE that if this value is equal for all entries whithin ++ this table, the driver will automatically use global-mask ++ (i.e. one common mask for all entries) instead of private ++ one; that is done in order to spare some memory and for ++ better performance. */ ++ t_FmPcdCcNextEngineParams ccNextEngineParams; ++ /**< parameters for the next for the defined Key in ++ the p_Key */ ++} t_FmPcdCcKeyParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining CC keys parameters ++ The driver supports two methods for CC node allocation: dynamic and static. ++ Static mode was created in order to prevent runtime alloc/free ++ of FMan memory (MURAM), which may cause fragmentation; in this mode, ++ the driver automatically allocates the memory according to ++ 'maxNumOfKeys' parameter. The driver calculates the maximal memory ++ size that may be used for this CC-Node taking into consideration ++ 'maskSupport' and 'statisticsMode' parameters. ++ When 'action' = e_FM_PCD_ACTION_INDEXED_LOOKUP in the extraction ++ parameters of this node, 'maxNumOfKeys' must be equal to 'numOfKeys'. ++ In dynamic mode, 'maxNumOfKeys' must be zero. At initialization, ++ all required structures are allocated according to 'numOfKeys' ++ parameter. During runtime modification, these structures are ++ re-allocated according to the updated number of keys. ++ ++ Please note that 'action' and 'icIndxMask' mentioned in the ++ specific parameter explanations are passed in the extraction ++ parameters of the node (fields of extractCcParams.extractNonHdr). ++*//***************************************************************************/ ++typedef struct t_KeysParams { ++ uint16_t maxNumOfKeys; /**< Maximum number of keys that will (ever) be used in this CC-Node; ++ A value of zero may be used for dynamic memory allocation. */ ++ bool maskSupport; /**< This parameter is relevant only if a node is initialized with ++ 'action' = e_FM_PCD_ACTION_EXACT_MATCH and maxNumOfKeys > 0; ++ Should be TRUE to reserve table memory for key masks, even if ++ initial keys do not contain masks, or if the node was initialized ++ as 'empty' (without keys); this will allow user to add keys with ++ masks at runtime. ++ NOTE that if user want to use only global-masks (i.e. one common mask ++ for all the entries within this table, this parameter should set to 'FALSE'. */ ++ e_FmPcdCcStatsMode statisticsMode; /**< Determines the supported statistics mode for all node's keys. ++ To enable statistics gathering, statistics should be enabled per ++ every key, using 'statisticsEn' in next engine parameters structure ++ of that key; ++ If 'maxNumOfKeys' is set, all required structures will be ++ preallocated for all keys. */ ++#if (DPAA_VERSION >= 11) ++ uint16_t frameLengthRanges[FM_PCD_CC_STATS_MAX_NUM_OF_FLR]; ++ /**< Relevant only for 'RMON' statistics mode ++ (this feature is supported only on B4860 device); ++ Holds a list of programmable thresholds - for each received frame, ++ its length in bytes is examined against these range thresholds and ++ the appropriate counter is incremented by 1 - for example, to belong ++ to range i, the following should hold: ++ range i-1 threshold < frame length <= range i threshold ++ Each range threshold must be larger then its preceding range ++ threshold, and last range threshold must be 0xFFFF. */ ++#endif /* (DPAA_VERSION >= 11) */ ++ uint16_t numOfKeys; /**< Number of initial keys; ++ Note that in case of 'action' = e_FM_PCD_ACTION_INDEXED_LOOKUP, ++ this field should be power-of-2 of the number of bits that are ++ set in 'icIndxMask'. */ ++ uint8_t keySize; /**< Size of key - for extraction of type FULL_FIELD, 'keySize' has ++ to be the standard size of the selected key; For other extraction ++ types, 'keySize' has to be as size of extraction; When 'action' = ++ e_FM_PCD_ACTION_INDEXED_LOOKUP, 'keySize' must be 2. */ ++ t_FmPcdCcKeyParams keyParams[FM_PCD_MAX_NUM_OF_KEYS]; ++ /**< An array with 'numOfKeys' entries, each entry specifies the ++ corresponding key parameters; ++ When 'action' = e_FM_PCD_ACTION_EXACT_MATCH, this value must not ++ exceed 255 (FM_PCD_MAX_NUM_OF_KEYS-1) as the last entry is saved ++ for the 'miss' entry. */ ++ t_FmPcdCcNextEngineParams ccNextEngineParamsForMiss; ++ /**< Parameters for defining the next engine when a key is not matched; ++ Not relevant if action = e_FM_PCD_ACTION_INDEXED_LOOKUP. */ ++} t_KeysParams; ++ ++ ++/**************************************************************************//** ++ @Description Parameters for defining a CC node ++*//***************************************************************************/ ++typedef struct t_FmPcdCcNodeParams { ++ t_FmPcdExtractEntry extractCcParams; /**< Extraction parameters */ ++ t_KeysParams keysParams; /**< Keys definition matching the selected extraction */ ++} t_FmPcdCcNodeParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a hash table ++*//***************************************************************************/ ++typedef struct t_FmPcdHashTableParams { ++ uint16_t maxNumOfKeys; /**< Maximum Number Of Keys that will (ever) be used in this Hash-table */ ++ e_FmPcdCcStatsMode statisticsMode; /**< If not e_FM_PCD_CC_STATS_MODE_NONE, the required structures for the ++ requested statistics mode will be allocated according to maxNumOfKeys. */ ++ uint8_t kgHashShift; /**< KG-Hash-shift as it was configured in the KG-scheme ++ that leads to this hash-table. */ ++ uint16_t hashResMask; /**< Mask that will be used on the hash-result; ++ The number-of-sets for this hash will be calculated ++ as (2^(number of bits set in 'hashResMask')); ++ The 4 lower bits must be cleared. */ ++ uint8_t hashShift; /**< Byte offset from the beginning of the KeyGen hash result to the ++ 2-bytes to be used as hash index. */ ++ uint8_t matchKeySize; /**< Size of the exact match keys held by the hash buckets */ ++ ++ t_FmPcdCcNextEngineParams ccNextEngineParamsForMiss; /**< Parameters for defining the next engine when a key is not matched */ ++ ++} t_FmPcdHashTableParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a CC tree group. ++ ++ This structure defines a CC group in terms of NetEnv units ++ and the action to be taken in each case. The unitIds list must ++ be given in order from low to high indices. ++ ++ t_FmPcdCcNextEngineParams is a list of 2^numOfDistinctionUnits ++ structures where each defines the next action to be taken for ++ each units combination. for example: ++ numOfDistinctionUnits = 2 ++ unitIds = {1,3} ++ p_NextEnginePerEntriesInGrp[0] = t_FmPcdCcNextEngineParams for the case that ++ unit 1 - not found; unit 3 - not found; ++ p_NextEnginePerEntriesInGrp[1] = t_FmPcdCcNextEngineParams for the case that ++ unit 1 - not found; unit 3 - found; ++ p_NextEnginePerEntriesInGrp[2] = t_FmPcdCcNextEngineParams for the case that ++ unit 1 - found; unit 3 - not found; ++ p_NextEnginePerEntriesInGrp[3] = t_FmPcdCcNextEngineParams for the case that ++ unit 1 - found; unit 3 - found; ++*//***************************************************************************/ ++typedef struct t_FmPcdCcGrpParams { ++ uint8_t numOfDistinctionUnits; /**< Up to 4 */ ++ uint8_t unitIds[FM_PCD_MAX_NUM_OF_CC_UNITS]; ++ /**< Indices of the units as defined in ++ FM_PCD_NetEnvCharacteristicsSet() */ ++ t_FmPcdCcNextEngineParams nextEnginePerEntriesInGrp[FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP]; ++ /**< Maximum entries per group is 16 */ ++} t_FmPcdCcGrpParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining CC tree groups ++*//***************************************************************************/ ++typedef struct t_FmPcdCcTreeParams { ++ t_Handle h_NetEnv; /**< A handle to the Network environment as returned ++ by FM_PCD_NetEnvCharacteristicsSet() */ ++ uint8_t numOfGrps; /**< Number of CC groups within the CC tree */ ++ t_FmPcdCcGrpParams ccGrpParams[FM_PCD_MAX_NUM_OF_CC_GROUPS]; ++ /**< Parameters for each group. */ ++} t_FmPcdCcTreeParams; ++ ++ ++/**************************************************************************//** ++ @Description CC key statistics structure ++*//***************************************************************************/ ++typedef struct t_FmPcdCcKeyStatistics { ++ uint32_t byteCount; /**< This counter reflects byte count of frames that ++ were matched by this key. */ ++ uint32_t frameCount; /**< This counter reflects count of frames that ++ were matched by this key. */ ++#if (DPAA_VERSION >= 11) ++ uint32_t frameLengthRangeCount[FM_PCD_CC_STATS_MAX_NUM_OF_FLR]; ++ /**< These counters reflect how many frames matched ++ this key in 'RMON' statistics mode: ++ Each counter holds the number of frames of a ++ specific frames length range, according to the ++ ranges provided at initialization. */ ++#endif /* (DPAA_VERSION >= 11) */ ++} t_FmPcdCcKeyStatistics; ++ ++/**************************************************************************//** ++ @Description Parameters for defining policer byte rate ++*//***************************************************************************/ ++typedef struct t_FmPcdPlcrByteRateModeParams { ++ e_FmPcdPlcrFrameLengthSelect frameLengthSelection; /**< Frame length selection */ ++ e_FmPcdPlcrRollBackFrameSelect rollBackFrameSelection; /**< relevant option only e_FM_PCD_PLCR_L2_FRM_LEN, ++ e_FM_PCD_PLCR_FULL_FRM_LEN */ ++} t_FmPcdPlcrByteRateModeParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining the policer profile (based on ++ RFC-2698 or RFC-4115 attributes). ++*//***************************************************************************/ ++typedef struct t_FmPcdPlcrNonPassthroughAlgParams { ++ e_FmPcdPlcrRateMode rateMode; /**< Byte mode or Packet mode */ ++ t_FmPcdPlcrByteRateModeParams byteModeParams; /**< Valid for Byte NULL for Packet */ ++ uint32_t committedInfoRate; /**< KBits/Second or Packets/Second */ ++ uint32_t committedBurstSize; /**< Bytes/Packets */ ++ uint32_t peakOrExcessInfoRate; /**< KBits/Second or Packets/Second */ ++ uint32_t peakOrExcessBurstSize; /**< Bytes/Packets */ ++} t_FmPcdPlcrNonPassthroughAlgParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining the next engine after policer ++*//***************************************************************************/ ++typedef union u_FmPcdPlcrNextEngineParams { ++ e_FmPcdDoneAction action; /**< Action - when next engine is BMI (done) */ ++ t_Handle h_Profile; /**< Policer profile handle - used when next engine ++ is Policer, must be a SHARED profile */ ++ t_Handle h_DirectScheme; /**< Direct scheme select - when next engine is KeyGen */ ++} u_FmPcdPlcrNextEngineParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining the policer profile entry ++*//***************************************************************************/ ++typedef struct t_FmPcdPlcrProfileParams { ++ bool modify; /**< TRUE to change an existing profile */ ++ union { ++ struct { ++ e_FmPcdProfileTypeSelection profileType; /**< Type of policer profile */ ++ t_Handle h_FmPort; /**< Relevant for per-port profiles only */ ++ uint16_t relativeProfileId; /**< Profile id - relative to shared group or to port */ ++ } newParams; /**< use it when modify = FALSE */ ++ t_Handle h_Profile; /**< A handle to a profile - use it when modify=TRUE */ ++ } id; ++ e_FmPcdPlcrAlgorithmSelection algSelection; /**< Profile Algorithm PASS_THROUGH, RFC_2698, RFC_4115 */ ++ e_FmPcdPlcrColorMode colorMode; /**< COLOR_BLIND, COLOR_AWARE */ ++ ++ union { ++ e_FmPcdPlcrColor dfltColor; /**< For Color-Blind Pass-Through mode; the policer will re-color ++ any incoming packet with the default value. */ ++ e_FmPcdPlcrColor override; /**< For Color-Aware modes; the profile response to a ++ pre-color value of 2'b11. */ ++ } color; ++ ++ t_FmPcdPlcrNonPassthroughAlgParams nonPassthroughAlgParams; /**< RFC2698 or RFC4115 parameters */ ++ ++ e_FmPcdEngine nextEngineOnGreen; /**< Next engine for green-colored frames */ ++ u_FmPcdPlcrNextEngineParams paramsOnGreen; /**< Next engine parameters for green-colored frames */ ++ ++ e_FmPcdEngine nextEngineOnYellow; /**< Next engine for yellow-colored frames */ ++ u_FmPcdPlcrNextEngineParams paramsOnYellow; /**< Next engine parameters for yellow-colored frames */ ++ ++ e_FmPcdEngine nextEngineOnRed; /**< Next engine for red-colored frames */ ++ u_FmPcdPlcrNextEngineParams paramsOnRed; /**< Next engine parameters for red-colored frames */ ++ ++ bool trapProfileOnFlowA; /**< Obsolete - do not use */ ++ bool trapProfileOnFlowB; /**< Obsolete - do not use */ ++ bool trapProfileOnFlowC; /**< Obsolete - do not use */ ++} t_FmPcdPlcrProfileParams; ++ ++/**************************************************************************//** ++ @Description Parameters for selecting a location for requested manipulation ++*//***************************************************************************/ ++typedef struct t_FmManipHdrInfo { ++ e_NetHeaderType hdr; /**< Header selection */ ++ e_FmPcdHdrIndex hdrIndex; /**< Relevant only for MPLS, VLAN and tunneled IP. Otherwise should be cleared. */ ++ bool byField; /**< TRUE if the location of manipulation is according to some field in the specific header*/ ++ t_FmPcdFields fullField; /**< Relevant only when byField = TRUE: Extract field */ ++} t_FmManipHdrInfo; ++ ++#if ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++/**************************************************************************//** ++ @Description Parameters for defining an insertion manipulation ++ of type e_FM_PCD_MANIP_INSRT_TO_START_OF_FRAME_TEMPLATE ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrInsrtByTemplateParams { ++ uint8_t size; /**< Size of insert template to the start of the frame. */ ++ uint8_t hdrTemplate[FM_PCD_MAX_MANIP_INSRT_TEMPLATE_SIZE]; ++ /**< Array of the insertion template. */ ++ ++ bool modifyOuterIp; /**< TRUE if user want to modify some fields in outer IP. */ ++ struct { ++ uint16_t ipOuterOffset; /**< Offset of outer IP in the insert template, relevant if modifyOuterIp = TRUE.*/ ++ uint16_t dscpEcn; /**< value of dscpEcn in IP outer, relevant if modifyOuterIp = TRUE. ++ in IPV4 dscpEcn only byte - it has to be adjusted to the right*/ ++ bool udpPresent; /**< TRUE if UDP is present in the insert template, relevant if modifyOuterIp = TRUE.*/ ++ uint8_t udpOffset; /**< Offset in the insert template of UDP, relevant if modifyOuterIp = TRUE and udpPresent=TRUE.*/ ++ uint8_t ipIdentGenId; /**< Used by FMan-CTRL to calculate IP-identification field,relevant if modifyOuterIp = TRUE.*/ ++ bool recalculateLength; /**< TRUE if recalculate length has to be performed due to the engines in the path which can change the frame later, relevant if modifyOuterIp = TRUE.*/ ++ struct { ++ uint8_t blockSize; /**< The CAAM block-size; Used by FMan-CTRL to calculate the IP Total Length field.*/ ++ uint8_t extraBytesAddedAlignedToBlockSize; /**< Used by FMan-CTRL to calculate the IP Total Length field and UDP length*/ ++ uint8_t extraBytesAddedNotAlignedToBlockSize;/**< Used by FMan-CTRL to calculate the IP Total Length field and UDP length.*/ ++ } recalculateLengthParams; /**< Recalculate length parameters - relevant if modifyOuterIp = TRUE and recalculateLength = TRUE */ ++ } modifyOuterIpParams; /**< Outer IP modification parameters - ignored if modifyOuterIp is FALSE */ ++ ++ bool modifyOuterVlan; /**< TRUE if user wants to modify VPri field in the outer VLAN header*/ ++ struct { ++ uint8_t vpri; /**< Value of VPri, relevant if modifyOuterVlan = TRUE ++ VPri only 3 bits, it has to be adjusted to the right*/ ++ } modifyOuterVlanParams; ++} t_FmPcdManipHdrInsrtByTemplateParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining CAPWAP fragmentation ++*//***************************************************************************/ ++typedef struct t_CapwapFragmentationParams { ++ uint16_t sizeForFragmentation; /**< if length of the frame is greater than this value, CAPWAP fragmentation will be executed.*/ ++ bool headerOptionsCompr; /**< TRUE - first fragment include the CAPWAP header options field, ++ and all other fragments exclude the CAPWAP options field, ++ FALSE - all fragments include CAPWAP header options field. */ ++} t_CapwapFragmentationParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining CAPWAP reassembly ++*//***************************************************************************/ ++typedef struct t_CapwapReassemblyParams { ++ uint16_t maxNumFramesInProcess; /**< Number of frames which can be reassembled concurrently; must be power of 2. ++ In case numOfFramesPerHashEntry == e_FM_PCD_MANIP_FOUR_WAYS_HASH, ++ maxNumFramesInProcess has to be in the range of 4 - 512, ++ In case numOfFramesPerHashEntry == e_FM_PCD_MANIP_EIGHT_WAYS_HASH, ++ maxNumFramesInProcess has to be in the range of 8 - 2048 */ ++ bool haltOnDuplicationFrag; /**< If TRUE, reassembly process will be halted due to duplicated fragment, ++ and all processed fragments will be enqueued with error indication; ++ If FALSE, only duplicated fragments will be enqueued with error indication. */ ++ ++ e_FmPcdManipReassemTimeOutMode timeOutMode; /**< Expiration delay initialized by the reassembly process */ ++ uint32_t fqidForTimeOutFrames; /**< FQID in which time out frames will enqueue during Time Out Process */ ++ uint32_t timeoutRoutineRequestTime; ++ /**< Represents the time interval in microseconds between consecutive ++ timeout routine requests It has to be power of 2. */ ++ uint32_t timeoutThresholdForReassmProcess; ++ /**< Time interval (microseconds) for marking frames in process as too old; ++ Frames in process are those for which at least one fragment was received ++ but not all fragments. */ ++ ++ e_FmPcdManipReassemWaysNumber numOfFramesPerHashEntry;/**< Number of frames per hash entry (needed for the reassembly process) */ ++} t_CapwapReassemblyParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining fragmentation/reassembly manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipFragOrReasmParams { ++ bool frag; /**< TRUE if using the structure for fragmentation, ++ otherwise this structure is used for reassembly */ ++ uint8_t sgBpid; /**< Scatter/Gather buffer pool id; ++ Same LIODN number is used for these buffers as for ++ the received frames buffers, so buffers of this pool ++ need to be allocated in the same memory area as the ++ received buffers. If the received buffers arrive ++ from different sources, the Scatter/Gather BP id ++ should be mutual to all these sources. */ ++ e_NetHeaderType hdr; /**< Header selection */ ++ union { ++ t_CapwapFragmentationParams capwapFragParams; /**< Structure for CAPWAP fragmentation, ++ relevant if 'frag' = TRUE, 'hdr' = HEADER_TYPE_CAPWAP */ ++ t_CapwapReassemblyParams capwapReasmParams; /**< Structure for CAPWAP reassembly, ++ relevant if 'frag' = FALSE, 'hdr' = HEADER_TYPE_CAPWAP */ ++ } u; ++} t_FmPcdManipFragOrReasmParams; ++#endif /* ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) */ ++ ++ ++/**************************************************************************//** ++ @Description Parameters for defining header removal by header type ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrRmvByHdrParams { ++ e_FmPcdManipHdrRmvByHdrType type; /**< Selection of header removal location */ ++ union { ++#if ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++ struct { ++ bool include; /**< If FALSE, remove until the specified header (not including the header); ++ If TRUE, remove also the specified header. */ ++ t_FmManipHdrInfo hdrInfo; ++ } fromStartByHdr; /**< Relevant when type = e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START */ ++#endif /* (DPAA_VERSION >= 11) || ... */ ++#if (DPAA_VERSION >= 11) ++ t_FmManipHdrInfo hdrInfo; /**< Relevant when type = e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START */ ++#endif /* (DPAA_VERSION >= 11) */ ++ e_FmPcdManipHdrRmvSpecificL2 specificL2; /**< Relevant when type = e_FM_PCD_MANIP_BY_HDR_SPECIFIC_L2; ++ Defines which L2 headers to remove. */ ++ } u; ++} t_FmPcdManipHdrRmvByHdrParams; ++ ++/**************************************************************************//** ++ @Description Parameters for configuring IP fragmentation manipulation ++ ++ Restrictions: ++ - IP Fragmentation output fragments must not be forwarded to application directly. ++ - Maximum number of fragments per frame is 16. ++ - Fragmentation of IP fragments is not supported. ++ - IPv4 packets containing header Option fields are fragmented by copying all option ++ fields to each fragment, regardless of the copy bit value. ++ - Transmit confirmation is not supported. ++ - Fragmentation after SEC can't handle S/G frames. ++ - Fragmentation nodes must be set as the last PCD action (i.e. the ++ corresponding CC node key must have next engine set to e_FM_PCD_DONE). ++ - Only BMan buffers shall be used for frames to be fragmented. ++ - IPF does not support VSP. Therefore, on the same port where we have IPF ++ we cannot support VSP. ++ - NOTE: The following comment is relevant only for FMAN v3 devices: IPF ++ does not support VSP. Therefore, on the same port where we have IPF we ++ cannot support VSP. ++*//***************************************************************************/ ++typedef struct t_FmPcdManipFragIpParams { ++ uint16_t sizeForFragmentation; /**< If length of the frame is greater than this value, ++ IP fragmentation will be executed.*/ ++#if (DPAA_VERSION == 10) ++ uint8_t scratchBpid; /**< Absolute buffer pool id according to BM configuration.*/ ++#endif /* (DPAA_VERSION == 10) */ ++ bool sgBpidEn; /**< Enable a dedicated buffer pool id for the Scatter/Gather buffer allocation; ++ If disabled, the Scatter/Gather buffer will be allocated from the same pool as the ++ received frame's buffer. */ ++ uint8_t sgBpid; /**< Scatter/Gather buffer pool id; ++ This parameters is relevant when 'sgBpidEn=TRUE'; ++ Same LIODN number is used for these buffers as for the received frames buffers, so buffers ++ of this pool need to be allocated in the same memory area as the received buffers. ++ If the received buffers arrive from different sources, the Scatter/Gather BP id should be ++ mutual to all these sources. */ ++ e_FmPcdManipDontFragAction dontFragAction; /**< Don't Fragment Action - If an IP packet is larger ++ than MTU and its DF bit is set, then this field will ++ determine the action to be taken.*/ ++} t_FmPcdManipFragIpParams; ++ ++/**************************************************************************//** ++ @Description Parameters for configuring IP reassembly manipulation. ++ ++ This is a common structure for both IPv4 and IPv6 reassembly ++ manipulation. For reassembly of both IPv4 and IPv6, make sure to ++ set the 'hdr' field in t_FmPcdManipReassemParams to HEADER_TYPE_IPv6. ++ ++ Restrictions: ++ - Application must define at least one scheme to catch the reassembled frames. ++ - Maximum number of fragments per frame is 16. ++ - Reassembly of IPv4 fragments containing Option fields is supported. ++ ++*//***************************************************************************/ ++typedef struct t_FmPcdManipReassemIpParams { ++ uint8_t relativeSchemeId[2]; /**< Partition relative scheme id: ++ relativeSchemeId[0] - Relative scheme ID for IPV4 Reassembly manipulation; ++ relativeSchemeId[1] - Relative scheme ID for IPV6 Reassembly manipulation; ++ NOTE: The following comment is relevant only for FMAN v2 devices: ++ Relative scheme ID for IPv4/IPv6 Reassembly manipulation must be smaller than ++ the user schemes id to ensure that the reassembly schemes will be first match; ++ Rest schemes, if defined, should have higher relative scheme ID. */ ++#if (DPAA_VERSION >= 11) ++ uint32_t nonConsistentSpFqid; /**< In case that other fragments of the frame corresponds to different storage ++ profile than the opening fragment (Non-Consistent-SP state) ++ then one of two possible scenarios occurs: ++ if 'nonConsistentSpFqid != 0', the reassembled frame will be enqueued to ++ this fqid, otherwise a 'Non Consistent SP' bit will be set in the FD[status].*/ ++#else ++ uint8_t sgBpid; /**< Buffer pool id for the S/G frame created by the reassembly process */ ++#endif /* (DPAA_VERSION >= 11) */ ++ uint8_t dataMemId; /**< Memory partition ID for the IPR's external tables structure */ ++ uint16_t dataLiodnOffset; /**< LIODN offset for access the IPR's external tables structure. */ ++ uint16_t minFragSize[2]; /**< Minimum fragment size: ++ minFragSize[0] - for ipv4, minFragSize[1] - for ipv6 */ ++ e_FmPcdManipReassemWaysNumber numOfFramesPerHashEntry[2]; ++ /**< Number of frames per hash entry needed for reassembly process: ++ numOfFramesPerHashEntry[0] - for ipv4 (max value is e_FM_PCD_MANIP_EIGHT_WAYS_HASH); ++ numOfFramesPerHashEntry[1] - for ipv6 (max value is e_FM_PCD_MANIP_SIX_WAYS_HASH). */ ++ uint16_t maxNumFramesInProcess; /**< Number of frames which can be processed by Reassembly in the same time; ++ Must be power of 2; ++ In the case numOfFramesPerHashEntry == e_FM_PCD_MANIP_FOUR_WAYS_HASH, ++ maxNumFramesInProcess has to be in the range of 4 - 512; ++ In the case numOfFramesPerHashEntry == e_FM_PCD_MANIP_EIGHT_WAYS_HASH, ++ maxNumFramesInProcess has to be in the range of 8 - 2048. */ ++ e_FmPcdManipReassemTimeOutMode timeOutMode; /**< Expiration delay initialized by Reassembly process */ ++ uint32_t fqidForTimeOutFrames; /**< FQID in which time out frames will enqueue during Time Out Process; ++ Recommended value for this field is 0; in this way timed-out frames will be discarded */ ++ uint32_t timeoutThresholdForReassmProcess; ++ /**< Represents the time interval in microseconds which defines ++ if opened frame (at least one fragment was processed but not all the fragments)is found as too old*/ ++} t_FmPcdManipReassemIpParams; ++ ++/**************************************************************************//** ++ @Description structure for defining IPSEC manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipSpecialOffloadIPSecParams { ++ bool decryption; /**< TRUE if being used in decryption direction; ++ FALSE if being used in encryption direction. */ ++ bool ecnCopy; /**< TRUE to copy the ECN bits from inner/outer to outer/inner ++ (direction depends on the 'decryption' field). */ ++ bool dscpCopy; /**< TRUE to copy the DSCP bits from inner/outer to outer/inner ++ (direction depends on the 'decryption' field). */ ++ bool variableIpHdrLen; /**< TRUE for supporting variable IP header length in decryption. */ ++ bool variableIpVersion; /**< TRUE for supporting both IP version on the same SA in encryption */ ++ uint8_t outerIPHdrLen; /**< if 'variableIpVersion == TRUE' then this field must be set to non-zero value; ++ It is specifies the length of the outer IP header that was configured in the ++ corresponding SA. */ ++ uint16_t arwSize; /**< if <> '0' then will perform ARW check for this SA; ++ The value must be a multiplication of 16 */ ++ uintptr_t arwAddr; /**< if arwSize <> '0' then this field must be set to non-zero value; ++ MUST be allocated from FMAN's MURAM that the post-sec op-port belongs to; ++ Must be 4B aligned. Required MURAM size is 'NEXT_POWER_OF_2(arwSize+32))/8+4' Bytes */ ++} t_FmPcdManipSpecialOffloadIPSecParams; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description Parameters for configuring CAPWAP fragmentation manipulation ++ ++ Restrictions: ++ - Maximum number of fragments per frame is 16. ++ - Transmit confirmation is not supported. ++ - Fragmentation nodes must be set as the last PCD action (i.e. the ++ corresponding CC node key must have next engine set to e_FM_PCD_DONE). ++ - Only BMan buffers shall be used for frames to be fragmented. ++ - NOTE: The following comment is relevant only for FMAN v3 devices: IPF ++ does not support VSP. Therefore, on the same port where we have IPF we ++ cannot support VSP. ++*//***************************************************************************/ ++typedef struct t_FmPcdManipFragCapwapParams { ++ uint16_t sizeForFragmentation; /**< If length of the frame is greater than this value, ++ CAPWAP fragmentation will be executed.*/ ++ bool sgBpidEn; /**< Enable a dedicated buffer pool id for the Scatter/Gather buffer allocation; ++ If disabled, the Scatter/Gather buffer will be allocated from the same pool as the ++ received frame's buffer. */ ++ uint8_t sgBpid; /**< Scatter/Gather buffer pool id; ++ This parameters is relevant when 'sgBpidEn=TRUE'; ++ Same LIODN number is used for these buffers as for the received frames buffers, so buffers ++ of this pool need to be allocated in the same memory area as the received buffers. ++ If the received buffers arrive from different sources, the Scatter/Gather BP id should be ++ mutual to all these sources. */ ++ bool compressModeEn; /**< CAPWAP Header Options Compress Enable mode; ++ When this mode is enabled then only the first fragment include the CAPWAP header options ++ field (if user provides it in the input frame) and all other fragments exclude the CAPWAP ++ options field (CAPWAP header is updated accordingly).*/ ++} t_FmPcdManipFragCapwapParams; ++ ++/**************************************************************************//** ++ @Description Parameters for configuring CAPWAP reassembly manipulation. ++ ++ Restrictions: ++ - Application must define one scheme to catch the reassembled frames. ++ - Maximum number of fragments per frame is 16. ++ ++*//***************************************************************************/ ++typedef struct t_FmPcdManipReassemCapwapParams { ++ uint8_t relativeSchemeId; /**< Partition relative scheme id; ++ NOTE: this id must be smaller than the user schemes id to ensure that the reassembly scheme will be first match; ++ Rest schemes, if defined, should have higher relative scheme ID. */ ++ uint8_t dataMemId; /**< Memory partition ID for the IPR's external tables structure */ ++ uint16_t dataLiodnOffset; /**< LIODN offset for access the IPR's external tables structure. */ ++ uint16_t maxReassembledFrameLength;/**< The maximum CAPWAP reassembled frame length in bytes; ++ If maxReassembledFrameLength == 0, any successful reassembled frame length is ++ considered as a valid length; ++ if maxReassembledFrameLength > 0, a successful reassembled frame which its length ++ exceeds this value is considered as an error frame (FD status[CRE] bit is set). */ ++ e_FmPcdManipReassemWaysNumber numOfFramesPerHashEntry; ++ /**< Number of frames per hash entry needed for reassembly process */ ++ uint16_t maxNumFramesInProcess; /**< Number of frames which can be processed by reassembly in the same time; ++ Must be power of 2; ++ In the case numOfFramesPerHashEntry == e_FM_PCD_MANIP_FOUR_WAYS_HASH, ++ maxNumFramesInProcess has to be in the range of 4 - 512; ++ In the case numOfFramesPerHashEntry == e_FM_PCD_MANIP_EIGHT_WAYS_HASH, ++ maxNumFramesInProcess has to be in the range of 8 - 2048. */ ++ e_FmPcdManipReassemTimeOutMode timeOutMode; /**< Expiration delay initialized by Reassembly process */ ++ uint32_t fqidForTimeOutFrames; /**< FQID in which time out frames will enqueue during Time Out Process; ++ Recommended value for this field is 0; in this way timed-out frames will be discarded */ ++ uint32_t timeoutThresholdForReassmProcess; ++ /**< Represents the time interval in microseconds which defines ++ if opened frame (at least one fragment was processed but not all the fragments)is found as too old*/ ++} t_FmPcdManipReassemCapwapParams; ++ ++/**************************************************************************//** ++ @Description structure for defining CAPWAP manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipSpecialOffloadCapwapParams { ++ bool dtls; /**< TRUE if continue to SEC DTLS encryption */ ++ e_FmPcdManipHdrQosSrc qosSrc; /**< TODO */ ++} t_FmPcdManipSpecialOffloadCapwapParams; ++ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ ++/**************************************************************************//** ++ @Description Parameters for defining special offload manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipSpecialOffloadParams { ++ e_FmPcdManipSpecialOffloadType type; /**< Type of special offload manipulation */ ++ union ++ { ++ t_FmPcdManipSpecialOffloadIPSecParams ipsec; /**< Parameters for IPSec; Relevant when ++ type = e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC */ ++#if (DPAA_VERSION >= 11) ++ t_FmPcdManipSpecialOffloadCapwapParams capwap; /**< Parameters for CAPWAP; Relevant when ++ type = e_FM_PCD_MANIP_SPECIAL_OFFLOAD_CAPWAP */ ++#endif /* (DPAA_VERSION >= 11) */ ++ } u; ++} t_FmPcdManipSpecialOffloadParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining insertion manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrInsrt { ++ uint8_t size; /**< size of inserted section */ ++ uint8_t *p_Data; /**< data to be inserted */ ++} t_FmPcdManipHdrInsrt; ++ ++ ++/**************************************************************************//** ++ @Description Parameters for defining generic removal manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrRmvGenericParams { ++ uint8_t offset; /**< Offset from beginning of header to the start ++ location of the removal */ ++ uint8_t size; /**< Size of removed section */ ++} t_FmPcdManipHdrRmvGenericParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining generic insertion manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrInsrtGenericParams { ++ uint8_t offset; /**< Offset from beginning of header to the start ++ location of the insertion */ ++ uint8_t size; /**< Size of inserted section */ ++ bool replace; /**< TRUE to override (replace) existing data at ++ 'offset', FALSE to insert */ ++ uint8_t *p_Data; /**< Pointer to data to be inserted */ ++} t_FmPcdManipHdrInsrtGenericParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation VLAN DSCP To Vpri translation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrFieldUpdateVlanDscpToVpri { ++ uint8_t dscpToVpriTable[FM_PCD_MANIP_DSCP_TO_VLAN_TRANS]; ++ /**< A table of VPri values for each DSCP value; ++ The index is the DSCP value (0-0x3F) and the ++ value is the corresponding VPRI (0-15). */ ++ uint8_t vpriDefVal; /**< 0-7, Relevant only if if updateType = ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN, ++ this field is the Q Tag default value if the ++ IP header is not found. */ ++} t_FmPcdManipHdrFieldUpdateVlanDscpToVpri; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation VLAN fields updates ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrFieldUpdateVlan { ++ e_FmPcdManipHdrFieldUpdateVlan updateType; /**< Selects VLAN update type */ ++ union { ++ uint8_t vpri; /**< 0-7, Relevant only if If updateType = ++ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_PRI, this ++ is the new VLAN pri. */ ++ t_FmPcdManipHdrFieldUpdateVlanDscpToVpri dscpToVpri; /**< Parameters structure, Relevant only if updateType ++ = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN. */ ++ } u; ++} t_FmPcdManipHdrFieldUpdateVlan; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation IPV4 fields updates ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrFieldUpdateIpv4 { ++ ipv4HdrManipUpdateFlags_t validUpdates; /**< ORed flag, selecting the required updates */ ++ uint8_t tos; /**< 8 bit New TOS; Relevant if validUpdates contains ++ HDR_MANIP_IPV4_TOS */ ++ uint16_t id; /**< 16 bit New IP ID; Relevant only if validUpdates ++ contains HDR_MANIP_IPV4_ID */ ++ uint32_t src; /**< 32 bit New IP SRC; Relevant only if validUpdates ++ contains HDR_MANIP_IPV4_SRC */ ++ uint32_t dst; /**< 32 bit New IP DST; Relevant only if validUpdates ++ contains HDR_MANIP_IPV4_DST */ ++} t_FmPcdManipHdrFieldUpdateIpv4; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation IPV6 fields updates ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrFieldUpdateIpv6 { ++ ipv6HdrManipUpdateFlags_t validUpdates; /**< ORed flag, selecting the required updates */ ++ uint8_t trafficClass; /**< 8 bit New Traffic Class; Relevant if validUpdates contains ++ HDR_MANIP_IPV6_TC */ ++ uint8_t src[NET_HEADER_FIELD_IPv6_ADDR_SIZE]; ++ /**< 16 byte new IP SRC; Relevant only if validUpdates ++ contains HDR_MANIP_IPV6_SRC */ ++ uint8_t dst[NET_HEADER_FIELD_IPv6_ADDR_SIZE]; ++ /**< 16 byte new IP DST; Relevant only if validUpdates ++ contains HDR_MANIP_IPV6_DST */ ++} t_FmPcdManipHdrFieldUpdateIpv6; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation TCP/UDP fields updates ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrFieldUpdateTcpUdp { ++ tcpUdpHdrManipUpdateFlags_t validUpdates; /**< ORed flag, selecting the required updates */ ++ uint16_t src; /**< 16 bit New TCP/UDP SRC; Relevant only if validUpdates ++ contains HDR_MANIP_TCP_UDP_SRC */ ++ uint16_t dst; /**< 16 bit New TCP/UDP DST; Relevant only if validUpdates ++ contains HDR_MANIP_TCP_UDP_DST */ ++} t_FmPcdManipHdrFieldUpdateTcpUdp; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation fields updates ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrFieldUpdateParams { ++ e_FmPcdManipHdrFieldUpdateType type; /**< Type of header field update manipulation */ ++ union { ++ t_FmPcdManipHdrFieldUpdateVlan vlan; /**< Parameters for VLAN update. Relevant when ++ type = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN */ ++ t_FmPcdManipHdrFieldUpdateIpv4 ipv4; /**< Parameters for IPv4 update. Relevant when ++ type = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4 */ ++ t_FmPcdManipHdrFieldUpdateIpv6 ipv6; /**< Parameters for IPv6 update. Relevant when ++ type = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6 */ ++ t_FmPcdManipHdrFieldUpdateTcpUdp tcpUdp; /**< Parameters for TCP/UDP update. Relevant when ++ type = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP */ ++ } u; ++} t_FmPcdManipHdrFieldUpdateParams; ++ ++ ++ ++/**************************************************************************//** ++ @Description Parameters for defining custom header manipulation for generic field replacement ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrCustomGenFieldReplace { ++ uint8_t srcOffset; /**< Location of new data - Offset from ++ Parse Result (>= 16, srcOffset+size <= 32, ) */ ++ uint8_t dstOffset; /**< Location of data to be overwritten - Offset from ++ start of frame (dstOffset + size <= 256). */ ++ uint8_t size; /**< The number of bytes (<=16) to be replaced */ ++ uint8_t mask; /**< Optional 1 byte mask. Set to select bits for ++ replacement (1 - bit will be replaced); ++ Clear to use field as is. */ ++ uint8_t maskOffset; /**< Relevant if mask != 0; ++ Mask offset within the replaces "size" */ ++} t_FmPcdManipHdrCustomGenFieldReplace; ++ ++/**************************************************************************//** ++ @Description Parameters for defining custom header manipulation for IP replacement ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrCustomIpHdrReplace { ++ e_FmPcdManipHdrCustomIpReplace replaceType; /**< Selects replace update type */ ++ bool decTtlHl; /**< Decrement TTL (IPV4) or Hop limit (IPV6) by 1 */ ++ bool updateIpv4Id; /**< Relevant when replaceType = ++ e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4 */ ++ uint16_t id; /**< 16 bit New IP ID; Relevant only if ++ updateIpv4Id = TRUE */ ++ uint8_t hdrSize; /**< The size of the new IP header */ ++ uint8_t hdr[FM_PCD_MANIP_MAX_HDR_SIZE]; ++ /**< The new IP header */ ++} t_FmPcdManipHdrCustomIpHdrReplace; ++ ++/**************************************************************************//** ++ @Description Parameters for defining custom header manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrCustomParams { ++ e_FmPcdManipHdrCustomType type; /**< Type of header field update manipulation */ ++ union { ++ t_FmPcdManipHdrCustomIpHdrReplace ipHdrReplace; /**< Parameters IP header replacement */ ++ t_FmPcdManipHdrCustomGenFieldReplace genFieldReplace; /**< Parameters IP header replacement */ ++ } u; ++} t_FmPcdManipHdrCustomParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining specific L2 insertion manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrInsrtSpecificL2Params { ++ e_FmPcdManipHdrInsrtSpecificL2 specificL2; /**< Selects which L2 headers to insert */ ++ bool update; /**< TRUE to update MPLS header */ ++ uint8_t size; /**< size of inserted section */ ++ uint8_t *p_Data; /**< data to be inserted */ ++} t_FmPcdManipHdrInsrtSpecificL2Params; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description Parameters for defining IP insertion manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrInsrtIpParams { ++ bool calcL4Checksum; /**< Calculate L4 checksum. */ ++ e_FmPcdManipHdrQosMappingMode mappingMode; /**< TODO */ ++ uint8_t lastPidOffset; /**< the offset of the last Protocol within ++ the inserted header */ ++ uint16_t id; /**< 16 bit New IP ID */ ++ bool dontFragOverwrite; ++ /**< IPv4 only. DF is overwritten with the hash-result next-to-last byte. ++ * This byte is configured to be overwritten when RPD is set. */ ++ uint8_t lastDstOffset; ++ /**< IPv6 only. if routing extension exist, user should set the offset of the destination address ++ * in order to calculate UDP checksum pseudo header; ++ * Otherwise set it to '0'. */ ++ t_FmPcdManipHdrInsrt insrt; /**< size and data to be inserted. */ ++} t_FmPcdManipHdrInsrtIpParams; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Description Parameters for defining header insertion manipulation by header type ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrInsrtByHdrParams { ++ e_FmPcdManipHdrInsrtByHdrType type; /**< Selects manipulation type */ ++ union { ++ ++ t_FmPcdManipHdrInsrtSpecificL2Params specificL2Params; ++ /**< Used when type = e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2: ++ Selects which L2 headers to insert */ ++#if (DPAA_VERSION >= 11) ++ t_FmPcdManipHdrInsrtIpParams ipParams; /**< Used when type = e_FM_PCD_MANIP_INSRT_BY_HDR_IP */ ++ t_FmPcdManipHdrInsrt insrt; /**< Used when type is one of e_FM_PCD_MANIP_INSRT_BY_HDR_UDP, ++ e_FM_PCD_MANIP_INSRT_BY_HDR_UDP_LITE, or ++ e_FM_PCD_MANIP_INSRT_BY_HDR_CAPWAP */ ++#endif /* (DPAA_VERSION >= 11) */ ++ } u; ++} t_FmPcdManipHdrInsrtByHdrParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header insertion manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrInsrtParams { ++ e_FmPcdManipHdrInsrtType type; /**< Type of insertion manipulation */ ++ union { ++ t_FmPcdManipHdrInsrtByHdrParams byHdr; /**< Parameters for defining header insertion manipulation by header type, ++ relevant if 'type' = e_FM_PCD_MANIP_INSRT_BY_HDR */ ++ t_FmPcdManipHdrInsrtGenericParams generic; /**< Parameters for defining generic header insertion manipulation, ++ relevant if 'type' = e_FM_PCD_MANIP_INSRT_GENERIC */ ++#if ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++ t_FmPcdManipHdrInsrtByTemplateParams byTemplate; /**< Parameters for defining header insertion manipulation by template, ++ relevant if 'type' = e_FM_PCD_MANIP_INSRT_BY_TEMPLATE */ ++#endif /* ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) */ ++ } u; ++} t_FmPcdManipHdrInsrtParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header removal manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrRmvParams { ++ e_FmPcdManipHdrRmvType type; /**< Type of header removal manipulation */ ++ union { ++ t_FmPcdManipHdrRmvByHdrParams byHdr; /**< Parameters for defining header removal manipulation by header type, ++ relevant if type = e_FM_PCD_MANIP_RMV_BY_HDR */ ++ t_FmPcdManipHdrRmvGenericParams generic; /**< Parameters for defining generic header removal manipulation, ++ relevant if type = e_FM_PCD_MANIP_RMV_GENERIC */ ++ } u; ++} t_FmPcdManipHdrRmvParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation node ++*//***************************************************************************/ ++typedef struct t_FmPcdManipHdrParams { ++ bool rmv; /**< TRUE, to define removal manipulation */ ++ t_FmPcdManipHdrRmvParams rmvParams; /**< Parameters for removal manipulation, relevant if 'rmv' = TRUE */ ++ ++ bool insrt; /**< TRUE, to define insertion manipulation */ ++ t_FmPcdManipHdrInsrtParams insrtParams; /**< Parameters for insertion manipulation, relevant if 'insrt' = TRUE */ ++ ++ bool fieldUpdate; /**< TRUE, to define field update manipulation */ ++ t_FmPcdManipHdrFieldUpdateParams fieldUpdateParams; /**< Parameters for field update manipulation, relevant if 'fieldUpdate' = TRUE */ ++ ++ bool custom; /**< TRUE, to define custom manipulation */ ++ t_FmPcdManipHdrCustomParams customParams; /**< Parameters for custom manipulation, relevant if 'custom' = TRUE */ ++ ++ bool dontParseAfterManip;/**< TRUE to de-activate the parser after the manipulation defined in this node. ++ Restrictions: ++ 1. MUST be set if the next engine after the CC is not another CC node ++ (but rather Policer or Keygen), and this is the last (no h_NextManip) in a chain ++ of manipulation nodes. This includes single nodes (i.e. no h_NextManip and ++ also never pointed as h_NextManip of other manipulation nodes) ++ 2. MUST be set if the next engine after the CC is another CC node, and ++ this is NOT the last manipulation node (i.e. it has h_NextManip).*/ ++} t_FmPcdManipHdrParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining fragmentation manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipFragParams { ++ e_NetHeaderType hdr; /**< Header selection */ ++ union { ++#if (DPAA_VERSION >= 11) ++ t_FmPcdManipFragCapwapParams capwapFrag; /**< Parameters for defining CAPWAP fragmentation, ++ relevant if 'hdr' = HEADER_TYPE_CAPWAP */ ++#endif /* (DPAA_VERSION >= 11) */ ++ t_FmPcdManipFragIpParams ipFrag; /**< Parameters for defining IP fragmentation, ++ relevant if 'hdr' = HEADER_TYPE_Ipv4 or HEADER_TYPE_Ipv6 */ ++ } u; ++} t_FmPcdManipFragParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining reassembly manipulation ++*//***************************************************************************/ ++typedef struct t_FmPcdManipReassemParams { ++ e_NetHeaderType hdr; /**< Header selection */ ++ union { ++#if (DPAA_VERSION >= 11) ++ t_FmPcdManipReassemCapwapParams capwapReassem; /**< Parameters for defining CAPWAP reassembly, ++ relevant if 'hdr' = HEADER_TYPE_CAPWAP */ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ t_FmPcdManipReassemIpParams ipReassem; /**< Parameters for defining IP reassembly, ++ relevant if 'hdr' = HEADER_TYPE_Ipv4 or HEADER_TYPE_Ipv6 */ ++ } u; ++} t_FmPcdManipReassemParams; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a manipulation node ++*//***************************************************************************/ ++typedef struct t_FmPcdManipParams { ++ e_FmPcdManipType type; /**< Selects type of manipulation node */ ++ union{ ++ t_FmPcdManipHdrParams hdr; /**< Parameters for defining header manipulation node */ ++ t_FmPcdManipReassemParams reassem; /**< Parameters for defining reassembly manipulation node */ ++ t_FmPcdManipFragParams frag; /**< Parameters for defining fragmentation manipulation node */ ++ t_FmPcdManipSpecialOffloadParams specialOffload; /**< Parameters for defining special offload manipulation node */ ++ } u; ++ ++ t_Handle h_NextManip; /**< Supported for Header Manipulation only; ++ Handle to another (previously defined) manipulation node; ++ Allows concatenation of manipulation actions; ++ This parameter is optional and may be NULL. */ ++#if ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++ bool fragOrReasm; /**< TRUE, if defined fragmentation/reassembly manipulation */ ++ t_FmPcdManipFragOrReasmParams fragOrReasmParams; /**< Parameters for fragmentation/reassembly manipulation, ++ relevant if fragOrReasm = TRUE */ ++#endif /* ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) */ ++} t_FmPcdManipParams; ++ ++/**************************************************************************//** ++ @Description Structure for retrieving IP reassembly statistics ++*//***************************************************************************/ ++typedef struct t_FmPcdManipReassemIpStats { ++ /* common counters for both IPv4 and IPv6 */ ++ uint32_t timeout; /**< Counts the number of timeout occurrences */ ++ uint32_t rfdPoolBusy; /**< Counts the number of failed attempts to allocate ++ a Reassembly Frame Descriptor */ ++ uint32_t internalBufferBusy; /**< Counts the number of times an internal buffer busy occurred */ ++ uint32_t externalBufferBusy; /**< Counts the number of times external buffer busy occurred */ ++ uint32_t sgFragments; /**< Counts the number of Scatter/Gather fragments */ ++ uint32_t dmaSemaphoreDepletion; /**< Counts the number of failed attempts to allocate a DMA semaphore */ ++#if (DPAA_VERSION >= 11) ++ uint32_t nonConsistentSp; /**< Counts the number of Non Consistent Storage Profile events for ++ successfully reassembled frames */ ++#endif /* (DPAA_VERSION >= 11) */ ++ struct { ++ uint32_t successfullyReassembled; /**< Counts the number of successfully reassembled frames */ ++ uint32_t validFragments; /**< Counts the total number of valid fragments that ++ have been processed for all frames */ ++ uint32_t processedFragments; /**< Counts the number of processed fragments ++ (valid and error fragments) for all frames */ ++ uint32_t malformedFragments; /**< Counts the number of malformed fragments processed for all frames */ ++ uint32_t discardedFragments; /**< Counts the number of fragments discarded by the reassembly process */ ++ uint32_t autoLearnBusy; /**< Counts the number of times a busy condition occurs when attempting ++ to access an IP-Reassembly Automatic Learning Hash set */ ++ uint32_t moreThan16Fragments; /**< Counts the fragment occurrences in which the number of fragments-per-frame ++ exceeds 16 */ ++ } specificHdrStatistics[2]; /**< slot '0' is for IPv4, slot '1' is for IPv6 */ ++} t_FmPcdManipReassemIpStats; ++ ++/**************************************************************************//** ++ @Description Structure for retrieving IP fragmentation statistics ++*//***************************************************************************/ ++typedef struct t_FmPcdManipFragIpStats { ++ uint32_t totalFrames; /**< Number of frames that passed through the manipulation node */ ++ uint32_t fragmentedFrames; /**< Number of frames that were fragmented */ ++ uint32_t generatedFragments; /**< Number of fragments that were generated */ ++} t_FmPcdManipFragIpStats; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description Structure for retrieving CAPWAP reassembly statistics ++*//***************************************************************************/ ++typedef struct t_FmPcdManipReassemCapwapStats { ++ uint32_t timeout; /**< Counts the number of timeout occurrences */ ++ uint32_t rfdPoolBusy; /**< Counts the number of failed attempts to allocate ++ a Reassembly Frame Descriptor */ ++ uint32_t internalBufferBusy; /**< Counts the number of times an internal buffer busy occurred */ ++ uint32_t externalBufferBusy; /**< Counts the number of times external buffer busy occurred */ ++ uint32_t sgFragments; /**< Counts the number of Scatter/Gather fragments */ ++ uint32_t dmaSemaphoreDepletion; /**< Counts the number of failed attempts to allocate a DMA semaphore */ ++ uint32_t successfullyReassembled; /**< Counts the number of successfully reassembled frames */ ++ uint32_t validFragments; /**< Counts the total number of valid fragments that ++ have been processed for all frames */ ++ uint32_t processedFragments; /**< Counts the number of processed fragments ++ (valid and error fragments) for all frames */ ++ uint32_t malformedFragments; /**< Counts the number of malformed fragments processed for all frames */ ++ uint32_t autoLearnBusy; /**< Counts the number of times a busy condition occurs when attempting ++ to access an Reassembly Automatic Learning Hash set */ ++ uint32_t discardedFragments; /**< Counts the number of fragments discarded by the reassembly process */ ++ uint32_t moreThan16Fragments; /**< Counts the fragment occurrences in which the number of fragments-per-frame ++ exceeds 16 */ ++ uint32_t exceedMaxReassemblyFrameLen;/**< ounts the number of times that a successful reassembled frame ++ length exceeds MaxReassembledFrameLength value */ ++} t_FmPcdManipReassemCapwapStats; ++ ++/**************************************************************************//** ++ @Description Structure for retrieving CAPWAP fragmentation statistics ++*//***************************************************************************/ ++typedef struct t_FmPcdManipFragCapwapStats { ++ uint32_t totalFrames; /**< Number of frames that passed through the manipulation node */ ++ uint32_t fragmentedFrames; /**< Number of frames that were fragmented */ ++ uint32_t generatedFragments; /**< Number of fragments that were generated */ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ uint8_t sgAllocationFailure; /**< Number of allocation failure of s/g buffers */ ++#endif /* (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) */ ++} t_FmPcdManipFragCapwapStats; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Description Structure for retrieving reassembly statistics ++*//***************************************************************************/ ++typedef struct t_FmPcdManipReassemStats { ++ union { ++ t_FmPcdManipReassemIpStats ipReassem; /**< Structure for IP reassembly statistics */ ++#if (DPAA_VERSION >= 11) ++ t_FmPcdManipReassemCapwapStats capwapReassem; /**< Structure for CAPWAP reassembly statistics */ ++#endif /* (DPAA_VERSION >= 11) */ ++ } u; ++} t_FmPcdManipReassemStats; ++ ++/**************************************************************************//** ++ @Description Structure for retrieving fragmentation statistics ++*//***************************************************************************/ ++typedef struct t_FmPcdManipFragStats { ++ union { ++ t_FmPcdManipFragIpStats ipFrag; /**< Structure for IP fragmentation statistics */ ++#if (DPAA_VERSION >= 11) ++ t_FmPcdManipFragCapwapStats capwapFrag; /**< Structure for CAPWAP fragmentation statistics */ ++#endif /* (DPAA_VERSION >= 11) */ ++ } u; ++} t_FmPcdManipFragStats; ++ ++/**************************************************************************//** ++ @Description Structure for selecting manipulation statistics ++*//***************************************************************************/ ++typedef struct t_FmPcdManipStats { ++ union { ++ t_FmPcdManipReassemStats reassem; /**< Structure for reassembly statistics */ ++ t_FmPcdManipFragStats frag; /**< Structure for fragmentation statistics */ ++ } u; ++} t_FmPcdManipStats; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description Parameters for defining frame replicator group and its members ++*//***************************************************************************/ ++typedef struct t_FmPcdFrmReplicGroupParams { ++ uint8_t maxNumOfEntries; /**< Maximal number of members in the group; ++ Must be at least 2. */ ++ uint8_t numOfEntries; /**< Number of members in the group; ++ Must be at least 1. */ ++ t_FmPcdCcNextEngineParams nextEngineParams[FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES]; ++ /**< Array of members' parameters */ ++} t_FmPcdFrmReplicGroupParams; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++#if ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++/**************************************************************************//** ++ @Description structure for defining statistics node ++*//***************************************************************************/ ++typedef struct t_FmPcdStatsParams { ++ e_FmPcdStatsType type; /**< type of statistics node */ ++} t_FmPcdStatsParams; ++#endif /* ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) */ ++ ++/**************************************************************************//** ++ @Function FM_PCD_NetEnvCharacteristicsSet ++ ++ @Description Define a set of Network Environment Characteristics. ++ ++ When setting an environment it is important to understand its ++ application. It is not meant to describe the flows that will run ++ on the ports using this environment, but what the user means TO DO ++ with the PCD mechanisms in order to parse-classify-distribute those ++ frames. ++ By specifying a distinction unit, the user means it would use that option ++ for distinction between frames at either a KeyGen scheme or a coarse ++ classification action descriptor. Using interchangeable headers to define a ++ unit means that the user is indifferent to which of the interchangeable ++ headers is present in the frame, and wants the distinction to be based ++ on the presence of either one of them. ++ ++ Depending on context, there are limitations to the use of environments. A ++ port using the PCD functionality is bound to an environment. Some or even ++ all ports may share an environment but also an environment per port is ++ possible. When initializing a scheme, a classification plan group (see below), ++ or a coarse classification tree, one of the initialized environments must be ++ stated and related to. When a port is bound to a scheme, a classification ++ plan group, or a coarse classification tree, it MUST be bound to the same ++ environment. ++ ++ The different PCD modules, may relate (for flows definition) ONLY on ++ distinction units as defined by their environment. When initializing a ++ scheme for example, it may not choose to select IPV4 as a match for ++ recognizing flows unless it was defined in the relating environment. In ++ fact, to guide the user through the configuration of the PCD, each module's ++ characterization in terms of flows is not done using protocol names, but using ++ environment indexes. ++ ++ In terms of HW implementation, the list of distinction units sets the LCV vectors ++ and later used for match vector, classification plan vectors and coarse classification ++ indexing. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] p_NetEnvParams A structure of parameters for the initialization of ++ the network environment. ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_NetEnvCharacteristicsSet(t_Handle h_FmPcd, t_FmPcdNetEnvParams *p_NetEnvParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_NetEnvCharacteristicsDelete ++ ++ @Description Deletes a set of Network Environment Characteristics. ++ ++ @Param[in] h_NetEnv A handle to the Network environment. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PCD_NetEnvCharacteristicsDelete(t_Handle h_NetEnv); ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgSchemeSet ++ ++ @Description Initializing or modifying and enabling a scheme for the KeyGen. ++ This routine should be called for adding or modifying a scheme. ++ When a scheme needs modifying, the API requires that it will be ++ rewritten. In such a case 'modify' should be TRUE. If the ++ routine is called for a valid scheme and 'modify' is FALSE, ++ it will return error. ++ ++ @Param[in] h_FmPcd If this is a new scheme - A handle to an FM PCD Module. ++ Otherwise NULL (ignored by driver). ++ @Param[in,out] p_SchemeParams A structure of parameters for defining the scheme ++ ++ @Return A handle to the initialized scheme on success; NULL code otherwise. ++ When used as "modify" (rather than for setting a new scheme), ++ p_SchemeParams->id.h_Scheme will return NULL if action fails due to scheme ++ BUSY state. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_KgSchemeSet(t_Handle h_FmPcd, ++ t_FmPcdKgSchemeParams *p_SchemeParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgSchemeDelete ++ ++ @Description Deleting an initialized scheme. ++ ++ @Param[in] h_Scheme scheme handle as returned by FM_PCD_KgSchemeSet() ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init() & FM_PCD_KgSchemeSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_KgSchemeDelete(t_Handle h_Scheme); ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgSchemeGetCounter ++ ++ @Description Reads scheme packet counter. ++ ++ @Param[in] h_Scheme scheme handle as returned by FM_PCD_KgSchemeSet(). ++ ++ @Return Counter's current value. ++ ++ @Cautions Allowed only following FM_PCD_Init() & FM_PCD_KgSchemeSet(). ++*//***************************************************************************/ ++uint32_t FM_PCD_KgSchemeGetCounter(t_Handle h_Scheme); ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgSchemeSetCounter ++ ++ @Description Writes scheme packet counter. ++ ++ @Param[in] h_Scheme scheme handle as returned by FM_PCD_KgSchemeSet(). ++ @Param[in] value New scheme counter value - typically '0' for ++ resetting the counter. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init() & FM_PCD_KgSchemeSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_KgSchemeSetCounter(t_Handle h_Scheme, uint32_t value); ++ ++/**************************************************************************//** ++ @Function FM_PCD_PlcrProfileSet ++ ++ @Description Sets a profile entry in the policer profile table. ++ The routine overrides any existing value. ++ ++ @Param[in] h_FmPcd A handle to an FM PCD Module. ++ @Param[in] p_Profile A structure of parameters for defining a ++ policer profile entry. ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ When used as "modify" (rather than for setting a new profile), ++ p_Profile->id.h_Profile will return NULL if action fails due to profile ++ BUSY state. ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_PlcrProfileSet(t_Handle h_FmPcd, ++ t_FmPcdPlcrProfileParams *p_Profile); ++ ++/**************************************************************************//** ++ @Function FM_PCD_PlcrProfileDelete ++ ++ @Description Delete a profile entry in the policer profile table. ++ The routine set entry to invalid. ++ ++ @Param[in] h_Profile A handle to the profile. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Error FM_PCD_PlcrProfileDelete(t_Handle h_Profile); ++ ++/**************************************************************************//** ++ @Function FM_PCD_PlcrProfileGetCounter ++ ++ @Description Sets an entry in the classification plan. ++ The routine overrides any existing value. ++ ++ @Param[in] h_Profile A handle to the profile. ++ @Param[in] counter Counter selector. ++ ++ @Return specific counter value. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++uint32_t FM_PCD_PlcrProfileGetCounter(t_Handle h_Profile, ++ e_FmPcdPlcrProfileCounters counter); ++ ++/**************************************************************************//** ++ @Function FM_PCD_PlcrProfileSetCounter ++ ++ @Description Sets an entry in the classification plan. ++ The routine overrides any existing value. ++ ++ @Param[in] h_Profile A handle to the profile. ++ @Param[in] counter Counter selector. ++ @Param[in] value value to set counter with. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Error FM_PCD_PlcrProfileSetCounter(t_Handle h_Profile, ++ e_FmPcdPlcrProfileCounters counter, ++ uint32_t value); ++ ++/**************************************************************************//** ++ @Function FM_PCD_CcRootBuild ++ ++ @Description This routine must be called to define a complete coarse ++ classification tree. This is the way to define coarse ++ classification to a certain flow - the KeyGen schemes ++ may point only to trees defined in this way. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] p_Params A structure of parameters to define the tree. ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_CcRootBuild (t_Handle h_FmPcd, ++ t_FmPcdCcTreeParams *p_Params); ++ ++/**************************************************************************//** ++ @Function FM_PCD_CcRootDelete ++ ++ @Description Deleting an built tree. ++ ++ @Param[in] h_CcTree A handle to a CC tree. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Error FM_PCD_CcRootDelete(t_Handle h_CcTree); ++ ++/**************************************************************************//** ++ @Function FM_PCD_CcRootModifyNextEngine ++ ++ @Description Modify the Next Engine Parameters in the entry of the tree. ++ ++ @Param[in] h_CcTree A handle to the tree ++ @Param[in] grpId A Group index in the tree ++ @Param[in] index Entry index in the group defined by grpId ++ @Param[in] p_FmPcdCcNextEngineParams Pointer to new next engine parameters ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_CcBuildTree(). ++*//***************************************************************************/ ++t_Error FM_PCD_CcRootModifyNextEngine(t_Handle h_CcTree, ++ uint8_t grpId, ++ uint8_t index, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableSet ++ ++ @Description This routine should be called for each CC (coarse classification) ++ node. The whole CC tree should be built bottom up so that each ++ node points to already defined nodes. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] p_Param A structure of parameters defining the CC node ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_Param); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableDelete ++ ++ @Description Deleting an built node. ++ ++ @Param[in] h_CcNode A handle to a CC node. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableDelete(t_Handle h_CcNode); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableModifyMissNextEngine ++ ++ @Description Modify the Next Engine Parameters of the Miss key case of the node. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] p_FmPcdCcNextEngineParams Parameters for defining next engine ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(); ++ Not relevant in the case the node is of type 'INDEXED_LOOKUP'. ++ When configuring nextEngine = e_FM_PCD_CC, note that ++ p_FmPcdCcNextEngineParams->ccParams.h_CcNode must be different ++ from the currently changed table. ++ ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableModifyMissNextEngine(t_Handle h_CcNode, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableRemoveKey ++ ++ @Description Remove the key (including next engine parameters of this key) ++ defined by the index of the relevant node. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keyIndex Key index for removing ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this ++ node and the nodes that lead to it. ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableRemoveKey(t_Handle h_CcNode, uint16_t keyIndex); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableAddKey ++ ++ @Description Add the key (including next engine parameters of this key in the ++ index defined by the keyIndex. Note that 'FM_PCD_LAST_KEY_INDEX' ++ may be used by user that don't care about the position of the ++ key in the table - in that case, the key will be automatically ++ added by the driver in the last available entry. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keyIndex Key index for adding. ++ @Param[in] keySize Key size of added key ++ @Param[in] p_KeyParams A pointer to the parameters includes ++ new key with Next Engine Parameters ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this ++ node and the nodes that lead to it. ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableAddKey(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ uint8_t keySize, ++ t_FmPcdCcKeyParams *p_KeyParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableModifyNextEngine ++ ++ @Description Modify the Next Engine Parameters in the relevant key entry of the node. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keyIndex Key index for Next Engine modifications ++ @Param[in] p_FmPcdCcNextEngineParams Parameters for defining next engine ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(). ++ When configuring nextEngine = e_FM_PCD_CC, note that ++ p_FmPcdCcNextEngineParams->ccParams.h_CcNode must be different ++ from the currently changed table. ++ ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableModifyNextEngine(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableModifyKeyAndNextEngine ++ ++ @Description Modify the key and Next Engine Parameters of this key in the ++ index defined by the keyIndex. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keyIndex Key index for adding ++ @Param[in] keySize Key size of added key ++ @Param[in] p_KeyParams A pointer to the parameters includes ++ modified key and modified Next Engine Parameters ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this ++ node and the nodes that lead to it. ++ When configuring nextEngine = e_FM_PCD_CC, note that ++ p_FmPcdCcNextEngineParams->ccParams.h_CcNode must be different ++ from the currently changed table. ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableModifyKeyAndNextEngine(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ uint8_t keySize, ++ t_FmPcdCcKeyParams *p_KeyParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableModifyKey ++ ++ @Description Modify the key in the index defined by the keyIndex. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keyIndex Key index for adding ++ @Param[in] keySize Key size of added key ++ @Param[in] p_Key A pointer to the new key ++ @Param[in] p_Mask A pointer to the new mask if relevant, ++ otherwise pointer to NULL ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this ++ node and the nodes that lead to it. ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableModifyKey(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableFindNRemoveKey ++ ++ @Description Remove the key (including next engine parameters of this key) ++ defined by the key and mask. Note that this routine will search ++ the node to locate the index of the required key (& mask) to remove. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keySize Key size of the one to remove. ++ @Param[in] p_Key A pointer to the requested key to remove. ++ @Param[in] p_Mask A pointer to the mask if relevant, ++ otherwise pointer to NULL ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this ++ node and the nodes that lead to it. ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableFindNRemoveKey(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableFindNModifyNextEngine ++ ++ @Description Modify the Next Engine Parameters in the relevant key entry of ++ the node. Note that this routine will search the node to locate ++ the index of the required key (& mask) to modify. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keySize Key size of the one to modify. ++ @Param[in] p_Key A pointer to the requested key to modify. ++ @Param[in] p_Mask A pointer to the mask if relevant, ++ otherwise pointer to NULL ++ @Param[in] p_FmPcdCcNextEngineParams Parameters for defining next engine ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(). ++ When configuring nextEngine = e_FM_PCD_CC, note that ++ p_FmPcdCcNextEngineParams->ccParams.h_CcNode must be different ++ from the currently changed table. ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableFindNModifyNextEngine(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableFindNModifyKeyAndNextEngine ++ ++ @Description Modify the key and Next Engine Parameters of this key in the ++ index defined by the keyIndex. Note that this routine will search ++ the node to locate the index of the required key (& mask) to modify. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keySize Key size of the one to modify. ++ @Param[in] p_Key A pointer to the requested key to modify. ++ @Param[in] p_Mask A pointer to the mask if relevant, ++ otherwise pointer to NULL ++ @Param[in] p_KeyParams A pointer to the parameters includes ++ modified key and modified Next Engine Parameters ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this ++ node and the nodes that lead to it. ++ When configuring nextEngine = e_FM_PCD_CC, note that ++ p_FmPcdCcNextEngineParams->ccParams.h_CcNode must be different ++ from the currently changed table. ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableFindNModifyKeyAndNextEngine(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask, ++ t_FmPcdCcKeyParams *p_KeyParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableFindNModifyKey ++ ++ @Description Modify the key in the index defined by the keyIndex. Note that ++ this routine will search the node to locate the index of the ++ required key (& mask) to modify. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keySize Key size of the one to modify. ++ @Param[in] p_Key A pointer to the requested key to modify. ++ @Param[in] p_Mask A pointer to the mask if relevant, ++ otherwise pointer to NULL ++ @Param[in] p_NewKey A pointer to the new key ++ @Param[in] p_NewMask A pointer to the new mask if relevant, ++ otherwise pointer to NULL ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this ++ node and the nodes that lead to it. ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableFindNModifyKey(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask, ++ uint8_t *p_NewKey, ++ uint8_t *p_NewMask); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableGetKeyCounter ++ ++ @Description This routine may be used to get a counter of specific key in a CC ++ Node; This counter reflects how many frames passed that were matched ++ this key. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keyIndex Key index for adding ++ ++ @Return The specific key counter. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(). ++*//***************************************************************************/ ++uint32_t FM_PCD_MatchTableGetKeyCounter(t_Handle h_CcNode, uint16_t keyIndex); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableGetKeyStatistics ++ ++ @Description This routine may be used to get statistics counters of specific key ++ in a CC Node. ++ ++ If 'e_FM_PCD_CC_STATS_MODE_FRAME' and ++ 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, ++ these counters reflect how many frames passed that were matched ++ this key; The total frames count will be returned in the counter ++ of the first range (as only one frame length range was defined). ++ If 'e_FM_PCD_CC_STATS_MODE_RMON' was set for this node, the total ++ frame count will be separated to frame length counters, based on ++ provided frame length ranges. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keyIndex Key index for adding ++ @Param[out] p_KeyStatistics Key statistics counters ++ ++ @Return The specific key statistics. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableGetKeyStatistics(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ t_FmPcdCcKeyStatistics *p_KeyStatistics); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableGetMissStatistics ++ ++ @Description This routine may be used to get statistics counters of miss entry ++ in a CC Node. ++ ++ If 'e_FM_PCD_CC_STATS_MODE_FRAME' and ++ 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, ++ these counters reflect how many frames were not matched to any ++ existing key and therefore passed through the miss entry; The ++ total frames count will be returned in the counter of the ++ first range (as only one frame length range was defined). ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[out] p_MissStatistics Statistics counters for 'miss' ++ ++ @Return The statistics for 'miss'. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableGetMissStatistics(t_Handle h_CcNode, ++ t_FmPcdCcKeyStatistics *p_MissStatistics); ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableFindNGetKeyStatistics ++ ++ @Description This routine may be used to get statistics counters of specific key ++ in a CC Node. ++ ++ If 'e_FM_PCD_CC_STATS_MODE_FRAME' and ++ 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, ++ these counters reflect how many frames passed that were matched ++ this key; The total frames count will be returned in the counter ++ of the first range (as only one frame length range was defined). ++ If 'e_FM_PCD_CC_STATS_MODE_RMON' was set for this node, the total ++ frame count will be separated to frame length counters, based on ++ provided frame length ranges. ++ Note that this routine will search the node to locate the index ++ of the required key based on received key parameters. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keySize Size of the requested key ++ @Param[in] p_Key A pointer to the requested key ++ @Param[in] p_Mask A pointer to the mask if relevant, ++ otherwise pointer to NULL ++ @Param[out] p_KeyStatistics Key statistics counters ++ ++ @Return The specific key statistics. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableFindNGetKeyStatistics(t_Handle h_CcNode, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ uint8_t *p_Mask, ++ t_FmPcdCcKeyStatistics *p_KeyStatistics); ++ ++/**************************************************************************//* ++ @Function FM_PCD_MatchTableGetNextEngine ++ ++ @Description Gets NextEngine of the relevant keyIndex. ++ ++ @Param[in] h_CcNode A handle to the node. ++ @Param[in] keyIndex keyIndex in the relevant node. ++ @Param[out] p_FmPcdCcNextEngineParams here updated nextEngine parameters for ++ the relevant keyIndex of the CC Node ++ received as parameter to this function ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableGetNextEngine(t_Handle h_CcNode, ++ uint16_t keyIndex, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++ ++/**************************************************************************//* ++ @Function FM_PCD_MatchTableGetIndexedHashBucket ++ ++ @Description This routine simulates KeyGen operation on the provided key and ++ calculates to which hash bucket it will be mapped. ++ ++ @Param[in] h_CcNode A handle to the node. ++ @Param[in] kgKeySize Key size as it was configured in the KG ++ scheme that leads to this hash. ++ @Param[in] p_KgKey Pointer to the key; must be like the key ++ that the KG is generated, i.e. the same ++ extraction and with mask if exist. ++ @Param[in] kgHashShift Hash-shift as it was configured in the KG ++ scheme that leads to this hash. ++ @Param[out] p_CcNodeBucketHandle Pointer to the bucket of the provided key. ++ @Param[out] p_BucketIndex Index to the bucket of the provided key ++ @Param[out] p_LastIndex Pointer to last index in the bucket of the ++ provided key. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet() ++*//***************************************************************************/ ++t_Error FM_PCD_MatchTableGetIndexedHashBucket(t_Handle h_CcNode, ++ uint8_t kgKeySize, ++ uint8_t *p_KgKey, ++ uint8_t kgHashShift, ++ t_Handle *p_CcNodeBucketHandle, ++ uint8_t *p_BucketIndex, ++ uint16_t *p_LastIndex); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableSet ++ ++ @Description This routine initializes a hash table structure. ++ KeyGen hash result determines the hash bucket. ++ Next, KeyGen key is compared against all keys of this ++ bucket (exact match). ++ Number of sets (number of buckets) of the hash equals to the ++ number of 1-s in 'hashResMask' in the provided parameters. ++ Number of hash table ways is then calculated by dividing ++ 'maxNumOfKeys' equally between the hash sets. This is the maximal ++ number of keys that a hash bucket may hold. ++ The hash table is initialized empty and keys may be ++ added to it following the initialization. Keys masks are not ++ supported in current hash table implementation. ++ The initialized hash table can be integrated as a node in a ++ CC tree. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] p_Param A structure of parameters defining the hash table ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableDelete ++ ++ @Description This routine deletes the provided hash table and released all ++ its allocated resources. ++ ++ @Param[in] h_HashTbl A handle to a hash table ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_HashTableDelete(t_Handle h_HashTbl); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableAddKey ++ ++ @Description This routine adds the provided key (including next engine ++ parameters of this key) to the hash table. ++ The key is added as the last key of the bucket that it is ++ mapped to. ++ ++ @Param[in] h_HashTbl A handle to a hash table ++ @Param[in] keySize Key size of added key ++ @Param[in] p_KeyParams A pointer to the parameters includes ++ new key with next engine parameters; The pointer ++ to the key mask must be NULL, as masks are not ++ supported in hash table implementation. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_HashTableAddKey(t_Handle h_HashTbl, ++ uint8_t keySize, ++ t_FmPcdCcKeyParams *p_KeyParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableRemoveKey ++ ++ @Description This routine removes the requested key (including next engine ++ parameters of this key) from the hash table. ++ ++ @Param[in] h_HashTbl A handle to a hash table ++ @Param[in] keySize Key size of the one to remove. ++ @Param[in] p_Key A pointer to the requested key to remove. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_HashTableRemoveKey(t_Handle h_HashTbl, ++ uint8_t keySize, ++ uint8_t *p_Key); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableModifyNextEngine ++ ++ @Description This routine modifies the next engine for the provided key. The ++ key should be previously added to the hash table. ++ ++ @Param[in] h_HashTbl A handle to a hash table ++ @Param[in] keySize Key size of the key to modify. ++ @Param[in] p_Key A pointer to the requested key to modify. ++ @Param[in] p_FmPcdCcNextEngineParams A structure for defining new next engine ++ parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++ When configuring nextEngine = e_FM_PCD_CC, note that ++ p_FmPcdCcNextEngineParams->ccParams.h_CcNode must be different ++ from the currently changed table. ++*//***************************************************************************/ ++t_Error FM_PCD_HashTableModifyNextEngine(t_Handle h_HashTbl, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableModifyMissNextEngine ++ ++ @Description This routine modifies the next engine on key match miss. ++ ++ @Param[in] h_HashTbl A handle to a hash table ++ @Param[in] p_FmPcdCcNextEngineParams A structure for defining new next engine ++ parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++ When configuring nextEngine = e_FM_PCD_CC, note that ++ p_FmPcdCcNextEngineParams->ccParams.h_CcNode must be different ++ from the currently changed table. ++*//***************************************************************************/ ++t_Error FM_PCD_HashTableModifyMissNextEngine(t_Handle h_HashTbl, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++ ++/**************************************************************************//* ++ @Function FM_PCD_HashTableGetMissNextEngine ++ ++ @Description Gets NextEngine in case of key match miss. ++ ++ @Param[in] h_HashTbl A handle to a hash table ++ @Param[out] p_FmPcdCcNextEngineParams Next engine parameters for the specified ++ hash table. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_HashTableGetMissNextEngine(t_Handle h_HashTbl, ++ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableFindNGetKeyStatistics ++ ++ @Description This routine may be used to get statistics counters of specific key ++ in a hash table. ++ ++ If 'e_FM_PCD_CC_STATS_MODE_FRAME' and ++ 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, ++ these counters reflect how many frames passed that were matched ++ this key; The total frames count will be returned in the counter ++ of the first range (as only one frame length range was defined). ++ If 'e_FM_PCD_CC_STATS_MODE_RMON' was set for this node, the total ++ frame count will be separated to frame length counters, based on ++ provided frame length ranges. ++ Note that this routine will identify the bucket of this key in ++ the hash table and will search the bucket to locate the index ++ of the required key based on received key parameters. ++ ++ @Param[in] h_HashTbl A handle to a hash table ++ @Param[in] keySize Size of the requested key ++ @Param[in] p_Key A pointer to the requested key ++ @Param[out] p_KeyStatistics Key statistics counters ++ ++ @Return The specific key statistics. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_HashTableFindNGetKeyStatistics(t_Handle h_HashTbl, ++ uint8_t keySize, ++ uint8_t *p_Key, ++ t_FmPcdCcKeyStatistics *p_KeyStatistics); ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableGetMissStatistics ++ ++ @Description This routine may be used to get statistics counters of 'miss' ++ entry of the a hash table. ++ ++ If 'e_FM_PCD_CC_STATS_MODE_FRAME' and ++ 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, ++ these counters reflect how many frames were not matched to any ++ existing key and therefore passed through the miss entry; ++ ++ @Param[in] h_HashTbl A handle to a hash table ++ @Param[out] p_MissStatistics Statistics counters for 'miss' ++ ++ @Return The statistics for 'miss'. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_HashTableGetMissStatistics(t_Handle h_HashTbl, ++ t_FmPcdCcKeyStatistics *p_MissStatistics); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ManipNodeSet ++ ++ @Description This routine should be called for defining a manipulation ++ node. A manipulation node must be defined before the CC node ++ that precedes it. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] p_FmPcdManipParams A structure of parameters defining the manipulation ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_ManipNodeSet(t_Handle h_FmPcd, t_FmPcdManipParams *p_FmPcdManipParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ManipNodeDelete ++ ++ @Description Delete an existing manipulation node. ++ ++ @Param[in] h_ManipNode A handle to a manipulation node. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_ManipNodeSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_ManipNodeDelete(t_Handle h_ManipNode); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ManipGetStatistics ++ ++ @Description Retrieve the manipulation statistics. ++ ++ @Param[in] h_ManipNode A handle to a manipulation node. ++ @Param[out] p_FmPcdManipStats A structure for retrieving the manipulation statistics ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_ManipNodeSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_ManipGetStatistics(t_Handle h_ManipNode, t_FmPcdManipStats *p_FmPcdManipStats); ++ ++/**************************************************************************//** ++ @Function FM_PCD_ManipNodeReplace ++ ++ @Description Change existing manipulation node to be according to new requirement. ++ ++ @Param[in] h_ManipNode A handle to a manipulation node. ++ @Param[out] p_ManipParams A structure of parameters defining the change requirement ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_ManipNodeSet(). ++*//***************************************************************************/ ++t_Error FM_PCD_ManipNodeReplace(t_Handle h_ManipNode, t_FmPcdManipParams *p_ManipParams); ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Function FM_PCD_FrmReplicSetGroup ++ ++ @Description Initialize a Frame Replicator group. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] p_FrmReplicGroupParam A structure of parameters for the initialization of ++ the frame replicator group. ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_FrmReplicSetGroup(t_Handle h_FmPcd, t_FmPcdFrmReplicGroupParams *p_FrmReplicGroupParam); ++ ++/**************************************************************************//** ++ @Function FM_PCD_FrmReplicDeleteGroup ++ ++ @Description Delete a Frame Replicator group. ++ ++ @Param[in] h_FrmReplicGroup A handle to the frame replicator group. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_FrmReplicSetGroup(). ++*//***************************************************************************/ ++t_Error FM_PCD_FrmReplicDeleteGroup(t_Handle h_FrmReplicGroup); ++ ++/**************************************************************************//** ++ @Function FM_PCD_FrmReplicAddMember ++ ++ @Description Add the member in the index defined by the memberIndex. ++ ++ @Param[in] h_FrmReplicGroup A handle to the frame replicator group. ++ @Param[in] memberIndex member index for adding. ++ @Param[in] p_MemberParams A pointer to the new member parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_FrmReplicSetGroup() of this group. ++*//***************************************************************************/ ++t_Error FM_PCD_FrmReplicAddMember(t_Handle h_FrmReplicGroup, ++ uint16_t memberIndex, ++ t_FmPcdCcNextEngineParams *p_MemberParams); ++ ++/**************************************************************************//** ++ @Function FM_PCD_FrmReplicRemoveMember ++ ++ @Description Remove the member defined by the index from the relevant group. ++ ++ @Param[in] h_FrmReplicGroup A handle to the frame replicator group. ++ @Param[in] memberIndex member index for removing. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_FrmReplicSetGroup() of this group. ++*//***************************************************************************/ ++t_Error FM_PCD_FrmReplicRemoveMember(t_Handle h_FrmReplicGroup, ++ uint16_t memberIndex); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++#if ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++/**************************************************************************//** ++ @Function FM_PCD_StatisticsSetNode ++ ++ @Description This routine should be called for defining a statistics node. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] p_FmPcdstatsParams A structure of parameters defining the statistics ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++t_Handle FM_PCD_StatisticsSetNode(t_Handle h_FmPcd, t_FmPcdStatsParams *p_FmPcdstatsParams); ++#endif /* ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) */ ++ ++/** @} */ /* end of FM_PCD_Runtime_build_grp group */ ++/** @} */ /* end of FM_PCD_Runtime_grp group */ ++/** @} */ /* end of FM_PCD_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++#ifdef NCSW_BACKWARD_COMPATIBLE_API ++#define FM_PCD_MAX_NUM_OF_INTERCHANGABLE_HDRS FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS ++#define e_FM_PCD_MANIP_ONE_WAYS_HASH e_FM_PCD_MANIP_ONE_WAY_HASH ++#define e_FM_PCD_MANIP_TOW_WAYS_HASH e_FM_PCD_MANIP_TWO_WAYS_HASH ++ ++#define e_FM_PCD_MANIP_FRAGMENT_PACKECT e_FM_PCD_MANIP_FRAGMENT_PACKET /* Feb13 */ ++ ++#define FM_PCD_SetNetEnvCharacteristics(_pcd, _params) \ ++ FM_PCD_NetEnvCharacteristicsSet(_pcd, _params) ++#define FM_PCD_KgSetScheme(_pcd, _params) FM_PCD_KgSchemeSet(_pcd, _params) ++#define FM_PCD_CcBuildTree(_pcd, _params) FM_PCD_CcRootBuild(_pcd, _params) ++#define FM_PCD_CcSetNode(_pcd, _params) FM_PCD_MatchTableSet(_pcd, _params) ++#define FM_PCD_PlcrSetProfile(_pcd, _params) FM_PCD_PlcrProfileSet(_pcd, _params) ++#define FM_PCD_ManipSetNode(_pcd, _params) FM_PCD_ManipNodeSet(_pcd, _params) ++ ++#define FM_PCD_DeleteNetEnvCharacteristics(_pcd, ...) \ ++ FM_PCD_NetEnvCharacteristicsDelete(__VA_ARGS__) ++#define FM_PCD_KgDeleteScheme(_pcd, ...) \ ++ FM_PCD_KgSchemeDelete(__VA_ARGS__) ++#define FM_PCD_KgGetSchemeCounter(_pcd, ...) \ ++ FM_PCD_KgSchemeGetCounter(__VA_ARGS__) ++#define FM_PCD_KgSetSchemeCounter(_pcd, ...) \ ++ FM_PCD_KgSchemeSetCounter(__VA_ARGS__) ++#define FM_PCD_PlcrDeleteProfile(_pcd, ...) \ ++ FM_PCD_PlcrProfileDelete(__VA_ARGS__) ++#define FM_PCD_PlcrGetProfileCounter(_pcd, ...) \ ++ FM_PCD_PlcrProfileGetCounter(__VA_ARGS__) ++#define FM_PCD_PlcrSetProfileCounter(_pcd, ...) \ ++ FM_PCD_PlcrProfileSetCounter(__VA_ARGS__) ++#define FM_PCD_CcDeleteTree(_pcd, ...) \ ++ FM_PCD_CcRootDelete(__VA_ARGS__) ++#define FM_PCD_CcTreeModifyNextEngine(_pcd, ...) \ ++ FM_PCD_CcRootModifyNextEngine(__VA_ARGS__) ++#define FM_PCD_CcDeleteNode(_pcd, ...) \ ++ FM_PCD_MatchTableDelete(__VA_ARGS__) ++#define FM_PCD_CcNodeModifyMissNextEngine(_pcd, ...) \ ++ FM_PCD_MatchTableModifyMissNextEngine(__VA_ARGS__) ++#define FM_PCD_CcNodeRemoveKey(_pcd, ...) \ ++ FM_PCD_MatchTableRemoveKey(__VA_ARGS__) ++#define FM_PCD_CcNodeAddKey(_pcd, ...) \ ++ FM_PCD_MatchTableAddKey(__VA_ARGS__) ++#define FM_PCD_CcNodeModifyNextEngine(_pcd, ...) \ ++ FM_PCD_MatchTableModifyNextEngine(__VA_ARGS__) ++#define FM_PCD_CcNodeModifyKeyAndNextEngine(_pcd, ...) \ ++ FM_PCD_MatchTableModifyKeyAndNextEngine(__VA_ARGS__) ++#define FM_PCD_CcNodeModifyKey(_pcd, ...) \ ++ FM_PCD_MatchTableModifyKey(__VA_ARGS__) ++#define FM_PCD_CcNodeFindNRemoveKey(_pcd, ...) \ ++ FM_PCD_MatchTableFindNRemoveKey(__VA_ARGS__) ++#define FM_PCD_CcNodeFindNModifyNextEngine(_pcd, ...) \ ++ FM_PCD_MatchTableFindNModifyNextEngine(__VA_ARGS__) ++#define FM_PCD_CcNodeFindNModifyKeyAndNextEngine(_pcd, ...) \ ++ FM_PCD_MatchTableFindNModifyKeyAndNextEngine(__VA_ARGS__) ++#define FM_PCD_CcNodeFindNModifyKey(_pcd, ...) \ ++ FM_PCD_MatchTableFindNModifyKey(__VA_ARGS__) ++#define FM_PCD_CcIndexedHashNodeGetBucket(_pcd, ...) \ ++ FM_PCD_MatchTableGetIndexedHashBucket(__VA_ARGS__) ++#define FM_PCD_CcNodeGetNextEngine(_pcd, ...) \ ++ FM_PCD_MatchTableGetNextEngine(__VA_ARGS__) ++#define FM_PCD_CcNodeGetKeyCounter(_pcd, ...) \ ++ FM_PCD_MatchTableGetKeyCounter(__VA_ARGS__) ++#define FM_PCD_ManipDeleteNode(_pcd, ...) \ ++ FM_PCD_ManipNodeDelete(__VA_ARGS__) ++#endif /* NCSW_BACKWARD_COMPATIBLE_API */ ++ ++ ++#endif /* __FM_PCD_EXT */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_port_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_port_ext.h +new file mode 100644 +index 0000000..08a5aa5 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_port_ext.h +@@ -0,0 +1,2608 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File fm_port_ext.h ++ ++ @Description FM-Port Application Programming Interface. ++*//***************************************************************************/ ++#ifndef __FM_PORT_EXT ++#define __FM_PORT_EXT ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "fm_pcd_ext.h" ++#include "fm_ext.h" ++#include "net_ext.h" ++ ++ ++/**************************************************************************//** ++ ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_PORT_grp FM Port ++ ++ @Description FM Port API ++ ++ The FM uses a general module called "port" to represent a Tx port ++ (MAC), an Rx port (MAC) or Offline Parsing port. ++ The number of ports in an FM varies between SOCs. ++ The SW driver manages these ports as sub-modules of the FM, i.e. ++ after an FM is initialized, its ports may be initialized and ++ operated upon. ++ ++ The port is initialized aware of its type, but other functions on ++ a port may be indifferent to its type. When necessary, the driver ++ verifies coherence and returns error if applicable. ++ ++ On initialization, user specifies the port type and it's index ++ (relative to the port's type) - always starting at 0. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description An enum for defining port PCD modes. ++ This enum defines the superset of PCD engines support - i.e. not ++ all engines have to be used, but all have to be enabled. The real ++ flow of a specific frame depends on the PCD configuration and the ++ frame headers and payload. ++ Note: the first engine and the first engine after the parser (if ++ exists) should be in order, the order is important as it will ++ define the flow of the port. However, as for the rest engines ++ (the ones that follows), the order is not important anymore as ++ it is defined by the PCD graph itself. ++*//***************************************************************************/ ++typedef enum e_FmPortPcdSupport { ++ e_FM_PORT_PCD_SUPPORT_NONE = 0 /**< BMI to BMI, PCD is not used */ ++ , e_FM_PORT_PCD_SUPPORT_PRS_ONLY /**< Use only Parser */ ++ , e_FM_PORT_PCD_SUPPORT_PLCR_ONLY /**< Use only Policer */ ++ , e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR /**< Use Parser and Policer */ ++ , e_FM_PORT_PCD_SUPPORT_PRS_AND_KG /**< Use Parser and Keygen */ ++ , e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC /**< Use Parser, Keygen and Coarse Classification */ ++ , e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR ++ /**< Use all PCD engines */ ++ , e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR /**< Use Parser, Keygen and Policer */ ++ , e_FM_PORT_PCD_SUPPORT_PRS_AND_CC /**< Use Parser and Coarse Classification */ ++ , e_FM_PORT_PCD_SUPPORT_PRS_AND_CC_AND_PLCR /**< Use Parser and Coarse Classification and Policer */ ++ , e_FM_PORT_PCD_SUPPORT_CC_ONLY /**< Use only Coarse Classification */ ++#ifdef FM_CAPWAP_SUPPORT ++ , e_FM_PORT_PCD_SUPPORT_CC_AND_KG /**< Use Coarse Classification,and Keygen */ ++ , e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR /**< Use Coarse Classification, Keygen and Policer */ ++#endif /* FM_CAPWAP_SUPPORT */ ++} e_FmPortPcdSupport; ++ ++/**************************************************************************//** ++ @Description Port interrupts ++*//***************************************************************************/ ++typedef enum e_FmPortExceptions { ++ e_FM_PORT_EXCEPTION_IM_BUSY /**< Independent-Mode Rx-BUSY */ ++} e_FmPortExceptions; ++ ++ ++/**************************************************************************//** ++ @Collection General FM Port defines ++*//***************************************************************************/ ++#define FM_PORT_PRS_RESULT_NUM_OF_WORDS 8 /**< Number of 4 bytes words in parser result */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection FM Frame error ++*//***************************************************************************/ ++typedef uint32_t fmPortFrameErrSelect_t; /**< typedef for defining Frame Descriptor errors */ ++ ++#define FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT FM_FD_ERR_UNSUPPORTED_FORMAT /**< Not for Rx-Port! Unsupported Format */ ++#define FM_PORT_FRM_ERR_LENGTH FM_FD_ERR_LENGTH /**< Not for Rx-Port! Length Error */ ++#define FM_PORT_FRM_ERR_DMA FM_FD_ERR_DMA /**< DMA Data error */ ++#define FM_PORT_FRM_ERR_NON_FM FM_FD_RX_STATUS_ERR_NON_FM /**< non Frame-Manager error; probably come from SEC that ++ was chained to FM */ ++ ++#define FM_PORT_FRM_ERR_IPRE (FM_FD_ERR_IPR & ~FM_FD_IPR) /**< IPR error */ ++#define FM_PORT_FRM_ERR_IPR_NCSP (FM_FD_ERR_IPR_NCSP & ~FM_FD_IPR) /**< IPR non-consistent-sp */ ++ ++#define FM_PORT_FRM_ERR_IPFE 0 /**< Obsolete; will be removed in the future */ ++ ++#ifdef FM_CAPWAP_SUPPORT ++#define FM_PORT_FRM_ERR_CRE FM_FD_ERR_CRE ++#define FM_PORT_FRM_ERR_CHE FM_FD_ERR_CHE ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++#define FM_PORT_FRM_ERR_PHYSICAL FM_FD_ERR_PHYSICAL /**< Rx FIFO overflow, FCS error, code error, running disparity ++ error (SGMII and TBI modes), FIFO parity error. PHY ++ Sequence error, PHY error control character detected. */ ++#define FM_PORT_FRM_ERR_SIZE FM_FD_ERR_SIZE /**< Frame too long OR Frame size exceeds max_length_frame */ ++#define FM_PORT_FRM_ERR_CLS_DISCARD FM_FD_ERR_CLS_DISCARD /**< indicates a classifier "drop" operation */ ++#define FM_PORT_FRM_ERR_EXTRACTION FM_FD_ERR_EXTRACTION /**< Extract Out of Frame */ ++#define FM_PORT_FRM_ERR_NO_SCHEME FM_FD_ERR_NO_SCHEME /**< No Scheme Selected */ ++#define FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW FM_FD_ERR_KEYSIZE_OVERFLOW /**< Keysize Overflow */ ++#define FM_PORT_FRM_ERR_COLOR_RED FM_FD_ERR_COLOR_RED /**< Frame color is red */ ++#define FM_PORT_FRM_ERR_COLOR_YELLOW FM_FD_ERR_COLOR_YELLOW /**< Frame color is yellow */ ++#define FM_PORT_FRM_ERR_ILL_PLCR FM_FD_ERR_ILL_PLCR /**< Illegal Policer Profile selected */ ++#define FM_PORT_FRM_ERR_PLCR_FRAME_LEN FM_FD_ERR_PLCR_FRAME_LEN /**< Policer frame length error */ ++#define FM_PORT_FRM_ERR_PRS_TIMEOUT FM_FD_ERR_PRS_TIMEOUT /**< Parser Time out Exceed */ ++#define FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT FM_FD_ERR_PRS_ILL_INSTRUCT /**< Invalid Soft Parser instruction */ ++#define FM_PORT_FRM_ERR_PRS_HDR_ERR FM_FD_ERR_PRS_HDR_ERR /**< Header error was identified during parsing */ ++#define FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED FM_FD_ERR_BLOCK_LIMIT_EXCEEDED /**< Frame parsed beyind 256 first bytes */ ++#define FM_PORT_FRM_ERR_PROCESS_TIMEOUT 0x00000001 /**< FPM Frame Processing Timeout Exceeded */ ++/* @} */ ++ ++ ++ ++/**************************************************************************//** ++ @Group FM_PORT_init_grp FM Port Initialization Unit ++ ++ @Description FM Port Initialization Unit ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Exceptions user callback routine, will be called upon an ++ exception passing the exception identification. ++ ++ @Param[in] h_App - User's application descriptor. ++ @Param[in] exception - The exception. ++ *//***************************************************************************/ ++typedef void (t_FmPortExceptionCallback) (t_Handle h_App, e_FmPortExceptions exception); ++ ++/**************************************************************************//** ++ @Description User callback function called by driver with received data. ++ ++ User provides this function. Driver invokes it. ++ ++ @Param[in] h_App Application's handle originally specified to ++ the API Config function ++ @Param[in] p_Data A pointer to data received ++ @Param[in] length length of received data ++ @Param[in] status receive status and errors ++ @Param[in] position position of buffer in frame ++ @Param[in] h_BufContext A handle of the user acossiated with this buffer ++ ++ @Retval e_RX_STORE_RESPONSE_CONTINUE - order the driver to continue Rx ++ operation for all ready data. ++ @Retval e_RX_STORE_RESPONSE_PAUSE - order the driver to stop Rx operation. ++*//***************************************************************************/ ++typedef e_RxStoreResponse (t_FmPortImRxStoreCallback) (t_Handle h_App, ++ uint8_t *p_Data, ++ uint16_t length, ++ uint16_t status, ++ uint8_t position, ++ t_Handle h_BufContext); ++ ++/**************************************************************************//** ++ @Description User callback function called by driver when transmit completed. ++ ++ User provides this function. Driver invokes it. ++ ++ @Param[in] h_App Application's handle originally specified to ++ the API Config function ++ @Param[in] p_Data A pointer to data received ++ @Param[in] status transmit status and errors ++ @Param[in] lastBuffer is last buffer in frame ++ @Param[in] h_BufContext A handle of the user acossiated with this buffer ++ *//***************************************************************************/ ++typedef void (t_FmPortImTxConfCallback) (t_Handle h_App, ++ uint8_t *p_Data, ++ uint16_t status, ++ t_Handle h_BufContext); ++ ++/**************************************************************************//** ++ @Description A structure for additional Rx port parameters ++*//***************************************************************************/ ++typedef struct t_FmPortRxParams { ++ uint32_t errFqid; /**< Error Queue Id. */ ++ uint32_t dfltFqid; /**< Default Queue Id. */ ++ uint16_t liodnOffset; /**< Port's LIODN offset. */ ++ t_FmExtPools extBufPools; /**< Which external buffer pools are used ++ (up to FM_PORT_MAX_NUM_OF_EXT_POOLS), and their sizes. */ ++} t_FmPortRxParams; ++ ++/**************************************************************************//** ++ @Description A structure for additional non-Rx port parameters ++*//***************************************************************************/ ++typedef struct t_FmPortNonRxParams { ++ uint32_t errFqid; /**< Error Queue Id. */ ++ uint32_t dfltFqid; /**< For Tx - Default Confirmation queue, ++ 0 means no Tx confirmation for processed ++ frames. For OP port - default Rx queue. */ ++ uint32_t qmChannel; /**< QM-channel dedicated to this port; will be used ++ by the FM for dequeue. */ ++} t_FmPortNonRxParams; ++ ++/**************************************************************************//** ++ @Description A structure for additional Rx port parameters ++*//***************************************************************************/ ++typedef struct t_FmPortImRxTxParams { ++ t_Handle h_FmMuram; /**< A handle of the FM-MURAM partition */ ++ uint16_t liodnOffset; /**< For Rx ports only. Port's LIODN Offset. */ ++ uint8_t dataMemId; /**< Memory partition ID for data buffers */ ++ uint32_t dataMemAttributes; /**< Memory attributes for data buffers */ ++ t_BufferPoolInfo rxPoolParams; /**< For Rx ports only. */ ++ t_FmPortImRxStoreCallback *f_RxStore; /**< For Rx ports only. */ ++ t_FmPortImTxConfCallback *f_TxConf; /**< For Tx ports only. */ ++} t_FmPortImRxTxParams; ++ ++/**************************************************************************//** ++ @Description A union for additional parameters depending on port type ++*//***************************************************************************/ ++typedef union u_FmPortSpecificParams { ++ t_FmPortImRxTxParams imRxTxParams; /**< Rx/Tx Independent-Mode port parameter structure */ ++ t_FmPortRxParams rxParams; /**< Rx port parameters structure */ ++ t_FmPortNonRxParams nonRxParams; /**< Non-Rx port parameters structure */ ++} u_FmPortSpecificParams; ++ ++/**************************************************************************//** ++ @Description A structure representing FM initialization parameters ++*//***************************************************************************/ ++typedef struct t_FmPortParams { ++ uintptr_t baseAddr; /**< Virtual Address of memory mapped FM Port registers.*/ ++ t_Handle h_Fm; /**< A handle to the FM object this port related to */ ++ e_FmPortType portType; /**< Port type */ ++ uint8_t portId; /**< Port Id - relative to type; ++ NOTE: When configuring Offline Parsing port for ++ FMANv3 devices (DPAA_VERSION 11 and higher), ++ it is highly recommended NOT to use portId=0 due to lack ++ of HW resources on portId=0. */ ++ bool independentModeEnable; ++ /**< This port is Independent-Mode - Used for Rx/Tx ports only! */ ++ uint16_t liodnBase; /**< Irrelevant for P4080 rev 1. LIODN base for this port, to be ++ used together with LIODN offset. */ ++ u_FmPortSpecificParams specificParams; /**< Additional parameters depending on port ++ type. */ ++ ++ t_FmPortExceptionCallback *f_Exception; /**< Relevant for IM only Callback routine to be called on BUSY exception */ ++ t_Handle h_App; /**< A handle to an application layer object; This handle will ++ be passed by the driver upon calling the above callbacks */ ++} t_FmPortParams; ++ ++ ++/**************************************************************************//** ++ @Function FM_PORT_Config ++ ++ @Description Creates a descriptor for the FM PORT module. ++ ++ The routine returns a handle (descriptor) to the FM PORT object. ++ This descriptor must be passed as first parameter to all other ++ FM PORT function calls. ++ ++ No actual initialization or configuration of FM hardware is ++ done by this routine. ++ ++ @Param[in] p_FmPortParams - Pointer to data structure of parameters ++ ++ @Retval Handle to FM object, or NULL for Failure. ++*//***************************************************************************/ ++t_Handle FM_PORT_Config(t_FmPortParams *p_FmPortParams); ++ ++/**************************************************************************//** ++ @Function FM_PORT_Init ++ ++ @Description Initializes the FM PORT module by defining the software structure ++ and configuring the hardware registers. ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PORT_Init(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_Free ++ ++ @Description Frees all resources that were assigned to FM PORT module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PORT_Free(t_Handle h_FmPort); ++ ++ ++/**************************************************************************//** ++ @Group FM_PORT_advanced_init_grp FM Port Advanced Configuration Unit ++ ++ @Description Configuration functions used to change default values. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description enum for defining QM frame dequeue ++*//***************************************************************************/ ++typedef enum e_FmPortDeqType { ++ e_FM_PORT_DEQ_TYPE1, /**< Dequeue from the SP channel - with priority precedence, ++ and Intra-Class Scheduling respected. */ ++ e_FM_PORT_DEQ_TYPE2, /**< Dequeue from the SP channel - with active FQ precedence, ++ and Intra-Class Scheduling respected. */ ++ e_FM_PORT_DEQ_TYPE3 /**< Dequeue from the SP channel - with active FQ precedence, ++ and override Intra-Class Scheduling */ ++} e_FmPortDeqType; ++ ++/**************************************************************************//** ++ @Description enum for defining QM frame dequeue ++*//***************************************************************************/ ++typedef enum e_FmPortDeqPrefetchOption { ++ e_FM_PORT_DEQ_NO_PREFETCH, /**< QMI preforms a dequeue action for a single frame ++ only when a dedicated portID Tnum is waiting. */ ++ e_FM_PORT_DEQ_PARTIAL_PREFETCH, /**< QMI preforms a dequeue action for 3 frames when ++ one dedicated portId tnum is waiting. */ ++ e_FM_PORT_DEQ_FULL_PREFETCH /**< QMI preforms a dequeue action for 3 frames when ++ no dedicated portId tnums are waiting. */ ++ ++} e_FmPortDeqPrefetchOption; ++ ++/**************************************************************************//** ++ @Description enum for defining port default color ++*//***************************************************************************/ ++typedef enum e_FmPortColor { ++ e_FM_PORT_COLOR_GREEN, /**< Default port color is green */ ++ e_FM_PORT_COLOR_YELLOW, /**< Default port color is yellow */ ++ e_FM_PORT_COLOR_RED, /**< Default port color is red */ ++ e_FM_PORT_COLOR_OVERRIDE /**< Ignore color */ ++} e_FmPortColor; ++ ++/**************************************************************************//** ++ @Description A structure for defining Dual Tx rate limiting scale ++*//***************************************************************************/ ++typedef enum e_FmPortDualRateLimiterScaleDown { ++ e_FM_PORT_DUAL_RATE_LIMITER_NONE = 0, /**< Use only single rate limiter */ ++ e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_2, /**< Divide high rate limiter by 2 */ ++ e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_4, /**< Divide high rate limiter by 4 */ ++ e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_8 /**< Divide high rate limiter by 8 */ ++} e_FmPortDualRateLimiterScaleDown; ++ ++ ++/**************************************************************************//** ++ @Description A structure for defining FM port resources ++*//***************************************************************************/ ++typedef struct t_FmPortRsrc { ++ uint32_t num; /**< Committed required resource */ ++ uint32_t extra; /**< Extra (not committed) required resource */ ++} t_FmPortRsrc; ++ ++/**************************************************************************//** ++ @Description A structure for defining observed pool depletion ++*//***************************************************************************/ ++typedef struct t_FmPortObservedBufPoolDepletion { ++ t_FmBufPoolDepletion poolDepletionParams;/**< parameters to define pool depletion */ ++ t_FmExtPools poolsParams; /**< Which external buffer pools are observed ++ (up to FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS), ++ and their sizes. */ ++} t_FmPortObservedBufPoolDepletion; ++ ++/**************************************************************************//** ++ @Description A structure for defining Tx rate limiting ++*//***************************************************************************/ ++typedef struct t_FmPortRateLimit { ++ uint16_t maxBurstSize; /**< in KBytes for Tx ports, in frames ++ for OP ports. (note that ++ for early chips burst size is ++ rounded up to a multiply of 1000 frames).*/ ++ uint32_t rateLimit; /**< in Kb/sec for Tx ports, in frame/sec for ++ OP ports. Rate limit refers to ++ data rate (rather than line rate). */ ++ e_FmPortDualRateLimiterScaleDown rateLimitDivider; /**< For OP ports only. Not-valid ++ for some earlier chip revisions */ ++} t_FmPortRateLimit; ++ ++/**************************************************************************//** ++ @Description A structure for defining the parameters of ++ the Rx port performance counters ++*//***************************************************************************/ ++typedef struct t_FmPortPerformanceCnt { ++ uint8_t taskCompVal; /**< Task compare value */ ++ uint8_t queueCompVal; /**< Rx queue/Tx confirm queue compare ++ value (unused for H/O) */ ++ uint8_t dmaCompVal; /**< Dma compare value */ ++ uint32_t fifoCompVal; /**< Fifo compare value (in bytes) */ ++} t_FmPortPerformanceCnt; ++ ++ ++/**************************************************************************//** ++ @Description A structure for defining the sizes of the Deep Sleep ++ the Auto Response tables ++*//***************************************************************************/ ++typedef struct t_FmPortDsarTablesSizes ++{ ++ uint16_t maxNumOfArpEntries; ++ uint16_t maxNumOfEchoIpv4Entries; ++ uint16_t maxNumOfNdpEntries; ++ uint16_t maxNumOfEchoIpv6Entries; ++ uint16_t maxNumOfSnmpIPV4Entries; ++ uint16_t maxNumOfSnmpIPV6Entries; ++ uint16_t maxNumOfSnmpOidEntries; ++ uint16_t maxNumOfSnmpOidChar; /* total amount of character needed for the snmp table */ ++ ++ uint16_t maxNumOfIpProtFiltering; ++ uint16_t maxNumOfTcpPortFiltering; ++ uint16_t maxNumOfUdpPortFiltering; ++} t_FmPortDsarTablesSizes; ++ ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDsarSupport ++ ++ @Description This function will allocate the amount of MURAM needed for ++ this max number of entries for Deep Sleep Auto Response. ++ it will calculate all needed MURAM for autoresponse including ++ necesary common stuff. ++ ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] params A pointer to a structure containing the maximum ++ sizes of the auto response tables ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDsarSupport(t_Handle h_FmPortRx, t_FmPortDsarTablesSizes *params); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigNumOfOpenDmas ++ ++ @Description Calling this routine changes the max number of open DMA's ++ available for this port. It changes this parameter in the ++ internal driver data base from its default configuration ++ [OP: 1] ++ [1G-RX, 1G-TX: 1 (+1)] ++ [10G-RX, 10G-TX: 8 (+8)] ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_OpenDmas A pointer to a structure of parameters defining ++ the open DMA allocation. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigNumOfOpenDmas(t_Handle h_FmPort, t_FmPortRsrc *p_OpenDmas); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigNumOfTasks ++ ++ @Description Calling this routine changes the max number of tasks ++ available for this port. It changes this parameter in the ++ internal driver data base from its default configuration ++ [OP: 1] ++ [1G-RX, 1G-TX: 3 (+2)] ++ [10G-RX, 10G-TX: 16 (+8)] ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_NumOfTasks A pointer to a structure of parameters defining ++ the tasks allocation. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigNumOfTasks(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfTasks); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigSizeOfFifo ++ ++ @Description Calling this routine changes the max FIFO size configured for this port. ++ ++ This function changes the internal driver data base from its ++ default configuration. Please refer to the driver's User Guide for ++ information on default FIFO sizes in the various devices. ++ [OP: 2KB] ++ [1G-RX, 1G-TX: 11KB] ++ [10G-RX, 10G-TX: 12KB] ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_SizeOfFifo A pointer to a structure of parameters defining ++ the FIFO allocation. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigSizeOfFifo(t_Handle h_FmPort, t_FmPortRsrc *p_SizeOfFifo); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDeqHighPriority ++ ++ @Description Calling this routine changes the dequeue priority in the ++ internal driver data base from its default configuration ++ 1G: [DEFAULT_PORT_deqHighPriority_1G] ++ 10G: [DEFAULT_PORT_deqHighPriority_10G] ++ ++ May be used for Non-Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] highPri TRUE to select high priority, FALSE for normal operation. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDeqHighPriority(t_Handle h_FmPort, bool highPri); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDeqType ++ ++ @Description Calling this routine changes the dequeue type parameter in the ++ internal driver data base from its default configuration ++ [DEFAULT_PORT_deqType]. ++ ++ May be used for Non-Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] deqType According to QM definition. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDeqType(t_Handle h_FmPort, e_FmPortDeqType deqType); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDeqPrefetchOption ++ ++ @Description Calling this routine changes the dequeue prefetch option parameter in the ++ internal driver data base from its default configuration ++ [DEFAULT_PORT_deqPrefetchOption] ++ Note: Available for some chips only ++ ++ May be used for Non-Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] deqPrefetchOption New option ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDeqPrefetchOption(t_Handle h_FmPort, e_FmPortDeqPrefetchOption deqPrefetchOption); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDeqByteCnt ++ ++ @Description Calling this routine changes the dequeue byte count parameter in ++ the internal driver data base from its default configuration ++ 1G:[DEFAULT_PORT_deqByteCnt_1G]. ++ 10G:[DEFAULT_PORT_deqByteCnt_10G]. ++ ++ May be used for Non-Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] deqByteCnt New byte count ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDeqByteCnt(t_Handle h_FmPort, uint16_t deqByteCnt); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigBufferPrefixContent ++ ++ @Description Defines the structure, size and content of the application buffer. ++ The prefix will ++ In Tx ports, if 'passPrsResult', the application ++ should set a value to their offsets in the prefix of ++ the FM will save the first 'privDataSize', than, ++ depending on 'passPrsResult' and 'passTimeStamp', copy parse result ++ and timeStamp, and the packet itself (in this order), to the ++ application buffer, and to offset. ++ Calling this routine changes the buffer margins definitions ++ in the internal driver data base from its default ++ configuration: Data size: [DEFAULT_PORT_bufferPrefixContent_privDataSize] ++ Pass Parser result: [DEFAULT_PORT_bufferPrefixContent_passPrsResult]. ++ Pass timestamp: [DEFAULT_PORT_bufferPrefixContent_passTimeStamp]. ++ ++ May be used for all ports ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in,out] p_FmBufferPrefixContent A structure of parameters describing the ++ structure of the buffer. ++ Out parameter: Start margin - offset ++ of data from start of external buffer. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigBufferPrefixContent(t_Handle h_FmPort, ++ t_FmBufferPrefixContent *p_FmBufferPrefixContent); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigCheksumLastBytesIgnore ++ ++ @Description Calling this routine changes the number of checksum bytes to ignore ++ parameter in the internal driver data base from its default configuration ++ [DEFAULT_PORT_cheksumLastBytesIgnore] ++ ++ May be used by Tx & Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] cheksumLastBytesIgnore New value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigCheksumLastBytesIgnore(t_Handle h_FmPort, uint8_t cheksumLastBytesIgnore); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigCutBytesFromEnd ++ ++ @Description Calling this routine changes the number of bytes to cut from a ++ frame's end parameter in the internal driver data base ++ from its default configuration [DEFAULT_PORT_cutBytesFromEnd] ++ Note that if the result of (frame length before chop - cutBytesFromEnd) is ++ less than 14 bytes, the chop operation is not executed. ++ ++ May be used for Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] cutBytesFromEnd New value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigCutBytesFromEnd(t_Handle h_FmPort, uint8_t cutBytesFromEnd); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigPoolDepletion ++ ++ @Description Calling this routine enables pause frame generation depending on the ++ depletion status of BM pools. It also defines the conditions to activate ++ this functionality. By default, this functionality is disabled. ++ ++ May be used for Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_BufPoolDepletion A structure of pool depletion parameters ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigPoolDepletion(t_Handle h_FmPort, t_FmBufPoolDepletion *p_BufPoolDepletion); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigObservedPoolDepletion ++ ++ @Description Calling this routine enables a mechanism to stop port enqueue ++ depending on the depletion status of selected BM pools. ++ It also defines the conditions to activate ++ this functionality. By default, this functionality is disabled. ++ ++ Note: Available for some chips only ++ ++ May be used for OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_FmPortObservedBufPoolDepletion A structure of parameters for pool depletion. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigObservedPoolDepletion(t_Handle h_FmPort, ++ t_FmPortObservedBufPoolDepletion *p_FmPortObservedBufPoolDepletion); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigExtBufPools ++ ++ @Description This routine should be called for OP ports ++ that internally use BM buffer pools. In such cases, e.g. for fragmentation and ++ re-assembly, the FM needs new BM buffers. By calling this routine the user ++ specifies the BM buffer pools that should be used. ++ ++ Note: Available for some chips only ++ ++ May be used for OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_FmExtPools A structure of parameters for the external pools. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigExtBufPools(t_Handle h_FmPort, t_FmExtPools *p_FmExtPools); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigBackupPools ++ ++ @Description Calling this routine allows the configuration of some of the BM pools ++ defined for this port as backup pools. ++ A pool configured to be a backup pool will be used only if all other ++ enabled non-backup pools are depleted. ++ ++ May be used for Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_FmPortBackupBmPools An array of pool id's. All pools specified here will ++ be defined as backup pools. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigBackupPools(t_Handle h_FmPort, t_FmBackupBmPools *p_FmPortBackupBmPools); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigFrmDiscardOverride ++ ++ @Description Calling this routine changes the error frames destination parameter ++ in the internal driver data base from its default configuration: ++ override = [DEFAULT_PORT_frmDiscardOverride] ++ ++ May be used for Rx and OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] override TRUE to override discarding of error frames and ++ enqueueing them to error queue. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigFrmDiscardOverride(t_Handle h_FmPort, bool override); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigErrorsToDiscard ++ ++ @Description Calling this routine changes the behaviour on error parameter ++ in the internal driver data base from its default configuration: ++ [DEFAULT_PORT_errorsToDiscard]. ++ If a requested error was previously defined as "ErrorsToEnqueue" it's ++ definition will change and the frame will be discarded. ++ Errors that were not defined either as "ErrorsToEnqueue" nor as ++ "ErrorsToDiscard", will be forwarded to CPU. ++ ++ May be used for Rx and OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] errs A list of errors to discard ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigErrorsToDiscard(t_Handle h_FmPort, fmPortFrameErrSelect_t errs); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDmaSwapData ++ ++ @Description Calling this routine changes the DMA swap data aparameter ++ in the internal driver data base from its default ++ configuration [DEFAULT_PORT_dmaSwapData] ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] swapData New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDmaSwapData(t_Handle h_FmPort, e_FmDmaSwapOption swapData); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDmaIcCacheAttr ++ ++ @Description Calling this routine changes the internal context cache ++ attribute parameter in the internal driver data base ++ from its default configuration [DEFAULT_PORT_dmaIntContextCacheAttr] ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] intContextCacheAttr New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDmaIcCacheAttr(t_Handle h_FmPort, e_FmDmaCacheOption intContextCacheAttr); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDmaHdrAttr ++ ++ @Description Calling this routine changes the header cache ++ attribute parameter in the internal driver data base ++ from its default configuration [DEFAULT_PORT_dmaHeaderCacheAttr] ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] headerCacheAttr New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDmaHdrAttr(t_Handle h_FmPort, e_FmDmaCacheOption headerCacheAttr); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDmaScatterGatherAttr ++ ++ @Description Calling this routine changes the scatter gather cache ++ attribute parameter in the internal driver data base ++ from its default configuration [DEFAULT_PORT_dmaScatterGatherCacheAttr] ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] scatterGatherCacheAttr New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDmaScatterGatherAttr(t_Handle h_FmPort, e_FmDmaCacheOption scatterGatherCacheAttr); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDmaWriteOptimize ++ ++ @Description Calling this routine changes the write optimization ++ parameter in the internal driver data base ++ from its default configuration: By default optimize = [DEFAULT_PORT_dmaWriteOptimize]. ++ Note: ++ ++ 1. For head optimization, data alignment must be >= 16 (supported by default). ++ ++ 3. For tail optimization, note that the optimization is performed by extending the write transaction ++ of the frame payload at the tail as needed to achieve optimal bus transfers, so that the last write ++ is extended to be on 16/64 bytes aligned block (chip dependent). ++ ++ Relevant for non-Tx port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] optimize TRUE to enable optimization, FALSE for normal operation ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDmaWriteOptimize(t_Handle h_FmPort, bool optimize); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigNoScatherGather ++ ++ @Description Calling this routine changes the noScatherGather parameter in internal driver data base ++ from its default configuration. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] noScatherGather (TRUE - frame is discarded if can not be stored in single buffer, ++ FALSE - frame can be stored in scatter gather (S/G) format). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigNoScatherGather(t_Handle h_FmPort, bool noScatherGather); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDfltColor ++ ++ @Description Calling this routine changes the internal default color parameter ++ in the internal driver data base ++ from its default configuration [DEFAULT_PORT_color] ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] color New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDfltColor(t_Handle h_FmPort, e_FmPortColor color); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigSyncReq ++ ++ @Description Calling this routine changes the synchronization attribute parameter ++ in the internal driver data base from its default configuration: ++ syncReq = [DEFAULT_PORT_syncReq] ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] syncReq TRUE to request synchronization, FALSE otherwize. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigSyncReq(t_Handle h_FmPort, bool syncReq); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigForwardReuseIntContext ++ ++ @Description This routine is relevant for Rx ports that are routed to OP port. ++ It changes the internal context reuse option in the internal ++ driver data base from its default configuration: ++ reuse = [DEFAULT_PORT_forwardIntContextReuse] ++ ++ May be used for Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] reuse TRUE to reuse internal context on frames ++ forwarded to OP port. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigForwardReuseIntContext(t_Handle h_FmPort, bool reuse); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigDontReleaseTxBufToBM ++ ++ @Description This routine should be called if no Tx confirmation ++ is done, and yet buffers should not be released to the BM. ++ Normally, buffers are returned using the Tx confirmation ++ process. When Tx confirmation is not used (defFqid=0), ++ buffers are typically released to the BM. This routine ++ may be called to avoid this behavior and not release the ++ buffers. ++ ++ May be used for Tx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigDontReleaseTxBufToBM(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigIMMaxRxBufLength ++ ++ @Description Changes the maximum receive buffer length from its default ++ configuration: Closest rounded down power of 2 value of the ++ data buffer size. ++ ++ The maximum receive buffer length directly affects the structure ++ of received frames (single- or multi-buffered) and the performance ++ of both the FM and the driver. ++ ++ The selection between single- or multi-buffered frames should be ++ done according to the characteristics of the specific application. ++ The recommended mode is to use a single data buffer per packet, ++ as this mode provides the best performance. However, the user can ++ select to use multiple data buffers per packet. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] newVal Maximum receive buffer length (in bytes). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++ This routine is to be used only if Independent-Mode is enabled. ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigIMMaxRxBufLength(t_Handle h_FmPort, uint16_t newVal); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigIMRxBdRingLength ++ ++ @Description Changes the receive BD ring length from its default ++ configuration:[DEFAULT_PORT_rxBdRingLength] ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] newVal The desired BD ring length. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++ This routine is to be used only if Independent-Mode is enabled. ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigIMRxBdRingLength(t_Handle h_FmPort, uint16_t newVal); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigIMTxBdRingLength ++ ++ @Description Changes the transmit BD ring length from its default ++ configuration:[DEFAULT_PORT_txBdRingLength] ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] newVal The desired BD ring length. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++ This routine is to be used only if Independent-Mode is enabled. ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigIMTxBdRingLength(t_Handle h_FmPort, uint16_t newVal); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigIMFmanCtrlExternalStructsMemory ++ ++ @Description Configures memory partition and attributes for FMan-Controller ++ data structures (e.g. BD rings). ++ Calling this routine changes the internal driver data base ++ from its default configuration ++ [DEFAULT_PORT_ImfwExtStructsMemId, DEFAULT_PORT_ImfwExtStructsMemAttr]. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] memId Memory partition ID. ++ @Param[in] memAttributes Memory attributes mask (a combination of MEMORY_ATTR_x flags). ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigIMFmanCtrlExternalStructsMemory(t_Handle h_FmPort, ++ uint8_t memId, ++ uint32_t memAttributes); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigIMPolling ++ ++ @Description Changes the Rx flow from interrupt driven (default) to polling. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++ This routine is to be used only if Independent-Mode is enabled. ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigIMPolling(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigMaxFrameLength ++ ++ @Description Changes the definition of the max size of frame that should be ++ transmitted/received on this port from its default value [DEFAULT_PORT_maxFrameLength]. ++ This parameter is used for confirmation of the minimum Fifo ++ size calculations and only for Tx ports or ports working in ++ independent mode. This should be larger than the maximum possible ++ MTU that will be used for this port (i.e. its MAC). ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] length Max size of frame ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++ This routine is to be used only if Independent-Mode is enabled. ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigMaxFrameLength(t_Handle h_FmPort, uint16_t length); ++ ++/**************************************************************************//* ++ @Function FM_PORT_ConfigTxFifoMinFillLevel ++ ++ @Description Calling this routine changes the fifo minimum ++ fill level parameter in the internal driver data base ++ from its default configuration [DEFAULT_PORT_txFifoMinFillLevel] ++ ++ May be used for Tx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] minFillLevel New value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigTxFifoMinFillLevel(t_Handle h_FmPort, uint32_t minFillLevel); ++ ++/**************************************************************************//* ++ @Function FM_PORT_ConfigFifoDeqPipelineDepth ++ ++ @Description Calling this routine changes the fifo dequeue ++ pipeline depth parameter in the internal driver data base ++ ++ from its default configuration: 1G ports: [DEFAULT_PORT_fifoDeqPipelineDepth_1G], ++ 10G port: [DEFAULT_PORT_fifoDeqPipelineDepth_10G], ++ OP port: [DEFAULT_PORT_fifoDeqPipelineDepth_OH] ++ ++ May be used for Tx/OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] deqPipelineDepth New value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigFifoDeqPipelineDepth(t_Handle h_FmPort, uint8_t deqPipelineDepth); ++ ++/**************************************************************************//* ++ @Function FM_PORT_ConfigTxFifoLowComfLevel ++ ++ @Description Calling this routine changes the fifo low comfort level ++ parameter in internal driver data base ++ from its default configuration [DEFAULT_PORT_txFifoLowComfLevel] ++ ++ May be used for Tx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] fifoLowComfLevel New value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigTxFifoLowComfLevel(t_Handle h_FmPort, uint32_t fifoLowComfLevel); ++ ++/**************************************************************************//* ++ @Function FM_PORT_ConfigRxFifoThreshold ++ ++ @Description Calling this routine changes the threshold of the FIFO ++ fill level parameter in the internal driver data base ++ from its default configuration [DEFAULT_PORT_rxFifoThreshold] ++ ++ If the total number of buffers which are ++ currently in use and associated with the ++ specific RX port exceed this threshold, the ++ BMI will signal the MAC to send a pause frame ++ over the link. ++ ++ May be used for Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] fifoThreshold New value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigRxFifoThreshold(t_Handle h_FmPort, uint32_t fifoThreshold); ++ ++/**************************************************************************//* ++ @Function FM_PORT_ConfigRxFifoPriElevationLevel ++ ++ @Description Calling this routine changes the priority elevation level ++ parameter in the internal driver data base from its default ++ configuration [DEFAULT_PORT_rxFifoPriElevationLevel] ++ ++ If the total number of buffers which are currently in use and ++ associated with the specific RX port exceed the amount specified ++ in priElevationLevel, BMI will signal the main FM's DMA to ++ elevate the FM priority on the system bus. ++ ++ May be used for Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] priElevationLevel New value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigRxFifoPriElevationLevel(t_Handle h_FmPort, uint32_t priElevationLevel); ++ ++#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 ++/**************************************************************************//* ++ @Function FM_PORT_ConfigBCBWorkaround ++ ++ @Description Configures BCB errata workaround. ++ ++ When BCB errata is applicable, the workaround is always ++ performed by FM Controller. Thus, this functions doesn't ++ actually enable errata workaround but rather allows driver ++ to perform adjustments required due to errata workaround ++ execution in FM controller. ++ ++ Applying BCB workaround also configures FM_PORT_FRM_ERR_PHYSICAL ++ errors to be discarded. Thus FM_PORT_FRM_ERR_PHYSICAL can't be ++ set by FM_PORT_SetErrorsRoute() function. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigBCBWorkaround(t_Handle h_FmPort); ++#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */ ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//* ++ @Function FM_PORT_ConfigInternalBuffOffset ++ ++ @Description Configures internal buffer offset. ++ ++ May be used for Rx and OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] val New value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ConfigInternalBuffOffset(t_Handle h_FmPort, uint8_t val); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/** @} */ /* end of FM_PORT_advanced_init_grp group */ ++/** @} */ /* end of FM_PORT_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_PORT_runtime_control_grp FM Port Runtime Control Unit ++ ++ @Description FM Port Runtime control unit API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description enum for defining FM Port counters ++*//***************************************************************************/ ++typedef enum e_FmPortCounters { ++ e_FM_PORT_COUNTERS_CYCLE, /**< BMI performance counter */ ++ e_FM_PORT_COUNTERS_TASK_UTIL, /**< BMI performance counter */ ++ e_FM_PORT_COUNTERS_QUEUE_UTIL, /**< BMI performance counter */ ++ e_FM_PORT_COUNTERS_DMA_UTIL, /**< BMI performance counter */ ++ e_FM_PORT_COUNTERS_FIFO_UTIL, /**< BMI performance counter */ ++ e_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION, /**< BMI Rx only performance counter */ ++ e_FM_PORT_COUNTERS_FRAME, /**< BMI statistics counter */ ++ e_FM_PORT_COUNTERS_DISCARD_FRAME, /**< BMI statistics counter */ ++ e_FM_PORT_COUNTERS_DEALLOC_BUF, /**< BMI deallocate buffer statistics counter */ ++ e_FM_PORT_COUNTERS_RX_BAD_FRAME, /**< BMI Rx only statistics counter */ ++ e_FM_PORT_COUNTERS_RX_LARGE_FRAME, /**< BMI Rx only statistics counter */ ++ e_FM_PORT_COUNTERS_RX_FILTER_FRAME, /**< BMI Rx & OP only statistics counter */ ++ e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR, /**< BMI Rx, OP & HC only statistics counter */ ++ e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD, /**< BMI Rx, OP & HC statistics counter */ ++ e_FM_PORT_COUNTERS_PREPARE_TO_ENQUEUE_COUNTER, /**< BMI Rx, OP & HC only statistics counter */ ++ e_FM_PORT_COUNTERS_WRED_DISCARD, /**< BMI OP & HC only statistics counter */ ++ e_FM_PORT_COUNTERS_LENGTH_ERR, /**< BMI non-Rx statistics counter */ ++ e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT, /**< BMI non-Rx statistics counter */ ++ e_FM_PORT_COUNTERS_DEQ_TOTAL, /**< QMI total QM dequeues counter */ ++ e_FM_PORT_COUNTERS_ENQ_TOTAL, /**< QMI total QM enqueues counter */ ++ e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT, /**< QMI counter */ ++ e_FM_PORT_COUNTERS_DEQ_CONFIRM /**< QMI counter */ ++} e_FmPortCounters; ++ ++typedef struct t_FmPortBmiStats { ++ uint32_t cntCycle; ++ uint32_t cntTaskUtil; ++ uint32_t cntQueueUtil; ++ uint32_t cntDmaUtil; ++ uint32_t cntFifoUtil; ++ uint32_t cntRxPauseActivation; ++ uint32_t cntFrame; ++ uint32_t cntDiscardFrame; ++ uint32_t cntDeallocBuf; ++ uint32_t cntRxBadFrame; ++ uint32_t cntRxLargeFrame; ++ uint32_t cntRxFilterFrame; ++ uint32_t cntRxListDmaErr; ++ uint32_t cntRxOutOfBuffersDiscard; ++ uint32_t cntWredDiscard; ++ uint32_t cntLengthErr; ++ uint32_t cntUnsupportedFormat; ++} t_FmPortBmiStats; ++ ++/**************************************************************************//** ++ @Description Structure for Port id parameters. ++ Fields commented 'IN' are passed by the port module to be used ++ by the FM module. ++ Fields commented 'OUT' will be filled by FM before returning to port. ++*//***************************************************************************/ ++typedef struct t_FmPortCongestionGrps { ++ uint16_t numOfCongestionGrpsToConsider; /**< The number of required CGs ++ to define the size of the following array */ ++ uint8_t congestionGrpsToConsider[FM_PORT_NUM_OF_CONGESTION_GRPS]; ++ /**< An array of CG indexes; ++ Note that the size of the array should be ++ 'numOfCongestionGrpsToConsider'. */ ++#if (DPAA_VERSION >= 11) ++ bool pfcPrioritiesEn[FM_PORT_NUM_OF_CONGESTION_GRPS][FM_MAX_NUM_OF_PFC_PRIORITIES]; ++ /**< a matrix that represents the map between the CG ids ++ defined in 'congestionGrpsToConsider' to the priorties ++ mapping array. */ ++#endif /* (DPAA_VERSION >= 11) */ ++} t_FmPortCongestionGrps; ++ ++/**************************************************************************//** ++ @Description Structure for Deep Sleep Auto Response ARP Entry ++*//***************************************************************************/ ++typedef struct t_FmPortDsarArpEntry ++{ ++ uint32_t ipAddress; ++ uint8_t mac[6]; ++ bool isVlan; ++ uint16_t vid; ++} t_FmPortDsarArpEntry; ++ ++/**************************************************************************//** ++ @Description Structure for Deep Sleep Auto Response ARP info ++*//***************************************************************************/ ++typedef struct t_FmPortDsarArpInfo ++{ ++ uint8_t tableSize; ++ t_FmPortDsarArpEntry *p_AutoResTable; ++ bool enableConflictDetection; /* when TRUE Conflict Detection will be checked and wake the host if needed */ ++} t_FmPortDsarArpInfo; ++ ++/**************************************************************************//** ++ @Description Structure for Deep Sleep Auto Response NDP Entry ++*//***************************************************************************/ ++typedef struct t_FmPortDsarNdpEntry ++{ ++ uint32_t ipAddress[4]; ++ uint8_t mac[6]; ++ bool isVlan; ++ uint16_t vid; ++} t_FmPortDsarNdpEntry; ++ ++/**************************************************************************//** ++ @Description Structure for Deep Sleep Auto Response NDP info ++*//***************************************************************************/ ++typedef struct t_FmPortDsarNdpInfo ++{ ++ uint32_t multicastGroup; ++ ++ uint8_t tableSizeAssigned; ++ t_FmPortDsarNdpEntry *p_AutoResTableAssigned; /* This list refer to solicitation IP addresses. ++ Note that all IP adresses must be from the same multicast group. ++ This will be checked and if not operation will fail. */ ++ uint8_t tableSizeTmp; ++ t_FmPortDsarNdpEntry *p_AutoResTableTmp; /* This list refer to temp IP addresses. ++ Note that all temp IP adresses must be from the same multicast group. ++ This will be checked and if not operation will fail. */ ++ ++ bool enableConflictDetection; /* when TRUE Conflict Detection will be checked and wake the host if needed */ ++ ++} t_FmPortDsarNdpInfo; ++ ++/**************************************************************************//** ++ @Description Structure for Deep Sleep Auto Response ICMPV4 info ++*//***************************************************************************/ ++typedef struct t_FmPortDsarEchoIpv4Info ++{ ++ uint8_t tableSize; ++ t_FmPortDsarArpEntry *p_AutoResTable; ++} t_FmPortDsarEchoIpv4Info; ++ ++/**************************************************************************//** ++ @Description Structure for Deep Sleep Auto Response ICMPV6 info ++*//***************************************************************************/ ++typedef struct t_FmPortDsarEchoIpv6Info ++{ ++ uint8_t tableSize; ++ t_FmPortDsarNdpEntry *p_AutoResTable; ++} t_FmPortDsarEchoIpv6Info; ++ ++/**************************************************************************//** ++ at Description Deep Sleep Auto Response SNMP OIDs table entry ++ ++*//***************************************************************************/ ++typedef struct { ++ uint16_t oidSize; ++ uint8_t *oidVal; /* only the oid string */ ++ uint16_t resSize; ++ uint8_t *resVal; /* resVal will be the entire reply, ++ i.e. "Type|Length|Value" */ ++} t_FmPortDsarOidsEntry; ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response SNMP IPv4 Addresses Table Entry ++ Refer to the FMan Controller spec for more details. ++*//***************************************************************************/ ++typedef struct ++{ ++ uint32_t ipv4Addr; /*!< 32 bit IPv4 Address. */ ++ bool isVlan; ++ uint16_t vid; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */ ++ /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */ ++} t_FmPortDsarSnmpIpv4AddrTblEntry; ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response SNMP IPv6 Addresses Table Entry ++ Refer to the FMan Controller spec for more details. ++*//***************************************************************************/ ++typedef struct ++{ ++ uint32_t ipv6Addr[4]; /*!< 4 * 32 bit IPv6 Address. */ ++ bool isVlan; ++ uint16_t vid; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */ ++ /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */ ++} t_FmPortDsarSnmpIpv6AddrTblEntry; ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response SNMP Descriptor ++ ++*//***************************************************************************/ ++typedef struct ++{ ++ uint16_t control; /**< Control bits [0-15]. */ ++ uint16_t maxSnmpMsgLength; /**< Maximal allowed SNMP message length. */ ++ uint16_t numOfIpv4Addresses; /**< Number of entries in IPv4 addresses table. */ ++ uint16_t numOfIpv6Addresses; /**< Number of entries in IPv6 addresses table. */ ++ t_FmPortDsarSnmpIpv4AddrTblEntry *p_Ipv4AddrTbl; /**< Pointer to IPv4 addresses table. */ ++ t_FmPortDsarSnmpIpv6AddrTblEntry *p_Ipv6AddrTbl; /**< Pointer to IPv6 addresses table. */ ++ uint8_t *p_RdOnlyCommunityStr; /**< Pointer to the Read Only Community String. */ ++ uint8_t *p_RdWrCommunityStr; /**< Pointer to the Read Write Community String. */ ++ t_FmPortDsarOidsEntry *p_OidsTbl; /**< Pointer to OIDs table. */ ++ uint32_t oidsTblSize; /**< Number of entries in OIDs table. */ ++} t_FmPortDsarSnmpInfo; ++ ++/**************************************************************************//** ++ @Description Structure for Deep Sleep Auto Response filtering Entry ++*//***************************************************************************/ ++typedef struct t_FmPortDsarFilteringEntry ++{ ++ uint16_t srcPort; ++ uint16_t dstPort; ++ uint16_t srcPortMask; ++ uint16_t dstPortMask; ++} t_FmPortDsarFilteringEntry; ++ ++/**************************************************************************//** ++ @Description Structure for Deep Sleep Auto Response filtering info ++*//***************************************************************************/ ++typedef struct t_FmPortDsarFilteringInfo ++{ ++ /* IP protocol filtering parameters */ ++ uint8_t ipProtTableSize; ++ uint8_t *p_IpProtTablePtr; ++ bool ipProtPassOnHit; /* when TRUE, miss in the table will cause the packet to be droped, ++ hit will pass the packet to UDP/TCP filters if needed and if not ++ to the classification tree. If the classification tree will pass ++ the packet to a queue it will cause a wake interupt. ++ When FALSE it the other way around. */ ++ /* UDP port filtering parameters */ ++ uint8_t udpPortsTableSize; ++ t_FmPortDsarFilteringEntry *p_UdpPortsTablePtr; ++ bool udpPortPassOnHit; /* when TRUE, miss in the table will cause the packet to be droped, ++ hit will pass the packet to classification tree. ++ If the classification tree will pass the packet to a queue it ++ will cause a wake interupt. ++ When FALSE it the other way around. */ ++ /* TCP port filtering parameters */ ++ uint16_t tcpFlagsMask; ++ uint8_t tcpPortsTableSize; ++ t_FmPortDsarFilteringEntry *p_TcpPortsTablePtr; ++ bool tcpPortPassOnHit; /* when TRUE, miss in the table will cause the packet to be droped, ++ hit will pass the packet to classification tree. ++ If the classification tree will pass the packet to a queue it ++ will cause a wake interupt. ++ When FALSE it the other way around. */ ++} t_FmPortDsarFilteringInfo; ++ ++/**************************************************************************//** ++ @Description Structure for Deep Sleep Auto Response parameters ++*//***************************************************************************/ ++typedef struct t_FmPortDsarParams ++{ ++ t_Handle h_FmPortTx; ++ t_FmPortDsarArpInfo *p_AutoResArpInfo; ++ t_FmPortDsarEchoIpv4Info *p_AutoResEchoIpv4Info; ++ t_FmPortDsarNdpInfo *p_AutoResNdpInfo; ++ t_FmPortDsarEchoIpv6Info *p_AutoResEchoIpv6Info; ++ t_FmPortDsarSnmpInfo *p_AutoResSnmpInfo; ++ t_FmPortDsarFilteringInfo *p_AutoResFilteringInfo; ++} t_FmPortDsarParams; ++ ++/**************************************************************************//** ++ @Function FM_PORT_EnterDsar ++ ++ @Description Enter Deep Sleep Auto Response mode. ++ This function write the apropriate values to in the relevant ++ tables in the MURAM. ++ ++ @Param[in] h_FmPortRx - FM PORT module descriptor ++ @Param[in] params - Auto Response parameters ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_EnterDsar(t_Handle h_FmPortRx, t_FmPortDsarParams *params); ++ ++/**************************************************************************//** ++ @Function FM_PORT_EnterDsarFinal ++ ++ @Description Enter Deep Sleep Auto Response mode. ++ This function sets the Tx port in independent mode as needed ++ and redirect the receive flow to go through the ++ Dsar Fman-ctrl code ++ ++ @Param[in] h_DsarRxPort - FM Rx PORT module descriptor ++ @Param[in] h_DsarTxPort - FM Tx PORT module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_EnterDsarFinal(t_Handle h_DsarRxPort, t_Handle h_DsarTxPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ExitDsar ++ ++ @Description Exit Deep Sleep Auto Response mode. ++ This function reverse the AR mode and put the ports back into ++ their original wake mode ++ ++ @Param[in] h_FmPortRx - FM PORT Rx module descriptor ++ @Param[in] h_FmPortTx - FM PORT Tx module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_EnterDsar(). ++*//***************************************************************************/ ++void FM_PORT_ExitDsar(t_Handle h_FmPortRx, t_Handle h_FmPortTx); ++ ++/**************************************************************************//** ++ @Function FM_PORT_IsInDsar ++ ++ @Description This function returns TRUE if the port was set as Auto Response ++ and FALSE if not. Once Exit AR mode it will return FALSE as well ++ until re-enabled once more. ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++bool FM_PORT_IsInDsar(t_Handle h_FmPort); ++ ++typedef struct t_FmPortDsarStats ++{ ++ uint32_t arpArCnt; ++ uint32_t echoIcmpv4ArCnt; ++ uint32_t ndpArCnt; ++ uint32_t echoIcmpv6ArCnt; ++ uint32_t snmpGetCnt; ++ uint32_t snmpGetNextCnt; ++} t_FmPortDsarStats; ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetDsarStats ++ ++ @Description Return statistics for Deep Sleep Auto Response ++ ++ @Param[in] h_FmPortRx - FM PORT module descriptor ++ @Param[out] stats - structure containing the statistics counters ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_PORT_GetDsarStats(t_Handle h_FmPortRx, t_FmPortDsarStats *stats); ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++/**************************************************************************//** ++ @Function FM_PORT_DumpRegs ++ ++ @Description Dump all regs. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_DumpRegs(t_Handle h_FmPort); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetBufferDataOffset ++ ++ @Description Relevant for Rx ports. ++ Returns the data offset from the beginning of the data buffer ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ ++ @Return data offset. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++uint32_t FM_PORT_GetBufferDataOffset(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetBufferICInfo ++ ++ @Description Returns the Internal Context offset from the beginning of the data buffer ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ @Param[in] p_Data - A pointer to the data buffer. ++ ++ @Return Internal context info pointer on success, NULL if 'allOtherInfo' was not ++ configured for this port. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++uint8_t * FM_PORT_GetBufferICInfo(t_Handle h_FmPort, char *p_Data); ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetBufferPrsResult ++ ++ @Description Returns the pointer to the parse result in the data buffer. ++ In Rx ports this is relevant after reception, if parse ++ result is configured to be part of the data passed to the ++ application. For non Rx ports it may be used to get the pointer ++ of the area in the buffer where parse result should be ++ initialized - if so configured. ++ See FM_PORT_ConfigBufferPrefixContent for data buffer prefix ++ configuration. ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ @Param[in] p_Data - A pointer to the data buffer. ++ ++ @Return Parse result pointer on success, NULL if parse result was not ++ configured for this port. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_FmPrsResult * FM_PORT_GetBufferPrsResult(t_Handle h_FmPort, char *p_Data); ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetBufferTimeStamp ++ ++ @Description Returns the time stamp in the data buffer. ++ Relevant for Rx ports for getting the buffer time stamp. ++ See FM_PORT_ConfigBufferPrefixContent for data buffer prefix ++ configuration. ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ @Param[in] p_Data - A pointer to the data buffer. ++ ++ @Return A pointer to the hash result on success, NULL otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++uint64_t * FM_PORT_GetBufferTimeStamp(t_Handle h_FmPort, char *p_Data); ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetBufferHashResult ++ ++ @Description Given a data buffer, on the condition that hash result was defined ++ as a part of the buffer content (see FM_PORT_ConfigBufferPrefixContent) ++ this routine will return the pointer to the hash result location in the ++ buffer prefix. ++ ++ @Param[in] h_FmPort - FM PORT module descriptor ++ @Param[in] p_Data - A pointer to the data buffer. ++ ++ @Return A pointer to the hash result on success, NULL otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++uint8_t * FM_PORT_GetBufferHashResult(t_Handle h_FmPort, char *p_Data); ++ ++/**************************************************************************//** ++ @Function FM_PORT_Disable ++ ++ @Description Gracefully disable an FM port. The port will not start new tasks after all ++ tasks associated with the port are terminated. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++ This is a blocking routine, it returns after port is ++ gracefully stopped, i.e. the port will not except new frames, ++ but it will finish all frames or tasks which were already began ++*//***************************************************************************/ ++t_Error FM_PORT_Disable(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_Enable ++ ++ @Description A runtime routine provided to allow disable/enable of port. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_Enable(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetRateLimit ++ ++ @Description Calling this routine enables rate limit algorithm. ++ By default, this functionality is disabled. ++ Note that rate-limit mechanism uses the FM time stamp. ++ The selected rate limit specified here would be ++ rounded DOWN to the nearest 16M. ++ ++ May be used for Tx and OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_RateLimit A structure of rate limit parameters ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++ If rate limit is set on a port that need to send PFC frames, ++ it might violate the stop transmit timing. ++*//***************************************************************************/ ++t_Error FM_PORT_SetRateLimit(t_Handle h_FmPort, t_FmPortRateLimit *p_RateLimit); ++ ++/**************************************************************************//** ++ @Function FM_PORT_DeleteRateLimit ++ ++ @Description Calling this routine disables and clears rate limit ++ initialization. ++ ++ May be used for Tx and OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_DeleteRateLimit(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetPfcPrioritiesMappingToQmanWQ ++ ++ @Description Calling this routine maps each PFC received priority to the transmit WQ. ++ This WQ will be blocked upon receiving a PFC frame with this priority. ++ ++ May be used for Tx ports only. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] prio PFC priority (0-7). ++ @Param[in] wq Work Queue (0-7). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetPfcPrioritiesMappingToQmanWQ(t_Handle h_FmPort, uint8_t prio, uint8_t wq); ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetStatisticsCounters ++ ++ @Description Calling this routine enables/disables port's statistics counters. ++ By default, counters are enabled. ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] enable TRUE to enable, FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetStatisticsCounters(t_Handle h_FmPort, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetFrameQueueCounters ++ ++ @Description Calling this routine enables/disables port's enqueue/dequeue counters. ++ By default, counters are enabled. ++ ++ May be used for all ports ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] enable TRUE to enable, FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetFrameQueueCounters(t_Handle h_FmPort, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_PORT_AnalyzePerformanceParams ++ ++ @Description User may call this routine to so the driver will analyze if the ++ basic performance parameters are correct and also the driver may ++ suggest of improvements; The basic parameters are FIFO sizes, number ++ of DMAs and number of TNUMs for the port. ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_AnalyzePerformanceParams(t_Handle h_FmPort); ++ ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetAllocBufCounter ++ ++ @Description Calling this routine enables/disables BM pool allocate ++ buffer counters. ++ By default, counters are enabled. ++ ++ May be used for Rx ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] poolId BM pool id. ++ @Param[in] enable TRUE to enable, FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetAllocBufCounter(t_Handle h_FmPort, uint8_t poolId, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetBmiCounters ++ ++ @Description Read port's BMI stat counters and place them into ++ a designated structure of counters. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[out] p_BmiStats counters structure ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_GetBmiCounters(t_Handle h_FmPort, t_FmPortBmiStats *p_BmiStats); ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetCounter ++ ++ @Description Reads one of the FM PORT counters. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] fmPortCounter The requested counter. ++ ++ @Return Counter's current value. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++ Note that it is user's responsibility to call this routine only ++ for enabled counters, and there will be no indication if a ++ disabled counter is accessed. ++*//***************************************************************************/ ++uint32_t FM_PORT_GetCounter(t_Handle h_FmPort, e_FmPortCounters fmPortCounter); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ModifyCounter ++ ++ @Description Sets a value to an enabled counter. Use "0" to reset the counter. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] fmPortCounter The requested counter. ++ @Param[in] value The requested value to be written into the counter. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ModifyCounter(t_Handle h_FmPort, e_FmPortCounters fmPortCounter, uint32_t value); ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetAllocBufCounter ++ ++ @Description Reads one of the FM PORT buffer counters. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] poolId The requested pool. ++ ++ @Return Counter's current value. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++ Note that it is user's responsibility to call this routine only ++ for enabled counters, and there will be no indication if a ++ disabled counter is accessed. ++*//***************************************************************************/ ++uint32_t FM_PORT_GetAllocBufCounter(t_Handle h_FmPort, uint8_t poolId); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ModifyAllocBufCounter ++ ++ @Description Sets a value to an enabled counter. Use "0" to reset the counter. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] poolId The requested pool. ++ @Param[in] value The requested value to be written into the counter. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ModifyAllocBufCounter(t_Handle h_FmPort, uint8_t poolId, uint32_t value); ++ ++/**************************************************************************//** ++ @Function FM_PORT_AddCongestionGrps ++ ++ @Description This routine effects the corresponding Tx port. ++ It should be called in order to enable pause ++ frame transmission in case of congestion in one or more ++ of the congestion groups relevant to this port. ++ Each call to this routine may add one or more congestion ++ groups to be considered relevant to this port. ++ ++ May be used for Rx, or RX+OP ports only (depending on chip) ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_CongestionGrps A pointer to an array of congestion groups ++ id's to consider. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_AddCongestionGrps(t_Handle h_FmPort, t_FmPortCongestionGrps *p_CongestionGrps); ++ ++/**************************************************************************//** ++ @Function FM_PORT_RemoveCongestionGrps ++ ++ @Description This routine effects the corresponding Tx port. It should be ++ called when congestion groups were ++ defined for this port and are no longer relevant, or pause ++ frames transmitting is not required on their behalf. ++ Each call to this routine may remove one or more congestion ++ groups to be considered relevant to this port. ++ ++ May be used for Rx, or RX+OP ports only (depending on chip) ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_CongestionGrps A pointer to an array of congestion groups ++ id's to consider. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_RemoveCongestionGrps(t_Handle h_FmPort, t_FmPortCongestionGrps *p_CongestionGrps); ++ ++/**************************************************************************//** ++ @Function FM_PORT_IsStalled ++ ++ @Description A routine for checking whether the specified port is stalled. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return TRUE if port is stalled, FALSE otherwize ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++bool FM_PORT_IsStalled(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ReleaseStalled ++ ++ @Description This routine may be called in case the port was stalled and may ++ now be released. ++ Note that this routine is available only on older FMan revisions ++ (FMan v2, DPAA v1.0 only). ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_ReleaseStalled(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetRxL4ChecksumVerify ++ ++ @Description This routine is relevant for Rx ports (1G and 10G). The routine ++ set/clear the L3/L4 checksum verification (on RX side). ++ Note that this takes affect only if hw-parser is enabled! ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] l4Checksum boolean indicates whether to do L3/L4 checksum ++ on frames or not. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetRxL4ChecksumVerify(t_Handle h_FmPort, bool l4Checksum); ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetErrorsRoute ++ ++ @Description Errors selected for this routine will cause a frame with that error ++ to be enqueued to error queue. ++ Errors not selected for this routine will cause a frame with that error ++ to be enqueued to the one of the other port queues. ++ By default all errors are defined to be enqueued to error queue. ++ Errors that were configured to be discarded (at initialization) ++ may not be selected here. ++ ++ May be used for Rx and OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] errs A list of errors to enqueue to error queue ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetErrorsRoute(t_Handle h_FmPort, fmPortFrameErrSelect_t errs); ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetIMExceptions ++ ++ @Description Calling this routine enables/disables FM PORT interrupts. ++ ++ @Param[in] h_FmPort FM PORT module descriptor. ++ @Param[in] exception The exception to be selected. ++ @Param[in] enable TRUE to enable interrupt, FALSE to mask it. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++ This routine should NOT be called from guest-partition ++ (i.e. guestId != NCSW_MASTER_ID) ++*//***************************************************************************/ ++t_Error FM_PORT_SetIMExceptions(t_Handle h_FmPort, e_FmPortExceptions exception, bool enable); ++ ++/**************************************************************************//* ++ @Function FM_PORT_SetPerformanceCounters ++ ++ @Description Calling this routine enables/disables port's performance counters. ++ By default, counters are enabled. ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] enable TRUE to enable, FALSE to disable. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetPerformanceCounters(t_Handle h_FmPort, bool enable); ++ ++/**************************************************************************//* ++ @Function FM_PORT_SetPerformanceCountersParams ++ ++ @Description Calling this routine defines port's performance ++ counters parameters. ++ ++ May be used for all port types ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_FmPortPerformanceCnt A pointer to a structure of performance ++ counters parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetPerformanceCountersParams(t_Handle h_FmPort, t_FmPortPerformanceCnt *p_FmPortPerformanceCnt); ++ ++/**************************************************************************//** ++ @Group FM_PORT_pcd_runtime_control_grp FM Port PCD Runtime Control Unit ++ ++ @Description FM Port PCD Runtime control unit API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description A structure defining the KG scheme after the parser. ++ This is relevant only to change scheme selection mode - from ++ direct to indirect and vice versa, or when the scheme is selected directly, ++ to select the scheme id. ++ ++*//***************************************************************************/ ++typedef struct t_FmPcdKgSchemeSelect { ++ bool direct; /**< TRUE to use 'h_Scheme' directly, FALSE to use LCV. */ ++ t_Handle h_DirectScheme; /**< Scheme handle, selects the scheme after parser; ++ Relevant only when 'direct' is TRUE. */ ++} t_FmPcdKgSchemeSelect; ++ ++/**************************************************************************//** ++ @Description A structure of scheme parameters ++*//***************************************************************************/ ++typedef struct t_FmPcdPortSchemesParams { ++ uint8_t numOfSchemes; /**< Number of schemes for port to be bound to. */ ++ t_Handle h_Schemes[FM_PCD_KG_NUM_OF_SCHEMES]; /**< Array of 'numOfSchemes' schemes for the ++ port to be bound to */ ++} t_FmPcdPortSchemesParams; ++ ++/**************************************************************************//** ++ @Description Union for defining port protocol parameters for parser ++*//***************************************************************************/ ++typedef union u_FmPcdHdrPrsOpts { ++ /* MPLS */ ++ struct { ++ bool labelInterpretationEnable; /**< When this bit is set, the last MPLS label will be ++ interpreted as described in HW spec table. When the bit ++ is cleared, the parser will advance to MPLS next parse */ ++ e_NetHeaderType nextParse; /**< must be equal or higher than IPv4 */ ++ } mplsPrsOptions; ++ /* VLAN */ ++ struct { ++ uint16_t tagProtocolId1; /**< User defined Tag Protocol Identifier, to be recognized ++ on VLAN TAG on top of 0x8100 and 0x88A8 */ ++ uint16_t tagProtocolId2; /**< User defined Tag Protocol Identifier, to be recognized ++ on VLAN TAG on top of 0x8100 and 0x88A8 */ ++ } vlanPrsOptions; ++ /* PPP */ ++ struct{ ++ bool enableMTUCheck; /**< Check validity of MTU according to RFC2516 */ ++ } pppoePrsOptions; ++ ++ /* IPV6 */ ++ struct{ ++ bool routingHdrEnable; /**< TRUE to enable routing header, otherwise ignore */ ++ } ipv6PrsOptions; ++ ++ /* UDP */ ++ struct{ ++ bool padIgnoreChecksum; /**< TRUE to ignore pad in checksum */ ++ } udpPrsOptions; ++ ++ /* TCP */ ++ struct { ++ bool padIgnoreChecksum; /**< TRUE to ignore pad in checksum */ ++ } tcpPrsOptions; ++} u_FmPcdHdrPrsOpts; ++ ++/**************************************************************************//** ++ @Description A structure for defining each header for the parser ++*//***************************************************************************/ ++typedef struct t_FmPcdPrsAdditionalHdrParams { ++ e_NetHeaderType hdr; /**< Selected header; use HEADER_TYPE_NONE ++ to indicate that sw parser is to run first ++ (before HW parser, and independent of the ++ existence of any protocol), in this case, ++ swPrsEnable must be set, and all other ++ parameters are irrelevant. */ ++ bool errDisable; /**< TRUE to disable error indication */ ++ bool swPrsEnable; /**< Enable jump to SW parser when this ++ header is recognized by the HW parser. */ ++ uint8_t indexPerHdr; /**< Normally 0, if more than one sw parser ++ attachments exists for the same header, ++ (in the main sw parser code) use this ++ index to distinguish between them. */ ++ bool usePrsOpts; /**< TRUE to use parser options. */ ++ u_FmPcdHdrPrsOpts prsOpts; /**< A union according to header type, ++ defining the parser options selected.*/ ++} t_FmPcdPrsAdditionalHdrParams; ++ ++/**************************************************************************//** ++ @Description struct for defining port PCD parameters ++*//***************************************************************************/ ++typedef struct t_FmPortPcdPrsParams { ++ uint8_t prsResultPrivateInfo; /**< The private info provides a method of inserting ++ port information into the parser result. This information ++ may be extracted by Keygen and be used for frames ++ distribution when a per-port distinction is required, ++ it may also be used as a port logical id for analyzing ++ incoming frames. */ ++ uint8_t parsingOffset; /**< Number of bytes from beginning of packet to start parsing */ ++ e_NetHeaderType firstPrsHdr; /**< The type of the first header expected at 'parsingOffset' */ ++ bool includeInPrsStatistics; /**< TRUE to include this port in the parser statistics; ++ NOTE: this field is not valid when the FM is in "guest" mode ++ and IPC is not available. */ ++ uint8_t numOfHdrsWithAdditionalParams; /**< Normally 0, some headers may get ++ special parameters */ ++ t_FmPcdPrsAdditionalHdrParams additionalParams[FM_PCD_PRS_NUM_OF_HDRS]; ++ /**< 'numOfHdrsWithAdditionalParams' structures ++ of additional parameters ++ for each header that requires them */ ++ bool setVlanTpid1; /**< TRUE to configure user selection of Ethertype to ++ indicate a VLAN tag (in addition to the TPID values ++ 0x8100 and 0x88A8). */ ++ uint16_t vlanTpid1; /**< extra tag to use if setVlanTpid1=TRUE. */ ++ bool setVlanTpid2; /**< TRUE to configure user selection of Ethertype to ++ indicate a VLAN tag (in addition to the TPID values ++ 0x8100 and 0x88A8). */ ++ uint16_t vlanTpid2; /**< extra tag to use if setVlanTpid1=TRUE. */ ++} t_FmPortPcdPrsParams; ++ ++/**************************************************************************//** ++ @Description struct for defining coarse alassification parameters ++*//***************************************************************************/ ++typedef struct t_FmPortPcdCcParams { ++ t_Handle h_CcTree; /**< A handle to a CC tree */ ++} t_FmPortPcdCcParams; ++ ++/**************************************************************************//** ++ @Description struct for defining keygen parameters ++*//***************************************************************************/ ++typedef struct t_FmPortPcdKgParams { ++ uint8_t numOfSchemes; /**< Number of schemes for port to be bound to. */ ++ t_Handle h_Schemes[FM_PCD_KG_NUM_OF_SCHEMES]; ++ /**< Array of 'numOfSchemes' schemes handles for the ++ port to be bound to */ ++ bool directScheme; /**< TRUE for going from parser to a specific scheme, ++ regardless of parser result */ ++ t_Handle h_DirectScheme; /**< relevant only if direct == TRUE, Scheme handle, ++ as returned by FM_PCD_KgSetScheme */ ++} t_FmPortPcdKgParams; ++ ++/**************************************************************************//** ++ @Description struct for defining policer parameters ++*//***************************************************************************/ ++typedef struct t_FmPortPcdPlcrParams { ++ t_Handle h_Profile; /**< Selected profile handle */ ++} t_FmPortPcdPlcrParams; ++ ++/**************************************************************************//** ++ @Description struct for defining port PCD parameters ++*//***************************************************************************/ ++typedef struct t_FmPortPcdParams { ++ e_FmPortPcdSupport pcdSupport; /**< Relevant for Rx and offline ports only. ++ Describes the active PCD engines for this port. */ ++ t_Handle h_NetEnv; /**< HL Unused in PLCR only mode */ ++ t_FmPortPcdPrsParams *p_PrsParams; /**< Parser parameters for this port */ ++ t_FmPortPcdCcParams *p_CcParams; /**< Coarse classification parameters for this port */ ++ t_FmPortPcdKgParams *p_KgParams; /**< Keygen parameters for this port */ ++ t_FmPortPcdPlcrParams *p_PlcrParams; /**< Policer parameters for this port; Relevant for one of ++ following cases: ++ e_FM_PORT_PCD_SUPPORT_PLCR_ONLY or ++ e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR were selected, ++ or if any flow uses a KG scheme were policer ++ profile is not generated ++ ('bypassPlcrProfileGeneration selected'). */ ++ t_Handle h_IpReassemblyManip; /**< IP Reassembly manipulation */ ++#if (DPAA_VERSION >= 11) ++ t_Handle h_CapwapReassemblyManip;/**< CAPWAP Reassembly manipulation */ ++#endif /* (DPAA_VERSION >= 11) */ ++} t_FmPortPcdParams; ++ ++/**************************************************************************//** ++ @Description A structure for defining the Parser starting point ++*//***************************************************************************/ ++typedef struct t_FmPcdPrsStart { ++ uint8_t parsingOffset; /**< Number of bytes from beginning of packet to ++ start parsing */ ++ e_NetHeaderType firstPrsHdr; /**< The type of the first header axpected at ++ 'parsingOffset' */ ++} t_FmPcdPrsStart; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description struct for defining external buffer margins ++*//***************************************************************************/ ++typedef struct t_FmPortVSPAllocParams { ++ uint8_t numOfProfiles; /**< Number of Virtual Storage Profiles; must be a power of 2 */ ++ uint8_t dfltRelativeId; /**< The default Virtual-Storage-Profile-id dedicated to Rx/OP port ++ The same default Virtual-Storage-Profile-id will be for coupled Tx port ++ if relevant function called for Rx port */ ++ t_Handle h_FmTxPort; /**< Handle to coupled Tx Port; not relevant for OP port. */ ++} t_FmPortVSPAllocParams; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetPCD ++ ++ @Description Calling this routine defines the port's PCD configuration. ++ It changes it from its default configuration which is PCD ++ disabled (BMI to BMI) and configures it according to the passed ++ parameters. ++ ++ May be used for Rx and OP ports only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_FmPortPcd A Structure of parameters defining the port's PCD ++ configuration. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_SetPCD(t_Handle h_FmPort, t_FmPortPcdParams *p_FmPortPcd); ++ ++/**************************************************************************//** ++ @Function FM_PORT_DeletePCD ++ ++ @Description Calling this routine releases the port's PCD configuration. ++ The port returns to its default configuration which is PCD ++ disabled (BMI to BMI) and all PCD configuration is removed. ++ ++ May be used for Rx and OP ports which are ++ in PCD mode only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_DeletePCD(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_AttachPCD ++ ++ @Description This routine may be called after FM_PORT_DetachPCD was called, ++ to return to the originally configured PCD support flow. ++ The couple of routines are used to allow PCD configuration changes ++ that demand that PCD will not be used while changes take place. ++ ++ May be used for Rx and OP ports which are ++ in PCD mode only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++t_Error FM_PORT_AttachPCD(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_DetachPCD ++ ++ @Description Calling this routine detaches the port from its PCD functionality. ++ The port returns to its default flow which is BMI to BMI. ++ ++ May be used for Rx and OP ports which are ++ in PCD mode only ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_AttachPCD(). ++*//***************************************************************************/ ++t_Error FM_PORT_DetachPCD(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdPlcrAllocProfiles ++ ++ @Description This routine may be called only for ports that use the Policer in ++ order to allocate private policer profiles. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] numOfProfiles The number of required policer profiles ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init() and FM_PCD_Init(), ++ and before FM_PORT_SetPCD(). ++*//***************************************************************************/ ++t_Error FM_PORT_PcdPlcrAllocProfiles(t_Handle h_FmPort, uint16_t numOfProfiles); ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdPlcrFreeProfiles ++ ++ @Description This routine should be called for freeing private policer profiles. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init() and FM_PCD_Init(), ++ and before FM_PORT_SetPCD(). ++*//***************************************************************************/ ++t_Error FM_PORT_PcdPlcrFreeProfiles(t_Handle h_FmPort); ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Function FM_PORT_VSPAlloc ++ ++ @Description This routine allocated VSPs per port and forces the port to work ++ in VSP mode. Note that the port is initialized by default with the ++ physical-storage-profile only. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_Params A structure of parameters for allocation VSP's per port ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(), and before FM_PORT_SetPCD() ++ and also before FM_PORT_Enable(); i.e. the port should be disabled. ++*//***************************************************************************/ ++t_Error FM_PORT_VSPAlloc(t_Handle h_FmPort, t_FmPortVSPAllocParams *p_Params); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdKgModifyInitialScheme ++ ++ @Description This routine may be called only for ports that use the keygen in ++ order to change the initial scheme frame should be routed to. ++ The change may be of a scheme id (in case of direct mode), ++ from direct to indirect, or from indirect to direct - specifying the scheme id. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_FmPcdKgScheme A structure of parameters for defining whether ++ a scheme is direct/indirect, and if direct - scheme id. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init() and FM_PORT_SetPCD(). ++*//***************************************************************************/ ++t_Error FM_PORT_PcdKgModifyInitialScheme (t_Handle h_FmPort, t_FmPcdKgSchemeSelect *p_FmPcdKgScheme); ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdPlcrModifyInitialProfile ++ ++ @Description This routine may be called for ports with flows ++ e_FM_PORT_PCD_SUPPORT_PLCR_ONLY or e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR ++ only, to change the initial Policer profile frame should be ++ routed to. The change may be of a profile and/or absolute/direct ++ mode selection. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] h_Profile Policer profile handle ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init() and FM_PORT_SetPCD(). ++*//***************************************************************************/ ++t_Error FM_PORT_PcdPlcrModifyInitialProfile (t_Handle h_FmPort, t_Handle h_Profile); ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdCcModifyTree ++ ++ @Description This routine may be called for ports that use coarse classification tree ++ if the user wishes to replace the tree. The routine may not be called while port ++ receives packets using the PCD functionalities, therefor port must be first detached ++ from the PCD, only than the routine may be called, and than port be attached to PCD again. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] h_CcTree A CC tree that was already built. The tree id as returned from ++ the BuildTree routine. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(), FM_PORT_SetPCD() and FM_PORT_DetachPCD() ++*//***************************************************************************/ ++t_Error FM_PORT_PcdCcModifyTree (t_Handle h_FmPort, t_Handle h_CcTree); ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdKgBindSchemes ++ ++ @Description These routines may be called for adding more schemes for the ++ port to be bound to. The selected schemes are not added, ++ just this specific port starts using them. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_PortScheme A structure defining the list of schemes to be added. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init() and FM_PORT_SetPCD(). ++*//***************************************************************************/ ++t_Error FM_PORT_PcdKgBindSchemes (t_Handle h_FmPort, t_FmPcdPortSchemesParams *p_PortScheme); ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdKgUnbindSchemes ++ ++ @Description These routines may be called for adding more schemes for the ++ port to be bound to. The selected schemes are not removed or invalidated, ++ just this specific port stops using them. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_PortScheme A structure defining the list of schemes to be added. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init() and FM_PORT_SetPCD(). ++*//***************************************************************************/ ++t_Error FM_PORT_PcdKgUnbindSchemes (t_Handle h_FmPort, t_FmPcdPortSchemesParams *p_PortScheme); ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetIPv4OptionsCount ++ ++ @Description TODO ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[out] p_Ipv4OptionsCount will hold the counter value ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init() ++*//***************************************************************************/ ++t_Error FM_PORT_GetIPv4OptionsCount(t_Handle h_FmPort, uint32_t *p_Ipv4OptionsCount); ++ ++/** @} */ /* end of FM_PORT_pcd_runtime_control_grp group */ ++/** @} */ /* end of FM_PORT_runtime_control_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_PORT_runtime_data_grp FM Port Runtime Data-path Unit ++ ++ @Description FM Port Runtime data unit API functions, definitions and enums. ++ This API is valid only if working in Independent-Mode. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_PORT_ImTx ++ ++ @Description Tx function, called to transmit a data buffer on the port. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_Data A pointer to an LCP data buffer. ++ @Param[in] length Size of data for transmission. ++ @Param[in] lastBuffer Buffer position - TRUE for the last buffer ++ of a frame, including a single buffer frame ++ @Param[in] h_BufContext A handle of the user acossiated with this buffer ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++ NOTE - This routine can be used only when working in ++ Independent-Mode mode. ++*//***************************************************************************/ ++t_Error FM_PORT_ImTx( t_Handle h_FmPort, ++ uint8_t *p_Data, ++ uint16_t length, ++ bool lastBuffer, ++ t_Handle h_BufContext); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ImTxConf ++ ++ @Description Tx port confirmation routine, optional, may be called to verify ++ transmission of all frames. The procedure performed by this ++ routine will be performed automatically on next buffer transmission, ++ but if desired, calling this routine will invoke this action on ++ demand. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++ NOTE - This routine can be used only when working in ++ Independent-Mode mode. ++*//***************************************************************************/ ++void FM_PORT_ImTxConf(t_Handle h_FmPort); ++ ++/**************************************************************************//** ++ @Function FM_PORT_ImRx ++ ++ @Description Rx function, may be called to poll for received buffers. ++ Normally, Rx process is invoked by the driver on Rx interrupt. ++ Alternatively, this routine may be called on demand. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++ NOTE - This routine can be used only when working in ++ Independent-Mode mode. ++*//***************************************************************************/ ++t_Error FM_PORT_ImRx(t_Handle h_FmPort); ++ ++/** @} */ /* end of FM_PORT_runtime_data_grp group */ ++/** @} */ /* end of FM_PORT_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++ ++#ifdef NCSW_BACKWARD_COMPATIBLE_API ++#define FM_PORT_ConfigTxFifoDeqPipelineDepth FM_PORT_ConfigFifoDeqPipelineDepth ++#endif /* NCSW_BACKWARD_COMPATIBLE_API */ ++ ++ ++#endif /* __FM_PORT_EXT */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_rtc_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_rtc_ext.h +new file mode 100644 +index 0000000..72078ac +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_rtc_ext.h +@@ -0,0 +1,619 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File fm_rtc_ext.h ++ ++ @Description External definitions and API for FM RTC IEEE1588 Timer Module. ++ ++ @Cautions None. ++*//***************************************************************************/ ++ ++#ifndef __FM_RTC_EXT_H__ ++#define __FM_RTC_EXT_H__ ++ ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "fsl_fman_rtc.h" ++ ++/**************************************************************************//** ++ ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group fm_rtc_grp FM RTC ++ ++ @Description FM RTC functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group fm_rtc_init_grp FM RTC Initialization Unit ++ ++ @Description FM RTC initialization API. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description FM RTC Alarm Polarity Options. ++*//***************************************************************************/ ++typedef enum e_FmRtcAlarmPolarity ++{ ++ e_FM_RTC_ALARM_POLARITY_ACTIVE_HIGH = E_FMAN_RTC_ALARM_POLARITY_ACTIVE_HIGH, /**< Active-high output polarity */ ++ e_FM_RTC_ALARM_POLARITY_ACTIVE_LOW = E_FMAN_RTC_ALARM_POLARITY_ACTIVE_LOW /**< Active-low output polarity */ ++} e_FmRtcAlarmPolarity; ++ ++/**************************************************************************//** ++ @Description FM RTC Trigger Polarity Options. ++*//***************************************************************************/ ++typedef enum e_FmRtcTriggerPolarity ++{ ++ e_FM_RTC_TRIGGER_ON_RISING_EDGE = E_FMAN_RTC_TRIGGER_ON_RISING_EDGE, /**< Trigger on rising edge */ ++ e_FM_RTC_TRIGGER_ON_FALLING_EDGE = E_FMAN_RTC_TRIGGER_ON_FALLING_EDGE /**< Trigger on falling edge */ ++} e_FmRtcTriggerPolarity; ++ ++/**************************************************************************//** ++ @Description IEEE1588 Timer Module FM RTC Optional Clock Sources. ++*//***************************************************************************/ ++typedef enum e_FmSrcClock ++{ ++ e_FM_RTC_SOURCE_CLOCK_EXTERNAL = E_FMAN_RTC_SOURCE_CLOCK_EXTERNAL, /**< external high precision timer reference clock */ ++ e_FM_RTC_SOURCE_CLOCK_SYSTEM = E_FMAN_RTC_SOURCE_CLOCK_SYSTEM, /**< MAC system clock */ ++ e_FM_RTC_SOURCE_CLOCK_OSCILATOR = E_FMAN_RTC_SOURCE_CLOCK_OSCILATOR /**< RTC clock oscilator */ ++}e_FmSrcClk; ++ ++/**************************************************************************//** ++ @Description FM RTC configuration parameters structure. ++ ++ This structure should be passed to FM_RTC_Config(). ++*//***************************************************************************/ ++typedef struct t_FmRtcParams ++{ ++ t_Handle h_Fm; /**< FM Handle*/ ++ uintptr_t baseAddress; /**< Base address of FM RTC registers */ ++ t_Handle h_App; /**< A handle to an application layer object; This handle will ++ be passed by the driver upon calling the above callbacks */ ++} t_FmRtcParams; ++ ++ ++/**************************************************************************//** ++ @Function FM_RTC_Config ++ ++ @Description Configures the FM RTC module according to user's parameters. ++ ++ The driver assigns default values to some FM RTC parameters. ++ These parameters can be overwritten using the advanced ++ configuration routines. ++ ++ @Param[in] p_FmRtcParam - FM RTC configuration parameters. ++ ++ @Return Handle to the new FM RTC object; NULL pointer on failure. ++ ++ @Cautions None ++*//***************************************************************************/ ++t_Handle FM_RTC_Config(t_FmRtcParams *p_FmRtcParam); ++ ++/**************************************************************************//** ++ @Function FM_RTC_Init ++ ++ @Description Initializes the FM RTC driver and hardware. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_Init(t_Handle h_FmRtc); ++ ++/**************************************************************************//** ++ @Function FM_RTC_Free ++ ++ @Description Frees the FM RTC object and all allocated resources. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_Free(t_Handle h_FmRtc); ++ ++ ++/**************************************************************************//** ++ @Group fm_rtc_adv_config_grp FM RTC Advanced Configuration Unit ++ ++ @Description FM RTC advanced configuration functions. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigPeriod ++ ++ @Description Configures the period of the timestamp if different than ++ default [DEFAULT_clockPeriod]. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] period - Period in nano-seconds. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigPeriod(t_Handle h_FmRtc, uint32_t period); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigSourceClock ++ ++ @Description Configures the source clock of the RTC. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] srcClk - Source clock selection. ++ @Param[in] freqInMhz - the source-clock frequency (in MHz). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigSourceClock(t_Handle h_FmRtc, ++ e_FmSrcClk srcClk, ++ uint32_t freqInMhz); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigPulseRealignment ++ ++ @Description Configures the RTC to automatic FIPER pulse realignment in ++ response to timer adjustments [DEFAULT_pulseRealign] ++ ++ In this mode, the RTC clock is identical to the source clock. ++ This feature can be useful when the system contains an external ++ RTC with inherent frequency compensation. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] enable - TRUE to enable automatic realignment. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigPulseRealignment(t_Handle h_FmRtc, bool enable); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigFrequencyBypass ++ ++ @Description Configures the RTC to bypass the frequency compensation ++ mechanism. [DEFAULT_bypass] ++ ++ In this mode, the RTC clock is identical to the source clock. ++ This feature can be useful when the system contains an external ++ RTC with inherent frequency compensation. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] enabled - TRUE to bypass frequency compensation; ++ FALSE otherwise. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigFrequencyBypass(t_Handle h_FmRtc, bool enabled); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigInvertedInputClockPhase ++ ++ @Description Configures the RTC to invert the source clock phase on input. ++ [DEFAULT_invertInputClkPhase] ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] inverted - TRUE to invert the source clock phase on input. ++ FALSE otherwise. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigInvertedInputClockPhase(t_Handle h_FmRtc, bool inverted); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigInvertedOutputClockPhase ++ ++ @Description Configures the RTC to invert the output clock phase. ++ [DEFAULT_invertOutputClkPhase] ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] inverted - TRUE to invert the output clock phase. ++ FALSE otherwise. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigInvertedOutputClockPhase(t_Handle h_FmRtc, bool inverted); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigOutputClockDivisor ++ ++ @Description Configures the divisor for generating the output clock from ++ the RTC clock. [DEFAULT_outputClockDivisor] ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] divisor - Divisor for generation of the output clock. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigOutputClockDivisor(t_Handle h_FmRtc, uint16_t divisor); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigAlarmPolarity ++ ++ @Description Configures the polarity (active-high/active-low) of a specific ++ alarm signal. [DEFAULT_alarmPolarity] ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] alarmId - Alarm ID. ++ @Param[in] alarmPolarity - Alarm polarity. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigAlarmPolarity(t_Handle h_FmRtc, ++ uint8_t alarmId, ++ e_FmRtcAlarmPolarity alarmPolarity); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ConfigExternalTriggerPolarity ++ ++ @Description Configures the polarity (rising/falling edge) of a specific ++ external trigger signal. [DEFAULT_triggerPolarity] ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] triggerId - Trigger ID. ++ @Param[in] triggerPolarity - Trigger polarity. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously created using FM_RTC_Config(). ++*//***************************************************************************/ ++t_Error FM_RTC_ConfigExternalTriggerPolarity(t_Handle h_FmRtc, ++ uint8_t triggerId, ++ e_FmRtcTriggerPolarity triggerPolarity); ++ ++/** @} */ /* end of fm_rtc_adv_config_grp */ ++/** @} */ /* end of fm_rtc_init_grp */ ++ ++ ++/**************************************************************************//** ++ @Group fm_rtc_control_grp FM RTC Control Unit ++ ++ @Description FM RTC runtime control API. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function t_FmRtcExceptionsCallback ++ ++ @Description Exceptions user callback routine, used for RTC different mechanisms. ++ ++ @Param[in] h_App - User's application descriptor. ++ @Param[in] id - source id. ++*//***************************************************************************/ ++typedef void (t_FmRtcExceptionsCallback) ( t_Handle h_App, uint8_t id); ++ ++/**************************************************************************//** ++ @Description FM RTC alarm parameters. ++*//***************************************************************************/ ++typedef struct t_FmRtcAlarmParams { ++ uint8_t alarmId; /**< 0 or 1 */ ++ uint64_t alarmTime; /**< In nanoseconds, the time when the alarm ++ should go off - must be a multiple of ++ the RTC period */ ++ t_FmRtcExceptionsCallback *f_AlarmCallback; /**< This routine will be called when RTC ++ reaches alarmTime */ ++ bool clearOnExpiration; /**< TRUE to turn off the alarm once expired. */ ++} t_FmRtcAlarmParams; ++ ++/**************************************************************************//** ++ @Description FM RTC Periodic Pulse parameters. ++*//***************************************************************************/ ++typedef struct t_FmRtcPeriodicPulseParams { ++ uint8_t periodicPulseId; /**< 0 or 1 */ ++ uint64_t periodicPulsePeriod; /**< In Nanoseconds. Must be ++ a multiple of the RTC period */ ++ t_FmRtcExceptionsCallback *f_PeriodicPulseCallback; /**< This routine will be called every ++ periodicPulsePeriod. */ ++} t_FmRtcPeriodicPulseParams; ++ ++/**************************************************************************//** ++ @Description FM RTC Periodic Pulse parameters. ++*//***************************************************************************/ ++typedef struct t_FmRtcExternalTriggerParams { ++ uint8_t externalTriggerId; /**< 0 or 1 */ ++ bool usePulseAsInput; /**< Use the pulse interrupt instead of ++ an external signal */ ++ t_FmRtcExceptionsCallback *f_ExternalTriggerCallback; /**< This routine will be called every ++ periodicPulsePeriod. */ ++} t_FmRtcExternalTriggerParams; ++ ++ ++/**************************************************************************//** ++ @Function FM_RTC_Enable ++ ++ @Description Enable the RTC (time count is started). ++ ++ The user can select to resume the time count from previous ++ point, or to restart the time count. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] resetClock - Restart the time count from zero. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_Enable(t_Handle h_FmRtc, bool resetClock); ++ ++/**************************************************************************//** ++ @Function FM_RTC_Disable ++ ++ @Description Disables the RTC (time count is stopped). ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_Disable(t_Handle h_FmRtc); ++ ++/**************************************************************************//** ++ @Function FM_RTC_SetClockOffset ++ ++ @Description Sets the clock offset (usually relative to another clock). ++ ++ The user can pass a negative offset value. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] offset - New clock offset (in nanoseconds). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_SetClockOffset(t_Handle h_FmRtc, int64_t offset); ++ ++/**************************************************************************//** ++ @Function FM_RTC_SetAlarm ++ ++ @Description Schedules an alarm event to a given RTC time. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] p_FmRtcAlarmParams - Alarm parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++ Must be called only prior to FM_RTC_Enable(). ++*//***************************************************************************/ ++t_Error FM_RTC_SetAlarm(t_Handle h_FmRtc, t_FmRtcAlarmParams *p_FmRtcAlarmParams); ++ ++/**************************************************************************//** ++ @Function FM_RTC_SetPeriodicPulse ++ ++ @Description Sets a periodic pulse. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] p_FmRtcPeriodicPulseParams - Periodic pulse parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++ Must be called only prior to FM_RTC_Enable(). ++*//***************************************************************************/ ++t_Error FM_RTC_SetPeriodicPulse(t_Handle h_FmRtc, t_FmRtcPeriodicPulseParams *p_FmRtcPeriodicPulseParams); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ClearPeriodicPulse ++ ++ @Description Clears a periodic pulse. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] periodicPulseId - Periodic pulse id. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_ClearPeriodicPulse(t_Handle h_FmRtc, uint8_t periodicPulseId); ++ ++/**************************************************************************//** ++ @Function FM_RTC_SetExternalTrigger ++ ++ @Description Sets an external trigger indication and define a callback ++ routine to be called on such event. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] p_FmRtcExternalTriggerParams - External Trigger parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_SetExternalTrigger(t_Handle h_FmRtc, t_FmRtcExternalTriggerParams *p_FmRtcExternalTriggerParams); ++ ++/**************************************************************************//** ++ @Function FM_RTC_ClearExternalTrigger ++ ++ @Description Clears external trigger indication. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] id - External Trigger id. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_ClearExternalTrigger(t_Handle h_FmRtc, uint8_t id); ++ ++/**************************************************************************//** ++ @Function FM_RTC_GetExternalTriggerTimeStamp ++ ++ @Description Reads the External Trigger TimeStamp. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] triggerId - External Trigger id. ++ @Param[out] p_TimeStamp - External Trigger timestamp (in nanoseconds). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_GetExternalTriggerTimeStamp(t_Handle h_FmRtc, ++ uint8_t triggerId, ++ uint64_t *p_TimeStamp); ++ ++/**************************************************************************//** ++ @Function FM_RTC_GetCurrentTime ++ ++ @Description Returns the current RTC time. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[out] p_Ts - returned time stamp (in nanoseconds). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_GetCurrentTime(t_Handle h_FmRtc, uint64_t *p_Ts); ++ ++/**************************************************************************//** ++ @Function FM_RTC_SetCurrentTime ++ ++ @Description Sets the current RTC time. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] ts - The new time stamp (in nanoseconds). ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_SetCurrentTime(t_Handle h_FmRtc, uint64_t ts); ++ ++/**************************************************************************//** ++ @Function FM_RTC_GetFreqCompensation ++ ++ @Description Retrieves the frequency compensation value ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[out] p_Compensation - A pointer to the returned value of compensation. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_GetFreqCompensation(t_Handle h_FmRtc, uint32_t *p_Compensation); ++ ++/**************************************************************************//** ++ @Function FM_RTC_SetFreqCompensation ++ ++ @Description Sets a new frequency compensation value. ++ ++ @Param[in] h_FmRtc - Handle to FM RTC object. ++ @Param[in] freqCompensation - The new frequency compensation value to set. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_SetFreqCompensation(t_Handle h_FmRtc, uint32_t freqCompensation); ++ ++#ifdef CONFIG_PTP_1588_CLOCK_DPAA ++/**************************************************************************//** ++*@Function FM_RTC_EnableInterrupt ++* ++*@Description Enable interrupt of FM RTC. ++* ++*@Param[in] h_FmRtc - Handle to FM RTC object. ++*@Param[in] events - Interrupt events. ++* ++*@Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_RTC_EnableInterrupt(t_Handle h_FmRtc, uint32_t events); ++ ++/**************************************************************************//** ++*@Function FM_RTC_DisableInterrupt ++* ++*@Description Disable interrupt of FM RTC. ++* ++*@Param[in] h_FmRtc - Handle to FM RTC object. ++*@Param[in] events - Interrupt events. ++* ++*@Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_RTC_DisableInterrupt(t_Handle h_FmRtc, uint32_t events); ++#endif ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++/**************************************************************************//** ++ @Function FM_RTC_DumpRegs ++ ++ @Description Dumps all FM registers ++ ++ @Param[in] h_FmRtc A handle to an FM RTC Module. ++ ++ @Return E_OK on success; ++ ++ @Cautions Allowed only FM_Init(). ++*//***************************************************************************/ ++t_Error FM_RTC_DumpRegs(t_Handle h_FmRtc); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++/** @} */ /* end of fm_rtc_control_grp */ ++/** @} */ /* end of fm_rtc_grp */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++#endif /* __FM_RTC_EXT_H__ */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_vsp_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_vsp_ext.h +new file mode 100644 +index 0000000..f9aed03 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_vsp_ext.h +@@ -0,0 +1,411 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File fm_vsp_ext.h ++ ++ @Description FM Virtual Storage-Profile ... ++*//***************************************************************************/ ++#ifndef __FM_VSP_EXT_H ++#define __FM_VSP_EXT_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "debug_ext.h" ++ ++#include "fm_ext.h" ++ ++ ++/**************************************************************************//** ++ ++ @Group FM_grp Frame Manager API ++ ++ @Description FM API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_VSP_grp FM Virtual-Storage-Profile ++ ++ @Description FM Virtual-Storage-Profile API ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_VSP_init_grp FM VSP Initialization Unit ++ ++ @Description FM VSP initialization API. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Virtual Storage Profile ++*//***************************************************************************/ ++typedef struct t_FmVspParams { ++ t_Handle h_Fm; /**< A handle to the FM object this VSP related to */ ++ t_FmExtPools extBufPools; /**< Which external buffer pools are used ++ (up to FM_PORT_MAX_NUM_OF_EXT_POOLS), and their sizes. ++ parameter associated with Rx / OP port */ ++ uint16_t liodnOffset; /**< VSP's LIODN offset */ ++ struct { ++ e_FmPortType portType; /**< Port type */ ++ uint8_t portId; /**< Port Id - relative to type */ ++ } portParams; ++ uint8_t relativeProfileId; /**< VSP Id - relative to VSP's range ++ defined in relevant FM object */ ++} t_FmVspParams; ++ ++ ++/**************************************************************************//** ++ @Function FM_VSP_Config ++ ++ @Description Creates descriptor for the FM VSP module. ++ ++ The routine returns a handle (descriptor) to the FM VSP object. ++ This descriptor must be passed as first parameter to all other ++ FM VSP function calls. ++ ++ No actual initialization or configuration of FM hardware is ++ done by this routine. ++ ++ at Param[in] p_FmVspParams Pointer to data structure of parameters ++ ++ @Retval Handle to FM VSP object, or NULL for Failure. ++*//***************************************************************************/ ++t_Handle FM_VSP_Config(t_FmVspParams *p_FmVspParams); ++ ++/**************************************************************************//** ++ @Function FM_VSP_Init ++ ++ @Description Initializes the FM VSP module ++ ++ @Param[in] h_FmVsp - FM VSP module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_VSP_Init(t_Handle h_FmVsp); ++ ++/**************************************************************************//** ++ @Function FM_VSP_Free ++ ++ @Description Frees all resources that were assigned to FM VSP module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmVsp - FM VSP module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error FM_VSP_Free(t_Handle h_FmVsp); ++ ++ ++/**************************************************************************//** ++ @Group FM_VSP_adv_config_grp FM VSP Advanced Configuration Unit ++ ++ @Description FM VSP advanced configuration functions. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigBufferPrefixContent ++ ++ @Description Defines the structure, size and content of the application buffer. ++ ++ The prefix will ++ In VSPs defined for Tx ports, if 'passPrsResult', the application ++ should set a value to their offsets in the prefix of ++ the FM will save the first 'privDataSize', than, ++ depending on 'passPrsResult' and 'passTimeStamp', copy parse result ++ and timeStamp, and the packet itself (in this order), to the ++ application buffer, and to offset. ++ ++ Calling this routine changes the buffer margins definitions ++ in the internal driver data base from its default ++ configuration: Data size: [DEFAULT_FM_SP_bufferPrefixContent_privDataSize] ++ Pass Parser result: [DEFAULT_FM_SP_bufferPrefixContent_passPrsResult]. ++ Pass timestamp: [DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp]. ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in,out] p_FmBufferPrefixContent A structure of parameters describing the ++ structure of the buffer. ++ Out parameter: Start margin - offset ++ of data from start of external buffer. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigBufferPrefixContent(t_Handle h_FmVsp, ++ t_FmBufferPrefixContent *p_FmBufferPrefixContent); ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigDmaSwapData ++ ++ @Description Calling this routine changes the DMA swap data parameter ++ in the internal driver data base from its default ++ configuration [DEFAULT_FM_SP_dmaSwapData] ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in] swapData New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigDmaSwapData(t_Handle h_FmVsp, e_FmDmaSwapOption swapData); ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigDmaIcCacheAttr ++ ++ @Description Calling this routine changes the internal context cache ++ attribute parameter in the internal driver data base ++ from its default configuration [DEFAULT_FM_SP_dmaIntContextCacheAttr] ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in] intContextCacheAttr New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigDmaIcCacheAttr(t_Handle h_FmVsp, ++ e_FmDmaCacheOption intContextCacheAttr); ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigDmaHdrAttr ++ ++ @Description Calling this routine changes the header cache ++ attribute parameter in the internal driver data base ++ from its default configuration [DEFAULT_FM_SP_dmaHeaderCacheAttr] ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in] headerCacheAttr New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigDmaHdrAttr(t_Handle h_FmVsp, e_FmDmaCacheOption headerCacheAttr); ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigDmaScatterGatherAttr ++ ++ @Description Calling this routine changes the scatter gather cache ++ attribute parameter in the internal driver data base ++ from its default configuration [DEFAULT_FM_SP_dmaScatterGatherCacheAttr] ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in] scatterGatherCacheAttr New selection ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigDmaScatterGatherAttr(t_Handle h_FmVsp, ++ e_FmDmaCacheOption scatterGatherCacheAttr); ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigDmaWriteOptimize ++ ++ @Description Calling this routine changes the write optimization ++ parameter in the internal driver data base ++ from its default configuration: optimize = [DEFAULT_FM_SP_dmaWriteOptimize] ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in] optimize TRUE to enable optimization, FALSE for normal operation ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigDmaWriteOptimize(t_Handle h_FmVsp, bool optimize); ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigNoScatherGather ++ ++ @Description Calling this routine changes the possibility to receive S/G frame ++ in the internal driver data base ++ from its default configuration: optimize = [DEFAULT_FM_SP_noScatherGather] ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in] noScatherGather TRUE to operate without scatter/gather capability. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigNoScatherGather(t_Handle h_FmVsp, bool noScatherGather); ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigPoolDepletion ++ ++ @Description Calling this routine enables pause frame generation depending on the ++ depletion status of BM pools. It also defines the conditions to activate ++ this functionality. By default, this functionality is disabled. ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in] p_BufPoolDepletion A structure of pool depletion parameters ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigPoolDepletion(t_Handle h_FmVsp, t_FmBufPoolDepletion *p_BufPoolDepletion); ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigBackupPools ++ ++ @Description Calling this routine allows the configuration of some of the BM pools ++ defined for this port as backup pools. ++ A pool configured to be a backup pool will be used only if all other ++ enabled non-backup pools are depleted. ++ ++ @Param[in] h_FmVsp A handle to a FM VSP module. ++ @Param[in] p_BackupBmPools An array of pool id's. All pools specified here will ++ be defined as backup pools. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++t_Error FM_VSP_ConfigBackupPools(t_Handle h_FmVsp, t_FmBackupBmPools *p_BackupBmPools); ++ ++/** @} */ /* end of FM_VSP_adv_config_grp group */ ++/** @} */ /* end of FM_VSP_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_VSP_control_grp FM VSP Control Unit ++ ++ @Description FM VSP runtime control API. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function FM_VSP_GetBufferDataOffset ++ ++ @Description Relevant for Rx ports. ++ Returns the data offset from the beginning of the data buffer ++ ++ @Param[in] h_FmVsp - FM PORT module descriptor ++ ++ @Return data offset. ++ ++ @Cautions Allowed only following FM_VSP_Init(). ++*//***************************************************************************/ ++uint32_t FM_VSP_GetBufferDataOffset(t_Handle h_FmVsp); ++ ++/**************************************************************************//** ++ @Function FM_VSP_GetBufferICInfo ++ ++ @Description Returns the Internal Context offset from the beginning of the data buffer ++ ++ @Param[in] h_FmVsp - FM PORT module descriptor ++ @Param[in] p_Data - A pointer to the data buffer. ++ ++ @Return Internal context info pointer on success, NULL if 'allOtherInfo' was not ++ configured for this port. ++ ++ @Cautions Allowed only following FM_VSP_Init(). ++*//***************************************************************************/ ++uint8_t * FM_VSP_GetBufferICInfo(t_Handle h_FmVsp, char *p_Data); ++ ++/**************************************************************************//** ++ @Function FM_VSP_GetBufferPrsResult ++ ++ @Description Returns the pointer to the parse result in the data buffer. ++ In Rx ports this is relevant after reception, if parse ++ result is configured to be part of the data passed to the ++ application. For non Rx ports it may be used to get the pointer ++ of the area in the buffer where parse result should be ++ initialized - if so configured. ++ See FM_VSP_ConfigBufferPrefixContent for data buffer prefix ++ configuration. ++ ++ @Param[in] h_FmVsp - FM PORT module descriptor ++ @Param[in] p_Data - A pointer to the data buffer. ++ ++ @Return Parse result pointer on success, NULL if parse result was not ++ configured for this port. ++ ++ @Cautions Allowed only following FM_VSP_Init(). ++*//***************************************************************************/ ++t_FmPrsResult * FM_VSP_GetBufferPrsResult(t_Handle h_FmVsp, char *p_Data); ++ ++/**************************************************************************//** ++ @Function FM_VSP_GetBufferTimeStamp ++ ++ @Description Returns the time stamp in the data buffer. ++ Relevant for Rx ports for getting the buffer time stamp. ++ See FM_VSP_ConfigBufferPrefixContent for data buffer prefix ++ configuration. ++ ++ @Param[in] h_FmVsp - FM PORT module descriptor ++ @Param[in] p_Data - A pointer to the data buffer. ++ ++ @Return A pointer to the hash result on success, NULL otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Init(). ++*//***************************************************************************/ ++uint64_t * FM_VSP_GetBufferTimeStamp(t_Handle h_FmVsp, char *p_Data); ++ ++/**************************************************************************//** ++ @Function FM_VSP_GetBufferHashResult ++ ++ @Description Given a data buffer, on the condition that hash result was defined ++ as a part of the buffer content (see FM_VSP_ConfigBufferPrefixContent) ++ this routine will return the pointer to the hash result location in the ++ buffer prefix. ++ ++ @Param[in] h_FmVsp - FM PORT module descriptor ++ @Param[in] p_Data - A pointer to the data buffer. ++ ++ @Return A pointer to the hash result on success, NULL otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Init(). ++*//***************************************************************************/ ++uint8_t * FM_VSP_GetBufferHashResult(t_Handle h_FmVsp, char *p_Data); ++ ++ ++/** @} */ /* end of FM_VSP_control_grp group */ ++/** @} */ /* end of FM_VSP_grp group */ ++/** @} */ /* end of FM_grp group */ ++ ++ ++#endif /* __FM_VSP_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/mii_acc_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/mii_acc_ext.h +new file mode 100644 +index 0000000..f635d3c +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/mii_acc_ext.h +@@ -0,0 +1,76 @@ ++/* ++ * Copyright 2008-2012 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 __MII_ACC_EXT_H ++#define __MII_ACC_EXT_H ++ ++ ++/**************************************************************************//** ++ @Function MII_ReadPhyReg ++ ++ @Description This routine is called to read a specified PHY ++ register value. ++ ++ @Param[in] h_MiiAccess - Handle to MII configuration access registers ++ @Param[in] phyAddr - PHY address (0-31). ++ @Param[in] reg - PHY register to read ++ @Param[out] p_Data - Gets the register value. ++ ++ @Return Always zero (success). ++*//***************************************************************************/ ++int MII_ReadPhyReg(t_Handle h_MiiAccess, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t *p_Data); ++ ++/**************************************************************************//** ++ @Function MII_WritePhyReg ++ ++ @Description This routine is called to write data to a specified PHY ++ register. ++ ++ @Param[in] h_MiiAccess - Handle to MII configuration access registers ++ @Param[in] phyAddr - PHY address (0-31). ++ @Param[in] reg - PHY register to write ++ @Param[in] data - Data to write in register. ++ ++ @Return Always zero (success). ++*//***************************************************************************/ ++int MII_WritePhyReg(t_Handle h_MiiAccess, ++ uint8_t phyAddr, ++ uint8_t reg, ++ uint16_t data); ++ ++ ++#endif /* __MII_ACC_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/core_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/core_ext.h +new file mode 100644 +index 0000000..42174cf +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/core_ext.h +@@ -0,0 +1,86 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File core_ext.h ++ ++ @Description Generic interface to basic core operations. ++ ++ The system integrator must ensure that this interface is ++ mapped to a specific core implementation, by including the ++ appropriate header file. ++*//***************************************************************************/ ++#ifndef __CORE_EXT_H ++#define __CORE_EXT_H ++ ++ ++#ifdef NCSW_PPC_CORE ++#include "ppc_ext.h" ++#elif defined(NCSW_VXWORKS) ++#include "core_vxw_ext.h" ++#else ++#error "Core is not defined!" ++#endif /* NCSW_CORE */ ++ ++#if (!defined(CORE_IS_LITTLE_ENDIAN) && !defined(CORE_IS_BIG_ENDIAN)) ++#error "Must define core as little-endian or big-endian!" ++#endif /* (!defined(CORE_IS_LITTLE_ENDIAN) && ... */ ++ ++#ifndef CORE_CACHELINE_SIZE ++#error "Must define the core cache-line size!" ++#endif /* !CORE_CACHELINE_SIZE */ ++ ++ ++/**************************************************************************//** ++ @Function CORE_GetId ++ ++ @Description Returns the core ID in the system. ++ ++ @Return Core ID. ++*//***************************************************************************/ ++uint32_t CORE_GetId(void); ++ ++/**************************************************************************//** ++ @Function CORE_MemoryBarrier ++ ++ @Description This routine will cause the core to stop executing any commands ++ until all previous memory read/write commands are completely out ++ of the core's pipeline. ++ ++ @Return None. ++*//***************************************************************************/ ++void CORE_MemoryBarrier(void); ++#define fsl_mem_core_barrier() CORE_MemoryBarrier() ++ ++#endif /* __CORE_EXT_H */ ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/cores/e500v2_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/cores/e500v2_ext.h +new file mode 100644 +index 0000000..e79b1dd +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/cores/e500v2_ext.h +@@ -0,0 +1,476 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File e500v2_ext.h ++ ++ @Description E500 external definitions prototypes ++ This file is not included by the E500 ++ source file as it is an assembly file. It is used ++ only for prototypes exposure, for inclusion ++ by user and other modules. ++*//***************************************************************************/ ++ ++#ifndef __E500V2_EXT_H ++#define __E500V2_EXT_H ++ ++#include "std_ext.h" ++ ++ ++/* Layer 1 Cache Manipulations ++ *============================== ++ * Should not be called directly by the user. ++ */ ++void L1DCache_Invalidate (void); ++void L1ICache_Invalidate(void); ++void L1DCache_Enable(void); ++void L1ICache_Enable(void); ++void L1DCache_Disable(void); ++void L1ICache_Disable(void); ++void L1DCache_Flush(void); ++void L1ICache_Flush(void); ++uint32_t L1ICache_IsEnabled(void); ++uint32_t L1DCache_IsEnabled(void); ++/* ++ * ++ */ ++uint32_t L1DCache_LineLock(uint32_t addr); ++uint32_t L1ICache_LineLock(uint32_t addr); ++void L1Cache_BroadCastEnable(void); ++void L1Cache_BroadCastDisable(void); ++ ++ ++#define CORE_DCacheEnable E500_DCacheEnable ++#define CORE_ICacheEnable E500_ICacheEnable ++#define CORE_DCacheDisable E500_DCacheDisable ++#define CORE_ICacheDisable E500_ICacheDisable ++#define CORE_GetId E500_GetId ++#define CORE_TestAndSet E500_TestAndSet ++#define CORE_MemoryBarrier E500_MemoryBarrier ++#define CORE_InstructionSync E500_InstructionSync ++ ++#define CORE_SetDozeMode E500_SetDozeMode ++#define CORE_SetNapMode E500_SetNapMode ++#define CORE_SetSleepMode E500_SetSleepMode ++#define CORE_SetJogMode E500_SetJogMode ++#define CORE_SetDeepSleepMode E500_SetDeepSleepMode ++ ++#define CORE_RecoverDozeMode E500_RecoverDozeMode ++#define CORE_RecoverNapMode E500_RecoverNapMode ++#define CORE_RecoverSleepMode E500_RecoverSleepMode ++#define CORE_RecoverJogMode E500_RecoverJogMode ++ ++void E500_SetDozeMode(void); ++void E500_SetNapMode(void); ++void E500_SetSleepMode(void); ++void E500_SetJogMode(void); ++t_Error E500_SetDeepSleepMode(uint32_t bptrAddress); ++ ++void E500_RecoverDozeMode(void); ++void E500_RecoverNapMode(void); ++void E500_RecoverSleepMode(void); ++void E500_RecoverJogMode(void); ++ ++ ++/**************************************************************************//** ++ @Group E500_id E500 Application Programming Interface ++ ++ @Description E500 API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group E500_init_grp E500 Initialization Unit ++ ++ @Description E500 initialization unit API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++ ++/**************************************************************************//** ++ @Function E500_DCacheEnable ++ ++ @Description Enables the data cache for memory pages that are ++ not cache inhibited. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_DCacheEnable(void); ++ ++/**************************************************************************//** ++ @Function E500_ICacheEnable ++ ++ @Description Enables the instruction cache for memory pages that are ++ not cache inhibited. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_ICacheEnable(void); ++ ++/**************************************************************************//** ++ @Function E500_DCacheDisable ++ ++ @Description Disables the data cache. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_DCacheDisable(void); ++ ++/**************************************************************************//** ++ @Function E500_ICacheDisable ++ ++ @Description Disables the instruction cache. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_ICacheDisable(void); ++ ++/**************************************************************************//** ++ @Function E500_DCacheFlush ++ ++ @Description Flushes the data cache ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_DCacheFlush(void); ++ ++/**************************************************************************//** ++ @Function E500_ICacheFlush ++ ++ @Description Flushes the instruction cache. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_ICacheFlush(void); ++ ++/**************************************************************************//** ++ @Function E500_DCacheSetStashId ++ ++ @Description Set Stash Id for data cache ++ ++ @Param[in] stashId the stash id to be set. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_DCacheSetStashId(uint8_t stashId); ++ ++/**************************************************************************//** ++ @Description E500mc L2 Cache Operation Mode ++*//***************************************************************************/ ++typedef enum e_E500mcL2CacheMode ++{ ++ e_L2_CACHE_MODE_DATA_ONLY = 0x00000001, /**< Cache data only */ ++ e_L2_CACHE_MODE_INST_ONLY = 0x00000002, /**< Cache instructions only */ ++ e_L2_CACHE_MODE_DATA_AND_INST = 0x00000003 /**< Cache data and instructions */ ++} e_E500mcL2CacheMode; ++ ++#if defined(CORE_E500MC) || defined(CORE_E5500) ++/**************************************************************************//** ++ @Function E500_L2CacheEnable ++ ++ @Description Enables the cache for memory pages that are not cache inhibited. ++ ++ @param[in] mode - L2 cache mode: data only, instruction only or instruction and data. ++ ++ @Return None. ++ ++ @Cautions This routine must be call only ONCE for both caches. I.e. it is ++ not possible to call this routine for i-cache and than to call ++ again for d-cache; The second call will override the first one. ++*//***************************************************************************/ ++void E500_L2CacheEnable(e_E500mcL2CacheMode mode); ++ ++/**************************************************************************//** ++ @Function E500_L2CacheDisable ++ ++ @Description Disables the cache (data instruction or both). ++ ++ @Return None. ++ ++*//***************************************************************************/ ++void E500_L2CacheDisable(void); ++ ++/**************************************************************************//** ++ @Function E500_L2CacheFlush ++ ++ @Description Flushes the cache. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_L2CacheFlush(void); ++ ++/**************************************************************************//** ++ @Function E500_L2SetStashId ++ ++ @Description Set Stash Id ++ ++ @Param[in] stashId the stash id to be set. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_L2SetStashId(uint8_t stashId); ++#endif /* defined(CORE_E500MC) || defined(CORE_E5500) */ ++ ++#ifdef CORE_E6500 ++/**************************************************************************//** ++ @Function E6500_L2CacheEnable ++ ++ @Description Enables the cache for memory pages that are not cache inhibited. ++ ++ @param[in] mode - L2 cache mode: support data & instruction only. ++ ++ @Return None. ++ ++ @Cautions This routine must be call only ONCE for both caches. I.e. it is ++ not possible to call this routine for i-cache and than to call ++ again for d-cache; The second call will override the first one. ++*//***************************************************************************/ ++void E6500_L2CacheEnable(uintptr_t clusterBase); ++ ++/**************************************************************************//** ++ @Function E6500_L2CacheDisable ++ ++ @Description Disables the cache (data instruction or both). ++ ++ @Return None. ++ ++*//***************************************************************************/ ++void E6500_L2CacheDisable(uintptr_t clusterBase); ++ ++/**************************************************************************//** ++ @Function E6500_L2CacheFlush ++ ++ @Description Flushes the cache. ++ ++ @Return None. ++*//***************************************************************************/ ++void E6500_L2CacheFlush(uintptr_t clusterBase); ++ ++/**************************************************************************//** ++ @Function E6500_L2SetStashId ++ ++ @Description Set Stash Id ++ ++ @Param[in] stashId the stash id to be set. ++ ++ @Return None. ++*//***************************************************************************/ ++void E6500_L2SetStashId(uintptr_t clusterBase, uint8_t stashId); ++ ++/**************************************************************************//** ++ @Function E6500_GetCcsrBase ++ ++ @Description Obtain SoC CCSR base address ++ ++ @Param[in] None. ++ ++ @Return Physical CCSR base address. ++*//***************************************************************************/ ++physAddress_t E6500_GetCcsrBase(void); ++#endif /* CORE_E6500 */ ++ ++/**************************************************************************//** ++ @Function E500_AddressBusStreamingEnable ++ ++ @Description Enables address bus streaming on the CCB. ++ ++ This setting, along with the ECM streaming configuration ++ parameters, enables address bus streaming on the CCB. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_AddressBusStreamingEnable(void); ++ ++/**************************************************************************//** ++ @Function E500_AddressBusStreamingDisable ++ ++ @Description Disables address bus streaming on the CCB. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_AddressBusStreamingDisable(void); ++ ++/**************************************************************************//** ++ @Function E500_AddressBroadcastEnable ++ ++ @Description Enables address broadcast. ++ ++ The e500 broadcasts cache management instructions (dcbst, dcblc ++ (CT = 1), icblc (CT = 1), dcbf, dcbi, mbar, msync, tlbsync, icbi) ++ based on ABE. ABE must be set to allow management of external ++ L2 caches. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_AddressBroadcastEnable(void); ++ ++/**************************************************************************//** ++ @Function E500_AddressBroadcastDisable ++ ++ @Description Disables address broadcast. ++ ++ The e500 broadcasts cache management instructions (dcbst, dcblc ++ (CT = 1), icblc (CT = 1), dcbf, dcbi, mbar, msync, tlbsync, icbi) ++ based on ABE. ABE must be set to allow management of external ++ L2 caches. ++ ++ @Return None. ++*//***************************************************************************/ ++void E500_AddressBroadcastDisable(void); ++ ++/**************************************************************************//** ++ @Function E500_IsTaskletSupported ++ ++ @Description Checks if tasklets are supported by the e500 interrupt handler. ++ ++ @Retval TRUE - Tasklets are supported. ++ @Retval FALSE - Tasklets are not supported. ++*//***************************************************************************/ ++bool E500_IsTaskletSupported(void); ++ ++void E500_EnableTimeBase(void); ++void E500_DisableTimeBase(void); ++ ++uint64_t E500_GetTimeBaseTime(void); ++ ++void E500_GenericIntrInit(void); ++ ++t_Error E500_SetIntr(int ppcIntrSrc, ++ void (* Isr)(t_Handle handle), ++ t_Handle handle); ++ ++t_Error E500_ClearIntr(int ppcIntrSrc); ++ ++/**************************************************************************//** ++ @Function E500_GenericIntrHandler ++ ++ @Description This is the general e500 interrupt handler. ++ ++ It is called by the main assembly interrupt handler ++ when an exception occurs and no other function has been ++ assigned to this exception. ++ ++ @Param intrEntry - (In) The exception interrupt vector entry. ++*//***************************************************************************/ ++void E500_GenericIntrHandler(uint32_t intrEntry); ++ ++/**************************************************************************//** ++ @Function CriticalIntr ++ ++ @Description This is the specific critical e500 interrupt handler. ++ ++ It is called by the main assembly interrupt handler ++ when an critical interrupt. ++ ++ @Param intrEntry - (In) The exception interrupt vector entry. ++*//***************************************************************************/ ++void CriticalIntr(uint32_t intrEntry); ++ ++ ++/**************************************************************************//** ++ @Function E500_GetId ++ ++ @Description Returns the core ID in the system. ++ ++ @Return Core ID. ++*//***************************************************************************/ ++uint32_t E500_GetId(void); ++ ++/**************************************************************************//** ++ @Function E500_TestAndSet ++ ++ @Description This routine tries to atomically test-and-set an integer ++ in memory to a non-zero value. ++ ++ The memory will be set only if it is tested as zero, in which ++ case the routine returns the new non-zero value; otherwise the ++ routine returns zero. ++ ++ @Param[in] p - pointer to a volatile int in memory, on which test-and-set ++ operation should be made. ++ ++ @Retval Zero - Operation failed - memory was already set. ++ @Retval Non-zero - Operation succeeded - memory has been set. ++*//***************************************************************************/ ++int E500_TestAndSet(volatile int *p); ++ ++/**************************************************************************//** ++ @Function E500_MemoryBarrier ++ ++ @Description This routine will cause the core to stop executing any commands ++ until all previous memory read/write commands are completely out ++ of the core's pipeline. ++ ++ @Return None. ++*//***************************************************************************/ ++static __inline__ void E500_MemoryBarrier(void) ++{ ++#ifndef CORE_E500V2 ++ __asm__ ("mbar 1"); ++#else /* CORE_E500V2 */ ++ /**** ERRATA WORK AROUND START ****/ ++ /* ERRATA num: CPU1 */ ++ /* Description: "mbar MO = 1" instruction fails to order caching-inhibited ++ guarded loads and stores. */ ++ ++ /* "msync" instruction is used instead */ ++ ++ __asm__ ("msync"); ++ ++ /**** ERRATA WORK AROUND END ****/ ++#endif /* CORE_E500V2 */ ++} ++ ++/**************************************************************************//** ++ @Function E500_InstructionSync ++ ++ @Description This routine will cause the core to wait for previous instructions ++ (including any interrupts they generate) to complete before the ++ synchronization command executes, which purges all instructions ++ from the processor's pipeline and refetches the next instruction. ++ ++ @Return None. ++*//***************************************************************************/ ++static __inline__ void E500_InstructionSync(void) ++{ ++ __asm__ ("isync"); ++} ++ ++ ++/** @} */ /* end of E500_init_grp group */ ++/** @} */ /* end of E500_grp group */ ++ ++ ++#endif /* __E500V2_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/cores/ppc_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/cores/ppc_ext.h +new file mode 100644 +index 0000000..9344b3a +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/cores/ppc_ext.h +@@ -0,0 +1,141 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File ppc_ext.h ++ ++ @Description Core API for PowerPC cores ++ ++ These routines must be implemented by each specific PowerPC ++ core driver. ++*//***************************************************************************/ ++#ifndef __PPC_EXT_H ++#define __PPC_EXT_H ++ ++#include "part_ext.h" ++ ++ ++#define CORE_IS_BIG_ENDIAN ++ ++#if defined(CORE_E300) || defined(CORE_E500V2) ++#define CORE_CACHELINE_SIZE 32 ++#elif defined(CORE_E500MC) || defined(CORE_E5500) || defined(CORE_E6500) ++#define CORE_CACHELINE_SIZE 64 ++#else ++#error "Core not defined!" ++#endif /* defined(CORE_E300) || ... */ ++ ++ ++/**************************************************************************//** ++ @Function CORE_TestAndSet ++ ++ @Description This routine tries to atomically test-and-set an integer ++ in memory to a non-zero value. ++ ++ The memory will be set only if it is tested as zero, in which ++ case the routine returns the new non-zero value; otherwise the ++ routine returns zero. ++ ++ @Param[in] p - pointer to a volatile int in memory, on which test-and-set ++ operation should be made. ++ ++ @Retval Zero - Operation failed - memory was already set. ++ @Retval Non-zero - Operation succeeded - memory has been set. ++*//***************************************************************************/ ++int CORE_TestAndSet(volatile int *p); ++ ++/**************************************************************************//** ++ @Function CORE_InstructionSync ++ ++ @Description This routine will cause the core to wait for previous instructions ++ (including any interrupts they generate) to complete before the ++ synchronization command executes, which purges all instructions ++ from the processor's pipeline and refetches the next instruction. ++ ++ @Return None. ++*//***************************************************************************/ ++void CORE_InstructionSync(void); ++ ++/**************************************************************************//** ++ @Function CORE_DCacheEnable ++ ++ @Description Enables the data cache for memory pages that are ++ not cache inhibited. ++ ++ @Return None. ++*//***************************************************************************/ ++void CORE_DCacheEnable(void); ++ ++/**************************************************************************//** ++ @Function CORE_ICacheEnable ++ ++ @Description Enables the instruction cache for memory pages that are ++ not cache inhibited. ++ ++ @Return None. ++*//***************************************************************************/ ++void CORE_ICacheEnable(void); ++ ++/**************************************************************************//** ++ @Function CORE_DCacheDisable ++ ++ @Description Disables the data cache. ++ ++ @Return None. ++*//***************************************************************************/ ++void CORE_DCacheDisable(void); ++ ++/**************************************************************************//** ++ @Function CORE_ICacheDisable ++ ++ @Description Disables the instruction cache. ++ ++ @Return None. ++*//***************************************************************************/ ++void CORE_ICacheDisable(void); ++ ++ ++ ++#if defined(CORE_E300) ++#include "e300_ext.h" ++#elif defined(CORE_E500V2) || defined(CORE_E500MC) || defined(CORE_E5500) || defined(CORE_E6500) ++#include "e500v2_ext.h" ++#if !defined(NCSW_LINUX) ++#include "e500v2_asm_ext.h" ++#endif ++#else ++#error "Core not defined!" ++#endif ++ ++ ++#endif /* __PPC_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/ddr_std_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/ddr_std_ext.h +new file mode 100644 +index 0000000..8bb343f +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/ddr_std_ext.h +@@ -0,0 +1,77 @@ ++/* ++ * Copyright 2008-2012 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 __DDR_SDT_EXT_H ++#define __DDR_SDT_EXT_H ++ ++ ++/**************************************************************************//** ++ @Group ddr_Generic_Resources ++ ++ @Description ddr generic functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++ ++/**************************************************************************//** ++ @Description SPD maximum size ++*//***************************************************************************/ ++#define SPD_MAX_SIZE 256 ++ ++/**************************************************************************//** ++ @Description DDR types select ++*//***************************************************************************/ ++typedef enum e_DdrType ++{ ++ e_DDR_DDR1, ++ e_DDR_DDR2, ++ e_DDR_DDR3, ++ e_DDR_DDR3L, ++ e_DDR_DDR4 ++} e_DdrType; ++ ++/**************************************************************************//** ++ @Description DDR Mode. ++*//***************************************************************************/ ++typedef enum e_DdrMode ++{ ++ e_DDR_BUS_WIDTH_32BIT, ++ e_DDR_BUS_WIDTH_64BIT ++} e_DdrMode; ++ ++/** @} */ /* end of ddr_Generic_Resources group */ ++ ++ ++ ++#endif /* __DDR_SDT_EXT_H */ ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/debug_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/debug_ext.h +new file mode 100644 +index 0000000..57db0a1 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/debug_ext.h +@@ -0,0 +1,233 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File debug_ext.h ++ ++ @Description Debug mode definitions. ++*//***************************************************************************/ ++ ++#ifndef __DEBUG_EXT_H ++#define __DEBUG_EXT_H ++ ++#include "std_ext.h" ++#include "xx_ext.h" ++#include "memcpy_ext.h" ++#if (DEBUG_ERRORS > 0) ++#include "sprint_ext.h" ++#include "string_ext.h" ++#endif /* DEBUG_ERRORS > 0 */ ++ ++ ++#if (DEBUG_ERRORS > 0) ++ ++/* Internally used macros */ ++ ++#define DUMP_Print XX_Print ++#define DUMP_MAX_LEVELS 6 ++#define DUMP_IDX_LEN 6 ++#define DUMP_MAX_STR 64 ++ ++ ++#define _CREATE_DUMP_SUBSTR(phrase) \ ++ dumpTmpLevel = 0; dumpSubStr[0] = '\0'; \ ++ snprintf(dumpTmpStr, DUMP_MAX_STR, "%s", #phrase); \ ++ p_DumpToken = strtok(dumpTmpStr, (dumpIsArr[0] ? "[" : ".")); \ ++ while ((p_DumpToken != NULL) && (dumpTmpLevel < DUMP_MAX_LEVELS)) \ ++ { \ ++ strlcat(dumpSubStr, p_DumpToken, DUMP_MAX_STR); \ ++ if (dumpIsArr[dumpTmpLevel]) \ ++ { \ ++ strlcat(dumpSubStr, dumpIdxStr[dumpTmpLevel], DUMP_MAX_STR); \ ++ p_DumpToken = strtok(NULL, "."); \ ++ } \ ++ if ((p_DumpToken != NULL) && \ ++ ((p_DumpToken = strtok(NULL, (dumpIsArr[++dumpTmpLevel] ? "[" : "."))) != NULL)) \ ++ strlcat(dumpSubStr, ".", DUMP_MAX_STR); \ ++ } ++ ++ ++/**************************************************************************//** ++ @Group gen_id General Drivers Utilities ++ ++ @Description External routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group dump_id Memory and Registers Dump Mechanism ++ ++ @Description Macros for dumping memory mapped structures. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Declaration of dump mechanism variables. ++ ++ This macro must be declared at the beginning of each routine ++ which uses the dump mechanism macros, before the routine's code ++ starts. ++*//***************************************************************************/ ++#define DECLARE_DUMP \ ++ char dumpIdxStr[DUMP_MAX_LEVELS + 1][DUMP_IDX_LEN] = { "", }; \ ++ char dumpSubStr[DUMP_MAX_STR] = ""; \ ++ char dumpTmpStr[DUMP_MAX_STR] = ""; \ ++ char *p_DumpToken = NULL; \ ++ int dumpArrIdx = 0, dumpArrSize = 0, dumpLevel = 0, dumpTmpLevel = 0; \ ++ uint8_t dumpIsArr[DUMP_MAX_LEVELS + 1] = { 0 }; \ ++ /* Prevent warnings if not all used */ \ ++ UNUSED(dumpIdxStr[0][0]); \ ++ UNUSED(dumpSubStr[0]); \ ++ UNUSED(dumpTmpStr[0]); \ ++ UNUSED(p_DumpToken); \ ++ UNUSED(dumpArrIdx); \ ++ UNUSED(dumpArrSize); \ ++ UNUSED(dumpLevel); \ ++ UNUSED(dumpTmpLevel); \ ++ UNUSED(dumpIsArr[0]); ++ ++ ++/**************************************************************************//** ++ @Description Prints a title for a subsequent dumped structure or memory. ++ ++ The inputs for this macro are the structure/memory title and ++ its base addresses. ++*//***************************************************************************/ ++#define DUMP_TITLE(addr, msg) \ ++ DUMP_Print("\r\n"); DUMP_Print msg; \ ++ if (addr) \ ++ DUMP_Print(" (%p)", (addr)); \ ++ DUMP_Print("\r\n---------------------------------------------------------\r\n"); ++ ++/**************************************************************************//** ++ @Description Prints a subtitle for a subsequent dumped sub-structure (optional). ++ ++ The inputs for this macro are the sub-structure subtitle. ++ A separating line with this subtitle will be printed. ++*//***************************************************************************/ ++#define DUMP_SUBTITLE(subtitle) \ ++ DUMP_Print("----------- "); DUMP_Print subtitle; DUMP_Print("\r\n") ++ ++ ++/**************************************************************************//** ++ @Description Dumps a memory region in 4-bytes aligned format. ++ ++ The inputs for this macro are the base addresses and size ++ (in bytes) of the memory region. ++*//***************************************************************************/ ++#define DUMP_MEMORY(addr, size) \ ++ MemDisp((uint8_t *)(addr), (int)(size)) ++ ++ ++/**************************************************************************//** ++ @Description Declares a dump loop, for dumping a sub-structure array. ++ ++ The inputs for this macro are: ++ - idx: an index variable, for indexing the sub-structure items ++ inside the loop. This variable must be declared separately ++ in the beginning of the routine. ++ - cnt: the number of times to repeat the loop. This number should ++ equal the number of items in the sub-structures array. ++ ++ Note, that the body of the loop must be written inside brackets. ++*//***************************************************************************/ ++#define DUMP_SUBSTRUCT_ARRAY(idx, cnt) \ ++ for (idx=0, dumpIsArr[dumpLevel++] = 1; \ ++ (idx < cnt) && (dumpLevel > 0) && snprintf(dumpIdxStr[dumpLevel-1], DUMP_IDX_LEN, "[%d]", idx); \ ++ idx++, ((idx < cnt) || (dumpIsArr[--dumpLevel] = 0))) ++ ++ ++/**************************************************************************//** ++ @Description Dumps a structure's member variable. ++ ++ The input for this macro is the full reference for the member ++ variable, where the structure is referenced using a pointer. ++ ++ Note, that a members array must be dumped using DUMP_ARR macro, ++ rather than using this macro. ++ ++ If the member variable is part of a sub-structure hierarchy, ++ the full hierarchy (including array indexing) must be specified. ++ ++ Examples: p_Struct->member ++ p_Struct->sub.member ++ p_Struct->sub[i].member ++*//***************************************************************************/ ++#define DUMP_VAR(st, phrase) \ ++ do { \ ++ void *addr = (void *)&((st)->phrase); \ ++ physAddress_t physAddr = XX_VirtToPhys(addr); \ ++ _CREATE_DUMP_SUBSTR(phrase); \ ++ DUMP_Print("0x%010llX: 0x%08x%8s\t%s\r\n", \ ++ physAddr, GET_UINT32(*(uint32_t*)addr), "", dumpSubStr); \ ++ } while (0) ++ ++ ++/**************************************************************************//** ++ @Description Dumps a structure's members array. ++ ++ The input for this macro is the full reference for the members ++ array, where the structure is referenced using a pointer. ++ ++ If the members array is part of a sub-structure hierarchy, ++ the full hierarchy (including array indexing) must be specified. ++ ++ Examples: p_Struct->array ++ p_Struct->sub.array ++ p_Struct->sub[i].array ++*//***************************************************************************/ ++#define DUMP_ARR(st, phrase) \ ++ do { \ ++ physAddress_t physAddr; \ ++ _CREATE_DUMP_SUBSTR(phrase); \ ++ dumpArrSize = ARRAY_SIZE((st)->phrase); \ ++ for (dumpArrIdx=0; dumpArrIdx < dumpArrSize; dumpArrIdx++) { \ ++ physAddr = XX_VirtToPhys((void *)&((st)->phrase[dumpArrIdx])); \ ++ DUMP_Print("0x%010llX: 0x%08x%8s\t%s[%d]\r\n", \ ++ physAddr, GET_UINT32((st)->phrase[dumpArrIdx]), "", dumpSubStr, dumpArrIdx); \ ++ } \ ++ } while (0) ++ ++ ++ ++#endif /* DEBUG_ERRORS > 0 */ ++ ++ ++/** @} */ /* end of dump_id group */ ++/** @} */ /* end of gen_id group */ ++ ++ ++#endif /* __DEBUG_EXT_H */ ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/endian_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/endian_ext.h +new file mode 100644 +index 0000000..5cdec66 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/endian_ext.h +@@ -0,0 +1,447 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/**************************************************************************//** ++ ++ @File endian_ext.h ++ ++ @Description Big/little endian swapping routines. ++*//***************************************************************************/ ++ ++#ifndef __ENDIAN_EXT_H ++#define __ENDIAN_EXT_H ++ ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group gen_id General Drivers Utilities ++ ++ @Description General usage API. This API is intended for usage by both the ++ internal modules and the user's application. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group endian_id Big/Little-Endian Conversion ++ ++ @Description Routines and macros for Big/Little-Endian conversion and ++ general byte swapping. ++ ++ All routines and macros are expecting unsigned values as ++ parameters, but will generate the correct result also for ++ signed values. Therefore, signed/unsigned casting is allowed. ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Collection Byte-Swap Macros ++ ++ Macros for swapping byte order. ++ ++ @Cautions The parameters of these macros are evaluated multiple times. ++ For calculated expressions or expressions that contain function ++ calls it is recommended to use the byte-swap routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Swaps the byte order of a given 16-bit value. ++ ++ @Param[in] val - The 16-bit value to swap. ++ ++ @Return The byte-swapped value.. ++ ++ @Cautions The given value is evaluated multiple times by this macro. ++ For calculated expressions or expressions that contain function ++ calls it is recommended to use the SwapUint16() routine. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define SWAP_UINT16(val) \ ++ ((uint16_t)((((val) & 0x00FF) << 8) | (((val) & 0xFF00) >> 8))) ++ ++/**************************************************************************//** ++ @Description Swaps the byte order of a given 32-bit value. ++ ++ @Param[in] val - The 32-bit value to swap. ++ ++ @Return The byte-swapped value.. ++ ++ @Cautions The given value is evaluated multiple times by this macro. ++ For calculated expressions or expressions that contain function ++ calls it is recommended to use the SwapUint32() routine. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define SWAP_UINT32(val) \ ++ ((uint32_t)((((val) & 0x000000FF) << 24) | \ ++ (((val) & 0x0000FF00) << 8) | \ ++ (((val) & 0x00FF0000) >> 8) | \ ++ (((val) & 0xFF000000) >> 24))) ++ ++/**************************************************************************//** ++ @Description Swaps the byte order of a given 64-bit value. ++ ++ @Param[in] val - The 64-bit value to swap. ++ ++ @Return The byte-swapped value.. ++ ++ @Cautions The given value is evaluated multiple times by this macro. ++ For calculated expressions or expressions that contain function ++ calls it is recommended to use the SwapUint64() routine. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define SWAP_UINT64(val) \ ++ ((uint64_t)((((val) & 0x00000000000000FFULL) << 56) | \ ++ (((val) & 0x000000000000FF00ULL) << 40) | \ ++ (((val) & 0x0000000000FF0000ULL) << 24) | \ ++ (((val) & 0x00000000FF000000ULL) << 8) | \ ++ (((val) & 0x000000FF00000000ULL) >> 8) | \ ++ (((val) & 0x0000FF0000000000ULL) >> 24) | \ ++ (((val) & 0x00FF000000000000ULL) >> 40) | \ ++ (((val) & 0xFF00000000000000ULL) >> 56))) ++ ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection Byte-Swap Routines ++ ++ Routines for swapping the byte order of a given parameter and ++ returning the swapped value. ++ ++ These inline routines are safer than the byte-swap macros, ++ because they evaluate the parameter expression only once. ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function SwapUint16 ++ ++ @Description Returns the byte-swapped value of a given 16-bit value. ++ ++ @Param[in] val - The 16-bit value. ++ ++ @Return The byte-swapped value of the parameter. ++*//***************************************************************************/ ++static __inline__ uint16_t SwapUint16(uint16_t val) ++{ ++ return (uint16_t)(((val & 0x00FF) << 8) | ++ ((val & 0xFF00) >> 8)); ++} ++ ++/**************************************************************************//** ++ @Function SwapUint32 ++ ++ @Description Returns the byte-swapped value of a given 32-bit value. ++ ++ @Param[in] val - The 32-bit value. ++ ++ @Return The byte-swapped value of the parameter. ++*//***************************************************************************/ ++static __inline__ uint32_t SwapUint32(uint32_t val) ++{ ++ return (uint32_t)(((val & 0x000000FF) << 24) | ++ ((val & 0x0000FF00) << 8) | ++ ((val & 0x00FF0000) >> 8) | ++ ((val & 0xFF000000) >> 24)); ++} ++ ++/**************************************************************************//** ++ @Function SwapUint64 ++ ++ @Description Returns the byte-swapped value of a given 64-bit value. ++ ++ @Param[in] val - The 64-bit value. ++ ++ @Return The byte-swapped value of the parameter. ++*//***************************************************************************/ ++static __inline__ uint64_t SwapUint64(uint64_t val) ++{ ++ return (uint64_t)(((val & 0x00000000000000FFULL) << 56) | ++ ((val & 0x000000000000FF00ULL) << 40) | ++ ((val & 0x0000000000FF0000ULL) << 24) | ++ ((val & 0x00000000FF000000ULL) << 8) | ++ ((val & 0x000000FF00000000ULL) >> 8) | ++ ((val & 0x0000FF0000000000ULL) >> 24) | ++ ((val & 0x00FF000000000000ULL) >> 40) | ++ ((val & 0xFF00000000000000ULL) >> 56)); ++} ++ ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection In-place Byte-Swap-And-Set Routines ++ ++ Routines for swapping the byte order of a given variable and ++ setting the swapped value back to the same variable. ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function SwapUint16P ++ ++ @Description Swaps the byte order of a given 16-bit variable. ++ ++ @Param[in] p_Val - Pointer to the 16-bit variable. ++ ++ @Return None. ++*//***************************************************************************/ ++static __inline__ void SwapUint16P(uint16_t *p_Val) ++{ ++ *p_Val = SwapUint16(*p_Val); ++} ++ ++/**************************************************************************//** ++ @Function SwapUint32P ++ ++ @Description Swaps the byte order of a given 32-bit variable. ++ ++ @Param[in] p_Val - Pointer to the 32-bit variable. ++ ++ @Return None. ++*//***************************************************************************/ ++static __inline__ void SwapUint32P(uint32_t *p_Val) ++{ ++ *p_Val = SwapUint32(*p_Val); ++} ++ ++/**************************************************************************//** ++ @Function SwapUint64P ++ ++ @Description Swaps the byte order of a given 64-bit variable. ++ ++ @Param[in] p_Val - Pointer to the 64-bit variable. ++ ++ @Return None. ++*//***************************************************************************/ ++static __inline__ void SwapUint64P(uint64_t *p_Val) ++{ ++ *p_Val = SwapUint64(*p_Val); ++} ++ ++/* @} */ ++ ++ ++/**************************************************************************//** ++ @Collection Little-Endian Conversion Macros ++ ++ These macros convert given parameters to or from Little-Endian ++ format. Use these macros when you want to read or write a specific ++ Little-Endian value in memory, without a-priori knowing the CPU ++ byte order. ++ ++ These macros use the byte-swap routines. For conversion of ++ constants in initialization structures, you may use the CONST ++ versions of these macros (see below), which are using the ++ byte-swap macros instead. ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Converts a given 16-bit value from CPU byte order to ++ Little-Endian byte order. ++ ++ @Param[in] val - The 16-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CPU_TO_LE16(val) SwapUint16(val) ++ ++/**************************************************************************//** ++ @Description Converts a given 32-bit value from CPU byte order to ++ Little-Endian byte order. ++ ++ @Param[in] val - The 32-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CPU_TO_LE32(val) SwapUint32(val) ++ ++/**************************************************************************//** ++ @Description Converts a given 64-bit value from CPU byte order to ++ Little-Endian byte order. ++ ++ @Param[in] val - The 64-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CPU_TO_LE64(val) SwapUint64(val) ++ ++ ++/**************************************************************************//** ++ @Description Converts a given 16-bit value from Little-Endian byte order to ++ CPU byte order. ++ ++ @Param[in] val - The 16-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define LE16_TO_CPU(val) CPU_TO_LE16(val) ++ ++/**************************************************************************//** ++ @Description Converts a given 32-bit value from Little-Endian byte order to ++ CPU byte order. ++ ++ @Param[in] val - The 32-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define LE32_TO_CPU(val) CPU_TO_LE32(val) ++ ++/**************************************************************************//** ++ @Description Converts a given 64-bit value from Little-Endian byte order to ++ CPU byte order. ++ ++ @Param[in] val - The 64-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define LE64_TO_CPU(val) CPU_TO_LE64(val) ++ ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection Little-Endian Constant Conversion Macros ++ ++ These macros convert given constants to or from Little-Endian ++ format. Use these macros when you want to read or write a specific ++ Little-Endian constant in memory, without a-priori knowing the ++ CPU byte order. ++ ++ These macros use the byte-swap macros, therefore can be used for ++ conversion of constants in initialization structures. ++ ++ @Cautions The parameters of these macros are evaluated multiple times. ++ For non-constant expressions, use the non-CONST macro versions. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Converts a given 16-bit constant from CPU byte order to ++ Little-Endian byte order. ++ ++ @Param[in] val - The 16-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CONST_CPU_TO_LE16(val) SWAP_UINT16(val) ++ ++/**************************************************************************//** ++ @Description Converts a given 32-bit constant from CPU byte order to ++ Little-Endian byte order. ++ ++ @Param[in] val - The 32-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CONST_CPU_TO_LE32(val) SWAP_UINT32(val) ++ ++/**************************************************************************//** ++ @Description Converts a given 64-bit constant from CPU byte order to ++ Little-Endian byte order. ++ ++ @Param[in] val - The 64-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CONST_CPU_TO_LE64(val) SWAP_UINT64(val) ++ ++ ++/**************************************************************************//** ++ @Description Converts a given 16-bit constant from Little-Endian byte order ++ to CPU byte order. ++ ++ @Param[in] val - The 16-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CONST_LE16_TO_CPU(val) CONST_CPU_TO_LE16(val) ++ ++/**************************************************************************//** ++ @Description Converts a given 32-bit constant from Little-Endian byte order ++ to CPU byte order. ++ ++ @Param[in] val - The 32-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CONST_LE32_TO_CPU(val) CONST_CPU_TO_LE32(val) ++ ++/**************************************************************************//** ++ @Description Converts a given 64-bit constant from Little-Endian byte order ++ to CPU byte order. ++ ++ @Param[in] val - The 64-bit value to convert. ++ ++ @Return The converted value. ++ ++ @hideinitializer ++*//***************************************************************************/ ++#define CONST_LE64_TO_CPU(val) CONST_CPU_TO_LE64(val) ++ ++/* @} */ ++ ++ ++/** @} */ /* end of endian_id group */ ++/** @} */ /* end of gen_id group */ ++ ++ ++#endif /* __ENDIAN_EXT_H */ ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/enet_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/enet_ext.h +new file mode 100644 +index 0000000..ef3bee5 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/enet_ext.h +@@ -0,0 +1,205 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File enet_ext.h ++ ++ @Description Ethernet generic definitions and enums. ++*//***************************************************************************/ ++ ++#ifndef __ENET_EXT_H ++#define __ENET_EXT_H ++ ++#include "fsl_enet.h" ++ ++#define ENET_NUM_OCTETS_PER_ADDRESS 6 /**< Number of octets (8-bit bytes) in an ethernet address */ ++#define ENET_GROUP_ADDR 0x01 /**< Group address mask for ethernet addresses */ ++ ++ ++/**************************************************************************//** ++ @Description Ethernet Address ++*//***************************************************************************/ ++typedef uint8_t t_EnetAddr[ENET_NUM_OCTETS_PER_ADDRESS]; ++ ++/**************************************************************************//** ++ @Description Ethernet Address Type. ++*//***************************************************************************/ ++typedef enum e_EnetAddrType ++{ ++ e_ENET_ADDR_TYPE_INDIVIDUAL, /**< Individual (unicast) address */ ++ e_ENET_ADDR_TYPE_GROUP, /**< Group (multicast) address */ ++ e_ENET_ADDR_TYPE_BROADCAST /**< Broadcast address */ ++} e_EnetAddrType; ++ ++/**************************************************************************//** ++ @Description Ethernet MAC-PHY Interface ++*//***************************************************************************/ ++typedef enum e_EnetInterface ++{ ++ e_ENET_IF_MII = E_ENET_IF_MII, /**< MII interface */ ++ e_ENET_IF_RMII = E_ENET_IF_RMII, /**< RMII interface */ ++ e_ENET_IF_SMII = E_ENET_IF_SMII, /**< SMII interface */ ++ e_ENET_IF_GMII = E_ENET_IF_GMII, /**< GMII interface */ ++ e_ENET_IF_RGMII = E_ENET_IF_RGMII, /**< RGMII interface */ ++ e_ENET_IF_TBI = E_ENET_IF_TBI, /**< TBI interface */ ++ e_ENET_IF_RTBI = E_ENET_IF_RTBI, /**< RTBI interface */ ++ e_ENET_IF_SGMII = E_ENET_IF_SGMII, /**< SGMII interface */ ++ e_ENET_IF_XGMII = E_ENET_IF_XGMII, /**< XGMII interface */ ++ e_ENET_IF_QSGMII= E_ENET_IF_QSGMII, /**< QSGMII interface */ ++ e_ENET_IF_XFI = E_ENET_IF_XFI /**< XFI interface */ ++} e_EnetInterface; ++ ++#define ENET_IF_SGMII_BASEX 0x80000000 /**< SGMII/QSGII interface with 1000BaseX ++ auto-negotiation between MAC and phy ++ or backplane; ++ Note: 1000BaseX auto-negotiation relates ++ only to interface between MAC and phy/backplane, ++ SGMII phy can still synchronize with far-end phy ++ at 10Mbps, 100Mbps or 1000Mbps */ ++ ++/**************************************************************************//** ++ @Description Ethernet Duplex Mode ++*//***************************************************************************/ ++typedef enum e_EnetDuplexMode ++{ ++ e_ENET_HALF_DUPLEX, /**< Half-Duplex mode */ ++ e_ENET_FULL_DUPLEX /**< Full-Duplex mode */ ++} e_EnetDuplexMode; ++ ++/**************************************************************************//** ++ @Description Ethernet Speed (nominal data rate) ++*//***************************************************************************/ ++typedef enum e_EnetSpeed ++{ ++ e_ENET_SPEED_10 = E_ENET_SPEED_10, /**< 10 Mbps */ ++ e_ENET_SPEED_100 = E_ENET_SPEED_100, /**< 100 Mbps */ ++ e_ENET_SPEED_1000 = E_ENET_SPEED_1000, /**< 1000 Mbps = 1 Gbps */ ++ e_ENET_SPEED_2500 = E_ENET_SPEED_2500, /**< 2500 Mbps = 2.5 Gbps */ ++ e_ENET_SPEED_10000 = E_ENET_SPEED_10000 /**< 10000 Mbps = 10 Gbps */ ++} e_EnetSpeed; ++ ++/**************************************************************************//** ++ @Description Ethernet mode (combination of MAC-PHY interface and speed) ++*//***************************************************************************/ ++typedef enum e_EnetMode ++{ ++ e_ENET_MODE_INVALID = 0, /**< Invalid Ethernet mode */ ++ e_ENET_MODE_MII_10 = (e_ENET_IF_MII | e_ENET_SPEED_10), /**< 10 Mbps MII */ ++ e_ENET_MODE_MII_100 = (e_ENET_IF_MII | e_ENET_SPEED_100), /**< 100 Mbps MII */ ++ e_ENET_MODE_RMII_10 = (e_ENET_IF_RMII | e_ENET_SPEED_10), /**< 10 Mbps RMII */ ++ e_ENET_MODE_RMII_100 = (e_ENET_IF_RMII | e_ENET_SPEED_100), /**< 100 Mbps RMII */ ++ e_ENET_MODE_SMII_10 = (e_ENET_IF_SMII | e_ENET_SPEED_10), /**< 10 Mbps SMII */ ++ e_ENET_MODE_SMII_100 = (e_ENET_IF_SMII | e_ENET_SPEED_100), /**< 100 Mbps SMII */ ++ e_ENET_MODE_GMII_1000 = (e_ENET_IF_GMII | e_ENET_SPEED_1000), /**< 1000 Mbps GMII */ ++ e_ENET_MODE_RGMII_10 = (e_ENET_IF_RGMII | e_ENET_SPEED_10), /**< 10 Mbps RGMII */ ++ e_ENET_MODE_RGMII_100 = (e_ENET_IF_RGMII | e_ENET_SPEED_100), /**< 100 Mbps RGMII */ ++ e_ENET_MODE_RGMII_1000 = (e_ENET_IF_RGMII | e_ENET_SPEED_1000), /**< 1000 Mbps RGMII */ ++ e_ENET_MODE_TBI_1000 = (e_ENET_IF_TBI | e_ENET_SPEED_1000), /**< 1000 Mbps TBI */ ++ e_ENET_MODE_RTBI_1000 = (e_ENET_IF_RTBI | e_ENET_SPEED_1000), /**< 1000 Mbps RTBI */ ++ e_ENET_MODE_SGMII_10 = (e_ENET_IF_SGMII | e_ENET_SPEED_10), ++ /**< 10 Mbps SGMII with auto-negotiation between MAC and ++ SGMII phy according to Cisco SGMII specification */ ++ e_ENET_MODE_SGMII_100 = (e_ENET_IF_SGMII | e_ENET_SPEED_100), ++ /**< 100 Mbps SGMII with auto-negotiation between MAC and ++ SGMII phy according to Cisco SGMII specification */ ++ e_ENET_MODE_SGMII_1000 = (e_ENET_IF_SGMII | e_ENET_SPEED_1000), ++ /**< 1000 Mbps SGMII with auto-negotiation between MAC and ++ SGMII phy according to Cisco SGMII specification */ ++ e_ENET_MODE_SGMII_2500 = (e_ENET_IF_SGMII | e_ENET_SPEED_2500), ++ e_ENET_MODE_SGMII_BASEX_10 = (ENET_IF_SGMII_BASEX | e_ENET_IF_SGMII | e_ENET_SPEED_10), ++ /**< 10 Mbps SGMII with 1000BaseX auto-negotiation between ++ MAC and SGMII phy or backplane */ ++ e_ENET_MODE_SGMII_BASEX_100 = (ENET_IF_SGMII_BASEX | e_ENET_IF_SGMII | e_ENET_SPEED_100), ++ /**< 100 Mbps SGMII with 1000BaseX auto-negotiation between ++ MAC and SGMII phy or backplane */ ++ e_ENET_MODE_SGMII_BASEX_1000 = (ENET_IF_SGMII_BASEX | e_ENET_IF_SGMII | e_ENET_SPEED_1000), ++ /**< 1000 Mbps SGMII with 1000BaseX auto-negotiation between ++ MAC and SGMII phy or backplane */ ++ e_ENET_MODE_QSGMII_1000 = (e_ENET_IF_QSGMII| e_ENET_SPEED_1000), ++ /**< 1000 Mbps QSGMII with auto-negotiation between MAC and ++ QSGMII phy according to Cisco QSGMII specification */ ++ e_ENET_MODE_QSGMII_BASEX_1000 = (ENET_IF_SGMII_BASEX | e_ENET_IF_QSGMII| e_ENET_SPEED_1000), ++ /**< 1000 Mbps QSGMII with 1000BaseX auto-negotiation between ++ MAC and QSGMII phy or backplane */ ++ e_ENET_MODE_XGMII_10000 = (e_ENET_IF_XGMII | e_ENET_SPEED_10000), /**< 10000 Mbps XGMII */ ++ e_ENET_MODE_XFI_10000 = (e_ENET_IF_XFI | e_ENET_SPEED_10000) /**< 10000 Mbps XFI */ ++} e_EnetMode; ++ ++ ++#define IS_ENET_MODE_VALID(mode) \ ++ (((mode) == e_ENET_MODE_MII_10 ) || \ ++ ((mode) == e_ENET_MODE_MII_100 ) || \ ++ ((mode) == e_ENET_MODE_RMII_10 ) || \ ++ ((mode) == e_ENET_MODE_RMII_100 ) || \ ++ ((mode) == e_ENET_MODE_SMII_10 ) || \ ++ ((mode) == e_ENET_MODE_SMII_100 ) || \ ++ ((mode) == e_ENET_MODE_GMII_1000 ) || \ ++ ((mode) == e_ENET_MODE_RGMII_10 ) || \ ++ ((mode) == e_ENET_MODE_RGMII_100 ) || \ ++ ((mode) == e_ENET_MODE_RGMII_1000 ) || \ ++ ((mode) == e_ENET_MODE_TBI_1000 ) || \ ++ ((mode) == e_ENET_MODE_RTBI_1000 ) || \ ++ ((mode) == e_ENET_MODE_SGMII_10 ) || \ ++ ((mode) == e_ENET_MODE_SGMII_100 ) || \ ++ ((mode) == e_ENET_MODE_SGMII_1000 ) || \ ++ ((mode) == e_ENET_MODE_SGMII_BASEX_10 ) || \ ++ ((mode) == e_ENET_MODE_SGMII_BASEX_100 ) || \ ++ ((mode) == e_ENET_MODE_SGMII_BASEX_1000 ) || \ ++ ((mode) == e_ENET_MODE_XGMII_10000) || \ ++ ((mode) == e_ENET_MODE_QSGMII_1000) || \ ++ ((mode) == e_ENET_MODE_QSGMII_BASEX_1000) || \ ++ ((mode) == e_ENET_MODE_XFI_10000)) ++ ++ ++#define MAKE_ENET_MODE(_interface, _speed) (e_EnetMode)((_interface) | (_speed)) ++ ++#define ENET_INTERFACE_FROM_MODE(mode) (e_EnetInterface)((mode) & 0x0FFF0000) ++#define ENET_SPEED_FROM_MODE(mode) (e_EnetSpeed)((mode) & 0x0000FFFF) ++ ++#define ENET_ADDR_TO_UINT64(_enetAddr) \ ++ (uint64_t)(((uint64_t)(_enetAddr)[0] << 40) | \ ++ ((uint64_t)(_enetAddr)[1] << 32) | \ ++ ((uint64_t)(_enetAddr)[2] << 24) | \ ++ ((uint64_t)(_enetAddr)[3] << 16) | \ ++ ((uint64_t)(_enetAddr)[4] << 8) | \ ++ ((uint64_t)(_enetAddr)[5])) ++ ++#define MAKE_ENET_ADDR_FROM_UINT64(_addr64, _enetAddr) \ ++ do { \ ++ int i; \ ++ for (i=0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++) \ ++ (_enetAddr)[i] = (uint8_t)((_addr64) >> ((5-i)*8)); \ ++ } while (0) ++ ++ ++#endif /* __ENET_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/error_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/error_ext.h +new file mode 100644 +index 0000000..71f9398 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/error_ext.h +@@ -0,0 +1,529 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File error_ext.h ++ ++ @Description Error definitions. ++*//***************************************************************************/ ++ ++#ifndef __ERROR_EXT_H ++#define __ERROR_EXT_H ++ ++#if !defined(NCSW_LINUX) ++#include ++#endif ++ ++#include "std_ext.h" ++#include "xx_ext.h" ++#include "core_ext.h" ++ ++ ++ ++ ++/**************************************************************************//** ++ @Group gen_id General Drivers Utilities ++ ++ @Description External routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group gen_error_id Errors, Events and Debug ++ ++ @Description External routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/****************************************************************************** ++The scheme below provides the bits description for error codes: ++ ++ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ++| Reserved (should be zero) | Module ID | ++ ++ 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ++| Error Type | ++******************************************************************************/ ++ ++#define ERROR_CODE(_err) ((((uint32_t)_err) & 0x0000FFFF) | __ERR_MODULE__) ++ ++#define GET_ERROR_TYPE(_errcode) ((_errcode) & 0x0000FFFF) ++ /**< Extract module code from error code (#t_Error) */ ++ ++#define GET_ERROR_MODULE(_errcode) ((_errcode) & 0x00FF0000) ++ /**< Extract error type (#e_ErrorType) from ++ error code (#t_Error) */ ++ ++ ++/**************************************************************************//** ++ @Description Error Type Enumeration ++*//***************************************************************************/ ++typedef enum e_ErrorType /* Comments / Associated Message Strings */ ++{ /* ------------------------------------------------------------ */ ++ E_OK = 0 /* Never use "RETURN_ERROR" with E_OK; Use "return E_OK;" */ ++ ,E_WRITE_FAILED = EIO /**< Write access failed on memory/device. */ ++ /* String: none, or device name. */ ++ ,E_NO_DEVICE = ENXIO /**< The associated device is not initialized. */ ++ /* String: none. */ ++ ,E_NOT_AVAILABLE = EAGAIN ++ /**< Resource is unavailable. */ ++ /* String: none, unless the operation is not the main goal ++ of the function (in this case add resource description). */ ++ ,E_NO_MEMORY = ENOMEM /**< External memory allocation failed. */ ++ /* String: description of item for which allocation failed. */ ++ ,E_INVALID_ADDRESS = EFAULT ++ /**< Invalid address. */ ++ /* String: description of the specific violation. */ ++ ,E_BUSY = EBUSY /**< Resource or module is busy. */ ++ /* String: none, unless the operation is not the main goal ++ of the function (in this case add resource description). */ ++ ,E_ALREADY_EXISTS = EEXIST ++ /**< Requested resource or item already exists. */ ++ /* Use when resource duplication or sharing are not allowed. ++ String: none, unless the operation is not the main goal ++ of the function (in this case add item description). */ ++ ,E_INVALID_OPERATION = ENODEV ++ /**< The operation/command is invalid (unrecognized). */ ++ /* String: none. */ ++ ,E_INVALID_VALUE = EDOM /**< Invalid value. */ ++ /* Use for non-enumeration parameters, and ++ only when other error types are not suitable. ++ String: parameter description + "(should be )", ++ e.g: "Maximum Rx buffer length (should be divisible by 8)", ++ "Channel number (should be even)". */ ++ ,E_NOT_IN_RANGE = ERANGE/**< Parameter value is out of range. */ ++ /* Don't use this error for enumeration parameters. ++ String: parameter description + "(should be %d-%d)", ++ e.g: "Number of pad characters (should be 0-15)". */ ++ ,E_NOT_SUPPORTED = ENOSYS ++ /**< The function is not supported or not implemented. */ ++ /* String: none. */ ++ ,E_INVALID_STATE /**< The operation is not allowed in current module state. */ ++ /* String: none. */ ++ ,E_INVALID_HANDLE /**< Invalid handle of module or object. */ ++ /* String: none, unless the function takes in more than one ++ handle (in this case add the handle description) */ ++ ,E_INVALID_ID /**< Invalid module ID (usually enumeration or index). */ ++ /* String: none, unless the function takes in more than one ++ ID (in this case add the ID description) */ ++ ,E_NULL_POINTER /**< Unexpected NULL pointer. */ ++ /* String: pointer description. */ ++ ,E_INVALID_SELECTION /**< Invalid selection or mode. */ ++ /* Use for enumeration values, only when other error types ++ are not suitable. ++ String: parameter description. */ ++ ,E_INVALID_COMM_MODE /**< Invalid communication mode. */ ++ /* String: none, unless the function takes in more than one ++ communication mode indications (in this case add ++ parameter description). */ ++ ,E_INVALID_MEMORY_TYPE /**< Invalid memory type. */ ++ /* String: none, unless the function takes in more than one ++ memory types (in this case add memory description, ++ e.g: "Data memory", "Buffer descriptors memory"). */ ++ ,E_INVALID_CLOCK /**< Invalid clock. */ ++ /* String: none, unless the function takes in more than one ++ clocks (in this case add clock description, ++ e.g: "Rx clock", "Tx clock"). */ ++ ,E_CONFLICT /**< Some setting conflicts with another setting. */ ++ /* String: description of the conflicting settings. */ ++ ,E_NOT_ALIGNED /**< Non-aligned address. */ ++ /* String: parameter description + "(should be %d-bytes aligned)", ++ e.g: "Rx data buffer (should be 32-bytes aligned)". */ ++ ,E_NOT_FOUND /**< Requested resource or item was not found. */ ++ /* Use only when the resource/item is uniquely identified. ++ String: none, unless the operation is not the main goal ++ of the function (in this case add item description). */ ++ ,E_FULL /**< Resource is full. */ ++ /* String: none, unless the operation is not the main goal ++ of the function (in this case add resource description). */ ++ ,E_EMPTY /**< Resource is empty. */ ++ /* String: none, unless the operation is not the main goal ++ of the function (in this case add resource description). */ ++ ,E_ALREADY_FREE /**< Specified resource or item is already free or deleted. */ ++ /* String: none, unless the operation is not the main goal ++ of the function (in this case add item description). */ ++ ,E_READ_FAILED /**< Read access failed on memory/device. */ ++ /* String: none, or device name. */ ++ ,E_INVALID_FRAME /**< Invalid frame object (NULL handle or missing buffers). */ ++ /* String: none. */ ++ ,E_SEND_FAILED /**< Send operation failed on device. */ ++ /* String: none, or device name. */ ++ ,E_RECEIVE_FAILED /**< Receive operation failed on device. */ ++ /* String: none, or device name. */ ++ ,E_TIMEOUT/* = ETIMEDOUT*/ /**< The operation timed out. */ ++ /* String: none. */ ++ ++ ,E_DUMMY_LAST /* NEVER USED */ ++ ++} e_ErrorType; ++ ++/**************************************************************************//** ++ @Description Event Type Enumeration ++*//***************************************************************************/ ++typedef enum e_Event /* Comments / Associated Flags and Message Strings */ ++{ /* ------------------------------------------------------------ */ ++ EV_NO_EVENT = 0 /**< No event; Never used. */ ++ ++ ,EV_RX_DISCARD /**< Received packet discarded (by the driver, and only for ++ complete packets); ++ Flags: error flags in case of error, zero otherwise. */ ++ /* String: reason for discard, e.g: "Error in frame", ++ "Disordered frame", "Incomplete frame", "No frame object". */ ++ ,EV_RX_ERROR /**< Receive error (by hardware/firmware); ++ Flags: usually status flags from the buffer descriptor. */ ++ /* String: none. */ ++ ,EV_TX_ERROR /**< Transmit error (by hardware/firmware); ++ Flags: usually status flags from the buffer descriptor. */ ++ /* String: none. */ ++ ,EV_NO_BUFFERS /**< System ran out of buffer objects; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_NO_MB_FRAMES /**< System ran out of multi-buffer frame objects; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_NO_SB_FRAMES /**< System ran out of single-buffer frame objects; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_TX_QUEUE_FULL /**< Transmit queue is full; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_RX_QUEUE_FULL /**< Receive queue is full; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_INTR_QUEUE_FULL /**< Interrupt queue overflow; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_NO_DATA_BUFFER /**< Data buffer allocation (from higher layer) failed; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_OBJ_POOL_EMPTY /**< Objects pool is empty; ++ Flags: zero. */ ++ /* String: object description (name). */ ++ ,EV_BUS_ERROR /**< Illegal access on bus; ++ Flags: the address (if available) or bus identifier */ ++ /* String: bus/address/module description. */ ++ ,EV_PTP_TXTS_QUEUE_FULL /**< PTP Tx timestamps queue is full; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_PTP_RXTS_QUEUE_FULL /**< PTP Rx timestamps queue is full; ++ Flags: zero. */ ++ /* String: none. */ ++ ,EV_DUMMY_LAST ++ ++} e_Event; ++ ++ ++/**************************************************************************//** ++ @Collection Debug Levels for Errors and Events ++ ++ The level description refers to errors only. ++ For events, classification is done by the user. ++ ++ The TRACE, INFO and WARNING levels are allowed only when using ++ the DBG macro, and are not allowed when using the error macros ++ (RETURN_ERROR or REPORT_ERROR). ++ @{ ++*//***************************************************************************/ ++#define REPORT_LEVEL_CRITICAL 1 /**< Crasher: Incorrect flow, NULL pointers/handles. */ ++#define REPORT_LEVEL_MAJOR 2 /**< Cannot proceed: Invalid operation, parameters or ++ configuration. */ ++#define REPORT_LEVEL_MINOR 3 /**< Recoverable problem: a repeating call with the same ++ parameters may be successful. */ ++#define REPORT_LEVEL_WARNING 4 /**< Something is not exactly right, yet it is not an error. */ ++#define REPORT_LEVEL_INFO 5 /**< Messages which may be of interest to user/programmer. */ ++#define REPORT_LEVEL_TRACE 6 /**< Program flow messages. */ ++ ++#define EVENT_DISABLED 0xFF /**< Disabled event (not reported at all) */ ++ ++/* @} */ ++ ++ ++ ++#define NO_MSG ("") ++ ++#ifndef DEBUG_GLOBAL_LEVEL ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_WARNING ++#endif /* DEBUG_GLOBAL_LEVEL */ ++ ++#ifndef ERROR_GLOBAL_LEVEL ++#define ERROR_GLOBAL_LEVEL DEBUG_GLOBAL_LEVEL ++#endif /* ERROR_GLOBAL_LEVEL */ ++ ++#ifndef EVENT_GLOBAL_LEVEL ++#define EVENT_GLOBAL_LEVEL REPORT_LEVEL_MINOR ++#endif /* EVENT_GLOBAL_LEVEL */ ++ ++#ifdef EVENT_LOCAL_LEVEL ++#define EVENT_DYNAMIC_LEVEL EVENT_LOCAL_LEVEL ++#else ++#define EVENT_DYNAMIC_LEVEL EVENT_GLOBAL_LEVEL ++#endif /* EVENT_LOCAL_LEVEL */ ++ ++ ++#ifndef DEBUG_DYNAMIC_LEVEL ++#define DEBUG_USING_STATIC_LEVEL ++ ++#ifdef DEBUG_STATIC_LEVEL ++#define DEBUG_DYNAMIC_LEVEL DEBUG_STATIC_LEVEL ++#else ++#define DEBUG_DYNAMIC_LEVEL DEBUG_GLOBAL_LEVEL ++#endif /* DEBUG_STATIC_LEVEL */ ++ ++#else /* DEBUG_DYNAMIC_LEVEL */ ++#ifdef DEBUG_STATIC_LEVEL ++#error "Please use either DEBUG_STATIC_LEVEL or DEBUG_DYNAMIC_LEVEL (not both)" ++#else ++int DEBUG_DYNAMIC_LEVEL = DEBUG_GLOBAL_LEVEL; ++#endif /* DEBUG_STATIC_LEVEL */ ++#endif /* !DEBUG_DYNAMIC_LEVEL */ ++ ++ ++#ifndef ERROR_DYNAMIC_LEVEL ++ ++#ifdef ERROR_STATIC_LEVEL ++#define ERROR_DYNAMIC_LEVEL ERROR_STATIC_LEVEL ++#else ++#define ERROR_DYNAMIC_LEVEL ERROR_GLOBAL_LEVEL ++#endif /* ERROR_STATIC_LEVEL */ ++ ++#else /* ERROR_DYNAMIC_LEVEL */ ++#ifdef ERROR_STATIC_LEVEL ++#error "Please use either ERROR_STATIC_LEVEL or ERROR_DYNAMIC_LEVEL (not both)" ++#else ++int ERROR_DYNAMIC_LEVEL = ERROR_GLOBAL_LEVEL; ++#endif /* ERROR_STATIC_LEVEL */ ++#endif /* !ERROR_DYNAMIC_LEVEL */ ++ ++#define PRINT_FORMAT "[CPU%02d, %s:%d %s]" ++#define PRINT_FMT_PARAMS CORE_GetId(), __FILE__, __LINE__, __FUNCTION__ ++ ++#if (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) ++/* No debug/error/event messages at all */ ++#define DBG(_level, _vmsg) ++ ++#define REPORT_ERROR(_level, _err, _vmsg) ++ ++#define RETURN_ERROR(_level, _err, _vmsg) \ ++ return ERROR_CODE(_err) ++ ++#if (REPORT_EVENTS > 0) ++ ++#define REPORT_EVENT(_ev, _appId, _flg, _vmsg) \ ++ do { \ ++ if (_ev##_LEVEL <= EVENT_DYNAMIC_LEVEL) { \ ++ XX_EventById((uint32_t)(_ev), (t_Handle)(_appId), (uint16_t)(_flg), NO_MSG); \ ++ } \ ++ } while (0) ++ ++#else ++ ++#define REPORT_EVENT(_ev, _appId, _flg, _vmsg) ++ ++#endif /* (REPORT_EVENTS > 0) */ ++ ++ ++#else /* DEBUG_ERRORS > 0 */ ++ ++extern const char *dbgLevelStrings[]; ++extern const char *moduleStrings[]; ++#if (REPORT_EVENTS > 0) ++extern const char *eventStrings[]; ++#endif /* (REPORT_EVENTS > 0) */ ++ ++char * ErrTypeStrings (e_ErrorType err); ++ ++ ++#if ((defined(DEBUG_USING_STATIC_LEVEL)) && (DEBUG_DYNAMIC_LEVEL < REPORT_LEVEL_WARNING)) ++/* No need for DBG macro - debug level is higher anyway */ ++#define DBG(_level, _vmsg) ++#else ++#define DBG(_level, _vmsg) \ ++ do { \ ++ if (REPORT_LEVEL_##_level <= DEBUG_DYNAMIC_LEVEL) { \ ++ XX_Print("> %s (%s) " PRINT_FORMAT ": ", \ ++ dbgLevelStrings[REPORT_LEVEL_##_level - 1], \ ++ moduleStrings[__ERR_MODULE__ >> 16], \ ++ PRINT_FMT_PARAMS); \ ++ XX_Print _vmsg; \ ++ XX_Print("\r\n"); \ ++ } \ ++ } while (0) ++#endif /* (defined(DEBUG_USING_STATIC_LEVEL) && (DEBUG_DYNAMIC_LEVEL < WARNING)) */ ++ ++ ++#define REPORT_ERROR(_level, _err, _vmsg) \ ++ do { \ ++ if (REPORT_LEVEL_##_level <= ERROR_DYNAMIC_LEVEL) { \ ++ XX_Print("! %s %s Error " PRINT_FORMAT ": %s; ", \ ++ dbgLevelStrings[REPORT_LEVEL_##_level - 1], \ ++ moduleStrings[__ERR_MODULE__ >> 16], \ ++ PRINT_FMT_PARAMS, \ ++ ErrTypeStrings((e_ErrorType)GET_ERROR_TYPE(_err))); \ ++ XX_Print _vmsg; \ ++ XX_Print("\r\n"); \ ++ } \ ++ } while (0) ++ ++ ++#define RETURN_ERROR(_level, _err, _vmsg) \ ++ do { \ ++ REPORT_ERROR(_level, (_err), _vmsg); \ ++ return ERROR_CODE(_err); \ ++ } while (0) ++ ++ ++#if (REPORT_EVENTS > 0) ++ ++#define REPORT_EVENT(_ev, _appId, _flg, _vmsg) \ ++ do { \ ++ if (_ev##_LEVEL <= EVENT_DYNAMIC_LEVEL) { \ ++ XX_Print("~ %s %s Event " PRINT_FORMAT ": %s (flags: 0x%04x); ", \ ++ dbgLevelStrings[_ev##_LEVEL - 1], \ ++ moduleStrings[__ERR_MODULE__ >> 16], \ ++ PRINT_FMT_PARAMS, \ ++ eventStrings[((_ev) - EV_NO_EVENT - 1)], \ ++ (uint16_t)(_flg)); \ ++ XX_Print _vmsg; \ ++ XX_Print("\r\n"); \ ++ XX_EventById((uint32_t)(_ev), (t_Handle)(_appId), (uint16_t)(_flg), NO_MSG); \ ++ } \ ++ } while (0) ++ ++#else /* not REPORT_EVENTS */ ++ ++#define REPORT_EVENT(_ev, _appId, _flg, _vmsg) ++ ++#endif /* (REPORT_EVENTS > 0) */ ++ ++#endif /* (DEBUG_ERRORS > 0) */ ++ ++ ++/**************************************************************************//** ++ @Function ASSERT_COND ++ ++ @Description Assertion macro. ++ ++ @Param[in] _cond - The condition being checked, in positive form; ++ Failure of the condition triggers the assert. ++*//***************************************************************************/ ++#ifdef DISABLE_ASSERTIONS ++#define ASSERT_COND(_cond) ++#else ++#define ASSERT_COND(_cond) \ ++ do { \ ++ if (!(_cond)) { \ ++ XX_Print("*** ASSERT_COND failed " PRINT_FORMAT "\r\n", \ ++ PRINT_FMT_PARAMS); \ ++ XX_Exit(1); \ ++ } \ ++ } while (0) ++#endif /* DISABLE_ASSERTIONS */ ++ ++ ++#ifdef DISABLE_INIT_PARAMETERS_CHECK ++ ++#define CHECK_INIT_PARAMETERS(handle, f_check) ++#define CHECK_INIT_PARAMETERS_RETURN_VALUE(handle, f_check, retval) ++ ++#else ++ ++#define CHECK_INIT_PARAMETERS(handle, f_check) \ ++ do { \ ++ t_Error err = f_check(handle); \ ++ if (err != E_OK) { \ ++ RETURN_ERROR(MAJOR, err, NO_MSG); \ ++ } \ ++ } while (0) ++ ++#define CHECK_INIT_PARAMETERS_RETURN_VALUE(handle, f_check, retval) \ ++ do { \ ++ t_Error err = f_check(handle); \ ++ if (err != E_OK) { \ ++ REPORT_ERROR(MAJOR, err, NO_MSG); \ ++ return (retval); \ ++ } \ ++ } while (0) ++ ++#endif /* DISABLE_INIT_PARAMETERS_CHECK */ ++ ++#ifdef DISABLE_SANITY_CHECKS ++ ++#define SANITY_CHECK_RETURN_ERROR(_cond, _err) ++#define SANITY_CHECK_RETURN_VALUE(_cond, _err, retval) ++#define SANITY_CHECK_RETURN(_cond, _err) ++#define SANITY_CHECK_EXIT(_cond, _err) ++ ++#else /* DISABLE_SANITY_CHECKS */ ++ ++#define SANITY_CHECK_RETURN_ERROR(_cond, _err) \ ++ do { \ ++ if (!(_cond)) { \ ++ RETURN_ERROR(CRITICAL, (_err), NO_MSG); \ ++ } \ ++ } while (0) ++ ++#define SANITY_CHECK_RETURN_VALUE(_cond, _err, retval) \ ++ do { \ ++ if (!(_cond)) { \ ++ REPORT_ERROR(CRITICAL, (_err), NO_MSG); \ ++ return (retval); \ ++ } \ ++ } while (0) ++ ++#define SANITY_CHECK_RETURN(_cond, _err) \ ++ do { \ ++ if (!(_cond)) { \ ++ REPORT_ERROR(CRITICAL, (_err), NO_MSG); \ ++ return; \ ++ } \ ++ } while (0) ++ ++#define SANITY_CHECK_EXIT(_cond, _err) \ ++ do { \ ++ if (!(_cond)) { \ ++ REPORT_ERROR(CRITICAL, (_err), NO_MSG); \ ++ XX_Exit(1); \ ++ } \ ++ } while (0) ++ ++#endif /* DISABLE_SANITY_CHECKS */ ++ ++/** @} */ /* end of Debug/error Utils group */ ++ ++/** @} */ /* end of General Utils group */ ++ ++#endif /* __ERROR_EXT_H */ ++ ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/etc/list_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/etc/list_ext.h +new file mode 100644 +index 0000000..ee6b9f2 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/etc/list_ext.h +@@ -0,0 +1,358 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/**************************************************************************//** ++ ++ @File list_ext.h ++ ++ @Description External prototypes for list.c ++*//***************************************************************************/ ++ ++#ifndef __LIST_EXT_H ++#define __LIST_EXT_H ++ ++ ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group etc_id Utility Library Application Programming Interface ++ ++ @Description External routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group list_id List ++ ++ @Description List module functions,definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description List structure. ++*//***************************************************************************/ ++typedef struct List ++{ ++ struct List *p_Next; /**< A pointer to the next list object */ ++ struct List *p_Prev; /**< A pointer to the previous list object */ ++} t_List; ++ ++ ++/**************************************************************************//** ++ @Function LIST_FIRST/LIST_LAST/LIST_NEXT/LIST_PREV ++ ++ @Description Macro to get first/last/next/previous entry in a list. ++ ++ @Param[in] p_List - A pointer to a list. ++*//***************************************************************************/ ++#define LIST_FIRST(p_List) (p_List)->p_Next ++#define LIST_LAST(p_List) (p_List)->p_Prev ++#define LIST_NEXT LIST_FIRST ++#define LIST_PREV LIST_LAST ++ ++ ++/**************************************************************************//** ++ @Function LIST_INIT ++ ++ @Description Macro for initialization of a list struct. ++ ++ @Param[in] lst - The t_List object to initialize. ++*//***************************************************************************/ ++#define LIST_INIT(lst) {&(lst), &(lst)} ++ ++ ++/**************************************************************************//** ++ @Function LIST ++ ++ @Description Macro to declare of a list. ++ ++ @Param[in] listName - The list object name. ++*//***************************************************************************/ ++#define LIST(listName) t_List listName = LIST_INIT(listName) ++ ++ ++/**************************************************************************//** ++ @Function INIT_LIST ++ ++ @Description Macro to initialize a list pointer. ++ ++ @Param[in] p_List - The list pointer. ++*//***************************************************************************/ ++#define INIT_LIST(p_List) LIST_FIRST(p_List) = LIST_LAST(p_List) = (p_List) ++ ++ ++/**************************************************************************//** ++ @Function LIST_OBJECT ++ ++ @Description Macro to get the struct (object) for this entry. ++ ++ @Param[in] type - The type of the struct (object) this list is embedded in. ++ @Param[in] member - The name of the t_List object within the struct. ++ ++ @Return The structure pointer for this entry. ++*//***************************************************************************/ ++#define MEMBER_OFFSET(type, member) (PTR_TO_UINT(&((type *)0)->member)) ++#define LIST_OBJECT(p_List, type, member) \ ++ ((type *)((char *)(p_List)-MEMBER_OFFSET(type, member))) ++ ++ ++/**************************************************************************//** ++ @Function LIST_FOR_EACH ++ ++ @Description Macro to iterate over a list. ++ ++ @Param[in] p_Pos - A pointer to a list to use as a loop counter. ++ @Param[in] p_Head - A pointer to the head for your list pointer. ++ ++ @Cautions You can't delete items with this routine. ++ For deletion use LIST_FOR_EACH_SAFE(). ++*//***************************************************************************/ ++#define LIST_FOR_EACH(p_Pos, p_Head) \ ++ for (p_Pos = LIST_FIRST(p_Head); p_Pos != (p_Head); p_Pos = LIST_NEXT(p_Pos)) ++ ++ ++/**************************************************************************//** ++ @Function LIST_FOR_EACH_SAFE ++ ++ @Description Macro to iterate over a list safe against removal of list entry. ++ ++ @Param[in] p_Pos - A pointer to a list to use as a loop counter. ++ @Param[in] p_Tmp - Another pointer to a list to use as temporary storage. ++ @Param[in] p_Head - A pointer to the head for your list pointer. ++*//***************************************************************************/ ++#define LIST_FOR_EACH_SAFE(p_Pos, p_Tmp, p_Head) \ ++ for (p_Pos = LIST_FIRST(p_Head), p_Tmp = LIST_FIRST(p_Pos); \ ++ p_Pos != (p_Head); \ ++ p_Pos = p_Tmp, p_Tmp = LIST_NEXT(p_Pos)) ++ ++ ++/**************************************************************************//** ++ @Function LIST_FOR_EACH_OBJECT_SAFE ++ ++ @Description Macro to iterate over list of given type safely. ++ ++ @Param[in] p_Pos - A pointer to a list to use as a loop counter. ++ @Param[in] p_Tmp - Another pointer to a list to use as temporary storage. ++ @Param[in] type - The type of the struct this is embedded in. ++ @Param[in] p_Head - A pointer to the head for your list pointer. ++ @Param[in] member - The name of the list_struct within the struct. ++ ++ @Cautions You can't delete items with this routine. ++ For deletion use LIST_FOR_EACH_SAFE(). ++*//***************************************************************************/ ++#define LIST_FOR_EACH_OBJECT_SAFE(p_Pos, p_Tmp, p_Head, type, member) \ ++ for (p_Pos = LIST_OBJECT(LIST_FIRST(p_Head), type, member), \ ++ p_Tmp = LIST_OBJECT(LIST_FIRST(&p_Pos->member), type, member); \ ++ &p_Pos->member != (p_Head); \ ++ p_Pos = p_Tmp, \ ++ p_Tmp = LIST_OBJECT(LIST_FIRST(&p_Pos->member), type, member)) ++ ++/**************************************************************************//** ++ @Function LIST_FOR_EACH_OBJECT ++ ++ @Description Macro to iterate over list of given type. ++ ++ @Param[in] p_Pos - A pointer to a list to use as a loop counter. ++ @Param[in] type - The type of the struct this is embedded in. ++ @Param[in] p_Head - A pointer to the head for your list pointer. ++ @Param[in] member - The name of the list_struct within the struct. ++ ++ @Cautions You can't delete items with this routine. ++ For deletion use LIST_FOR_EACH_SAFE(). ++*//***************************************************************************/ ++#define LIST_FOR_EACH_OBJECT(p_Pos, type, p_Head, member) \ ++ for (p_Pos = LIST_OBJECT(LIST_FIRST(p_Head), type, member); \ ++ &p_Pos->member != (p_Head); \ ++ p_Pos = LIST_OBJECT(LIST_FIRST(&(p_Pos->member)), type, member)) ++ ++ ++/**************************************************************************//** ++ @Function LIST_Add ++ ++ @Description Add a new entry to a list. ++ ++ Insert a new entry after the specified head. ++ This is good for implementing stacks. ++ ++ @Param[in] p_New - A pointer to a new list entry to be added. ++ @Param[in] p_Head - A pointer to a list head to add it after. ++ ++ @Return none. ++*//***************************************************************************/ ++static __inline__ void LIST_Add(t_List *p_New, t_List *p_Head) ++{ ++ LIST_PREV(LIST_NEXT(p_Head)) = p_New; ++ LIST_NEXT(p_New) = LIST_NEXT(p_Head); ++ LIST_PREV(p_New) = p_Head; ++ LIST_NEXT(p_Head) = p_New; ++} ++ ++ ++/**************************************************************************//** ++ @Function LIST_AddToTail ++ ++ @Description Add a new entry to a list. ++ ++ Insert a new entry before the specified head. ++ This is useful for implementing queues. ++ ++ @Param[in] p_New - A pointer to a new list entry to be added. ++ @Param[in] p_Head - A pointer to a list head to add it before. ++ ++ @Return none. ++*//***************************************************************************/ ++static __inline__ void LIST_AddToTail(t_List *p_New, t_List *p_Head) ++{ ++ LIST_NEXT(LIST_PREV(p_Head)) = p_New; ++ LIST_PREV(p_New) = LIST_PREV(p_Head); ++ LIST_NEXT(p_New) = p_Head; ++ LIST_PREV(p_Head) = p_New; ++} ++ ++ ++/**************************************************************************//** ++ @Function LIST_Del ++ ++ @Description Deletes entry from a list. ++ ++ @Param[in] p_Entry - A pointer to the element to delete from the list. ++ ++ @Return none. ++ ++ @Cautions LIST_IsEmpty() on entry does not return true after this, ++ the entry is in an undefined state. ++*//***************************************************************************/ ++static __inline__ void LIST_Del(t_List *p_Entry) ++{ ++ LIST_PREV(LIST_NEXT(p_Entry)) = LIST_PREV(p_Entry); ++ LIST_NEXT(LIST_PREV(p_Entry)) = LIST_NEXT(p_Entry); ++} ++ ++ ++/**************************************************************************//** ++ @Function LIST_DelAndInit ++ ++ @Description Deletes entry from list and reinitialize it. ++ ++ @Param[in] p_Entry - A pointer to the element to delete from the list. ++ ++ @Return none. ++*//***************************************************************************/ ++static __inline__ void LIST_DelAndInit(t_List *p_Entry) ++{ ++ LIST_Del(p_Entry); ++ INIT_LIST(p_Entry); ++} ++ ++ ++/**************************************************************************//** ++ @Function LIST_Move ++ ++ @Description Delete from one list and add as another's head. ++ ++ @Param[in] p_Entry - A pointer to the list entry to move. ++ @Param[in] p_Head - A pointer to the list head that will precede our entry. ++ ++ @Return none. ++*//***************************************************************************/ ++static __inline__ void LIST_Move(t_List *p_Entry, t_List *p_Head) ++{ ++ LIST_Del(p_Entry); ++ LIST_Add(p_Entry, p_Head); ++} ++ ++ ++/**************************************************************************//** ++ @Function LIST_MoveToTail ++ ++ @Description Delete from one list and add as another's tail. ++ ++ @Param[in] p_Entry - A pointer to the entry to move. ++ @Param[in] p_Head - A pointer to the list head that will follow our entry. ++ ++ @Return none. ++*//***************************************************************************/ ++static __inline__ void LIST_MoveToTail(t_List *p_Entry, t_List *p_Head) ++{ ++ LIST_Del(p_Entry); ++ LIST_AddToTail(p_Entry, p_Head); ++} ++ ++ ++/**************************************************************************//** ++ @Function LIST_IsEmpty ++ ++ @Description Tests whether a list is empty. ++ ++ @Param[in] p_List - A pointer to the list to test. ++ ++ @Return 1 if the list is empty, 0 otherwise. ++*//***************************************************************************/ ++static __inline__ int LIST_IsEmpty(t_List *p_List) ++{ ++ return (LIST_FIRST(p_List) == p_List); ++} ++ ++ ++/**************************************************************************//** ++ @Function LIST_Append ++ ++ @Description Join two lists. ++ ++ @Param[in] p_NewList - A pointer to the new list to add. ++ @Param[in] p_Head - A pointer to the place to add it in the first list. ++ ++ @Return none. ++*//***************************************************************************/ ++void LIST_Append(t_List *p_NewList, t_List *p_Head); ++ ++ ++/**************************************************************************//** ++ @Function LIST_NumOfObjs ++ ++ @Description Counts number of objects in the list ++ ++ @Param[in] p_List - A pointer to the list which objects are to be counted. ++ ++ @Return Number of objects in the list. ++*//***************************************************************************/ ++int LIST_NumOfObjs(t_List *p_List); ++ ++/** @} */ /* end of list_id group */ ++/** @} */ /* end of etc_id group */ ++ ++ ++#endif /* __LIST_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/etc/mem_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/etc/mem_ext.h +new file mode 100644 +index 0000000..d0565d4 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/etc/mem_ext.h +@@ -0,0 +1,318 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/**************************************************************************//** ++ ++ @File mem_ext.h ++ ++ @Description External prototypes for the memory manager object ++*//***************************************************************************/ ++ ++#ifndef __MEM_EXT_H ++#define __MEM_EXT_H ++ ++#include "std_ext.h" ++#include "part_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group etc_id Utility Library Application Programming Interface ++ ++ @Description External routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group mem_id Slab Memory Manager ++ ++ @Description Slab Memory Manager module functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/* Each block is of the following structure: ++ * ++ * ++ * +-----------+----------+---------------------------+-----------+-----------+ ++ * | Alignment | Prefix | Data | Postfix | Alignment | ++ * | field | field | field | field | Padding | ++ * | | | | | | ++ * +-----------+----------+---------------------------+-----------+-----------+ ++ * and at the beginning of all bytes, an additional optional padding might reside ++ * to ensure that the first blocks data field is aligned as requested. ++ */ ++ ++ ++#define MEM_MAX_NAME_LENGTH 8 ++ ++/**************************************************************************//* ++ @Description Memory Segment structure ++*//***************************************************************************/ ++ ++typedef struct ++{ ++ char name[MEM_MAX_NAME_LENGTH]; ++ /* The segment's name */ ++ uint8_t **p_Bases; /* Base addresses of the segments */ ++ uint8_t **p_BlocksStack; /* Array of pointers to blocks */ ++ t_Handle h_Spinlock; ++ uint16_t dataSize; /* Size of each data block */ ++ uint16_t prefixSize; /* How many bytes to reserve before the data */ ++ uint16_t postfixSize; /* How many bytes to reserve after the data */ ++ uint16_t alignment; /* Requested alignment for the data field */ ++ int allocOwner; /* Memory allocation owner */ ++ uint32_t getFailures; /* Number of times get failed */ ++ uint32_t num; /* Number of blocks in segment */ ++ uint32_t current; /* Current block */ ++ bool consecutiveMem; /* Allocate consecutive data blocks memory */ ++#ifdef DEBUG_MEM_LEAKS ++ void *p_MemDbg; /* MEM debug database (MEM leaks detection) */ ++ uint32_t blockOffset; ++ uint32_t blockSize; ++#endif /* DEBUG_MEM_LEAKS */ ++} t_MemorySegment; ++ ++ ++ ++/**************************************************************************//** ++ @Function MEM_Init ++ ++ @Description Create a new memory segment. ++ ++ @Param[in] name - Name of memory partition. ++ @Param[in] p_Handle - Handle to new segment is returned through here. ++ @Param[in] num - Number of blocks in new segment. ++ @Param[in] dataSize - Size of blocks in segment. ++ @Param[in] prefixSize - How many bytes to allocate before the data. ++ @Param[in] postfixSize - How many bytes to allocate after the data. ++ @Param[in] alignment - Requested alignment for data field (in bytes). ++ ++ @Return E_OK - success, E_NO_MEMORY - out of memory. ++*//***************************************************************************/ ++t_Error MEM_Init(char name[], ++ t_Handle *p_Handle, ++ uint32_t num, ++ uint16_t dataSize, ++ uint16_t prefixSize, ++ uint16_t postfixSize, ++ uint16_t alignment); ++ ++/**************************************************************************//** ++ @Function MEM_InitSmart ++ ++ @Description Create a new memory segment. ++ ++ @Param[in] name - Name of memory partition. ++ @Param[in] p_Handle - Handle to new segment is returned through here. ++ @Param[in] num - Number of blocks in new segment. ++ @Param[in] dataSize - Size of blocks in segment. ++ @Param[in] prefixSize - How many bytes to allocate before the data. ++ @Param[in] postfixSize - How many bytes to allocate after the data. ++ @Param[in] alignment - Requested alignment for data field (in bytes). ++ @Param[in] memPartitionId - Memory partition ID for allocation. ++ @Param[in] consecutiveMem - Whether to allocate the memory blocks ++ continuously or not. ++ ++ @Return E_OK - success, E_NO_MEMORY - out of memory. ++*//***************************************************************************/ ++t_Error MEM_InitSmart(char name[], ++ t_Handle *p_Handle, ++ uint32_t num, ++ uint16_t dataSize, ++ uint16_t prefixSize, ++ uint16_t postfixSize, ++ uint16_t alignment, ++ uint8_t memPartitionId, ++ bool consecutiveMem); ++ ++/**************************************************************************//** ++ @Function MEM_InitByAddress ++ ++ @Description Create a new memory segment with a specified base address. ++ ++ @Param[in] name - Name of memory partition. ++ @Param[in] p_Handle - Handle to new segment is returned through here. ++ @Param[in] num - Number of blocks in new segment. ++ @Param[in] dataSize - Size of blocks in segment. ++ @Param[in] prefixSize - How many bytes to allocate before the data. ++ @Param[in] postfixSize - How many bytes to allocate after the data. ++ @Param[in] alignment - Requested alignment for data field (in bytes). ++ @Param[in] address - The required base address. ++ ++ @Return E_OK - success, E_NO_MEMORY - out of memory. ++ *//***************************************************************************/ ++t_Error MEM_InitByAddress(char name[], ++ t_Handle *p_Handle, ++ uint32_t num, ++ uint16_t dataSize, ++ uint16_t prefixSize, ++ uint16_t postfixSize, ++ uint16_t alignment, ++ uint8_t *address); ++ ++/**************************************************************************//** ++ @Function MEM_Free ++ ++ @Description Free a specific memory segment. ++ ++ @Param[in] h_Mem - Handle to memory segment. ++ ++ @Return None. ++*//***************************************************************************/ ++void MEM_Free(t_Handle h_Mem); ++ ++/**************************************************************************//** ++ @Function MEM_Get ++ ++ @Description Get a block of memory from a segment. ++ ++ @Param[in] h_Mem - Handle to memory segment. ++ ++ @Return Pointer to new memory block on success,0 otherwise. ++*//***************************************************************************/ ++void * MEM_Get(t_Handle h_Mem); ++ ++/**************************************************************************//** ++ @Function MEM_GetN ++ ++ @Description Get up to N blocks of memory from a segment. ++ ++ The blocks are assumed to be of a fixed size (one size per segment). ++ ++ @Param[in] h_Mem - Handle to memory segment. ++ @Param[in] num - Number of blocks to allocate. ++ @Param[out] array - Array of at least num pointers to which the addresses ++ of the allocated blocks are written. ++ ++ @Return The number of blocks actually allocated. ++ ++ @Cautions Interrupts are disabled for all of the allocation loop. ++ Although this loop is very short for each block (several machine ++ instructions), you should not allocate a very large number ++ of blocks via this routine. ++*//***************************************************************************/ ++uint16_t MEM_GetN(t_Handle h_Mem, uint32_t num, void *array[]); ++ ++/**************************************************************************//** ++ @Function MEM_Put ++ ++ @Description Put a block of memory back to a segment. ++ ++ @Param[in] h_Mem - Handle to memory segment. ++ @Param[in] p_Block - The block to return. ++ ++ @Return Pointer to new memory block on success,0 otherwise. ++*//***************************************************************************/ ++t_Error MEM_Put(t_Handle h_Mem, void *p_Block); ++ ++/**************************************************************************//** ++ @Function MEM_ComputePartitionSize ++ ++ @Description calculate a tight upper boundary of the size of a partition with ++ given attributes. ++ ++ The returned value is suitable if one wants to use MEM_InitByAddress(). ++ ++ @Param[in] num - The number of blocks in the segment. ++ @Param[in] dataSize - Size of block to get. ++ @Param[in] prefixSize - The prefix size ++ @Param postfixSize - The postfix size ++ @Param[in] alignment - The requested alignment value (in bytes) ++ ++ @Return The memory block size a segment with the given attributes needs. ++*//***************************************************************************/ ++uint32_t MEM_ComputePartitionSize(uint32_t num, ++ uint16_t dataSize, ++ uint16_t prefixSize, ++ uint16_t postfixSize, ++ uint16_t alignment); ++ ++#ifdef DEBUG_MEM_LEAKS ++#if !((defined(__MWERKS__) || defined(__GNUC__)) && (__dest_os == __ppc_eabi)) ++#error "Memory-Leaks-Debug option is supported only for freescale CodeWarrior" ++#endif /* !(defined(__MWERKS__) && ... */ ++ ++/**************************************************************************//** ++ @Function MEM_CheckLeaks ++ ++ @Description Report MEM object leaks. ++ ++ This routine is automatically called by the MEM_Free() routine, ++ but it can also be invoked while the MEM object is alive. ++ ++ @Param[in] h_Mem - Handle to memory segment. ++ ++ @Return None. ++*//***************************************************************************/ ++void MEM_CheckLeaks(t_Handle h_Mem); ++ ++#else /* not DEBUG_MEM_LEAKS */ ++#define MEM_CheckLeaks(h_Mem) ++#endif /* not DEBUG_MEM_LEAKS */ ++ ++/**************************************************************************//** ++ @Description Get base of MEM ++*//***************************************************************************/ ++#define MEM_GetBase(h_Mem) ((t_MemorySegment *)(h_Mem))->p_Bases[0] ++ ++/**************************************************************************//** ++ @Description Get size of MEM block ++*//***************************************************************************/ ++#define MEM_GetSize(h_Mem) ((t_MemorySegment *)(h_Mem))->dataSize ++ ++/**************************************************************************//** ++ @Description Get prefix size of MEM block ++*//***************************************************************************/ ++#define MEM_GetPrefixSize(h_Mem) ((t_MemorySegment *)(h_Mem))->prefixSize ++ ++/**************************************************************************//** ++ @Description Get postfix size of MEM block ++*//***************************************************************************/ ++#define MEM_GetPostfixSize(h_Mem) ((t_MemorySegment *)(h_Mem))->postfixSize ++ ++/**************************************************************************//** ++ @Description Get alignment of MEM block (in bytes) ++*//***************************************************************************/ ++#define MEM_GetAlignment(h_Mem) ((t_MemorySegment *)(h_Mem))->alignment ++ ++/**************************************************************************//** ++ @Description Get the number of blocks in the segment ++*//***************************************************************************/ ++#define MEM_GetNumOfBlocks(h_Mem) ((t_MemorySegment *)(h_Mem))->num ++ ++/** @} */ /* end of MEM group */ ++/** @} */ /* end of etc_id group */ ++ ++ ++#endif /* __MEM_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/etc/memcpy_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/etc/memcpy_ext.h +new file mode 100644 +index 0000000..cc5bb72 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/etc/memcpy_ext.h +@@ -0,0 +1,174 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/**************************************************************************//** ++ ++ @File memcpy_ext.h ++ ++ @Description Efficient functions for copying and setting blocks of memory. ++*//***************************************************************************/ ++ ++#ifndef __MEMCPY_EXT_H ++#define __MEMCPY_EXT_H ++ ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group etc_id Utility Library Application Programming Interface ++ ++ @Description External routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group mem_cpy Memory Copy ++ ++ @Description Memory Copy module functions,definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function MemCpy32 ++ ++ @Description Copies one memory buffer into another one in 4-byte chunks! ++ Which should be more efficient than byte by byte. ++ ++ For large buffers (over 60 bytes) this function is about 4 times ++ more efficient than the trivial memory copy. For short buffers ++ it is reduced to the trivial copy and may be a bit worse. ++ ++ @Param[in] pDst - The address of the destination buffer. ++ @Param[in] pSrc - The address of the source buffer. ++ @Param[in] size - The number of bytes that will be copied from pSrc to pDst. ++ ++ @Return pDst (the address of the destination buffer). ++ ++ @Cautions There is no parameter or boundary checking! It is up to the user ++ to supply non-null parameters as source & destination and size ++ that actually fits into the destination buffer. ++*//***************************************************************************/ ++void * MemCpy32(void* pDst,void* pSrc, uint32_t size); ++void * IO2IOCpy32(void* pDst,void* pSrc, uint32_t size); ++void * IO2MemCpy32(void* pDst,void* pSrc, uint32_t size); ++void * Mem2IOCpy32(void* pDst,void* pSrc, uint32_t size); ++ ++/**************************************************************************//** ++ @Function MemCpy64 ++ ++ @Description Copies one memory buffer into another one in 8-byte chunks! ++ Which should be more efficient than byte by byte. ++ ++ For large buffers (over 60 bytes) this function is about 8 times ++ more efficient than the trivial memory copy. For short buffers ++ it is reduced to the trivial copy and may be a bit worse. ++ ++ Some testing suggests that MemCpy32() preforms better than ++ MemCpy64() over small buffers. On average they break even at ++ 100 byte buffers. For buffers larger than that MemCpy64 is ++ superior. ++ ++ @Param[in] pDst - The address of the destination buffer. ++ @Param[in] pSrc - The address of the source buffer. ++ @Param[in] size - The number of bytes that will be copied from pSrc to pDst. ++ ++ @Return pDst (the address of the destination buffer). ++ ++ @Cautions There is no parameter or boundary checking! It is up to the user ++ to supply non null parameters as source & destination and size ++ that actually fits into their buffer. ++ ++ Do not use under Linux. ++*//***************************************************************************/ ++void * MemCpy64(void* pDst,void* pSrc, uint32_t size); ++ ++/**************************************************************************//** ++ @Function MemSet32 ++ ++ @Description Sets all bytes of a memory buffer to a specific value, in ++ 4-byte chunks. ++ ++ @Param[in] pDst - The address of the destination buffer. ++ @Param[in] val - Value to set destination bytes to. ++ @Param[in] size - The number of bytes that will be set to val. ++ ++ @Return pDst (the address of the destination buffer). ++ ++ @Cautions There is no parameter or boundary checking! It is up to the user ++ to supply non null parameter as destination and size ++ that actually fits into the destination buffer. ++*//***************************************************************************/ ++void * MemSet32(void* pDst, uint8_t val, uint32_t size); ++void * IOMemSet32(void* pDst, uint8_t val, uint32_t size); ++ ++/**************************************************************************//** ++ @Function MemSet64 ++ ++ @Description Sets all bytes of a memory buffer to a specific value, in ++ 8-byte chunks. ++ ++ @Param[in] pDst - The address of the destination buffer. ++ @Param[in] val - Value to set destination bytes to. ++ @Param[in] size - The number of bytes that will be set to val. ++ ++ @Return pDst (the address of the destination buffer). ++ ++ @Cautions There is no parameter or boundary checking! It is up to the user ++ to supply non null parameter as destination and size ++ that actually fits into the destination buffer. ++*//***************************************************************************/ ++void * MemSet64(void* pDst, uint8_t val, uint32_t size); ++ ++/**************************************************************************//** ++ @Function MemDisp ++ ++ @Description Displays a block of memory in chunks of 32 bits. ++ ++ @Param[in] addr - The address of the memory to display. ++ @Param[in] size - The number of bytes that will be displayed. ++ ++ @Return None. ++ ++ @Cautions There is no parameter or boundary checking! It is up to the user ++ to supply non null parameter as destination and size ++ that actually fits into the destination buffer. ++*//***************************************************************************/ ++void MemDisp(uint8_t *addr, int size); ++ ++/** @} */ /* end of mem_cpy group */ ++/** @} */ /* end of etc_id group */ ++ ++ ++#endif /* __MEMCPY_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/etc/mm_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/etc/mm_ext.h +new file mode 100644 +index 0000000..fa7c85e +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/etc/mm_ext.h +@@ -0,0 +1,310 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File mm_ext.h ++ ++ @Description Memory Manager Application Programming Interface ++*//***************************************************************************/ ++#ifndef __MM_EXT ++#define __MM_EXT ++ ++#include "std_ext.h" ++ ++#define MM_MAX_ALIGNMENT 20 /* Alignments from 2 to 128 are available ++ where maximum alignment defined as ++ MM_MAX_ALIGNMENT power of 2 */ ++ ++#define MM_MAX_NAME_LEN 32 ++ ++/**************************************************************************//** ++ @Group etc_id Utility Library Application Programming Interface ++ ++ @Description External routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group mm_grp Flexible Memory Manager ++ ++ @Description Flexible Memory Manager module functions,definitions and enums. ++ (All of the following functions,definitions and enums can be found in mm_ext.h) ++ ++ @{ ++*//***************************************************************************/ ++ ++ ++/**************************************************************************//** ++ @Function MM_Init ++ ++ @Description Initializes a new MM object. ++ ++ It initializes a new memory block consisting of base address ++ and size of the available memory by calling to MemBlock_Init ++ routine. It is also initializes a new free block for each ++ by calling FreeBlock_Init routine, which is pointed to ++ the almost all memory started from the required alignment ++ from the base address and to the end of the memory. ++ The handle to the new MM object is returned via "MM" ++ argument (passed by reference). ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] base - Base address of the MM. ++ @Param[in] size - Size of the MM. ++ ++ @Return E_OK is returned on success. E_NOMEMORY is returned if the new MM object or a new free block can not be initialized. ++*//***************************************************************************/ ++t_Error MM_Init(t_Handle *h_MM, uint64_t base, uint64_t size); ++ ++/**************************************************************************//** ++ @Function MM_Get ++ ++ @Description Allocates a block of memory according to the given size and the alignment. ++ ++ The Alignment argument tells from which ++ free list allocate a block of memory. 2^alignment indicates ++ the alignment that the base address of the allocated block ++ should have. So, the only values 1, 2, 4, 8, 16, 32 and 64 ++ are available for the alignment argument. ++ The routine passes through the specific free list of free ++ blocks and seeks for a first block that have anough memory ++ that is required (best fit). ++ After the block is found and data is allocated, it calls ++ the internal MM_CutFree routine to update all free lists ++ do not include a just allocated block. Of course, each ++ free list contains a free blocks with the same alignment. ++ It is also creates a busy block that holds ++ information about an allocated block. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] size - Size of the MM. ++ @Param[in] alignment - Index as a power of two defines a required ++ alignment (in bytes); Should be 1, 2, 4, 8, 16, 32 or 64 ++ @Param[in] name - The name that specifies an allocated block. ++ ++ @Return base address of an allocated block ILLEGAL_BASE if can't allocate a block ++*//***************************************************************************/ ++uint64_t MM_Get(t_Handle h_MM, uint64_t size, uint64_t alignment, char *name); ++ ++/**************************************************************************//** ++ @Function MM_GetBase ++ ++ @Description Gets the base address of the required MM objects. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ ++ @Return base address of the block. ++*//***************************************************************************/ ++uint64_t MM_GetBase(t_Handle h_MM); ++ ++/**************************************************************************//** ++ @Function MM_GetForce ++ ++ @Description Force memory allocation. ++ ++ It means to allocate a block of memory of the given ++ size from the given base address. ++ The routine checks if the required block can be allocated ++ (that is it is free) and then, calls the internal MM_CutFree ++ routine to update all free lists do not include that block. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] base - Base address of the MM. ++ @Param[in] size - Size of the MM. ++ @Param[in] name - Name that specifies an allocated block. ++ ++ @Return base address of an allocated block, ILLEGAL_BASE if can't allocate a block. ++*//***************************************************************************/ ++uint64_t MM_GetForce(t_Handle h_MM, uint64_t base, uint64_t size, char *name); ++ ++/**************************************************************************//** ++ @Function MM_GetForceMin ++ ++ @Description Allocates a block of memory according to the given size, the alignment and minimum base address. ++ ++ The Alignment argument tells from which ++ free list allocate a block of memory. 2^alignment indicates ++ the alignment that the base address of the allocated block ++ should have. So, the only values 1, 2, 4, 8, 16, 32 and 64 ++ are available for the alignment argument. ++ The minimum baser address forces the location of the block ++ to be from a given address onward. ++ The routine passes through the specific free list of free ++ blocks and seeks for the first base address equal or smaller ++ than the required minimum address and end address larger than ++ than the required base + its size - i.e. that may contain ++ the required block. ++ After the block is found and data is allocated, it calls ++ the internal MM_CutFree routine to update all free lists ++ do not include a just allocated block. Of course, each ++ free list contains a free blocks with the same alignment. ++ It is also creates a busy block that holds ++ information about an allocated block. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] size - Size of the MM. ++ @Param[in] alignment - Index as a power of two defines a required ++ alignment (in bytes); Should be 1, 2, 4, 8, 16, 32 or 64 ++ @Param[in] min - The minimum base address of the block. ++ @Param[in] name - Name that specifies an allocated block. ++ ++ @Return base address of an allocated block,ILLEGAL_BASE if can't allocate a block. ++*//***************************************************************************/ ++uint64_t MM_GetForceMin(t_Handle h_MM, ++ uint64_t size, ++ uint64_t alignment, ++ uint64_t min, ++ char *name); ++ ++/**************************************************************************//** ++ @Function MM_Put ++ ++ @Description Puts a block of memory of the given base address back to the memory. ++ ++ It checks if there is a busy block with the ++ given base address. If not, it returns 0, that ++ means can't free a block. Otherwise, it gets parameters of ++ the busy block and after it updates lists of free blocks, ++ removes that busy block from the list by calling to MM_CutBusy ++ routine. ++ After that it calls to MM_AddFree routine to add a new free ++ block to the free lists. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] base - Base address of the MM. ++ ++ @Return The size of bytes released, 0 if failed. ++*//***************************************************************************/ ++uint64_t MM_Put(t_Handle h_MM, uint64_t base); ++ ++/**************************************************************************//** ++ @Function MM_PutForce ++ ++ @Description Releases a block of memory of the required size from the required base address. ++ ++ First, it calls to MM_CutBusy routine ++ to cut a free block from the busy list. And then, calls to ++ MM_AddFree routine to add the free block to the free lists. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] base - Base address of of a block to free. ++ @Param[in] size - Size of a block to free. ++ ++ @Return The number of bytes released, 0 on failure. ++*//***************************************************************************/ ++uint64_t MM_PutForce(t_Handle h_MM, uint64_t base, uint64_t size); ++ ++/**************************************************************************//** ++ @Function MM_Add ++ ++ @Description Adds a new memory block for memory allocation. ++ ++ When a new memory block is initialized and added to the ++ memory list, it calls to MM_AddFree routine to add the ++ new free block to the free lists. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] base - Base address of the memory block. ++ @Param[in] size - Size of the memory block. ++ ++ @Return E_OK on success, otherwise returns an error code. ++*//***************************************************************************/ ++t_Error MM_Add(t_Handle h_MM, uint64_t base, uint64_t size); ++ ++/**************************************************************************//** ++ @Function MM_Dump ++ ++ @Description Prints results of free and busy lists. ++ ++ @Param[in] h_MM - Handle to the MM object. ++*//***************************************************************************/ ++void MM_Dump(t_Handle h_MM); ++ ++/**************************************************************************//** ++ @Function MM_Free ++ ++ @Description Releases memory allocated for MM object. ++ ++ @Param[in] h_MM - Handle of the MM object. ++*//***************************************************************************/ ++void MM_Free(t_Handle h_MM); ++ ++/**************************************************************************//** ++ @Function MM_GetMemBlock ++ ++ @Description Returns base address of the memory block specified by the index. ++ ++ If index is 0, returns base address ++ of the first memory block, 1 - returns base address ++ of the second memory block, etc. ++ Note, those memory blocks are allocated by the ++ application before MM_Init or MM_Add and have to ++ be released by the application before or after invoking ++ the MM_Free routine. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] index - Index of the memory block. ++ ++ @Return valid base address or ILLEGAL_BASE if no memory block specified by the index. ++*//***************************************************************************/ ++uint64_t MM_GetMemBlock(t_Handle h_MM, int index); ++ ++/**************************************************************************//** ++ @Function MM_InRange ++ ++ @Description Checks if a specific address is in the memory range of the passed MM object. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ @Param[in] addr - The address to be checked. ++ ++ @Return TRUE if the address is in the address range of the block, FALSE otherwise. ++*//***************************************************************************/ ++bool MM_InRange(t_Handle h_MM, uint64_t addr); ++ ++/**************************************************************************//** ++ @Function MM_GetFreeMemSize ++ ++ @Description Returns the size (in bytes) of free memory. ++ ++ @Param[in] h_MM - Handle to the MM object. ++ ++ @Return Free memory size in bytes. ++*//***************************************************************************/ ++uint64_t MM_GetFreeMemSize(t_Handle h_MM); ++ ++ ++/** @} */ /* end of mm_grp group */ ++/** @} */ /* end of etc_id group */ ++ ++#endif /* __MM_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/etc/sprint_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/etc/sprint_ext.h +new file mode 100644 +index 0000000..52f7a9d +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/etc/sprint_ext.h +@@ -0,0 +1,118 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File sprint_ext.h ++ ++ @Description Debug routines (externals). ++ ++*//***************************************************************************/ ++ ++#ifndef __SPRINT_EXT_H ++#define __SPRINT_EXT_H ++ ++ ++#if defined(NCSW_LINUX) && defined(__KERNEL__) ++#include ++ ++#elif defined(NCSW_VXWORKS) ++#include "private/stdioP.h" ++ ++#else ++#include ++#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */ ++ ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group etc_id Utility Library Application Programming Interface ++ ++ @Description External routines. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group sprint_id Sprint ++ ++ @Description Sprint & Sscan module functions,definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Function Sprint ++ ++ @Description Format a string and place it in a buffer. ++ ++ @Param[in] buff - The buffer to place the result into. ++ @Param[in] str - The format string to use. ++ @Param[in] ... - Arguments for the format string. ++ ++ @Return Number of bytes formatted. ++*//***************************************************************************/ ++int Sprint(char *buff, const char *str, ...); ++ ++/**************************************************************************//** ++ @Function Snprint ++ ++ @Description Format a string and place it in a buffer. ++ ++ @Param[in] buf - The buffer to place the result into. ++ @Param[in] size - The size of the buffer, including the trailing null space. ++ @Param[in] fmt - The format string to use. ++ @Param[in] ... - Arguments for the format string. ++ ++ @Return Number of bytes formatted. ++*//***************************************************************************/ ++int Snprint(char * buf, uint32_t size, const char *fmt, ...); ++ ++/**************************************************************************//** ++ @Function Sscan ++ ++ @Description Unformat a buffer into a list of arguments. ++ ++ @Param[in] buf - input buffer. ++ @Param[in] fmt - formatting of buffer. ++ @Param[out] ... - resulting arguments. ++ ++ @Return Number of bytes unformatted. ++*//***************************************************************************/ ++int Sscan(const char * buf, const char * fmt, ...); ++ ++/** @} */ /* end of sprint_id group */ ++/** @} */ /* end of etc_id group */ ++ ++ ++#endif /* __SPRINT_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/common/arch/ppc_access.h b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/common/arch/ppc_access.h +new file mode 100644 +index 0000000..c7b9b46 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/common/arch/ppc_access.h +@@ -0,0 +1,37 @@ ++/* ++ * Copyright 2008-2012 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 FL_E500_MACROS_H ++#define FL_E500_MACROS_H ++ ++#endif /* FL_E500_MACROS_H */ ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/common/general.h b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/common/general.h +new file mode 100644 +index 0000000..8150e01 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/common/general.h +@@ -0,0 +1,51 @@ ++/* ++ * Copyright 2008-2012 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 __GENERAL_H ++#define __GENERAL_H ++ ++#include "std_ext.h" ++#if !defined(NCSW_LINUX) ++#include "errno.h" ++#endif ++ ++ ++extern uint32_t get_mac_addr_crc(uint64_t _addr); ++ ++ ++#define iowrite32be(val, addr) WRITE_UINT32(*addr, val) ++#define ioread32be(addr) GET_UINT32(*addr) ++ ++#define ether_crc(len, addr) get_mac_addr_crc(*(uint64_t *)(addr)>>16) ++ ++ ++#endif /* __GENERAL_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fman_common.h b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fman_common.h +new file mode 100755 +index 0000000..8b194e9 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fman_common.h +@@ -0,0 +1,78 @@ ++/* ++ * Copyright 2008-2013 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 __FMAN_COMMON_H ++#define __FMAN_COMMON_H ++ ++/**************************************************************************//** ++ @Description NIA Description ++*//***************************************************************************/ ++#define NIA_ORDER_RESTOR 0x00800000 ++#define NIA_ENG_FM_CTL 0x00000000 ++#define NIA_ENG_PRS 0x00440000 ++#define NIA_ENG_KG 0x00480000 ++#define NIA_ENG_PLCR 0x004C0000 ++#define NIA_ENG_BMI 0x00500000 ++#define NIA_ENG_QMI_ENQ 0x00540000 ++#define NIA_ENG_QMI_DEQ 0x00580000 ++#define NIA_ENG_MASK 0x007C0000 ++ ++#define NIA_FM_CTL_AC_CC 0x00000006 ++#define NIA_FM_CTL_AC_HC 0x0000000C ++#define NIA_FM_CTL_AC_IND_MODE_TX 0x00000008 ++#define NIA_FM_CTL_AC_IND_MODE_RX 0x0000000A ++#define NIA_FM_CTL_AC_FRAG 0x0000000e ++#define NIA_FM_CTL_AC_PRE_FETCH 0x00000010 ++#define NIA_FM_CTL_AC_POST_FETCH_PCD 0x00000012 ++#define NIA_FM_CTL_AC_POST_FETCH_PCD_UDP_LEN 0x00000018 ++#define NIA_FM_CTL_AC_POST_FETCH_NO_PCD 0x00000012 ++#define NIA_FM_CTL_AC_FRAG_CHECK 0x00000014 ++#define NIA_FM_CTL_AC_PRE_CC 0x00000020 ++ ++ ++#define NIA_BMI_AC_ENQ_FRAME 0x00000002 ++#define NIA_BMI_AC_TX_RELEASE 0x000002C0 ++#define NIA_BMI_AC_RELEASE 0x000000C0 ++#define NIA_BMI_AC_DISCARD 0x000000C1 ++#define NIA_BMI_AC_TX 0x00000274 ++#define NIA_BMI_AC_FETCH 0x00000208 ++#define NIA_BMI_AC_MASK 0x000003FF ++ ++#define NIA_KG_DIRECT 0x00000100 ++#define NIA_KG_CC_EN 0x00000200 ++#define NIA_PLCR_ABSOLUTE 0x00008000 ++ ++#define NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA 0x00000202 ++#define NIA_BMI_AC_FETCH_ALL_FRAME 0x0000020c ++ ++#endif /* __FMAN_COMMON_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_enet.h b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_enet.h +new file mode 100644 +index 0000000..caa87fc +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_enet.h +@@ -0,0 +1,273 @@ ++/* ++ * Copyright 2008-2012 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 __FSL_ENET_H ++#define __FSL_ENET_H ++ ++/** ++ @Description Ethernet MAC-PHY Interface ++*/ ++ ++enum enet_interface { ++ E_ENET_IF_MII = 0x00010000, /**< MII interface */ ++ E_ENET_IF_RMII = 0x00020000, /**< RMII interface */ ++ E_ENET_IF_SMII = 0x00030000, /**< SMII interface */ ++ E_ENET_IF_GMII = 0x00040000, /**< GMII interface */ ++ E_ENET_IF_RGMII = 0x00050000, /**< RGMII interface */ ++ E_ENET_IF_TBI = 0x00060000, /**< TBI interface */ ++ E_ENET_IF_RTBI = 0x00070000, /**< RTBI interface */ ++ E_ENET_IF_SGMII = 0x00080000, /**< SGMII interface */ ++ E_ENET_IF_XGMII = 0x00090000, /**< XGMII interface */ ++ E_ENET_IF_QSGMII = 0x000a0000, /**< QSGMII interface */ ++ E_ENET_IF_XFI = 0x000b0000 /**< XFI interface */ ++}; ++ ++/** ++ @Description Ethernet Speed (nominal data rate) ++*/ ++enum enet_speed { ++ E_ENET_SPEED_10 = 10, /**< 10 Mbps */ ++ E_ENET_SPEED_100 = 100, /**< 100 Mbps */ ++ E_ENET_SPEED_1000 = 1000, /**< 1000 Mbps = 1 Gbps */ ++ E_ENET_SPEED_2500 = 2500, /**< 2500 Mbps = 2.5 Gbps */ ++ E_ENET_SPEED_10000 = 10000 /**< 10000 Mbps = 10 Gbps */ ++}; ++ ++enum mac_type { ++ E_MAC_DTSEC, ++ E_MAC_TGEC, ++ E_MAC_MEMAC ++}; ++ ++/**************************************************************************//** ++ @Description Enum for inter-module interrupts registration ++*//***************************************************************************/ ++enum fman_event_modules { ++ E_FMAN_MOD_PRS, /**< Parser event */ ++ E_FMAN_MOD_KG, /**< Keygen event */ ++ E_FMAN_MOD_PLCR, /**< Policer event */ ++ E_FMAN_MOD_10G_MAC, /**< 10G MAC event */ ++ E_FMAN_MOD_1G_MAC, /**< 1G MAC event */ ++ E_FMAN_MOD_TMR, /**< Timer event */ ++ E_FMAN_MOD_FMAN_CTRL, /**< FMAN Controller Timer event */ ++ E_FMAN_MOD_MACSEC, ++ E_FMAN_MOD_DUMMY_LAST ++}; ++ ++/**************************************************************************//** ++ @Description Enum for interrupts types ++*//***************************************************************************/ ++enum fman_intr_type { ++ E_FMAN_INTR_TYPE_ERR, ++ E_FMAN_INTR_TYPE_NORMAL ++}; ++ ++/**************************************************************************//** ++ @Description enum for defining MAC types ++*//***************************************************************************/ ++enum fman_mac_type { ++ E_FMAN_MAC_10G = 0, /**< 10G MAC */ ++ E_FMAN_MAC_1G /**< 1G MAC */ ++}; ++ ++enum fman_mac_exceptions { ++ E_FMAN_MAC_EX_10G_MDIO_SCAN_EVENTMDIO = 0, ++ /**< 10GEC MDIO scan event interrupt */ ++ E_FMAN_MAC_EX_10G_MDIO_CMD_CMPL, ++ /**< 10GEC MDIO command completion interrupt */ ++ E_FMAN_MAC_EX_10G_REM_FAULT, ++ /**< 10GEC, mEMAC Remote fault interrupt */ ++ E_FMAN_MAC_EX_10G_LOC_FAULT, ++ /**< 10GEC, mEMAC Local fault interrupt */ ++ E_FMAN_MAC_EX_10G_1TX_ECC_ER, ++ /**< 10GEC, mEMAC Transmit frame ECC error interrupt */ ++ E_FMAN_MAC_EX_10G_TX_FIFO_UNFL, ++ /**< 10GEC, mEMAC Transmit FIFO underflow interrupt */ ++ E_FMAN_MAC_EX_10G_TX_FIFO_OVFL, ++ /**< 10GEC, mEMAC Transmit FIFO overflow interrupt */ ++ E_FMAN_MAC_EX_10G_TX_ER, ++ /**< 10GEC Transmit frame error interrupt */ ++ E_FMAN_MAC_EX_10G_RX_FIFO_OVFL, ++ /**< 10GEC, mEMAC Receive FIFO overflow interrupt */ ++ E_FMAN_MAC_EX_10G_RX_ECC_ER, ++ /**< 10GEC, mEMAC Receive frame ECC error interrupt */ ++ E_FMAN_MAC_EX_10G_RX_JAB_FRM, ++ /**< 10GEC Receive jabber frame interrupt */ ++ E_FMAN_MAC_EX_10G_RX_OVRSZ_FRM, ++ /**< 10GEC Receive oversized frame interrupt */ ++ E_FMAN_MAC_EX_10G_RX_RUNT_FRM, ++ /**< 10GEC Receive runt frame interrupt */ ++ E_FMAN_MAC_EX_10G_RX_FRAG_FRM, ++ /**< 10GEC Receive fragment frame interrupt */ ++ E_FMAN_MAC_EX_10G_RX_LEN_ER, ++ /**< 10GEC Receive payload length error interrupt */ ++ E_FMAN_MAC_EX_10G_RX_CRC_ER, ++ /**< 10GEC Receive CRC error interrupt */ ++ E_FMAN_MAC_EX_10G_RX_ALIGN_ER, ++ /**< 10GEC Receive alignment error interrupt */ ++ E_FMAN_MAC_EX_1G_BAB_RX, ++ /**< dTSEC Babbling receive error */ ++ E_FMAN_MAC_EX_1G_RX_CTL, ++ /**< dTSEC Receive control (pause frame) interrupt */ ++ E_FMAN_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET, ++ /**< dTSEC Graceful transmit stop complete */ ++ E_FMAN_MAC_EX_1G_BAB_TX, ++ /**< dTSEC Babbling transmit error */ ++ E_FMAN_MAC_EX_1G_TX_CTL, ++ /**< dTSEC Transmit control (pause frame) interrupt */ ++ E_FMAN_MAC_EX_1G_TX_ERR, ++ /**< dTSEC Transmit error */ ++ E_FMAN_MAC_EX_1G_LATE_COL, ++ /**< dTSEC Late collision */ ++ E_FMAN_MAC_EX_1G_COL_RET_LMT, ++ /**< dTSEC Collision retry limit */ ++ E_FMAN_MAC_EX_1G_TX_FIFO_UNDRN, ++ /**< dTSEC Transmit FIFO underrun */ ++ E_FMAN_MAC_EX_1G_MAG_PCKT, ++ /**< dTSEC Magic Packet detection */ ++ E_FMAN_MAC_EX_1G_MII_MNG_RD_COMPLET, ++ /**< dTSEC MII management read completion */ ++ E_FMAN_MAC_EX_1G_MII_MNG_WR_COMPLET, ++ /**< dTSEC MII management write completion */ ++ E_FMAN_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET, ++ /**< dTSEC Graceful receive stop complete */ ++ E_FMAN_MAC_EX_1G_TX_DATA_ERR, ++ /**< dTSEC Internal data error on transmit */ ++ E_FMAN_MAC_EX_1G_RX_DATA_ERR, ++ /**< dTSEC Internal data error on receive */ ++ E_FMAN_MAC_EX_1G_1588_TS_RX_ERR, ++ /**< dTSEC Time-Stamp Receive Error */ ++ E_FMAN_MAC_EX_1G_RX_MIB_CNT_OVFL, ++ /**< dTSEC MIB counter overflow */ ++ E_FMAN_MAC_EX_TS_FIFO_ECC_ERR, ++ /**< mEMAC Time-stamp FIFO ECC error interrupt; ++ not supported on T4240/B4860 rev1 chips */ ++}; ++ ++#define ENET_IF_SGMII_BASEX 0x80000000 ++ /**< SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC ++ and phy or backplane; ++ Note: 1000BaseX auto-negotiation relates only to interface between MAC ++ and phy/backplane, SGMII phy can still synchronize with far-end phy at ++ 10Mbps, 100Mbps or 1000Mbps */ ++ ++enum enet_mode { ++ E_ENET_MODE_INVALID = 0, ++ /**< Invalid Ethernet mode */ ++ E_ENET_MODE_MII_10 = (E_ENET_IF_MII | E_ENET_SPEED_10), ++ /**< 10 Mbps MII */ ++ E_ENET_MODE_MII_100 = (E_ENET_IF_MII | E_ENET_SPEED_100), ++ /**< 100 Mbps MII */ ++ E_ENET_MODE_RMII_10 = (E_ENET_IF_RMII | E_ENET_SPEED_10), ++ /**< 10 Mbps RMII */ ++ E_ENET_MODE_RMII_100 = (E_ENET_IF_RMII | E_ENET_SPEED_100), ++ /**< 100 Mbps RMII */ ++ E_ENET_MODE_SMII_10 = (E_ENET_IF_SMII | E_ENET_SPEED_10), ++ /**< 10 Mbps SMII */ ++ E_ENET_MODE_SMII_100 = (E_ENET_IF_SMII | E_ENET_SPEED_100), ++ /**< 100 Mbps SMII */ ++ E_ENET_MODE_GMII_1000 = (E_ENET_IF_GMII | E_ENET_SPEED_1000), ++ /**< 1000 Mbps GMII */ ++ E_ENET_MODE_RGMII_10 = (E_ENET_IF_RGMII | E_ENET_SPEED_10), ++ /**< 10 Mbps RGMII */ ++ E_ENET_MODE_RGMII_100 = (E_ENET_IF_RGMII | E_ENET_SPEED_100), ++ /**< 100 Mbps RGMII */ ++ E_ENET_MODE_RGMII_1000 = (E_ENET_IF_RGMII | E_ENET_SPEED_1000), ++ /**< 1000 Mbps RGMII */ ++ E_ENET_MODE_TBI_1000 = (E_ENET_IF_TBI | E_ENET_SPEED_1000), ++ /**< 1000 Mbps TBI */ ++ E_ENET_MODE_RTBI_1000 = (E_ENET_IF_RTBI | E_ENET_SPEED_1000), ++ /**< 1000 Mbps RTBI */ ++ E_ENET_MODE_SGMII_10 = (E_ENET_IF_SGMII | E_ENET_SPEED_10), ++ /**< 10 Mbps SGMII with auto-negotiation between MAC and ++ SGMII phy according to Cisco SGMII specification */ ++ E_ENET_MODE_SGMII_100 = (E_ENET_IF_SGMII | E_ENET_SPEED_100), ++ /**< 100 Mbps SGMII with auto-negotiation between MAC and ++ SGMII phy according to Cisco SGMII specification */ ++ E_ENET_MODE_SGMII_1000 = (E_ENET_IF_SGMII | E_ENET_SPEED_1000), ++ /**< 1000 Mbps SGMII with auto-negotiation between MAC and ++ SGMII phy according to Cisco SGMII specification */ ++ E_ENET_MODE_SGMII_BASEX_10 = (ENET_IF_SGMII_BASEX | E_ENET_IF_SGMII ++ | E_ENET_SPEED_10), ++ /**< 10 Mbps SGMII with 1000BaseX auto-negotiation between ++ MAC and SGMII phy or backplane */ ++ E_ENET_MODE_SGMII_BASEX_100 = (ENET_IF_SGMII_BASEX | E_ENET_IF_SGMII ++ | E_ENET_SPEED_100), ++ /**< 100 Mbps SGMII with 1000BaseX auto-negotiation between ++ MAC and SGMII phy or backplane */ ++ E_ENET_MODE_SGMII_BASEX_1000 = (ENET_IF_SGMII_BASEX | E_ENET_IF_SGMII ++ | E_ENET_SPEED_1000), ++ /**< 1000 Mbps SGMII with 1000BaseX auto-negotiation between ++ MAC and SGMII phy or backplane */ ++ E_ENET_MODE_QSGMII_1000 = (E_ENET_IF_QSGMII | E_ENET_SPEED_1000), ++ /**< 1000 Mbps QSGMII with auto-negotiation between MAC and ++ QSGMII phy according to Cisco QSGMII specification */ ++ E_ENET_MODE_QSGMII_BASEX_1000 = (ENET_IF_SGMII_BASEX | E_ENET_IF_QSGMII ++ | E_ENET_SPEED_1000), ++ /**< 1000 Mbps QSGMII with 1000BaseX auto-negotiation between ++ MAC and QSGMII phy or backplane */ ++ E_ENET_MODE_XGMII_10000 = (E_ENET_IF_XGMII | E_ENET_SPEED_10000), ++ /**< 10000 Mbps XGMII */ ++ E_ENET_MODE_XFI_10000 = (E_ENET_IF_XFI | E_ENET_SPEED_10000) ++ /**< 10000 Mbps XFI */ ++}; ++ ++enum fmam_mac_statistics_level { ++ E_FMAN_MAC_NONE_STATISTICS, /**< No statistics */ ++ E_FMAN_MAC_PARTIAL_STATISTICS, /**< Only error counters are available; ++ Optimized for performance */ ++ E_FMAN_MAC_FULL_STATISTICS /**< All counters available; Not ++ optimized for performance */ ++}; ++ ++#define _MAKE_ENET_MODE(_interface, _speed) (enum enet_mode)((_interface) \ ++ | (_speed)) ++ ++#define _ENET_INTERFACE_FROM_MODE(mode) (enum enet_interface) \ ++ ((mode) & 0x0FFF0000) ++#define _ENET_SPEED_FROM_MODE(mode) (enum enet_speed)((mode) & 0x0000FFFF) ++#define _ENET_ADDR_TO_UINT64(_enet_addr) \ ++ (uint64_t)(((uint64_t)(_enet_addr)[0] << 40) | \ ++ ((uint64_t)(_enet_addr)[1] << 32) | \ ++ ((uint64_t)(_enet_addr)[2] << 24) | \ ++ ((uint64_t)(_enet_addr)[3] << 16) | \ ++ ((uint64_t)(_enet_addr)[4] << 8) | \ ++ ((uint64_t)(_enet_addr)[5])) ++ ++#define _MAKE_ENET_ADDR_FROM_UINT64(_addr64, _enet_addr) \ ++ do { \ ++ int i; \ ++ for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++) \ ++ (_enet_addr)[i] = (uint8_t)((_addr64) >> ((5-i)*8));\ ++ } while (0) ++ ++#endif /* __FSL_ENET_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman.h b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman.h +new file mode 100755 +index 0000000..96a63fa +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman.h +@@ -0,0 +1,825 @@ ++/* ++ * Copyright 2013 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 __FSL_FMAN_H ++#define __FSL_FMAN_H ++ ++#include "common/general.h" ++ ++struct fman_ext_pool_params { ++ uint8_t id; /**< External buffer pool id */ ++ uint16_t size; /**< External buffer pool buffer size */ ++}; ++ ++struct fman_ext_pools { ++ uint8_t num_pools_used; /**< Number of pools use by this port */ ++ struct fman_ext_pool_params *ext_buf_pool; ++ /**< Parameters for each port */ ++}; ++ ++struct fman_backup_bm_pools { ++ uint8_t num_backup_pools; /**< Number of BM backup pools - ++ must be smaller than the total number ++ of pools defined for the specified ++ port.*/ ++ uint8_t *pool_ids; /**< numOfBackupPools pool id's, ++ specifying which pools should be used ++ only as backup. Pool id's specified ++ here must be a subset of the pools ++ used by the specified port.*/ ++}; ++ ++/**************************************************************************//** ++ @Description A structure for defining BM pool depletion criteria ++*//***************************************************************************/ ++struct fman_buf_pool_depletion { ++ bool buf_pool_depletion_enabled; ++ bool pools_grp_mode_enable; /**< select mode in which pause frames ++ will be sent after a number of pools ++ (all together!) are depleted */ ++ uint8_t num_pools; /**< the number of depleted pools that ++ will invoke pause frames transmission. ++ */ ++ bool *pools_to_consider; /**< For each pool, TRUE if it should be ++ considered for depletion (Note - this ++ pool must be used by this port!). */ ++ bool single_pool_mode_enable; /**< select mode in which pause frames ++ will be sent after a single-pool ++ is depleted; */ ++ bool *pools_to_consider_for_single_mode; ++ /**< For each pool, TRUE if it should be ++ considered for depletion (Note - this ++ pool must be used by this port!) */ ++ bool has_pfc_priorities; ++ bool *pfc_priorities_en; /**< This field is used by the MAC as ++ the Priority Enable Vector in the PFC ++ frame which is transmitted */ ++}; ++ ++/**************************************************************************//** ++ @Description Enum for defining port DMA swap mode ++*//***************************************************************************/ ++enum fman_dma_swap_option { ++ FMAN_DMA_NO_SWP, /**< No swap, transfer data as is.*/ ++ FMAN_DMA_SWP_PPC_LE, /**< The transferred data should be swapped ++ in PowerPc Little Endian mode. */ ++ FMAN_DMA_SWP_BE /**< The transferred data should be swapped ++ in Big Endian mode */ ++}; ++ ++/**************************************************************************//** ++ @Description Enum for defining port DMA cache attributes ++*//***************************************************************************/ ++enum fman_dma_cache_option { ++ FMAN_DMA_NO_STASH = 0, /**< Cacheable, no Allocate (No Stashing) */ ++ FMAN_DMA_STASH = 1 /**< Cacheable and Allocate (Stashing on) */ ++}; ++ ++typedef struct t_FmPrsResult fm_prs_result_t; ++typedef enum e_EnetMode enet_mode_t; ++typedef t_Handle handle_t; ++ ++struct fman_revision_info { ++ uint8_t majorRev; /**< Major revision */ ++ uint8_t minorRev; /**< Minor revision */ ++}; ++ ++/* sizes */ ++#define CAPWAP_FRAG_EXTRA_SPACE 32 ++#define OFFSET_UNITS 16 ++#define MAX_INT_OFFSET 240 ++#define MAX_IC_SIZE 256 ++#define MAX_EXT_OFFSET 496 ++#define MAX_EXT_BUFFER_OFFSET 511 ++ ++/************************************************************************** ++ @Description Memory Mapped Registers ++***************************************************************************/ ++#define FMAN_LIODN_TBL 64 /* size of LIODN table */ ++ ++struct fman_fpm_regs { ++ uint32_t fmfp_tnc; /**< FPM TNUM Control 0x00 */ ++ uint32_t fmfp_prc; /**< FPM Port_ID FmCtl Association 0x04 */ ++ uint32_t fmfp_brkc; /**< FPM Breakpoint Control 0x08 */ ++ uint32_t fmfp_mxd; /**< FPM Flush Control 0x0c */ ++ uint32_t fmfp_dist1; /**< FPM Dispatch Thresholds1 0x10 */ ++ uint32_t fmfp_dist2; /**< FPM Dispatch Thresholds2 0x14 */ ++ uint32_t fm_epi; /**< FM Error Pending Interrupts 0x18 */ ++ uint32_t fm_rie; /**< FM Error Interrupt Enable 0x1c */ ++ uint32_t fmfp_fcev[4]; /**< FPM FMan-Controller Event 1-4 0x20-0x2f */ ++ uint32_t res0030[4]; /**< res 0x30 - 0x3f */ ++ uint32_t fmfp_cee[4]; /**< PM FMan-Controller Event 1-4 0x40-0x4f */ ++ uint32_t res0050[4]; /**< res 0x50-0x5f */ ++ uint32_t fmfp_tsc1; /**< FPM TimeStamp Control1 0x60 */ ++ uint32_t fmfp_tsc2; /**< FPM TimeStamp Control2 0x64 */ ++ uint32_t fmfp_tsp; /**< FPM Time Stamp 0x68 */ ++ uint32_t fmfp_tsf; /**< FPM Time Stamp Fraction 0x6c */ ++ uint32_t fm_rcr; /**< FM Rams Control 0x70 */ ++ uint32_t fmfp_extc; /**< FPM External Requests Control 0x74 */ ++ uint32_t fmfp_ext1; /**< FPM External Requests Config1 0x78 */ ++ uint32_t fmfp_ext2; /**< FPM External Requests Config2 0x7c */ ++ uint32_t fmfp_drd[16]; /**< FPM Data_Ram Data 0-15 0x80 - 0xbf */ ++ uint32_t fmfp_dra; /**< FPM Data Ram Access 0xc0 */ ++ uint32_t fm_ip_rev_1; /**< FM IP Block Revision 1 0xc4 */ ++ uint32_t fm_ip_rev_2; /**< FM IP Block Revision 2 0xc8 */ ++ uint32_t fm_rstc; /**< FM Reset Command 0xcc */ ++ uint32_t fm_cld; /**< FM Classifier Debug 0xd0 */ ++ uint32_t fm_npi; /**< FM Normal Pending Interrupts 0xd4 */ ++ uint32_t fmfp_exte; /**< FPM External Requests Enable 0xd8 */ ++ uint32_t fmfp_ee; /**< FPM Event & Mask 0xdc */ ++ uint32_t fmfp_cev[4]; /**< FPM CPU Event 1-4 0xe0-0xef */ ++ uint32_t res00f0[4]; /**< res 0xf0-0xff */ ++ uint32_t fmfp_ps[64]; /**< FPM Port Status 0x100-0x1ff */ ++ uint32_t fmfp_clfabc; /**< FPM CLFABC 0x200 */ ++ uint32_t fmfp_clfcc; /**< FPM CLFCC 0x204 */ ++ uint32_t fmfp_clfaval; /**< FPM CLFAVAL 0x208 */ ++ uint32_t fmfp_clfbval; /**< FPM CLFBVAL 0x20c */ ++ uint32_t fmfp_clfcval; /**< FPM CLFCVAL 0x210 */ ++ uint32_t fmfp_clfamsk; /**< FPM CLFAMSK 0x214 */ ++ uint32_t fmfp_clfbmsk; /**< FPM CLFBMSK 0x218 */ ++ uint32_t fmfp_clfcmsk; /**< FPM CLFCMSK 0x21c */ ++ uint32_t fmfp_clfamc; /**< FPM CLFAMC 0x220 */ ++ uint32_t fmfp_clfbmc; /**< FPM CLFBMC 0x224 */ ++ uint32_t fmfp_clfcmc; /**< FPM CLFCMC 0x228 */ ++ uint32_t fmfp_decceh; /**< FPM DECCEH 0x22c */ ++ uint32_t res0230[116]; /**< res 0x230 - 0x3ff */ ++ uint32_t fmfp_ts[128]; /**< 0x400: FPM Task Status 0x400 - 0x5ff */ ++ uint32_t res0600[0x400 - 384]; ++}; ++ ++struct fman_bmi_regs { ++ uint32_t fmbm_init; /**< BMI Initialization 0x00 */ ++ uint32_t fmbm_cfg1; /**< BMI Configuration 1 0x04 */ ++ uint32_t fmbm_cfg2; /**< BMI Configuration 2 0x08 */ ++ uint32_t res000c[5]; /**< 0x0c - 0x1f */ ++ uint32_t fmbm_ievr; /**< Interrupt Event Register 0x20 */ ++ uint32_t fmbm_ier; /**< Interrupt Enable Register 0x24 */ ++ uint32_t fmbm_ifr; /**< Interrupt Force Register 0x28 */ ++ uint32_t res002c[5]; /**< 0x2c - 0x3f */ ++ uint32_t fmbm_arb[8]; /**< BMI Arbitration 0x40 - 0x5f */ ++ uint32_t res0060[12]; /**<0x60 - 0x8f */ ++ uint32_t fmbm_dtc[3]; /**< Debug Trap Counter 0x90 - 0x9b */ ++ uint32_t res009c; /**< 0x9c */ ++ uint32_t fmbm_dcv[3][4]; /**< Debug Compare val 0xa0-0xcf */ ++ uint32_t fmbm_dcm[3][4]; /**< Debug Compare Mask 0xd0-0xff */ ++ uint32_t fmbm_gde; /**< BMI Global Debug Enable 0x100 */ ++ uint32_t fmbm_pp[63]; /**< BMI Port Parameters 0x104 - 0x1ff */ ++ uint32_t res0200; /**< 0x200 */ ++ uint32_t fmbm_pfs[63]; /**< BMI Port FIFO Size 0x204 - 0x2ff */ ++ uint32_t res0300; /**< 0x300 */ ++ uint32_t fmbm_spliodn[63]; /**< Port Partition ID 0x304 - 0x3ff */ ++}; ++ ++struct fman_qmi_regs { ++ uint32_t fmqm_gc; /**< General Configuration Register 0x00 */ ++ uint32_t res0004; /**< 0x04 */ ++ uint32_t fmqm_eie; /**< Error Interrupt Event Register 0x08 */ ++ uint32_t fmqm_eien; /**< Error Interrupt Enable Register 0x0c */ ++ uint32_t fmqm_eif; /**< Error Interrupt Force Register 0x10 */ ++ uint32_t fmqm_ie; /**< Interrupt Event Register 0x14 */ ++ uint32_t fmqm_ien; /**< Interrupt Enable Register 0x18 */ ++ uint32_t fmqm_if; /**< Interrupt Force Register 0x1c */ ++ uint32_t fmqm_gs; /**< Global Status Register 0x20 */ ++ uint32_t fmqm_ts; /**< Task Status Register 0x24 */ ++ uint32_t fmqm_etfc; /**< Enqueue Total Frame Counter 0x28 */ ++ uint32_t fmqm_dtfc; /**< Dequeue Total Frame Counter 0x2c */ ++ uint32_t fmqm_dc0; /**< Dequeue Counter 0 0x30 */ ++ uint32_t fmqm_dc1; /**< Dequeue Counter 1 0x34 */ ++ uint32_t fmqm_dc2; /**< Dequeue Counter 2 0x38 */ ++ uint32_t fmqm_dc3; /**< Dequeue Counter 3 0x3c */ ++ uint32_t fmqm_dfdc; /**< Dequeue FQID from Default Counter 0x40 */ ++ uint32_t fmqm_dfcc; /**< Dequeue FQID from Context Counter 0x44 */ ++ uint32_t fmqm_dffc; /**< Dequeue FQID from FD Counter 0x48 */ ++ uint32_t fmqm_dcc; /**< Dequeue Confirm Counter 0x4c */ ++ uint32_t res0050[7]; /**< 0x50 - 0x6b */ ++ uint32_t fmqm_tapc; /**< Tnum Aging Period Control 0x6c */ ++ uint32_t fmqm_dmcvc; /**< Dequeue MAC Command Valid Counter 0x70 */ ++ uint32_t fmqm_difdcc; /**< Dequeue Invalid FD Command Counter 0x74 */ ++ uint32_t fmqm_da1v; /**< Dequeue A1 Valid Counter 0x78 */ ++ uint32_t res007c; /**< 0x7c */ ++ uint32_t fmqm_dtc; /**< 0x80 Debug Trap Counter 0x80 */ ++ uint32_t fmqm_efddd; /**< 0x84 Enqueue Frame desc Dynamic dbg 0x84 */ ++ uint32_t res0088[2]; /**< 0x88 - 0x8f */ ++ struct { ++ uint32_t fmqm_dtcfg1; /**< 0x90 dbg trap cfg 1 Register 0x00 */ ++ uint32_t fmqm_dtval1; /**< Debug Trap Value 1 Register 0x04 */ ++ uint32_t fmqm_dtm1; /**< Debug Trap Mask 1 Register 0x08 */ ++ uint32_t fmqm_dtc1; /**< Debug Trap Counter 1 Register 0x0c */ ++ uint32_t fmqm_dtcfg2; /**< dbg Trap cfg 2 Register 0x10 */ ++ uint32_t fmqm_dtval2; /**< Debug Trap Value 2 Register 0x14 */ ++ uint32_t fmqm_dtm2; /**< Debug Trap Mask 2 Register 0x18 */ ++ uint32_t res001c; /**< 0x1c */ ++ } dbg_traps[3]; /**< 0x90 - 0xef */ ++ uint8_t res00f0[0x400 - 0xf0]; /**< 0xf0 - 0x3ff */ ++}; ++ ++struct fman_dma_regs { ++ uint32_t fmdmsr; /**< FM DMA status register 0x00 */ ++ uint32_t fmdmmr; /**< FM DMA mode register 0x04 */ ++ uint32_t fmdmtr; /**< FM DMA bus threshold register 0x08 */ ++ uint32_t fmdmhy; /**< FM DMA bus hysteresis register 0x0c */ ++ uint32_t fmdmsetr; /**< FM DMA SOS emergency Threshold Register 0x10 */ ++ uint32_t fmdmtah; /**< FM DMA transfer bus address high reg 0x14 */ ++ uint32_t fmdmtal; /**< FM DMA transfer bus address low reg 0x18 */ ++ uint32_t fmdmtcid; /**< FM DMA transfer bus communication ID reg 0x1c */ ++ uint32_t fmdmra; /**< FM DMA bus internal ram address register 0x20 */ ++ uint32_t fmdmrd; /**< FM DMA bus internal ram data register 0x24 */ ++ uint32_t fmdmwcr; /**< FM DMA CAM watchdog counter value 0x28 */ ++ uint32_t fmdmebcr; /**< FM DMA CAM base in MURAM register 0x2c */ ++ uint32_t fmdmccqdr; /**< FM DMA CAM and CMD Queue Debug reg 0x30 */ ++ uint32_t fmdmccqvr1; /**< FM DMA CAM and CMD Queue Value reg #1 0x34 */ ++ uint32_t fmdmccqvr2; /**< FM DMA CAM and CMD Queue Value reg #2 0x38 */ ++ uint32_t fmdmcqvr3; /**< FM DMA CMD Queue Value register #3 0x3c */ ++ uint32_t fmdmcqvr4; /**< FM DMA CMD Queue Value register #4 0x40 */ ++ uint32_t fmdmcqvr5; /**< FM DMA CMD Queue Value register #5 0x44 */ ++ uint32_t fmdmsefrc; /**< FM DMA Semaphore Entry Full Reject Cntr 0x48 */ ++ uint32_t fmdmsqfrc; /**< FM DMA Semaphore Queue Full Reject Cntr 0x4c */ ++ uint32_t fmdmssrc; /**< FM DMA Semaphore SYNC Reject Counter 0x50 */ ++ uint32_t fmdmdcr; /**< FM DMA Debug Counter 0x54 */ ++ uint32_t fmdmemsr; /**< FM DMA Emergency Smoother Register 0x58 */ ++ uint32_t res005c; /**< 0x5c */ ++ uint32_t fmdmplr[FMAN_LIODN_TBL / 2]; /**< DMA LIODN regs 0x60-0xdf */ ++ uint32_t res00e0[0x400 - 56]; ++}; ++ ++struct fman_rg { ++ struct fman_fpm_regs *fpm_rg; ++ struct fman_dma_regs *dma_rg; ++ struct fman_bmi_regs *bmi_rg; ++ struct fman_qmi_regs *qmi_rg; ++}; ++ ++enum fman_dma_cache_override { ++ E_FMAN_DMA_NO_CACHE_OR = 0, /**< No override of the Cache field */ ++ E_FMAN_DMA_NO_STASH_DATA, /**< No data stashing in system level cache */ ++ E_FMAN_DMA_MAY_STASH_DATA, /**< Stashing allowed in sys level cache */ ++ E_FMAN_DMA_STASH_DATA /**< Stashing performed in system level cache */ ++}; ++ ++enum fman_dma_aid_mode { ++ E_FMAN_DMA_AID_OUT_PORT_ID = 0, /**< 4 LSB of PORT_ID */ ++ E_FMAN_DMA_AID_OUT_TNUM /**< 4 LSB of TNUM */ ++}; ++ ++enum fman_dma_dbg_cnt_mode { ++ E_FMAN_DMA_DBG_NO_CNT = 0, /**< No counting */ ++ E_FMAN_DMA_DBG_CNT_DONE, /**< Count DONE commands */ ++ E_FMAN_DMA_DBG_CNT_COMM_Q_EM, /**< command Q emergency signal */ ++ E_FMAN_DMA_DBG_CNT_INT_READ_EM, /**< Read buf emergency signal */ ++ E_FMAN_DMA_DBG_CNT_INT_WRITE_EM, /**< Write buf emergency signal */ ++ E_FMAN_DMA_DBG_CNT_FPM_WAIT, /**< FPM WAIT signal */ ++ E_FMAN_DMA_DBG_CNT_SIGLE_BIT_ECC, /**< Single bit ECC errors */ ++ E_FMAN_DMA_DBG_CNT_RAW_WAR_PROT /**< RAW & WAR protection counter */ ++}; ++ ++enum fman_dma_emergency_level { ++ E_FMAN_DMA_EM_EBS = 0, /**< EBS emergency */ ++ E_FMAN_DMA_EM_SOS /**< SOS emergency */ ++}; ++ ++enum fman_catastrophic_err { ++ E_FMAN_CATAST_ERR_STALL_PORT = 0, /**< Port_ID stalled reset required */ ++ E_FMAN_CATAST_ERR_STALL_TASK /**< Only erroneous task is stalled */ ++}; ++ ++enum fman_dma_err { ++ E_FMAN_DMA_ERR_CATASTROPHIC = 0, /**< Catastrophic DMA error */ ++ E_FMAN_DMA_ERR_REPORT /**< Reported DMA error */ ++}; ++ ++struct fman_cfg { ++ uint16_t liodn_bs_pr_port[FMAN_LIODN_TBL];/* base per port */ ++ bool en_counters; ++ uint8_t disp_limit_tsh; ++ uint8_t prs_disp_tsh; ++ uint8_t plcr_disp_tsh; ++ uint8_t kg_disp_tsh; ++ uint8_t bmi_disp_tsh; ++ uint8_t qmi_enq_disp_tsh; ++ uint8_t qmi_deq_disp_tsh; ++ uint8_t fm_ctl1_disp_tsh; ++ uint8_t fm_ctl2_disp_tsh; ++ enum fman_dma_cache_override dma_cache_override; ++ enum fman_dma_aid_mode dma_aid_mode; ++ bool dma_aid_override; ++ uint8_t dma_axi_dbg_num_of_beats; ++ uint8_t dma_cam_num_of_entries; ++ uint32_t dma_watchdog; ++ uint8_t dma_comm_qtsh_asrt_emer; ++ uint8_t dma_write_buf_tsh_asrt_emer; ++ uint8_t dma_read_buf_tsh_asrt_emer; ++ uint8_t dma_comm_qtsh_clr_emer; ++ uint8_t dma_write_buf_tsh_clr_emer; ++ uint8_t dma_read_buf_tsh_clr_emer; ++ uint32_t dma_sos_emergency; ++ enum fman_dma_dbg_cnt_mode dma_dbg_cnt_mode; ++ bool dma_stop_on_bus_error; ++ bool dma_en_emergency; ++ uint32_t dma_emergency_bus_select; ++ enum fman_dma_emergency_level dma_emergency_level; ++ bool dma_en_emergency_smoother; ++ uint32_t dma_emergency_switch_counter; ++ bool halt_on_external_activ; ++ bool halt_on_unrecov_ecc_err; ++ enum fman_catastrophic_err catastrophic_err; ++ enum fman_dma_err dma_err; ++ bool en_muram_test_mode; ++ bool en_iram_test_mode; ++ bool external_ecc_rams_enable; ++ uint16_t tnum_aging_period; ++ uint32_t exceptions; ++ uint16_t clk_freq; ++ bool pedantic_dma; ++ uint32_t cam_base_addr; ++ uint32_t fifo_base_addr; ++ uint32_t total_fifo_size; ++ uint8_t total_num_of_tasks; ++ bool qmi_deq_option_support; ++ uint32_t qmi_def_tnums_thresh; ++ bool fman_partition_array; ++ uint8_t num_of_fman_ctrl_evnt_regs; ++}; ++ ++/**************************************************************************//** ++ @Description Exceptions ++*//***************************************************************************/ ++#define FMAN_EX_DMA_BUS_ERROR 0x80000000 ++#define FMAN_EX_DMA_READ_ECC 0x40000000 ++#define FMAN_EX_DMA_SYSTEM_WRITE_ECC 0x20000000 ++#define FMAN_EX_DMA_FM_WRITE_ECC 0x10000000 ++#define FMAN_EX_FPM_STALL_ON_TASKS 0x08000000 ++#define FMAN_EX_FPM_SINGLE_ECC 0x04000000 ++#define FMAN_EX_FPM_DOUBLE_ECC 0x02000000 ++#define FMAN_EX_QMI_SINGLE_ECC 0x01000000 ++#define FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID 0x00800000 ++#define FMAN_EX_QMI_DOUBLE_ECC 0x00400000 ++#define FMAN_EX_BMI_LIST_RAM_ECC 0x00200000 ++#define FMAN_EX_BMI_PIPELINE_ECC 0x00100000 ++#define FMAN_EX_BMI_STATISTICS_RAM_ECC 0x00080000 ++#define FMAN_EX_IRAM_ECC 0x00040000 ++#define FMAN_EX_NURAM_ECC 0x00020000 ++#define FMAN_EX_BMI_DISPATCH_RAM_ECC 0x00010000 ++ ++enum fman_exceptions { ++ E_FMAN_EX_DMA_BUS_ERROR = 0, /**< DMA bus error. */ ++ E_FMAN_EX_DMA_READ_ECC, /**< Read Buffer ECC error */ ++ E_FMAN_EX_DMA_SYSTEM_WRITE_ECC, /**< Write Buffer ECC err on sys side */ ++ E_FMAN_EX_DMA_FM_WRITE_ECC, /**< Write Buffer ECC error on FM side */ ++ E_FMAN_EX_FPM_STALL_ON_TASKS, /**< Stall of tasks on FPM */ ++ E_FMAN_EX_FPM_SINGLE_ECC, /**< Single ECC on FPM. */ ++ E_FMAN_EX_FPM_DOUBLE_ECC, /**< Double ECC error on FPM ram access */ ++ E_FMAN_EX_QMI_SINGLE_ECC, /**< Single ECC on QMI. */ ++ E_FMAN_EX_QMI_DOUBLE_ECC, /**< Double bit ECC occurred on QMI */ ++ E_FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID,/**< DeQ from unknown port id */ ++ E_FMAN_EX_BMI_LIST_RAM_ECC, /**< Linked List RAM ECC error */ ++ E_FMAN_EX_BMI_STORAGE_PROFILE_ECC, /**< storage profile */ ++ E_FMAN_EX_BMI_STATISTICS_RAM_ECC, /**< Statistics RAM ECC Err Enable */ ++ E_FMAN_EX_BMI_DISPATCH_RAM_ECC, /**< Dispatch RAM ECC Error Enable */ ++ E_FMAN_EX_IRAM_ECC, /**< Double bit ECC occurred on IRAM*/ ++ E_FMAN_EX_MURAM_ECC /**< Double bit ECC occurred on MURAM*/ ++}; ++ ++enum fman_counters { ++ E_FMAN_COUNTERS_ENQ_TOTAL_FRAME = 0, /**< QMI tot enQ frames counter */ ++ E_FMAN_COUNTERS_DEQ_TOTAL_FRAME, /**< QMI tot deQ frames counter */ ++ E_FMAN_COUNTERS_DEQ_0, /**< QMI 0 frames from QMan counter */ ++ E_FMAN_COUNTERS_DEQ_1, /**< QMI 1 frames from QMan counter */ ++ E_FMAN_COUNTERS_DEQ_2, /**< QMI 2 frames from QMan counter */ ++ E_FMAN_COUNTERS_DEQ_3, /**< QMI 3 frames from QMan counter */ ++ E_FMAN_COUNTERS_DEQ_FROM_DEFAULT, /**< QMI deQ from dflt queue cntr */ ++ E_FMAN_COUNTERS_DEQ_FROM_CONTEXT, /**< QMI deQ from FQ context cntr */ ++ E_FMAN_COUNTERS_DEQ_FROM_FD, /**< QMI deQ from FD command field cntr */ ++ E_FMAN_COUNTERS_DEQ_CONFIRM, /**< QMI dequeue confirm counter */ ++ E_FMAN_COUNTERS_SEMAPHOR_ENTRY_FULL_REJECT, /**< DMA full entry cntr */ ++ E_FMAN_COUNTERS_SEMAPHOR_QUEUE_FULL_REJECT, /**< DMA full CAM Q cntr */ ++ E_FMAN_COUNTERS_SEMAPHOR_SYNC_REJECT /**< DMA sync counter */ ++}; ++ ++#define FPM_PRT_FM_CTL1 0x00000001 ++#define FPM_PRT_FM_CTL2 0x00000002 ++ ++/**************************************************************************//** ++ @Description DMA definitions ++*//***************************************************************************/ ++ ++/* masks */ ++#define DMA_MODE_AID_OR 0x20000000 ++#define DMA_MODE_SBER 0x10000000 ++#define DMA_MODE_BER 0x00200000 ++#define DMA_MODE_EB 0x00100000 ++#define DMA_MODE_ECC 0x00000020 ++#define DMA_MODE_PRIVILEGE_PROT 0x00001000 ++#define DMA_MODE_SECURE_PROT 0x00000800 ++#define DMA_MODE_EMER_READ 0x00080000 ++#define DMA_MODE_EMER_WRITE 0x00040000 ++#define DMA_MODE_CACHE_OR_MASK 0xC0000000 ++#define DMA_MODE_CEN_MASK 0x0000E000 ++#define DMA_MODE_DBG_MASK 0x00000380 ++#define DMA_MODE_AXI_DBG_MASK 0x0F000000 ++ ++#define DMA_EMSR_EMSTR_MASK 0x0000FFFF ++ ++#define DMA_TRANSFER_PORTID_MASK 0xFF000000 ++#define DMA_TRANSFER_TNUM_MASK 0x00FF0000 ++#define DMA_TRANSFER_LIODN_MASK 0x00000FFF ++ ++#define DMA_HIGH_LIODN_MASK 0x0FFF0000 ++#define DMA_LOW_LIODN_MASK 0x00000FFF ++ ++#define DMA_STATUS_CMD_QUEUE_NOT_EMPTY 0x10000000 ++#define DMA_STATUS_BUS_ERR 0x08000000 ++#define DMA_STATUS_READ_ECC 0x04000000 ++#define DMA_STATUS_SYSTEM_WRITE_ECC 0x02000000 ++#define DMA_STATUS_FM_WRITE_ECC 0x01000000 ++#define DMA_STATUS_SYSTEM_DPEXT_ECC 0x00800000 ++#define DMA_STATUS_FM_DPEXT_ECC 0x00400000 ++#define DMA_STATUS_SYSTEM_DPDAT_ECC 0x00200000 ++#define DMA_STATUS_FM_DPDAT_ECC 0x00100000 ++#define DMA_STATUS_FM_SPDAT_ECC 0x00080000 ++ ++#define FM_LIODN_BASE_MASK 0x00000FFF ++ ++/* shifts */ ++#define DMA_MODE_CACHE_OR_SHIFT 30 ++#define DMA_MODE_BUS_PRI_SHIFT 16 ++#define DMA_MODE_AXI_DBG_SHIFT 24 ++#define DMA_MODE_CEN_SHIFT 13 ++#define DMA_MODE_BUS_PROT_SHIFT 10 ++#define DMA_MODE_DBG_SHIFT 7 ++#define DMA_MODE_EMER_LVL_SHIFT 6 ++#define DMA_MODE_AID_MODE_SHIFT 4 ++#define DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS 16 ++#define DMA_MODE_MAX_CAM_NUM_OF_ENTRIES 32 ++ ++#define DMA_THRESH_COMMQ_SHIFT 24 ++#define DMA_THRESH_READ_INT_BUF_SHIFT 16 ++ ++#define DMA_LIODN_SHIFT 16 ++ ++#define DMA_TRANSFER_PORTID_SHIFT 24 ++#define DMA_TRANSFER_TNUM_SHIFT 16 ++ ++/* sizes */ ++#define DMA_MAX_WATCHDOG 0xffffffff ++ ++/* others */ ++#define DMA_CAM_SIZEOF_ENTRY 0x40 ++#define DMA_CAM_ALIGN 0x1000 ++#define DMA_CAM_UNITS 8 ++ ++/**************************************************************************//** ++ @Description General defines ++*//***************************************************************************/ ++ ++#define FM_DEBUG_STATUS_REGISTER_OFFSET 0x000d1084UL ++#define FM_UCODE_DEBUG_INSTRUCTION 0x6ffff805UL ++ ++/**************************************************************************//** ++ @Description FPM defines ++*//***************************************************************************/ ++ ++/* masks */ ++#define FPM_EV_MASK_DOUBLE_ECC 0x80000000 ++#define FPM_EV_MASK_STALL 0x40000000 ++#define FPM_EV_MASK_SINGLE_ECC 0x20000000 ++#define FPM_EV_MASK_RELEASE_FM 0x00010000 ++#define FPM_EV_MASK_DOUBLE_ECC_EN 0x00008000 ++#define FPM_EV_MASK_STALL_EN 0x00004000 ++#define FPM_EV_MASK_SINGLE_ECC_EN 0x00002000 ++#define FPM_EV_MASK_EXTERNAL_HALT 0x00000008 ++#define FPM_EV_MASK_ECC_ERR_HALT 0x00000004 ++ ++#define FPM_RAM_RAMS_ECC_EN 0x80000000 ++#define FPM_RAM_IRAM_ECC_EN 0x40000000 ++#define FPM_RAM_MURAM_ECC 0x00008000 ++#define FPM_RAM_IRAM_ECC 0x00004000 ++#define FPM_RAM_MURAM_TEST_ECC 0x20000000 ++#define FPM_RAM_IRAM_TEST_ECC 0x10000000 ++#define FPM_RAM_RAMS_ECC_EN_SRC_SEL 0x08000000 ++ ++#define FPM_IRAM_ECC_ERR_EX_EN 0x00020000 ++#define FPM_MURAM_ECC_ERR_EX_EN 0x00040000 ++ ++#define FPM_REV1_MAJOR_MASK 0x0000FF00 ++#define FPM_REV1_MINOR_MASK 0x000000FF ++ ++#define FPM_REV2_INTEG_MASK 0x00FF0000 ++#define FPM_REV2_ERR_MASK 0x0000FF00 ++#define FPM_REV2_CFG_MASK 0x000000FF ++ ++#define FPM_TS_FRACTION_MASK 0x0000FFFF ++#define FPM_TS_CTL_EN 0x80000000 ++ ++#define FPM_PRC_REALSE_STALLED 0x00800000 ++ ++#define FPM_PS_STALLED 0x00800000 ++#define FPM_PS_FM_CTL1_SEL 0x80000000 ++#define FPM_PS_FM_CTL2_SEL 0x40000000 ++#define FPM_PS_FM_CTL_SEL_MASK (FPM_PS_FM_CTL1_SEL | FPM_PS_FM_CTL2_SEL) ++ ++#define FPM_RSTC_FM_RESET 0x80000000 ++#define FPM_RSTC_10G0_RESET 0x04000000 ++#define FPM_RSTC_1G0_RESET 0x40000000 ++#define FPM_RSTC_1G1_RESET 0x20000000 ++#define FPM_RSTC_1G2_RESET 0x10000000 ++#define FPM_RSTC_1G3_RESET 0x08000000 ++#define FPM_RSTC_1G4_RESET 0x02000000 ++ ++ ++#define FPM_DISP_LIMIT_MASK 0x1F000000 ++#define FPM_THR1_PRS_MASK 0xFF000000 ++#define FPM_THR1_KG_MASK 0x00FF0000 ++#define FPM_THR1_PLCR_MASK 0x0000FF00 ++#define FPM_THR1_BMI_MASK 0x000000FF ++ ++#define FPM_THR2_QMI_ENQ_MASK 0xFF000000 ++#define FPM_THR2_QMI_DEQ_MASK 0x000000FF ++#define FPM_THR2_FM_CTL1_MASK 0x00FF0000 ++#define FPM_THR2_FM_CTL2_MASK 0x0000FF00 ++ ++/* shifts */ ++#define FPM_DISP_LIMIT_SHIFT 24 ++ ++#define FPM_THR1_PRS_SHIFT 24 ++#define FPM_THR1_KG_SHIFT 16 ++#define FPM_THR1_PLCR_SHIFT 8 ++#define FPM_THR1_BMI_SHIFT 0 ++ ++#define FPM_THR2_QMI_ENQ_SHIFT 24 ++#define FPM_THR2_QMI_DEQ_SHIFT 0 ++#define FPM_THR2_FM_CTL1_SHIFT 16 ++#define FPM_THR2_FM_CTL2_SHIFT 8 ++ ++#define FPM_EV_MASK_CAT_ERR_SHIFT 1 ++#define FPM_EV_MASK_DMA_ERR_SHIFT 0 ++ ++#define FPM_REV1_MAJOR_SHIFT 8 ++#define FPM_REV1_MINOR_SHIFT 0 ++ ++#define FPM_REV2_INTEG_SHIFT 16 ++#define FPM_REV2_ERR_SHIFT 8 ++#define FPM_REV2_CFG_SHIFT 0 ++ ++#define FPM_TS_INT_SHIFT 16 ++ ++#define FPM_PORT_FM_CTL_PORTID_SHIFT 24 ++ ++#define FPM_PS_FM_CTL_SEL_SHIFT 30 ++#define FPM_PRC_ORA_FM_CTL_SEL_SHIFT 16 ++ ++#define FPM_DISP_LIMIT_SHIFT 24 ++ ++/* Interrupts defines */ ++#define FPM_EVENT_FM_CTL_0 0x00008000 ++#define FPM_EVENT_FM_CTL 0x0000FF00 ++#define FPM_EVENT_FM_CTL_BRK 0x00000080 ++ ++/* others */ ++#define FPM_MAX_DISP_LIMIT 31 ++#define FPM_RSTC_FM_RESET 0x80000000 ++#define FPM_RSTC_1G0_RESET 0x40000000 ++#define FPM_RSTC_1G1_RESET 0x20000000 ++#define FPM_RSTC_1G2_RESET 0x10000000 ++#define FPM_RSTC_1G3_RESET 0x08000000 ++#define FPM_RSTC_10G0_RESET 0x04000000 ++#define FPM_RSTC_1G4_RESET 0x02000000 ++#define FPM_RSTC_1G5_RESET 0x01000000 ++#define FPM_RSTC_1G6_RESET 0x00800000 ++#define FPM_RSTC_1G7_RESET 0x00400000 ++#define FPM_RSTC_10G1_RESET 0x00200000 ++/**************************************************************************//** ++ @Description BMI defines ++*//***************************************************************************/ ++/* masks */ ++#define BMI_INIT_START 0x80000000 ++#define BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC 0x80000000 ++#define BMI_ERR_INTR_EN_LIST_RAM_ECC 0x40000000 ++#define BMI_ERR_INTR_EN_STATISTICS_RAM_ECC 0x20000000 ++#define BMI_ERR_INTR_EN_DISPATCH_RAM_ECC 0x10000000 ++#define BMI_NUM_OF_TASKS_MASK 0x3F000000 ++#define BMI_NUM_OF_EXTRA_TASKS_MASK 0x000F0000 ++#define BMI_NUM_OF_DMAS_MASK 0x00000F00 ++#define BMI_NUM_OF_EXTRA_DMAS_MASK 0x0000000F ++#define BMI_FIFO_SIZE_MASK 0x000003FF ++#define BMI_EXTRA_FIFO_SIZE_MASK 0x03FF0000 ++#define BMI_CFG2_DMAS_MASK 0x0000003F ++#define BMI_TOTAL_FIFO_SIZE_MASK 0x07FF0000 ++#define BMI_TOTAL_NUM_OF_TASKS_MASK 0x007F0000 ++ ++/* shifts */ ++#define BMI_CFG2_TASKS_SHIFT 16 ++#define BMI_CFG2_DMAS_SHIFT 0 ++#define BMI_CFG1_FIFO_SIZE_SHIFT 16 ++#define BMI_FIFO_SIZE_SHIFT 0 ++#define BMI_EXTRA_FIFO_SIZE_SHIFT 16 ++#define BMI_NUM_OF_TASKS_SHIFT 24 ++#define BMI_EXTRA_NUM_OF_TASKS_SHIFT 16 ++#define BMI_NUM_OF_DMAS_SHIFT 8 ++#define BMI_EXTRA_NUM_OF_DMAS_SHIFT 0 ++ ++/* others */ ++#define BMI_FIFO_ALIGN 0x100 ++#define FMAN_BMI_FIFO_UNITS 0x100 ++ ++ ++/**************************************************************************//** ++ @Description QMI defines ++*//***************************************************************************/ ++/* masks */ ++#define QMI_CFG_ENQ_EN 0x80000000 ++#define QMI_CFG_DEQ_EN 0x40000000 ++#define QMI_CFG_EN_COUNTERS 0x10000000 ++#define QMI_CFG_SOFT_RESET 0x01000000 ++#define QMI_CFG_DEQ_MASK 0x0000003F ++#define QMI_CFG_ENQ_MASK 0x00003F00 ++ ++#define QMI_ERR_INTR_EN_DOUBLE_ECC 0x80000000 ++#define QMI_ERR_INTR_EN_DEQ_FROM_DEF 0x40000000 ++#define QMI_INTR_EN_SINGLE_ECC 0x80000000 ++ ++/* shifts */ ++#define QMI_CFG_ENQ_SHIFT 8 ++#define QMI_TAPC_TAP 22 ++ ++#define QMI_GS_HALT_NOT_BUSY 0x00000002 ++ ++/**************************************************************************//** ++ @Description IRAM defines ++*//***************************************************************************/ ++/* masks */ ++#define IRAM_IADD_AIE 0x80000000 ++#define IRAM_READY 0x80000000 ++ ++uint32_t fman_get_bmi_err_event(struct fman_bmi_regs *bmi_rg); ++uint32_t fman_get_qmi_err_event(struct fman_qmi_regs *qmi_rg); ++uint32_t fman_get_dma_com_id(struct fman_dma_regs *dma_rg); ++uint64_t fman_get_dma_addr(struct fman_dma_regs *dma_rg); ++uint32_t fman_get_dma_err_event(struct fman_dma_regs *dma_rg); ++uint32_t fman_get_fpm_err_event(struct fman_fpm_regs *fpm_rg); ++uint32_t fman_get_muram_err_event(struct fman_fpm_regs *fpm_rg); ++uint32_t fman_get_iram_err_event(struct fman_fpm_regs *fpm_rg); ++uint32_t fman_get_qmi_event(struct fman_qmi_regs *qmi_rg); ++uint32_t fman_get_fpm_error_interrupts(struct fman_fpm_regs *fpm_rg); ++uint32_t fman_get_ctrl_intr(struct fman_fpm_regs *fpm_rg, ++ uint8_t event_reg_id); ++uint8_t fman_get_qmi_deq_th(struct fman_qmi_regs *qmi_rg); ++uint8_t fman_get_qmi_enq_th(struct fman_qmi_regs *qmi_rg); ++uint16_t fman_get_size_of_fifo(struct fman_bmi_regs *bmi_rg, uint8_t port_id); ++uint32_t fman_get_total_fifo_size(struct fman_bmi_regs *bmi_rg); ++uint16_t fman_get_size_of_extra_fifo(struct fman_bmi_regs *bmi_rg, ++ uint8_t port_id); ++uint8_t fman_get_num_of_tasks(struct fman_bmi_regs *bmi_rg, uint8_t port_id); ++uint8_t fman_get_num_extra_tasks(struct fman_bmi_regs *bmi_rg, ++ uint8_t port_id); ++uint8_t fman_get_num_of_dmas(struct fman_bmi_regs *bmi_rg, uint8_t port_id); ++uint8_t fman_get_num_extra_dmas(struct fman_bmi_regs *bmi_rg, ++ uint8_t port_id); ++uint32_t fman_get_normal_pending(struct fman_fpm_regs *fpm_rg); ++uint32_t fman_get_controller_event(struct fman_fpm_regs *fpm_rg, ++ uint8_t reg_id); ++uint32_t fman_get_error_pending(struct fman_fpm_regs *fpm_rg); ++void fman_get_revision(struct fman_fpm_regs *fpm_rg, uint8_t *major, ++ uint8_t *minor); ++uint32_t fman_get_counter(struct fman_rg *fman_rg, ++ enum fman_counters reg_name); ++uint32_t fman_get_dma_status(struct fman_dma_regs *dma_rg); ++ ++ ++int fman_set_erratum_10gmac_a004_wa(struct fman_fpm_regs *fpm_rg); ++void fman_set_ctrl_intr(struct fman_fpm_regs *fpm_rg, uint8_t event_reg_id, ++ uint32_t enable_events); ++void fman_set_num_of_riscs_per_port(struct fman_fpm_regs *fpm_rg, ++ uint8_t port_id, ++ uint8_t num_fman_ctrls, ++ uint32_t or_fman_ctrl); ++void fman_set_order_restoration_per_port(struct fman_fpm_regs *fpm_rg, ++ uint8_t port_id, ++ bool independent_mode, ++ bool is_rx_port); ++void fman_set_qmi_enq_th(struct fman_qmi_regs *qmi_rg, uint8_t val); ++void fman_set_qmi_deq_th(struct fman_qmi_regs *qmi_rg, uint8_t val); ++void fman_set_liodn_per_port(struct fman_rg *fman_rg, ++ uint8_t port_id, ++ uint16_t liodn_base, ++ uint16_t liodn_offset); ++void fman_set_size_of_fifo(struct fman_bmi_regs *bmi_rg, ++ uint8_t port_id, ++ uint32_t size_of_fifo, ++ uint32_t extra_size_of_fifo); ++void fman_set_num_of_tasks(struct fman_bmi_regs *bmi_rg, ++ uint8_t port_id, ++ uint8_t num_of_tasks, ++ uint8_t num_of_extra_tasks); ++void fman_set_num_of_open_dmas(struct fman_bmi_regs *bmi_rg, ++ uint8_t port_id, ++ uint8_t num_of_open_dmas, ++ uint8_t num_of_extra_open_dmas, ++ uint8_t total_num_of_dmas); ++void fman_set_ports_bandwidth(struct fman_bmi_regs *bmi_rg, uint8_t *weights); ++int fman_set_exception(struct fman_rg *fman_rg, ++ enum fman_exceptions exception, ++ bool enable); ++void fman_set_dma_emergency(struct fman_dma_regs *dma_rg, bool is_write, ++ bool enable); ++void fman_set_dma_ext_bus_pri(struct fman_dma_regs *dma_rg, uint32_t pri); ++void fman_set_congestion_group_pfc_priority(uint32_t *cpg_rg, ++ uint32_t congestion_group_id, ++ uint8_t piority_bit_map, ++ uint32_t reg_num); ++ ++ ++void fman_defconfig(struct fman_cfg *cfg, bool is_master); ++void fman_regconfig(struct fman_rg *fman_rg, struct fman_cfg *cfg); ++int fman_fpm_init(struct fman_fpm_regs *fpm_rg, struct fman_cfg *cfg); ++int fman_bmi_init(struct fman_bmi_regs *bmi_rg, struct fman_cfg *cfg); ++int fman_qmi_init(struct fman_qmi_regs *qmi_rg, struct fman_cfg *cfg); ++int fman_dma_init(struct fman_dma_regs *dma_rg, struct fman_cfg *cfg); ++void fman_free_resources(struct fman_rg *fman_rg); ++int fman_enable(struct fman_rg *fman_rg, struct fman_cfg *cfg); ++void fman_reset(struct fman_fpm_regs *fpm_rg); ++void fman_resume(struct fman_fpm_regs *fpm_rg); ++ ++ ++void fman_enable_time_stamp(struct fman_fpm_regs *fpm_rg, ++ uint8_t count1ubit, ++ uint16_t fm_clk_freq); ++void fman_enable_rams_ecc(struct fman_fpm_regs *fpm_rg); ++void fman_qmi_disable_dispatch_limit(struct fman_fpm_regs *fpm_rg); ++void fman_disable_rams_ecc(struct fman_fpm_regs *fpm_rg); ++void fman_resume_stalled_port(struct fman_fpm_regs *fpm_rg, uint8_t port_id); ++int fman_reset_mac(struct fman_fpm_regs *fpm_rg, uint8_t macId, bool is_10g); ++bool fman_is_port_stalled(struct fman_fpm_regs *fpm_rg, uint8_t port_id); ++bool fman_rams_ecc_is_external_ctl(struct fman_fpm_regs *fpm_rg); ++bool fman_is_qmi_halt_not_busy_state(struct fman_qmi_regs *qmi_rg); ++int fman_modify_counter(struct fman_rg *fman_rg, ++ enum fman_counters reg_name, ++ uint32_t val); ++void fman_force_intr(struct fman_rg *fman_rg, ++ enum fman_exceptions exception); ++void fman_set_vsp_window(struct fman_bmi_regs *bmi_rg, ++ uint8_t port_id, ++ uint8_t base_storage_profile, ++ uint8_t log2_num_of_profiles); ++ ++/**************************************************************************//** ++ @Description default values ++*//***************************************************************************/ ++#define DEFAULT_CATASTROPHIC_ERR E_FMAN_CATAST_ERR_STALL_PORT ++#define DEFAULT_DMA_ERR E_FMAN_DMA_ERR_CATASTROPHIC ++#define DEFAULT_HALT_ON_EXTERNAL_ACTIVATION FALSE /* do not change! if changed, must be disabled for rev1 ! */ ++#define DEFAULT_HALT_ON_UNRECOVERABLE_ECC_ERROR FALSE /* do not change! if changed, must be disabled for rev1 ! */ ++#define DEFAULT_EXTERNAL_ECC_RAMS_ENABLE FALSE ++#define DEFAULT_AID_OVERRIDE FALSE ++#define DEFAULT_AID_MODE E_FMAN_DMA_AID_OUT_TNUM ++#define DEFAULT_DMA_COMM_Q_LOW 0x2A ++#define DEFAULT_DMA_COMM_Q_HIGH 0x3F ++#define DEFAULT_CACHE_OVERRIDE E_FMAN_DMA_NO_CACHE_OR ++#define DEFAULT_DMA_CAM_NUM_OF_ENTRIES 64 ++#define DEFAULT_DMA_DBG_CNT_MODE E_FMAN_DMA_DBG_NO_CNT ++#define DEFAULT_DMA_EN_EMERGENCY FALSE ++#define DEFAULT_DMA_SOS_EMERGENCY 0 ++#define DEFAULT_DMA_WATCHDOG 0 /* disabled */ ++#define DEFAULT_DMA_EN_EMERGENCY_SMOOTHER FALSE ++#define DEFAULT_DMA_EMERGENCY_SWITCH_COUNTER 0 ++#define DEFAULT_DISP_LIMIT 0 ++#define DEFAULT_PRS_DISP_TH 16 ++#define DEFAULT_PLCR_DISP_TH 16 ++#define DEFAULT_KG_DISP_TH 16 ++#define DEFAULT_BMI_DISP_TH 16 ++#define DEFAULT_QMI_ENQ_DISP_TH 16 ++#define DEFAULT_QMI_DEQ_DISP_TH 16 ++#define DEFAULT_FM_CTL1_DISP_TH 16 ++#define DEFAULT_FM_CTL2_DISP_TH 16 ++#define DEFAULT_TNUM_AGING_PERIOD 4 ++ ++ ++#endif /* __FSL_FMAN_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_dtsec.h b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_dtsec.h +new file mode 100644 +index 0000000..6004e47 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_dtsec.h +@@ -0,0 +1,1096 @@ ++/* ++ * Copyright 2008-2012 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 __FSL_FMAN_DTSEC_H ++#define __FSL_FMAN_DTSEC_H ++ ++#include "common/general.h" ++#include "fsl_enet.h" ++ ++/** ++ * DOC: dTSEC Init sequence ++ * ++ * To prepare dTSEC block for transfer use the following call sequence: ++ * ++ * - fman_dtsec_defconfig() - This step is optional and yet recommended. Its ++ * use is to obtain the default dTSEC configuration parameters. ++ * ++ * - Change dtsec configuration in &dtsec_cfg. This structure will be used ++ * to customize the dTSEC behavior. ++ * ++ * - fman_dtsec_init() - Applies the configuration on dTSEC hardware. Note that ++ * dTSEC is initialized while both Tx and Rx are disabled. ++ * ++ * - fman_dtsec_set_mac_address() - Set the station address (mac address). ++ * This is used by dTSEC to match against received packets. ++ * ++ * - fman_dtsec_adjust_link() - Set the link speed and duplex parameters ++ * after the PHY establishes the link. ++ * ++ * - dtsec_enable_tx() and dtsec_enable_rx() to enable transmission and ++ * reception. ++ */ ++ ++/** ++ * DOC: dTSEC Graceful stop ++ * ++ * To temporary stop dTSEC activity use fman_dtsec_stop_tx() and ++ * fman_dtsec_stop_rx(). Note that these functions request dTSEC graceful stop ++ * but return before this stop is complete. To query for graceful stop ++ * completion use fman_dtsec_get_event() and check DTSEC_IEVENT_GTSC and ++ * DTSEC_IEVENT_GRSC bits. Alternatively the dTSEC interrupt mask can be set to ++ * enable graceful stop interrupts. ++ * ++ * To resume operation after graceful stop use fman_dtsec_start_tx() and ++ * fman_dtsec_start_rx(). ++ */ ++ ++/** ++ * DOC: dTSEC interrupt handling ++ * ++ * This code does not provide an interrupt handler for dTSEC. Instead this ++ * handler should be implemented and registered to the operating system by the ++ * caller. Some primitives for accessing the event status and mask registers ++ * are provided. ++ * ++ * See "dTSEC Events" section for a list of events that dTSEC can generate. ++ */ ++ ++/** ++ * DOC: dTSEC Events ++ * ++ * Interrupt events cause dTSEC event bits to be set. Software may poll the ++ * event register at any time to check for pending interrupts. If an event ++ * occurs and its corresponding enable bit is set in the interrupt mask ++ * register, the event also causes a hardware interrupt at the PIC. ++ * ++ * To poll for event status use the fman_dtsec_get_event() function. ++ * To configure the interrupt mask use fman_dtsec_enable_interrupt() and ++ * fman_dtsec_disable_interrupt() functions. ++ * After servicing a dTSEC interrupt use fman_dtsec_ack_event to reset the ++ * serviced event bit. ++ * ++ * The following events may be signaled by dTSEC hardware: ++ * ++ * %DTSEC_IEVENT_BABR - Babbling receive error. This bit indicates that ++ * a frame was received with length in excess of the MAC's maximum frame length ++ * register. ++ * ++ * %DTSEC_IEVENT_RXC - Receive control (pause frame) interrupt. A pause ++ * control frame was received while Rx pause frame handling is enabled. ++ * Also see fman_dtsec_handle_rx_pause(). ++ * ++ * %DTSEC_IEVENT_MSRO - MIB counter overflow. The count for one of the MIB ++ * counters has exceeded the size of its register. ++ * ++ * %DTSEC_IEVENT_GTSC - Graceful transmit stop complete. Graceful stop is now ++ * complete. The transmitter is in a stopped state, in which only pause frames ++ * can be transmitted. ++ * Also see fman_dtsec_stop_tx(). ++ * ++ * %DTSEC_IEVENT_BABT - Babbling transmit error. The transmitted frame length ++ * has exceeded the value in the MAC's Maximum Frame Length register. ++ * ++ * %DTSEC_IEVENT_TXC - Transmit control (pause frame) interrupt. his bit ++ * indicates that a control frame was transmitted. ++ * ++ * %DTSEC_IEVENT_TXE - Transmit error. This bit indicates that an error ++ * occurred on the transmitted channel. This bit is set whenever any transmit ++ * error occurs which causes the dTSEC to discard all or part of a frame ++ * (LC, CRL, XFUN). ++ * ++ * %DTSEC_IEVENT_LC - Late collision. This bit indicates that a collision ++ * occurred beyond the collision window (slot time) in half-duplex mode. ++ * The frame is truncated with a bad CRC and the remainder of the frame ++ * is discarded. ++ * ++ * %DTSEC_IEVENT_CRL - Collision retry limit. is bit indicates that the number ++ * of successive transmission collisions has exceeded the MAC's half-duplex ++ * register's retransmission maximum count. The frame is discarded without ++ * being transmitted and transmission of the next frame commences. This only ++ * occurs while in half-duplex mode. ++ * The number of retransmit attempts can be set in ++ * &dtsec_halfdup_cfg. at retransmit before calling fman_dtsec_init(). ++ * ++ * %DTSEC_IEVENT_XFUN - Transmit FIFO underrun. This bit indicates that the ++ * transmit FIFO became empty before the complete frame was transmitted. ++ * The frame is truncated with a bad CRC and the remainder of the frame is ++ * discarded. ++ * ++ * %DTSEC_IEVENT_MAG - TBD ++ * ++ * %DTSEC_IEVENT_MMRD - MII management read completion. ++ * ++ * %DTSEC_IEVENT_MMWR - MII management write completion. ++ * ++ * %DTSEC_IEVENT_GRSC - Graceful receive stop complete. It allows the user to ++ * know if the system has completed the stop and it is safe to write to receive ++ * registers (status, control or configuration registers) that are used by the ++ * system during normal operation. ++ * ++ * %DTSEC_IEVENT_TDPE - Internal data error on transmit. This bit indicates ++ * that the dTSEC has detected a parity error on its stored transmit data, which ++ * is likely to compromise the validity of recently transferred frames. ++ * ++ * %DTSEC_IEVENT_RDPE - Internal data error on receive. This bit indicates that ++ * the dTSEC has detected a parity error on its stored receive data, which is ++ * likely to compromise the validity of recently transferred frames. ++ */ ++/* Interrupt Mask Register (IMASK) */ ++#define DTSEC_IMASK_BREN 0x80000000 ++#define DTSEC_IMASK_RXCEN 0x40000000 ++#define DTSEC_IMASK_MSROEN 0x04000000 ++#define DTSEC_IMASK_GTSCEN 0x02000000 ++#define DTSEC_IMASK_BTEN 0x01000000 ++#define DTSEC_IMASK_TXCEN 0x00800000 ++#define DTSEC_IMASK_TXEEN 0x00400000 ++#define DTSEC_IMASK_LCEN 0x00040000 ++#define DTSEC_IMASK_CRLEN 0x00020000 ++#define DTSEC_IMASK_XFUNEN 0x00010000 ++#define DTSEC_IMASK_ABRTEN 0x00008000 ++#define DTSEC_IMASK_IFERREN 0x00004000 ++#define DTSEC_IMASK_MAGEN 0x00000800 ++#define DTSEC_IMASK_MMRDEN 0x00000400 ++#define DTSEC_IMASK_MMWREN 0x00000200 ++#define DTSEC_IMASK_GRSCEN 0x00000100 ++#define DTSEC_IMASK_TDPEEN 0x00000002 ++#define DTSEC_IMASK_RDPEEN 0x00000001 ++ ++#define DTSEC_EVENTS_MASK \ ++ ((uint32_t)(DTSEC_IMASK_BREN | \ ++ DTSEC_IMASK_RXCEN | \ ++ DTSEC_IMASK_BTEN | \ ++ DTSEC_IMASK_TXCEN | \ ++ DTSEC_IMASK_TXEEN | \ ++ DTSEC_IMASK_ABRTEN | \ ++ DTSEC_IMASK_LCEN | \ ++ DTSEC_IMASK_CRLEN | \ ++ DTSEC_IMASK_XFUNEN | \ ++ DTSEC_IMASK_IFERREN | \ ++ DTSEC_IMASK_MAGEN | \ ++ DTSEC_IMASK_TDPEEN | \ ++ DTSEC_IMASK_RDPEEN)) ++ ++/* dtsec timestamp event bits */ ++#define TMR_PEMASK_TSREEN 0x00010000 ++#define TMR_PEVENT_TSRE 0x00010000 ++ ++/* Group address bit indication */ ++#define MAC_GROUP_ADDRESS 0x0000010000000000ULL ++/* size in bytes of L2 address */ ++#define MAC_ADDRLEN 6 ++ ++#define DEFAULT_HALFDUP_ON FALSE ++#define DEFAULT_HALFDUP_RETRANSMIT 0xf ++#define DEFAULT_HALFDUP_COLL_WINDOW 0x37 ++#define DEFAULT_HALFDUP_EXCESS_DEFER TRUE ++#define DEFAULT_HALFDUP_NO_BACKOFF FALSE ++#define DEFAULT_HALFDUP_BP_NO_BACKOFF FALSE ++#define DEFAULT_HALFDUP_ALT_BACKOFF_VAL 0x0A ++#define DEFAULT_HALFDUP_ALT_BACKOFF_EN FALSE ++#define DEFAULT_RX_DROP_BCAST FALSE ++#define DEFAULT_RX_SHORT_FRM TRUE ++#define DEFAULT_RX_LEN_CHECK FALSE ++#define DEFAULT_TX_PAD_CRC TRUE ++#define DEFAULT_TX_CRC FALSE ++#define DEFAULT_RX_CTRL_ACC FALSE ++#define DEFAULT_TX_PAUSE_TIME 0xf000 ++#define DEFAULT_TBIPA 5 ++#define DEFAULT_RX_PREPEND 0 ++#define DEFAULT_PTP_TSU_EN TRUE ++#define DEFAULT_PTP_EXCEPTION_EN TRUE ++#define DEFAULT_PREAMBLE_LEN 7 ++#define DEFAULT_RX_PREAMBLE FALSE ++#define DEFAULT_TX_PREAMBLE FALSE ++#define DEFAULT_LOOPBACK FALSE ++#define DEFAULT_RX_TIME_STAMP_EN FALSE ++#define DEFAULT_TX_TIME_STAMP_EN FALSE ++#define DEFAULT_RX_FLOW TRUE ++#define DEFAULT_TX_FLOW TRUE ++#define DEFAULT_RX_GROUP_HASH_EXD FALSE ++#define DEFAULT_TX_PAUSE_TIME_EXTD 0 ++#define DEFAULT_RX_PROMISC FALSE ++#define DEFAULT_NON_BACK_TO_BACK_IPG1 0x40 ++#define DEFAULT_NON_BACK_TO_BACK_IPG2 0x60 ++#define DEFAULT_MIN_IFG_ENFORCEMENT 0x50 ++#define DEFAULT_BACK_TO_BACK_IPG 0x60 ++#define DEFAULT_MAXIMUM_FRAME 0x600 ++#define DEFAULT_TBI_PHY_ADDR 5 ++#define DEFAULT_WAKE_ON_LAN FALSE ++ ++/* register related defines (bits, field offsets..) */ ++#define DTSEC_ID1_ID 0xffff0000 ++#define DTSEC_ID1_REV_MJ 0x0000FF00 ++#define DTSEC_ID1_REV_MN 0x000000ff ++ ++#define DTSEC_ID2_INT_REDUCED_OFF 0x00010000 ++#define DTSEC_ID2_INT_NORMAL_OFF 0x00020000 ++ ++#define DTSEC_ECNTRL_CLRCNT 0x00004000 ++#define DTSEC_ECNTRL_AUTOZ 0x00002000 ++#define DTSEC_ECNTRL_STEN 0x00001000 ++#define DTSEC_ECNTRL_CFG_RO 0x80000000 ++#define DTSEC_ECNTRL_GMIIM 0x00000040 ++#define DTSEC_ECNTRL_TBIM 0x00000020 ++#define DTSEC_ECNTRL_SGMIIM 0x00000002 ++#define DTSEC_ECNTRL_RPM 0x00000010 ++#define DTSEC_ECNTRL_R100M 0x00000008 ++#define DTSEC_ECNTRL_RMM 0x00000004 ++#define DTSEC_ECNTRL_QSGMIIM 0x00000001 ++ ++#define DTSEC_TCTRL_THDF 0x00000800 ++#define DTSEC_TCTRL_TTSE 0x00000040 ++#define DTSEC_TCTRL_GTS 0x00000020 ++#define DTSEC_TCTRL_TFC_PAUSE 0x00000010 ++ ++/* PTV offsets */ ++#define PTV_PTE_OFST 16 ++ ++#define RCTRL_CFA 0x00008000 ++#define RCTRL_GHTX 0x00000400 ++#define RCTRL_RTSE 0x00000040 ++#define RCTRL_GRS 0x00000020 ++#define RCTRL_BC_REJ 0x00000010 ++#define RCTRL_MPROM 0x00000008 ++#define RCTRL_RSF 0x00000004 ++#define RCTRL_UPROM 0x00000001 ++#define RCTRL_PROM (RCTRL_UPROM | RCTRL_MPROM) ++ ++#define TMR_CTL_ESFDP 0x00000800 ++#define TMR_CTL_ESFDE 0x00000400 ++ ++#define MACCFG1_SOFT_RESET 0x80000000 ++#define MACCFG1_LOOPBACK 0x00000100 ++#define MACCFG1_RX_FLOW 0x00000020 ++#define MACCFG1_TX_FLOW 0x00000010 ++#define MACCFG1_TX_EN 0x00000001 ++#define MACCFG1_RX_EN 0x00000004 ++#define MACCFG1_RESET_RxMC 0x00080000 ++#define MACCFG1_RESET_TxMC 0x00040000 ++#define MACCFG1_RESET_RxFUN 0x00020000 ++#define MACCFG1_RESET_TxFUN 0x00010000 ++ ++#define MACCFG2_NIBBLE_MODE 0x00000100 ++#define MACCFG2_BYTE_MODE 0x00000200 ++#define MACCFG2_PRE_AM_Rx_EN 0x00000080 ++#define MACCFG2_PRE_AM_Tx_EN 0x00000040 ++#define MACCFG2_LENGTH_CHECK 0x00000010 ++#define MACCFG2_MAGIC_PACKET_EN 0x00000008 ++#define MACCFG2_PAD_CRC_EN 0x00000004 ++#define MACCFG2_CRC_EN 0x00000002 ++#define MACCFG2_FULL_DUPLEX 0x00000001 ++ ++#define PREAMBLE_LENGTH_SHIFT 12 ++ ++#define IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT 24 ++#define IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT 16 ++#define IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT 8 ++ ++#define IPGIFG_NON_BACK_TO_BACK_IPG_1 0x7F000000 ++#define IPGIFG_NON_BACK_TO_BACK_IPG_2 0x007F0000 ++#define IPGIFG_MIN_IFG_ENFORCEMENT 0x0000FF00 ++#define IPGIFG_BACK_TO_BACK_IPG 0x0000007F ++ ++#define HAFDUP_ALT_BEB 0x00080000 ++#define HAFDUP_BP_NO_BACKOFF 0x00040000 ++#define HAFDUP_NO_BACKOFF 0x00020000 ++#define HAFDUP_EXCESS_DEFER 0x00010000 ++#define HAFDUP_COLLISION_WINDOW 0x000003ff ++ ++#define HAFDUP_ALTERNATE_BEB_TRUNCATION_SHIFT 20 ++#define HAFDUP_RETRANSMISSION_MAX_SHIFT 12 ++#define HAFDUP_RETRANSMISSION_MAX 0x0000f000 ++ ++#define NUM_OF_HASH_REGS 8 /* Number of hash table registers */ ++ ++/* CAR1/2 bits */ ++#define DTSEC_CAR1_TR64 0x80000000 ++#define DTSEC_CAR1_TR127 0x40000000 ++#define DTSEC_CAR1_TR255 0x20000000 ++#define DTSEC_CAR1_TR511 0x10000000 ++#define DTSEC_CAR1_TRK1 0x08000000 ++#define DTSEC_CAR1_TRMAX 0x04000000 ++#define DTSEC_CAR1_TRMGV 0x02000000 ++ ++#define DTSEC_CAR1_RBYT 0x00010000 ++#define DTSEC_CAR1_RPKT 0x00008000 ++#define DTSEC_CAR1_RFCS 0x00004000 ++#define DTSEC_CAR1_RMCA 0x00002000 ++#define DTSEC_CAR1_RBCA 0x00001000 ++#define DTSEC_CAR1_RXCF 0x00000800 ++#define DTSEC_CAR1_RXPF 0x00000400 ++#define DTSEC_CAR1_RXUO 0x00000200 ++#define DTSEC_CAR1_RALN 0x00000100 ++#define DTSEC_CAR1_RFLR 0x00000080 ++#define DTSEC_CAR1_RCDE 0x00000040 ++#define DTSEC_CAR1_RCSE 0x00000020 ++#define DTSEC_CAR1_RUND 0x00000010 ++#define DTSEC_CAR1_ROVR 0x00000008 ++#define DTSEC_CAR1_RFRG 0x00000004 ++#define DTSEC_CAR1_RJBR 0x00000002 ++#define DTSEC_CAR1_RDRP 0x00000001 ++ ++#define DTSEC_CAR2_TJBR 0x00080000 ++#define DTSEC_CAR2_TFCS 0x00040000 ++#define DTSEC_CAR2_TXCF 0x00020000 ++#define DTSEC_CAR2_TOVR 0x00010000 ++#define DTSEC_CAR2_TUND 0x00008000 ++#define DTSEC_CAR2_TFRG 0x00004000 ++#define DTSEC_CAR2_TBYT 0x00002000 ++#define DTSEC_CAR2_TPKT 0x00001000 ++#define DTSEC_CAR2_TMCA 0x00000800 ++#define DTSEC_CAR2_TBCA 0x00000400 ++#define DTSEC_CAR2_TXPF 0x00000200 ++#define DTSEC_CAR2_TDFR 0x00000100 ++#define DTSEC_CAR2_TEDF 0x00000080 ++#define DTSEC_CAR2_TSCL 0x00000040 ++#define DTSEC_CAR2_TMCL 0x00000020 ++#define DTSEC_CAR2_TLCL 0x00000010 ++#define DTSEC_CAR2_TXCL 0x00000008 ++#define DTSEC_CAR2_TNCL 0x00000004 ++#define DTSEC_CAR2_TDRP 0x00000001 ++ ++#define CAM1_ERRORS_ONLY \ ++ (DTSEC_CAR1_RXPF | DTSEC_CAR1_RALN | DTSEC_CAR1_RFLR \ ++ | DTSEC_CAR1_RCDE | DTSEC_CAR1_RCSE | DTSEC_CAR1_RUND \ ++ | DTSEC_CAR1_ROVR | DTSEC_CAR1_RFRG | DTSEC_CAR1_RJBR \ ++ | DTSEC_CAR1_RDRP) ++ ++#define CAM2_ERRORS_ONLY (DTSEC_CAR2_TFCS | DTSEC_CAR2_TXPF | DTSEC_CAR2_TDRP) ++ ++/* ++ * Group of dTSEC specific counters relating to the standard RMON MIB Group 1 ++ * (or Ethernet) statistics. ++ */ ++#define CAM1_MIB_GRP_1 \ ++ (DTSEC_CAR1_RDRP | DTSEC_CAR1_RBYT | DTSEC_CAR1_RPKT | DTSEC_CAR1_RMCA\ ++ | DTSEC_CAR1_RBCA | DTSEC_CAR1_RALN | DTSEC_CAR1_RUND | DTSEC_CAR1_ROVR\ ++ | DTSEC_CAR1_RFRG | DTSEC_CAR1_RJBR \ ++ | DTSEC_CAR1_TR64 | DTSEC_CAR1_TR127 | DTSEC_CAR1_TR255 \ ++ | DTSEC_CAR1_TR511 | DTSEC_CAR1_TRMAX) ++ ++#define CAM2_MIB_GRP_1 (DTSEC_CAR2_TNCL | DTSEC_CAR2_TDRP) ++ ++/* memory map */ ++ ++struct dtsec_regs { ++ /* dTSEC General Control and Status Registers */ ++ uint32_t tsec_id; /* 0x000 ETSEC_ID register */ ++ uint32_t tsec_id2; /* 0x004 ETSEC_ID2 register */ ++ uint32_t ievent; /* 0x008 Interrupt event register */ ++ uint32_t imask; /* 0x00C Interrupt mask register */ ++ uint32_t reserved0010[1]; ++ uint32_t ecntrl; /* 0x014 E control register */ ++ uint32_t ptv; /* 0x018 Pause time value register */ ++ uint32_t tbipa; /* 0x01C TBI PHY address register */ ++ uint32_t tmr_ctrl; /* 0x020 Time-stamp Control register */ ++ uint32_t tmr_pevent; /* 0x024 Time-stamp event register */ ++ uint32_t tmr_pemask; /* 0x028 Timer event mask register */ ++ uint32_t reserved002c[5]; ++ uint32_t tctrl; /* 0x040 Transmit control register */ ++ uint32_t reserved0044[3]; ++ uint32_t rctrl; /* 0x050 Receive control register */ ++ uint32_t reserved0054[11]; ++ uint32_t igaddr[8]; /* 0x080-0x09C Individual/group address */ ++ uint32_t gaddr[8]; /* 0x0A0-0x0BC Group address registers 0-7 */ ++ uint32_t reserved00c0[16]; ++ uint32_t maccfg1; /* 0x100 MAC configuration #1 */ ++ uint32_t maccfg2; /* 0x104 MAC configuration #2 */ ++ uint32_t ipgifg; /* 0x108 IPG/IFG */ ++ uint32_t hafdup; /* 0x10C Half-duplex */ ++ uint32_t maxfrm; /* 0x110 Maximum frame */ ++ uint32_t reserved0114[10]; ++ uint32_t ifstat; /* 0x13C Interface status */ ++ uint32_t macstnaddr1; /* 0x140 Station Address,part 1 */ ++ uint32_t macstnaddr2; /* 0x144 Station Address,part 2 */ ++ struct { ++ uint32_t exact_match1; /* octets 1-4 */ ++ uint32_t exact_match2; /* octets 5-6 */ ++ } macaddr[15]; /* 0x148-0x1BC mac exact match addresses 1-15 */ ++ uint32_t reserved01c0[16]; ++ uint32_t tr64; /* 0x200 transmit and receive 64 byte frame counter */ ++ uint32_t tr127; /* 0x204 transmit and receive 65 to 127 byte frame ++ * counter */ ++ uint32_t tr255; /* 0x208 transmit and receive 128 to 255 byte frame ++ * counter */ ++ uint32_t tr511; /* 0x20C transmit and receive 256 to 511 byte frame ++ * counter */ ++ uint32_t tr1k; /* 0x210 transmit and receive 512 to 1023 byte frame ++ * counter */ ++ uint32_t trmax; /* 0x214 transmit and receive 1024 to 1518 byte frame ++ * counter */ ++ uint32_t trmgv; /* 0x218 transmit and receive 1519 to 1522 byte good ++ * VLAN frame count */ ++ uint32_t rbyt; /* 0x21C receive byte counter */ ++ uint32_t rpkt; /* 0x220 receive packet counter */ ++ uint32_t rfcs; /* 0x224 receive FCS error counter */ ++ uint32_t rmca; /* 0x228 RMCA receive multicast packet counter */ ++ uint32_t rbca; /* 0x22C receive broadcast packet counter */ ++ uint32_t rxcf; /* 0x230 receive control frame packet counter */ ++ uint32_t rxpf; /* 0x234 receive pause frame packet counter */ ++ uint32_t rxuo; /* 0x238 receive unknown OP code counter */ ++ uint32_t raln; /* 0x23C receive alignment error counter */ ++ uint32_t rflr; /* 0x240 receive frame length error counter */ ++ uint32_t rcde; /* 0x244 receive code error counter */ ++ uint32_t rcse; /* 0x248 receive carrier sense error counter */ ++ uint32_t rund; /* 0x24C receive undersize packet counter */ ++ uint32_t rovr; /* 0x250 receive oversize packet counter */ ++ uint32_t rfrg; /* 0x254 receive fragments counter */ ++ uint32_t rjbr; /* 0x258 receive jabber counter */ ++ uint32_t rdrp; /* 0x25C receive drop */ ++ uint32_t tbyt; /* 0x260 transmit byte counter */ ++ uint32_t tpkt; /* 0x264 transmit packet counter */ ++ uint32_t tmca; /* 0x268 transmit multicast packet counter */ ++ uint32_t tbca; /* 0x26C transmit broadcast packet counter */ ++ uint32_t txpf; /* 0x270 transmit pause control frame counter */ ++ uint32_t tdfr; /* 0x274 transmit deferral packet counter */ ++ uint32_t tedf; /* 0x278 transmit excessive deferral packet counter */ ++ uint32_t tscl; /* 0x27C transmit single collision packet counter */ ++ uint32_t tmcl; /* 0x280 transmit multiple collision packet counter */ ++ uint32_t tlcl; /* 0x284 transmit late collision packet counter */ ++ uint32_t txcl; /* 0x288 transmit excessive collision packet counter */ ++ uint32_t tncl; /* 0x28C transmit total collision counter */ ++ uint32_t reserved0290[1]; ++ uint32_t tdrp; /* 0x294 transmit drop frame counter */ ++ uint32_t tjbr; /* 0x298 transmit jabber frame counter */ ++ uint32_t tfcs; /* 0x29C transmit FCS error counter */ ++ uint32_t txcf; /* 0x2A0 transmit control frame counter */ ++ uint32_t tovr; /* 0x2A4 transmit oversize frame counter */ ++ uint32_t tund; /* 0x2A8 transmit undersize frame counter */ ++ uint32_t tfrg; /* 0x2AC transmit fragments frame counter */ ++ uint32_t car1; /* 0x2B0 carry register one register* */ ++ uint32_t car2; /* 0x2B4 carry register two register* */ ++ uint32_t cam1; /* 0x2B8 carry register one mask register */ ++ uint32_t cam2; /* 0x2BC carry register two mask register */ ++ uint32_t reserved02c0[848]; ++}; ++ ++/** ++ * struct dtsec_mib_grp_1_counters - MIB counter overflows ++ * ++ * @tr64: Transmit and Receive 64 byte frame count. Increment for each ++ * good or bad frame, of any type, transmitted or received, which ++ * is 64 bytes in length. ++ * @tr127: Transmit and Receive 65 to 127 byte frame count. Increments for ++ * each good or bad frame of any type, transmitted or received, ++ * which is 65-127 bytes in length. ++ * @tr255: Transmit and Receive 128 to 255 byte frame count. Increments ++ * for each good or bad frame, of any type, transmitted or ++ * received, which is 128-255 bytes in length. ++ * @tr511: Transmit and Receive 256 to 511 byte frame count. Increments ++ * for each good or bad frame, of any type, transmitted or ++ * received, which is 256-511 bytes in length. ++ * @tr1k: Transmit and Receive 512 to 1023 byte frame count. Increments ++ * for each good or bad frame, of any type, transmitted or ++ * received, which is 512-1023 bytes in length. ++ * @trmax: Transmit and Receive 1024 to 1518 byte frame count. Increments ++ * for each good or bad frame, of any type, transmitted or ++ * received, which is 1024-1518 bytes in length. ++ * @rfrg: Receive fragments count. Increments for each received frame ++ * which is less than 64 bytes in length and contains an invalid ++ * FCS. This includes integral and non-integral lengths. ++ * @rjbr: Receive jabber count. Increments for received frames which ++ * exceed 1518 (non VLAN) or 1522 (VLAN) bytes and contain an ++ * invalid FCS. This includes alignment errors. ++ * @rdrp: Receive dropped packets count. Increments for received frames ++ * which are streamed to system but are later dropped due to lack ++ * of system resources. Does not increment for frames rejected due ++ * to address filtering. ++ * @raln: Receive alignment error count. Increments for each received ++ * frame from 64 to 1518 (non VLAN) or 1522 (VLAN) which contains ++ * an invalid FCS and is not an integral number of bytes. ++ * @rund: Receive undersize packet count. Increments each time a frame is ++ * received which is less than 64 bytes in length and contains a ++ * valid FCS and is otherwise well formed. This count does not ++ * include range length errors. ++ * @rovr: Receive oversize packet count. Increments each time a frame is ++ * received which exceeded 1518 (non VLAN) or 1522 (VLAN) and ++ * contains a valid FCS and is otherwise well formed. ++ * @rbyt: Receive byte count. Increments by the byte count of frames ++ * received, including those in bad packets, excluding preamble and ++ * SFD but including FCS bytes. ++ * @rpkt: Receive packet count. Increments for each received frame ++ * (including bad packets, all unicast, broadcast, and multicast ++ * packets). ++ * @rmca: Receive multicast packet count. Increments for each multicast ++ * frame with valid CRC and of lengths 64 to 1518 (non VLAN) or ++ * 1522 (VLAN), excluding broadcast frames. This count does not ++ * include range/length errors. ++ * @rbca: Receive broadcast packet count. Increments for each broadcast ++ * frame with valid CRC and of lengths 64 to 1518 (non VLAN) or ++ * 1522 (VLAN), excluding multicast frames. Does not include ++ * range/length errors. ++ * @tdrp: Transmit drop frame count. Increments each time a memory error ++ * or an underrun has occurred. ++ * @tncl: Transmit total collision counter. Increments by the number of ++ * collisions experienced during the transmission of a frame. Does ++ * not increment for aborted frames. ++ * ++ * The structure contains a group of dTSEC HW specific counters relating to the ++ * standard RMON MIB Group 1 (or Ethernet statistics) counters. This structure ++ * is counting only the carry events of the corresponding HW counters. ++ * ++ * tr64 to trmax notes: Frame sizes specified are considered excluding preamble ++ * and SFD but including FCS bytes. ++ */ ++struct dtsec_mib_grp_1_counters { ++ uint64_t rdrp; ++ uint64_t tdrp; ++ uint64_t rbyt; ++ uint64_t rpkt; ++ uint64_t rbca; ++ uint64_t rmca; ++ uint64_t raln; ++ uint64_t rund; ++ uint64_t rovr; ++ uint64_t rfrg; ++ uint64_t rjbr; ++ uint64_t tncl; ++ uint64_t tr64; ++ uint64_t tr127; ++ uint64_t tr255; ++ uint64_t tr511; ++ uint64_t tr1k; ++ uint64_t trmax; ++}; ++ ++enum dtsec_stat_counters { ++ E_DTSEC_STAT_TR64, ++ E_DTSEC_STAT_TR127, ++ E_DTSEC_STAT_TR255, ++ E_DTSEC_STAT_TR511, ++ E_DTSEC_STAT_TR1K, ++ E_DTSEC_STAT_TRMAX, ++ E_DTSEC_STAT_TRMGV, ++ E_DTSEC_STAT_RBYT, ++ E_DTSEC_STAT_RPKT, ++ E_DTSEC_STAT_RMCA, ++ E_DTSEC_STAT_RBCA, ++ E_DTSEC_STAT_RXPF, ++ E_DTSEC_STAT_RALN, ++ E_DTSEC_STAT_RFLR, ++ E_DTSEC_STAT_RCDE, ++ E_DTSEC_STAT_RCSE, ++ E_DTSEC_STAT_RUND, ++ E_DTSEC_STAT_ROVR, ++ E_DTSEC_STAT_RFRG, ++ E_DTSEC_STAT_RJBR, ++ E_DTSEC_STAT_RDRP, ++ E_DTSEC_STAT_TFCS, ++ E_DTSEC_STAT_TBYT, ++ E_DTSEC_STAT_TPKT, ++ E_DTSEC_STAT_TMCA, ++ E_DTSEC_STAT_TBCA, ++ E_DTSEC_STAT_TXPF, ++ E_DTSEC_STAT_TNCL, ++ E_DTSEC_STAT_TDRP ++}; ++ ++enum dtsec_stat_level { ++ /* No statistics */ ++ E_MAC_STAT_NONE = 0, ++ /* Only RMON MIB group 1 (ether stats). Optimized for performance */ ++ E_MAC_STAT_MIB_GRP1, ++ /* Only error counters are available. Optimized for performance */ ++ E_MAC_STAT_PARTIAL, ++ /* All counters available. Not optimized for performance */ ++ E_MAC_STAT_FULL ++}; ++ ++ ++/** ++ * struct dtsec_cfg - dTSEC configuration ++ * ++ * @halfdup_on: Transmit half-duplex flow control, under software ++ * control for 10/100-Mbps half-duplex media. If set, ++ * back pressure is applied to media by raising carrier. ++ * @halfdup_retransmit: Number of retransmission attempts following a collision. ++ * If this is exceeded dTSEC aborts transmission due to ++ * excessive collisions. The standard specifies the ++ * attempt limit to be 15. ++ * @halfdup_coll_window:The number of bytes of the frame during which ++ * collisions may occur. The default value of 55 ++ * corresponds to the frame byte at the end of the ++ * standard 512-bit slot time window. If collisions are ++ * detected after this byte, the late collision event is ++ * asserted and transmission of current frame is aborted. ++ * @rx_drop_bcast: Discard broadcast frames. If set, all broadcast frames ++ * will be discarded by dTSEC. ++ * @rx_short_frm: Accept short frames. If set, dTSEC will accept frames ++ * of length 14..63 bytes. ++ * @rx_len_check: Length check for received frames. If set, the MAC ++ * checks the frame's length field on receive to ensure it ++ * matches the actual data field length. This only works ++ * for received frames with length field less than 1500. ++ * No check is performed for larger frames. ++ * @tx_pad_crc: Pad and append CRC. If set, the MAC pads all ++ * transmitted short frames and appends a CRC to every ++ * frame regardless of padding requirement. ++ * @tx_crc: Transmission CRC enable. If set, the MAC appends a CRC ++ * to all frames. If frames presented to the MAC have a ++ * valid length and contain a valid CRC, @tx_crc should be ++ * reset. ++ * This field is ignored if @tx_pad_crc is set. ++ * @rx_ctrl_acc: Control frame accept. If set, this overrides 802.3 ++ * standard control frame behavior, and all Ethernet frames ++ * that have an ethertype of 0x8808 are treated as normal ++ * Ethernet frames and passed up to the packet interface on ++ * a DA match. Received pause control frames are passed to ++ * the packet interface only if Rx flow control is also ++ * disabled. See fman_dtsec_handle_rx_pause() function. ++ * @tx_pause_time: Transmit pause time value. This pause value is used as ++ * part of the pause frame to be sent when a transmit pause ++ * frame is initiated. If set to 0 this disables ++ * transmission of pause frames. ++ * @rx_preamble: Receive preamble enable. If set, the MAC recovers the ++ * received Ethernet 7-byte preamble and passes it to the ++ * packet interface at the start of each received frame. ++ * This field should be reset for internal MAC loop-back ++ * mode. ++ * @tx_preamble: User defined preamble enable for transmitted frames. ++ * If set, a user-defined preamble must passed to the MAC ++ * and it is transmitted instead of the standard preamble. ++ * @preamble_len: Length, in bytes, of the preamble field preceding each ++ * Ethernet start-of-frame delimiter byte. The default ++ * value of 0x7 should be used in order to guarantee ++ * reliable operation with IEEE 802.3 compliant hardware. ++ * @rx_prepend: Packet alignment padding length. The specified number ++ * of bytes (1-31) of zero padding are inserted before the ++ * start of each received frame. For Ethernet, where ++ * optional preamble extraction is enabled, the padding ++ * appears before the preamble, otherwise the padding ++ * precedes the layer 2 header. ++ * ++ * This structure contains basic dTSEC configuration and must be passed to ++ * fman_dtsec_init() function. A default set of configuration values can be ++ * obtained by calling fman_dtsec_defconfig(). ++ */ ++struct dtsec_cfg { ++ bool halfdup_on; ++ bool halfdup_alt_backoff_en; ++ bool halfdup_excess_defer; ++ bool halfdup_no_backoff; ++ bool halfdup_bp_no_backoff; ++ uint8_t halfdup_alt_backoff_val; ++ uint16_t halfdup_retransmit; ++ uint16_t halfdup_coll_window; ++ bool rx_drop_bcast; ++ bool rx_short_frm; ++ bool rx_len_check; ++ bool tx_pad_crc; ++ bool tx_crc; ++ bool rx_ctrl_acc; ++ unsigned short tx_pause_time; ++ unsigned short tbipa; ++ bool ptp_tsu_en; ++ bool ptp_exception_en; ++ bool rx_preamble; ++ bool tx_preamble; ++ unsigned char preamble_len; ++ unsigned char rx_prepend; ++ bool loopback; ++ bool rx_time_stamp_en; ++ bool tx_time_stamp_en; ++ bool rx_flow; ++ bool tx_flow; ++ bool rx_group_hash_exd; ++ bool rx_promisc; ++ uint8_t tbi_phy_addr; ++ uint16_t tx_pause_time_extd; ++ uint16_t maximum_frame; ++ uint32_t non_back_to_back_ipg1; ++ uint32_t non_back_to_back_ipg2; ++ uint32_t min_ifg_enforcement; ++ uint32_t back_to_back_ipg; ++ bool wake_on_lan; ++}; ++ ++ ++/** ++ * fman_dtsec_defconfig() - Get default dTSEC configuration ++ * @cfg: pointer to configuration structure. ++ * ++ * Call this function to obtain a default set of configuration values for ++ * initializing dTSEC. The user can overwrite any of the values before calling ++ * fman_dtsec_init(), if specific configuration needs to be applied. ++ */ ++void fman_dtsec_defconfig(struct dtsec_cfg *cfg); ++ ++/** ++ * fman_dtsec_init() - Init dTSEC hardware block ++ * @regs: Pointer to dTSEC register block ++ * @cfg: dTSEC configuration data ++ * @iface_mode: dTSEC interface mode, the type of MAC - PHY interface. ++ * @iface_speed: 1G or 10G ++ * @macaddr: MAC station address to be assigned to the device ++ * @fm_rev_maj: major rev number ++ * @fm_rev_min: minor rev number ++ * @exceptions_mask: initial exceptions mask ++ * ++ * This function initializes dTSEC and applies basic configuration. ++ * ++ * dTSEC initialization sequence: ++ * Before enabling Rx/Tx call dtsec_set_address() to set MAC address, ++ * fman_dtsec_adjust_link() to configure interface speed and duplex and finally ++ * dtsec_enable_tx()/dtsec_enable_rx() to start transmission and reception. ++ * ++ * Returns: 0 if successful, an error code otherwise. ++ */ ++int fman_dtsec_init(struct dtsec_regs *regs, struct dtsec_cfg *cfg, ++ enum enet_interface iface_mode, ++ enum enet_speed iface_speed, ++ uint8_t *macaddr, uint8_t fm_rev_maj, ++ uint8_t fm_rev_min, ++ uint32_t exception_mask); ++ ++/** ++ * fman_dtsec_enable() - Enable dTSEC Tx and Tx ++ * @regs: Pointer to dTSEC register block ++ * @apply_rx: enable rx side ++ * @apply_tx: enable tx side ++ * ++ * This function resets Tx and Rx graceful stop bit and enables dTSEC Tx and Rx. ++ */ ++void fman_dtsec_enable(struct dtsec_regs *regs, bool apply_rx, bool apply_tx); ++ ++/** ++ * fman_dtsec_disable() - Disable dTSEC Tx and Rx ++ * @regs: Pointer to dTSEC register block ++ * @apply_rx: disable rx side ++ * @apply_tx: disable tx side ++ * ++ * This function disables Tx and Rx in dTSEC. ++ */ ++void fman_dtsec_disable(struct dtsec_regs *regs, bool apply_rx, bool apply_tx); ++ ++/** ++ * fman_dtsec_get_revision() - Get dTSEC hardware revision ++ * @regs: Pointer to dTSEC register block ++ * ++ * Returns dtsec_id content ++ * ++ * Call this function to obtain the dTSEC hardware version. ++ */ ++uint32_t fman_dtsec_get_revision(struct dtsec_regs *regs); ++ ++/** ++ * fman_dtsec_set_mac_address() - Set MAC station address ++ * @regs: Pointer to dTSEC register block ++ * @macaddr: MAC address array ++ * ++ * This function sets MAC station address. To enable unicast reception call ++ * this after fman_dtsec_init(). While promiscuous mode is disabled dTSEC will ++ * match the destination address of received unicast frames against this ++ * address. ++ */ ++void fman_dtsec_set_mac_address(struct dtsec_regs *regs, uint8_t *macaddr); ++ ++/** ++ * fman_dtsec_get_mac_address() - Query MAC station address ++ * @regs: Pointer to dTSEC register block ++ * @macaddr: MAC address array ++ */ ++void fman_dtsec_get_mac_address(struct dtsec_regs *regs, uint8_t *macaddr); ++ ++/** ++ * fman_dtsec_set_uc_promisc() - Sets unicast promiscuous mode ++ * @regs: Pointer to dTSEC register block ++ * @enable: Enable unicast promiscuous mode ++ * ++ * Use this function to enable/disable dTSEC L2 address filtering. If the ++ * address filtering is disabled all unicast packets are accepted. ++ * To set dTSEC in promiscuous mode call both fman_dtsec_set_uc_promisc() and ++ * fman_dtsec_set_mc_promisc() to disable filtering for both unicast and ++ * multicast addresses. ++ */ ++void fman_dtsec_set_uc_promisc(struct dtsec_regs *regs, bool enable); ++ ++/** ++ * fman_dtsec_set_wol() - Enable/Disable wake on lan ++ * (magic packet support) ++ * @regs: Pointer to dTSEC register block ++ * @en: Enable Wake On Lan support in dTSEC ++ * ++ */ ++void fman_dtsec_set_wol(struct dtsec_regs *regs, bool en); ++ ++/** ++ * fman_dtsec_adjust_link() - Adjust dTSEC speed/duplex settings ++ * @regs: Pointer to dTSEC register block ++ * @iface_mode: dTSEC interface mode ++ * @speed: Link speed ++ * @full_dx: True for full-duplex, false for half-duplex. ++ * ++ * This function configures the MAC to function and the desired rates. Use it ++ * to configure dTSEC after fman_dtsec_init() and whenever the link speed ++ * changes (for instance following PHY auto-negociation). ++ * ++ * Returns: 0 if successful, an error code otherwise. ++ */ ++int fman_dtsec_adjust_link(struct dtsec_regs *regs, ++ enum enet_interface iface_mode, ++ enum enet_speed speed, bool full_dx); ++ ++/** ++ * fman_dtsec_set_tbi_phy_addr() - Updates TBI address field ++ * @regs: Pointer to dTSEC register block ++ * @address: Valid PHY address in the range of 1 to 31. 0 is reserved. ++ * ++ * In SGMII mode, the dTSEC's TBIPA field must contain a valid TBI PHY address ++ * so that the associated TBI PHY (i.e. the link) may be initialized. ++ * ++ * Returns: 0 if successful, an error code otherwise. ++ */ ++int fman_dtsec_set_tbi_phy_addr(struct dtsec_regs *regs, ++ uint8_t addr); ++ ++/** ++ * fman_dtsec_set_max_frame_len() - Set max frame length ++ * @regs: Pointer to dTSEC register block ++ * @length: Max frame length. ++ * ++ * Sets maximum frame length for received and transmitted frames. Frames that ++ * exceeds this length are truncated. ++ */ ++void fman_dtsec_set_max_frame_len(struct dtsec_regs *regs, uint16_t length); ++ ++/** ++ * fman_dtsec_get_max_frame_len() - Query max frame length ++ * @regs: Pointer to dTSEC register block ++ * ++ * Returns: the current value of the maximum frame length. ++ */ ++uint16_t fman_dtsec_get_max_frame_len(struct dtsec_regs *regs); ++ ++/** ++ * fman_dtsec_handle_rx_pause() - Configure pause frame handling ++ * @regs: Pointer to dTSEC register block ++ * @en: Enable pause frame handling in dTSEC ++ * ++ * If enabled, dTSEC will handle pause frames internally. This must be disabled ++ * if dTSEC is set in half-duplex mode. ++ * If pause frame handling is disabled and &dtsec_cfg.rx_ctrl_acc is set, pause ++ * frames will be transferred to the packet interface just like regular Ethernet ++ * frames. ++ */ ++void fman_dtsec_handle_rx_pause(struct dtsec_regs *regs, bool en); ++ ++/** ++ * fman_dtsec_set_tx_pause_frames() - Configure Tx pause time ++ * @regs: Pointer to dTSEC register block ++ * @time: Time value included in pause frames ++ * ++ * Call this function to set the time value used in transmitted pause frames. ++ * If time is 0, transmission of pause frames is disabled ++ */ ++void fman_dtsec_set_tx_pause_frames(struct dtsec_regs *regs, uint16_t time); ++ ++/** ++ * fman_dtsec_ack_event() - Acknowledge handled events ++ * @regs: Pointer to dTSEC register block ++ * @ev_mask: Events to acknowledge ++ * ++ * After handling events signaled by dTSEC in either polling or interrupt mode, ++ * call this function to reset the associated status bits in dTSEC event ++ * register. ++ */ ++void fman_dtsec_ack_event(struct dtsec_regs *regs, uint32_t ev_mask); ++ ++/** ++ * fman_dtsec_get_event() - Returns currently asserted events ++ * @regs: Pointer to dTSEC register block ++ * @ev_mask: Mask of relevant events ++ * ++ * Call this function to obtain a bit-mask of events that are currently asserted ++ * in dTSEC, taken from IEVENT register. ++ * ++ * Returns: a bit-mask of events asserted in dTSEC. ++ */ ++uint32_t fman_dtsec_get_event(struct dtsec_regs *regs, uint32_t ev_mask); ++ ++/** ++ * fman_dtsec_get_interrupt_mask() - Returns a bit-mask of enabled interrupts ++ * @regs: Pointer to dTSEC register block ++ * ++ * Call this function to obtain a bit-mask of enabled interrupts ++ * in dTSEC, taken from IMASK register. ++ * ++ * Returns: a bit-mask of enabled interrupts in dTSEC. ++ */ ++uint32_t fman_dtsec_get_interrupt_mask(struct dtsec_regs *regs); ++ ++void fman_dtsec_clear_addr_in_paddr(struct dtsec_regs *regs, ++ uint8_t paddr_num); ++ ++void fman_dtsec_add_addr_in_paddr(struct dtsec_regs *regs, ++ uint64_t addr, ++ uint8_t paddr_num); ++ ++void fman_dtsec_enable_tmr_interrupt (struct dtsec_regs *regs); ++ ++void fman_dtsec_disable_tmr_interrupt(struct dtsec_regs *regs); ++ ++/** ++ * fman_dtsec_disable_interrupt() - Disables interrupts for the specified events ++ * @regs: Pointer to dTSEC register block ++ * @ev_mask: Mask of relevant events ++ * ++ * Call this function to disable interrupts in dTSEC for the specified events. ++ * To enable interrupts use fman_dtsec_enable_interrupt(). ++ */ ++void fman_dtsec_disable_interrupt(struct dtsec_regs *regs, uint32_t ev_mask); ++ ++/** ++ * fman_dtsec_enable_interrupt() - Enable interrupts for the specified events ++ * @regs: Pointer to dTSEC register block ++ * @ev_mask: Mask of relevant events ++ * ++ * Call this function to enable interrupts in dTSEC for the specified events. ++ * To disable interrupts use fman_dtsec_disable_interrupt(). ++ */ ++void fman_dtsec_enable_interrupt(struct dtsec_regs *regs, uint32_t ev_mask); ++ ++/** ++ * fman_dtsec_set_ts() - Enables dTSEC timestamps ++ * @regs: Pointer to dTSEC register block ++ * @en: true to enable timestamps, false to disable them ++ * ++ * Call this function to enable/disable dTSEC timestamps. This affects both ++ * Tx and Rx. ++ */ ++void fman_dtsec_set_ts(struct dtsec_regs *regs, bool en); ++ ++/** ++ * fman_dtsec_set_bucket() - Enables/disables a filter bucket ++ * @regs: Pointer to dTSEC register block ++ * @bucket: Bucket index ++ * @enable: true/false to enable/disable this bucket ++ * ++ * This function enables or disables the specified bucket. Enabling a bucket ++ * associated with an address configures dTSEC to accept received packets ++ * with that destination address. ++ * Multiple addresses may be associated with the same bucket. Disabling a ++ * bucket will affect all addresses associated with that bucket. A bucket that ++ * is enabled requires further filtering and verification in the upper layers ++ * ++ */ ++void fman_dtsec_set_bucket(struct dtsec_regs *regs, int bucket, bool enable); ++ ++/** ++ * dtsec_set_hash_table() - insert a crc code into thr filter table ++ * @regs: Pointer to dTSEC register block ++ * @crc: crc to insert ++ * @mcast: true is this is a multicast address ++ * @ghtx: true if we are in ghtx mode ++ * ++ * This function inserts a crc code into the filter table. ++ */ ++void fman_dtsec_set_hash_table(struct dtsec_regs *regs, uint32_t crc, ++ bool mcast, bool ghtx); ++ ++/** ++ * fman_dtsec_reset_filter_table() - Resets the address filtering table ++ * @regs: Pointer to dTSEC register block ++ * @mcast: Reset multicast entries ++ * @ucast: Reset unicast entries ++ * ++ * Resets all entries in L2 address filter table. After calling this function ++ * all buckets enabled using fman_dtsec_set_bucket() will be disabled. ++ * If dtsec_init_filter_table() was called with @unicast_hash set to false, ++ * @ucast argument is ignored. ++ * This does not affect the primary nor the 15 additional addresses configured ++ * using dtsec_set_address() or dtsec_set_match_address(). ++ */ ++void fman_dtsec_reset_filter_table(struct dtsec_regs *regs, bool mcast, ++ bool ucast); ++ ++/** ++ * fman_dtsec_set_mc_promisc() - Set multicast promiscuous mode ++ * @regs: Pointer to dTSEC register block ++ * @enable: Enable multicast promiscuous mode ++ * ++ * Call this to enable/disable L2 address filtering for multicast packets. ++ */ ++void fman_dtsec_set_mc_promisc(struct dtsec_regs *regs, bool enable); ++ ++/* statistics APIs */ ++ ++/** ++ * fman_dtsec_set_stat_level() - Enable a group of MIB statistics counters ++ * @regs: Pointer to dTSEC register block ++ * @level: Specifies a certain group of dTSEC MIB HW counters or _all_, ++ * to specify all the existing counters. ++ * If set to _none_, it disables all the counters. ++ * ++ * Enables the MIB statistics hw counters and sets up the carry interrupt ++ * masks for the counters corresponding to the @level input parameter. ++ * ++ * Returns: error if invalid @level value given. ++ */ ++int fman_dtsec_set_stat_level(struct dtsec_regs *regs, ++ enum dtsec_stat_level level); ++ ++/** ++ * fman_dtsec_reset_stat() - Completely resets all dTSEC HW counters ++ * @regs: Pointer to dTSEC register block ++ */ ++void fman_dtsec_reset_stat(struct dtsec_regs *regs); ++ ++/** ++ * fman_dtsec_get_clear_carry_regs() - Read and clear carry bits (CAR1-2 registers) ++ * @regs: Pointer to dTSEC register block ++ * @car1: car1 register value ++ * @car2: car2 register value ++ * ++ * When set, the carry bits signal that an overflow occurred on the ++ * corresponding counters. ++ * Note that the carry bits (CAR1-2 registers) will assert the ++ * %DTSEC_IEVENT_MSRO interrupt if unmasked (via CAM1-2 regs). ++ * ++ * Returns: true if overflow occurred, otherwise - false ++ */ ++bool fman_dtsec_get_clear_carry_regs(struct dtsec_regs *regs, ++ uint32_t *car1, uint32_t *car2); ++ ++uint32_t fman_dtsec_check_and_clear_tmr_event(struct dtsec_regs *regs); ++ ++uint32_t fman_dtsec_get_stat_counter(struct dtsec_regs *regs, ++ enum dtsec_stat_counters reg_name); ++ ++void fman_dtsec_start_tx(struct dtsec_regs *regs); ++void fman_dtsec_start_rx(struct dtsec_regs *regs); ++void fman_dtsec_stop_tx(struct dtsec_regs *regs); ++void fman_dtsec_stop_rx(struct dtsec_regs *regs); ++uint32_t fman_dtsec_get_rctrl(struct dtsec_regs *regs); ++ ++ ++#endif /* __FSL_FMAN_DTSEC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_dtsec_mii_acc.h b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_dtsec_mii_acc.h +new file mode 100644 +index 0000000..0dda09c +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_dtsec_mii_acc.h +@@ -0,0 +1,107 @@ ++/* ++ * Copyright 2008-2013 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 __FSL_FMAN_DTSEC_MII_ACC_H ++#define __FSL_FMAN_DTSEC_MII_ACC_H ++ ++#include "common/general.h" ++ ++ ++/* MII Management Configuration Register */ ++#define MIIMCFG_RESET_MGMT 0x80000000 ++#define MIIMCFG_MGNTCLK_MASK 0x00000007 ++#define MIIMCFG_MGNTCLK_SHIFT 0 ++ ++/* MII Management Command Register */ ++#define MIIMCOM_SCAN_CYCLE 0x00000002 ++#define MIIMCOM_READ_CYCLE 0x00000001 ++ ++/* MII Management Address Register */ ++#define MIIMADD_PHY_ADDR_SHIFT 8 ++#define MIIMADD_PHY_ADDR_MASK 0x00001f00 ++ ++#define MIIMADD_REG_ADDR_SHIFT 0 ++#define MIIMADD_REG_ADDR_MASK 0x0000001f ++ ++/* MII Management Indicator Register */ ++#define MIIMIND_BUSY 0x00000001 ++ ++ ++/* PHY Control Register */ ++#define PHY_CR_PHY_RESET 0x8000 ++#define PHY_CR_LOOPBACK 0x4000 ++#define PHY_CR_SPEED0 0x2000 ++#define PHY_CR_ANE 0x1000 ++#define PHY_CR_RESET_AN 0x0200 ++#define PHY_CR_FULLDUPLEX 0x0100 ++#define PHY_CR_SPEED1 0x0040 ++ ++#define PHY_TBICON_SRESET 0x8000 ++#define PHY_TBICON_SPEED2 0x0020 ++#define PHY_TBICON_CLK_SEL 0x0020 ++#define PHY_TBIANA_SGMII 0x4001 ++#define PHY_TBIANA_1000X 0x01a0 ++/* register map */ ++ ++/* MII Configuration Control Memory Map Registers */ ++struct dtsec_mii_reg { ++ uint32_t reserved1[72]; ++ uint32_t miimcfg; /* MII Mgmt:configuration */ ++ uint32_t miimcom; /* MII Mgmt:command */ ++ uint32_t miimadd; /* MII Mgmt:address */ ++ uint32_t miimcon; /* MII Mgmt:control 3 */ ++ uint32_t miimstat; /* MII Mgmt:status */ ++ uint32_t miimind; /* MII Mgmt:indicators */ ++}; ++ ++/* dTSEC MII API */ ++ ++/* functions to access the mii registers for phy configuration. ++ * this functionality may not be available for all dtsecs in the system. ++ * consult the reference manual for details */ ++void fman_dtsec_mii_reset(struct dtsec_mii_reg *regs); ++/* frequency is in MHz. ++ * note that dtsec clock is 1/2 of fman clock */ ++void fman_dtsec_mii_init(struct dtsec_mii_reg *regs, uint16_t dtsec_freq); ++int fman_dtsec_mii_write_reg(struct dtsec_mii_reg *regs, ++ uint8_t addr, ++ uint8_t reg, ++ uint16_t data, ++ uint16_t dtsec_freq); ++ ++int fman_dtsec_mii_read_reg(struct dtsec_mii_reg *regs, ++ uint8_t addr, ++ uint8_t reg, ++ uint16_t *data, ++ uint16_t dtsec_freq); ++ ++#endif /* __FSL_FMAN_DTSEC_MII_ACC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_kg.h b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_kg.h +new file mode 100644 +index 0000000..010e4b7 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_kg.h +@@ -0,0 +1,514 @@ ++/* ++ * Copyright 2008-2012 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 __FSL_FMAN_KG_H ++#define __FSL_FMAN_KG_H ++ ++#include "common/general.h" ++ ++#define FM_KG_NUM_OF_GENERIC_REGS 8 /**< Num of generic KeyGen regs */ ++#define FMAN_MAX_NUM_OF_HW_PORTS 64 ++/**< Total num of masks allowed on KG extractions */ ++#define FM_KG_EXTRACT_MASKS_NUM 4 ++#define FM_KG_NUM_CLS_PLAN_ENTR 8 /**< Num of class. plan regs */ ++#define FM_KG_CLS_PLAN_GRPS_NUM 32 /**< Max num of class. groups */ ++ ++struct fman_kg_regs { ++ uint32_t fmkg_gcr; ++ uint32_t res004; ++ uint32_t res008; ++ uint32_t fmkg_eer; ++ uint32_t fmkg_eeer; ++ uint32_t res014; ++ uint32_t res018; ++ uint32_t fmkg_seer; ++ uint32_t fmkg_seeer; ++ uint32_t fmkg_gsr; ++ uint32_t fmkg_tpc; ++ uint32_t fmkg_serc; ++ uint32_t res030[4]; ++ uint32_t fmkg_fdor; ++ uint32_t fmkg_gdv0r; ++ uint32_t fmkg_gdv1r; ++ uint32_t res04c[6]; ++ uint32_t fmkg_feer; ++ uint32_t res068[38]; ++ uint32_t fmkg_indirect[63]; ++ uint32_t fmkg_ar; ++}; ++ ++struct fman_kg_scheme_regs { ++ uint32_t kgse_mode; /**< MODE */ ++ uint32_t kgse_ekfc; /**< Extract Known Fields Command */ ++ uint32_t kgse_ekdv; /**< Extract Known Default Value */ ++ uint32_t kgse_bmch; /**< Bit Mask Command High */ ++ uint32_t kgse_bmcl; /**< Bit Mask Command Low */ ++ uint32_t kgse_fqb; /**< Frame Queue Base */ ++ uint32_t kgse_hc; /**< Hash Command */ ++ uint32_t kgse_ppc; /**< Policer Profile Command */ ++ uint32_t kgse_gec[FM_KG_NUM_OF_GENERIC_REGS]; ++ /**< Generic Extract Command */ ++ uint32_t kgse_spc; /**< KeyGen Scheme Entry Statistic Packet Counter */ ++ uint32_t kgse_dv0; /**< KeyGen Scheme Entry Default Value 0 */ ++ uint32_t kgse_dv1; /**< KeyGen Scheme Entry Default Value 1 */ ++ uint32_t kgse_ccbs; /**< KeyGen Scheme Entry Coarse Classification Bit*/ ++ uint32_t kgse_mv; /**< KeyGen Scheme Entry Match vector */ ++ uint32_t kgse_om; /**< KeyGen Scheme Entry Operation Mode bits */ ++ uint32_t kgse_vsp; /**< KeyGen Scheme Entry Virtual Storage Profile */ ++}; ++ ++struct fman_kg_pe_regs{ ++ uint32_t fmkg_pe_sp; ++ uint32_t fmkg_pe_cpp; ++}; ++ ++struct fman_kg_cp_regs { ++ uint32_t kgcpe[FM_KG_NUM_CLS_PLAN_ENTR]; ++}; ++ ++ ++#define FM_KG_KGAR_GO 0x80000000 ++#define FM_KG_KGAR_READ 0x40000000 ++#define FM_KG_KGAR_WRITE 0x00000000 ++#define FM_KG_KGAR_SEL_SCHEME_ENTRY 0x00000000 ++#define FM_KG_KGAR_SCM_WSEL_UPDATE_CNT 0x00008000 ++ ++#define KG_SCH_PP_SHIFT_HIGH 0x80000000 ++#define KG_SCH_PP_NO_GEN 0x10000000 ++#define KG_SCH_PP_SHIFT_LOW 0x0000F000 ++#define KG_SCH_MODE_NIA_PLCR 0x40000000 ++#define KG_SCH_GEN_EXTRACT_TYPE 0x00008000 ++#define KG_SCH_BITMASK_MASK 0x000000FF ++#define KG_SCH_GEN_VALID 0x80000000 ++#define KG_SCH_GEN_MASK 0x00FF0000 ++#define FM_PCD_KG_KGAR_ERR 0x20000000 ++#define FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY 0x01000000 ++#define FM_PCD_KG_KGAR_SEL_PORT_ENTRY 0x02000000 ++#define FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP 0x00008000 ++#define FM_PCD_KG_KGAR_SEL_PORT_WSEL_CPP 0x00004000 ++#define FM_PCD_KG_KGAR_WSEL_MASK 0x0000FF00 ++#define KG_SCH_HASH_CONFIG_NO_FQID 0x80000000 ++#define KG_SCH_HASH_CONFIG_SYM 0x40000000 ++ ++#define FM_EX_KG_DOUBLE_ECC 0x80000000 ++#define FM_EX_KG_KEYSIZE_OVERFLOW 0x40000000 ++ ++/* ECC capture register */ ++#define KG_FMKG_SERC_CAP 0x80000000 ++#define KG_FMKG_SERC_CET 0x40000000 ++#define KG_FMKG_SERC_CNT_MSK 0x00FF0000 ++#define KG_FMKG_SERC_CNT_SHIFT 16 ++#define KG_FMKG_SERC_ADDR_MSK 0x000003FF ++ ++/* Masks */ ++#define FM_KG_KGGCR_EN 0x80000000 ++#define KG_SCH_GEN_VALID 0x80000000 ++#define KG_SCH_GEN_EXTRACT_TYPE 0x00008000 ++#define KG_ERR_TYPE_DOUBLE 0x40000000 ++#define KG_ERR_ADDR_MASK 0x00000FFF ++#define KG_SCH_MODE_EN 0x80000000 ++ ++/* shifts */ ++#define FM_KG_KGAR_NUM_SHIFT 16 ++#define FM_KG_PE_CPP_MASK_SHIFT 16 ++#define FM_KG_KGAR_WSEL_SHIFT 8 ++ ++#define FM_KG_SCH_GEN_HT_INVALID 0 ++ ++#define FM_KG_MASK_SEL_GEN_BASE 0x20 ++ ++#define KG_GET_MASK_SEL_SHIFT(shift, i) \ ++switch (i) \ ++{ \ ++ case 0: (shift) = 26; break; \ ++ case 1: (shift) = 20; break; \ ++ case 2: (shift) = 10; break; \ ++ case 3: (shift) = 4; break; \ ++ default: (shift) = 0; \ ++} ++ ++#define KG_GET_MASK_OFFSET_SHIFT(shift, i) \ ++switch (i) \ ++{ \ ++ case 0: (shift) = 16; break; \ ++ case 1: (shift) = 0; break; \ ++ case 2: (shift) = 28; break; \ ++ case 3: (shift) = 24; break; \ ++ default: (shift) = 0; \ ++} ++ ++#define KG_GET_MASK_SHIFT(shift, i) \ ++switch (i) \ ++{ \ ++ case 0: shift = 24; break; \ ++ case 1: shift = 16; break; \ ++ case 2: shift = 8; break; \ ++ case 3: shift = 0; break; \ ++ default: shift = 0; \ ++} ++ ++/* Port entry CPP register */ ++#define FMAN_KG_PE_CPP_MASK_SHIFT 16 ++ ++/* Scheme registers */ ++#define FMAN_KG_SCH_MODE_EN 0x80000000 ++#define FMAN_KG_SCH_MODE_NIA_PLCR 0x40000000 ++#define FMAN_KG_SCH_MODE_CCOBASE_SHIFT 24 ++ ++#define FMAN_KG_SCH_DEF_MAC_ADDR_SHIFT 30 ++#define FMAN_KG_SCH_DEF_VLAN_TCI_SHIFT 28 ++#define FMAN_KG_SCH_DEF_ETYPE_SHIFT 26 ++#define FMAN_KG_SCH_DEF_PPP_SID_SHIFT 24 ++#define FMAN_KG_SCH_DEF_PPP_PID_SHIFT 22 ++#define FMAN_KG_SCH_DEF_MPLS_SHIFT 20 ++#define FMAN_KG_SCH_DEF_IP_ADDR_SHIFT 18 ++#define FMAN_KG_SCH_DEF_PTYPE_SHIFT 16 ++#define FMAN_KG_SCH_DEF_IP_TOS_TC_SHIFT 14 ++#define FMAN_KG_SCH_DEF_IPv6_FL_SHIFT 12 ++#define FMAN_KG_SCH_DEF_IPSEC_SPI_SHIFT 10 ++#define FMAN_KG_SCH_DEF_L4_PORT_SHIFT 8 ++#define FMAN_KG_SCH_DEF_TCP_FLG_SHIFT 6 ++ ++#define FMAN_KG_SCH_GEN_VALID 0x80000000 ++#define FMAN_KG_SCH_GEN_SIZE_MAX 16 ++#define FMAN_KG_SCH_GEN_OR 0x00008000 ++ ++#define FMAN_KG_SCH_GEN_DEF_SHIFT 29 ++#define FMAN_KG_SCH_GEN_SIZE_SHIFT 24 ++#define FMAN_KG_SCH_GEN_MASK_SHIFT 16 ++#define FMAN_KG_SCH_GEN_HT_SHIFT 8 ++ ++#define FMAN_KG_SCH_HASH_HSHIFT_SHIFT 24 ++#define FMAN_KG_SCH_HASH_HSHIFT_MAX 0x28 ++#define FMAN_KG_SCH_HASH_SYM 0x40000000 ++#define FMAN_KG_SCH_HASH_NO_FQID_GEN 0x80000000 ++ ++#define FMAN_KG_SCH_PP_SH_SHIFT 27 ++#define FMAN_KG_SCH_PP_SL_SHIFT 12 ++#define FMAN_KG_SCH_PP_SH_MASK 0x80000000 ++#define FMAN_KG_SCH_PP_SL_MASK 0x0000F000 ++#define FMAN_KG_SCH_PP_SHIFT_MAX 0x17 ++#define FMAN_KG_SCH_PP_MASK_SHIFT 16 ++#define FMAN_KG_SCH_PP_NO_GEN 0x10000000 ++ ++enum fman_kg_gen_extract_src { ++ E_FMAN_KG_GEN_EXTRACT_ETH, ++ E_FMAN_KG_GEN_EXTRACT_ETYPE, ++ E_FMAN_KG_GEN_EXTRACT_SNAP, ++ E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_1, ++ E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_N, ++ E_FMAN_KG_GEN_EXTRACT_PPPoE, ++ E_FMAN_KG_GEN_EXTRACT_MPLS_1, ++ E_FMAN_KG_GEN_EXTRACT_MPLS_2, ++ E_FMAN_KG_GEN_EXTRACT_MPLS_3, ++ E_FMAN_KG_GEN_EXTRACT_MPLS_N, ++ E_FMAN_KG_GEN_EXTRACT_IPv4_1, ++ E_FMAN_KG_GEN_EXTRACT_IPv6_1, ++ E_FMAN_KG_GEN_EXTRACT_IPv4_2, ++ E_FMAN_KG_GEN_EXTRACT_IPv6_2, ++ E_FMAN_KG_GEN_EXTRACT_MINENCAP, ++ E_FMAN_KG_GEN_EXTRACT_IP_PID, ++ E_FMAN_KG_GEN_EXTRACT_GRE, ++ E_FMAN_KG_GEN_EXTRACT_TCP, ++ E_FMAN_KG_GEN_EXTRACT_UDP, ++ E_FMAN_KG_GEN_EXTRACT_SCTP, ++ E_FMAN_KG_GEN_EXTRACT_DCCP, ++ E_FMAN_KG_GEN_EXTRACT_IPSEC_AH, ++ E_FMAN_KG_GEN_EXTRACT_IPSEC_ESP, ++ E_FMAN_KG_GEN_EXTRACT_SHIM_1, ++ E_FMAN_KG_GEN_EXTRACT_SHIM_2, ++ E_FMAN_KG_GEN_EXTRACT_FROM_DFLT, ++ E_FMAN_KG_GEN_EXTRACT_FROM_FRAME_START, ++ E_FMAN_KG_GEN_EXTRACT_FROM_PARSE_RESULT, ++ E_FMAN_KG_GEN_EXTRACT_FROM_END_OF_PARSE, ++ E_FMAN_KG_GEN_EXTRACT_FROM_FQID ++}; ++ ++struct fman_kg_ex_ecc_attr ++{ ++ bool valid; ++ bool double_ecc; ++ uint16_t addr; ++ uint8_t single_ecc_count; ++}; ++ ++enum fman_kg_def_select ++{ ++ E_FMAN_KG_DEF_GLOBAL_0, ++ E_FMAN_KG_DEF_GLOBAL_1, ++ E_FMAN_KG_DEF_SCHEME_0, ++ E_FMAN_KG_DEF_SCHEME_1 ++}; ++ ++struct fman_kg_extract_def ++{ ++ enum fman_kg_def_select mac_addr; ++ enum fman_kg_def_select vlan_tci; ++ enum fman_kg_def_select etype; ++ enum fman_kg_def_select ppp_sid; ++ enum fman_kg_def_select ppp_pid; ++ enum fman_kg_def_select mpls; ++ enum fman_kg_def_select ip_addr; ++ enum fman_kg_def_select ptype; ++ enum fman_kg_def_select ip_tos_tc; ++ enum fman_kg_def_select ipv6_fl; ++ enum fman_kg_def_select ipsec_spi; ++ enum fman_kg_def_select l4_port; ++ enum fman_kg_def_select tcp_flg; ++}; ++ ++enum fman_kg_gen_extract_type ++{ ++ E_FMAN_KG_HASH_EXTRACT, ++ E_FMAN_KG_OR_EXTRACT ++}; ++ ++struct fman_kg_gen_extract_params ++{ ++ /* Hash or Or-ed extract */ ++ enum fman_kg_gen_extract_type type; ++ enum fman_kg_gen_extract_src src; ++ bool no_validation; ++ /* Extraction offset from the header location specified above */ ++ uint8_t offset; ++ /* Size of extraction for FMAN_KG_HASH_EXTRACT, ++ * hash result shift for FMAN_KG_OR_EXTRACT */ ++ uint8_t extract; ++ uint8_t mask; ++ /* Default value to use when header specified ++ * by fman_kg_gen_extract_src doesn't present */ ++ enum fman_kg_def_select def_val; ++}; ++ ++struct fman_kg_extract_mask ++{ ++ /**< Indication if mask is on known field extraction or ++ * on general extraction; TRUE for known field */ ++ bool is_known; ++ /**< One of FMAN_KG_EXTRACT_xxx defines for known fields mask and ++ * generic register index for generic extracts mask */ ++ uint32_t field_or_gen_idx; ++ /**< Byte offset from start of the extracted data specified ++ * by field_or_gen_idx */ ++ uint8_t offset; ++ /**< Byte mask (selected bits will be used) */ ++ uint8_t mask; ++}; ++ ++struct fman_kg_extract_params ++{ ++ /* Or-ed mask of FMAN_KG_EXTRACT_xxx defines */ ++ uint32_t known_fields; ++ struct fman_kg_extract_def known_fields_def; ++ /* Number of entries in gen_extract */ ++ uint8_t gen_extract_num; ++ struct fman_kg_gen_extract_params gen_extract[FM_KG_NUM_OF_GENERIC_REGS]; ++ /* Number of entries in masks */ ++ uint8_t masks_num; ++ struct fman_kg_extract_mask masks[FM_KG_EXTRACT_MASKS_NUM]; ++ uint32_t def_scheme_0; ++ uint32_t def_scheme_1; ++}; ++ ++struct fman_kg_hash_params ++{ ++ bool use_hash; ++ uint8_t shift_r; ++ uint32_t mask; /**< 24-bit mask */ ++ bool sym; /**< Symmetric hash for src and dest pairs */ ++}; ++ ++struct fman_kg_pp_params ++{ ++ uint8_t base; ++ uint8_t shift; ++ uint8_t mask; ++ bool bypass_pp_gen; ++}; ++ ++struct fman_kg_cc_params ++{ ++ uint8_t base_offset; ++ uint32_t qlcv_bits_sel; ++}; ++ ++enum fman_pcd_engine ++{ ++ E_FMAN_PCD_INVALID = 0, /**< Invalid PCD engine indicated*/ ++ E_FMAN_PCD_DONE, /**< No PCD Engine indicated */ ++ E_FMAN_PCD_KG, /**< Keygen indicated */ ++ E_FMAN_PCD_CC, /**< Coarse classification indicated */ ++ E_FMAN_PCD_PLCR, /**< Policer indicated */ ++ E_FMAN_PCD_PRS /**< Parser indicated */ ++}; ++ ++struct fman_kg_cls_plan_params ++{ ++ uint8_t entries_mask; ++ uint32_t mask_vector[FM_KG_NUM_CLS_PLAN_ENTR]; ++}; ++ ++struct fman_kg_scheme_params ++{ ++ uint32_t match_vector; ++ struct fman_kg_extract_params extract_params; ++ struct fman_kg_hash_params hash_params; ++ uint32_t base_fqid; ++ /* What we do w/features supported per FM version ?? */ ++ bool bypass_fqid_gen; ++ struct fman_kg_pp_params policer_params; ++ struct fman_kg_cc_params cc_params; ++ bool update_counter; ++ /**< counter_value: Set scheme counter to the specified value; ++ * relevant only when update_counter = TRUE. */ ++ uint32_t counter_value; ++ enum fman_pcd_engine next_engine; ++ /**< Next engine action code */ ++ uint32_t next_engine_action; ++}; ++ ++ ++ ++int fman_kg_write_ar_wait(struct fman_kg_regs *regs, uint32_t fmkg_ar); ++void fman_kg_write_sp(struct fman_kg_regs *regs, uint32_t sp, bool add); ++void fman_kg_write_cpp(struct fman_kg_regs *regs, uint32_t cpp); ++void fman_kg_get_event(struct fman_kg_regs *regs, ++ uint32_t *event, ++ uint32_t *scheme_idx); ++void fman_kg_init(struct fman_kg_regs *regs, ++ uint32_t exceptions, ++ uint32_t dflt_nia); ++void fman_kg_enable_scheme_interrupts(struct fman_kg_regs *regs); ++void fman_kg_enable(struct fman_kg_regs *regs); ++void fman_kg_disable(struct fman_kg_regs *regs); ++int fman_kg_write_bind_cls_plans(struct fman_kg_regs *regs, ++ uint8_t hwport_id, ++ uint32_t bind_cls_plans); ++int fman_kg_build_bind_cls_plans(uint8_t grp_base, ++ uint8_t grp_mask, ++ uint32_t *bind_cls_plans); ++int fman_kg_write_bind_schemes(struct fman_kg_regs *regs, ++ uint8_t hwport_id, ++ uint32_t schemes); ++int fman_kg_write_cls_plan(struct fman_kg_regs *regs, ++ uint8_t grp_id, ++ uint8_t entries_mask, ++ uint8_t hwport_id, ++ struct fman_kg_cp_regs *cls_plan_regs); ++int fman_kg_build_cls_plan(struct fman_kg_cls_plan_params *params, ++ struct fman_kg_cp_regs *cls_plan_regs); ++uint32_t fman_kg_get_schemes_total_counter(struct fman_kg_regs *regs); ++int fman_kg_set_scheme_counter(struct fman_kg_regs *regs, ++ uint8_t scheme_id, ++ uint8_t hwport_id, ++ uint32_t counter); ++int fman_kg_get_scheme_counter(struct fman_kg_regs *regs, ++ uint8_t scheme_id, ++ uint8_t hwport_id, ++ uint32_t *counter); ++int fman_kg_delete_scheme(struct fman_kg_regs *regs, ++ uint8_t scheme_id, ++ uint8_t hwport_id); ++int fman_kg_write_scheme(struct fman_kg_regs *regs, ++ uint8_t scheme_id, ++ uint8_t hwport_id, ++ struct fman_kg_scheme_regs *scheme_regs, ++ bool update_counter); ++int fman_kg_build_scheme(struct fman_kg_scheme_params *params, ++ struct fman_kg_scheme_regs *scheme_regs); ++void fman_kg_get_capture(struct fman_kg_regs *regs, ++ struct fman_kg_ex_ecc_attr *ecc_attr, ++ bool clear); ++void fman_kg_get_exception(struct fman_kg_regs *regs, ++ uint32_t *events, ++ uint32_t *scheme_ids, ++ bool clear); ++void fman_kg_set_exception(struct fman_kg_regs *regs, ++ uint32_t exception, ++ bool enable); ++void fman_kg_set_dflt_val(struct fman_kg_regs *regs, ++ uint8_t def_id, ++ uint32_t val); ++void fman_kg_set_data_after_prs(struct fman_kg_regs *regs, uint8_t offset); ++ ++ ++ ++/**************************************************************************//** ++ @Description NIA Description ++*//***************************************************************************/ ++#define KG_NIA_ORDER_RESTOR 0x00800000 ++#define KG_NIA_ENG_FM_CTL 0x00000000 ++#define KG_NIA_ENG_PRS 0x00440000 ++#define KG_NIA_ENG_KG 0x00480000 ++#define KG_NIA_ENG_PLCR 0x004C0000 ++#define KG_NIA_ENG_BMI 0x00500000 ++#define KG_NIA_ENG_QMI_ENQ 0x00540000 ++#define KG_NIA_ENG_QMI_DEQ 0x00580000 ++#define KG_NIA_ENG_MASK 0x007C0000 ++ ++#define KG_NIA_AC_MASK 0x0003FFFF ++ ++#define KG_NIA_INVALID 0xFFFFFFFF ++ ++static __inline__ uint32_t fm_kg_build_nia(enum fman_pcd_engine next_engine, ++ uint32_t next_engine_action) ++{ ++ uint32_t nia; ++ ++ if (next_engine_action & ~KG_NIA_AC_MASK) ++ return KG_NIA_INVALID; ++ ++ switch (next_engine) { ++ case E_FMAN_PCD_DONE: ++ nia = KG_NIA_ENG_BMI | next_engine_action; ++ break; ++ ++ case E_FMAN_PCD_KG: ++ nia = KG_NIA_ENG_KG | next_engine_action; ++ break; ++ ++ case E_FMAN_PCD_CC: ++ nia = KG_NIA_ENG_FM_CTL | next_engine_action; ++ break; ++ ++ case E_FMAN_PCD_PLCR: ++ nia = KG_NIA_ENG_PLCR | next_engine_action; ++ break; ++ ++ default: ++ nia = KG_NIA_INVALID; ++ } ++ ++ return nia; ++} ++ ++#endif /* __FSL_FMAN_KG_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_memac.h b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_memac.h +new file mode 100644 +index 0000000..0dd8286 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_memac.h +@@ -0,0 +1,427 @@ ++/* ++ * Copyright 2008-2012 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 __FSL_FMAN_MEMAC_H ++#define __FSL_FMAN_MEMAC_H ++ ++#include "common/general.h" ++#include "fsl_enet.h" ++ ++ ++#define MEMAC_NUM_OF_PADDRS 7 /* Num of additional exact match MAC adr regs */ ++ ++/* Control and Configuration Register (COMMAND_CONFIG) */ ++#define CMD_CFG_MG 0x80000000 /* 00 Magic Packet detection */ ++#define CMD_CFG_REG_LOWP_RXETY 0x01000000 /* 07 Rx low power indication */ ++#define CMD_CFG_TX_LOWP_ENA 0x00800000 /* 08 Tx Low Power Idle Enable */ ++#define CMD_CFG_SFD_ANY 0x00200000 /* 10 Disable SFD check */ ++#define CMD_CFG_PFC_MODE 0x00080000 /* 12 Enable PFC */ ++#define CMD_CFG_NO_LEN_CHK 0x00020000 /* 14 Payload length check disable */ ++#define CMD_CFG_SEND_IDLE 0x00010000 /* 15 Force idle generation */ ++#define CMD_CFG_CNT_FRM_EN 0x00002000 /* 18 Control frame rx enable */ ++#define CMD_CFG_SW_RESET 0x00001000 /* 19 S/W Reset, self clearing bit */ ++#define CMD_CFG_TX_PAD_EN 0x00000800 /* 20 Enable Tx padding of frames */ ++#define CMD_CFG_LOOPBACK_EN 0x00000400 /* 21 XGMII/GMII loopback enable */ ++#define CMD_CFG_TX_ADDR_INS 0x00000200 /* 22 Tx source MAC addr insertion */ ++#define CMD_CFG_PAUSE_IGNORE 0x00000100 /* 23 Ignore Pause frame quanta */ ++#define CMD_CFG_PAUSE_FWD 0x00000080 /* 24 Terminate/frwd Pause frames */ ++#define CMD_CFG_CRC_FWD 0x00000040 /* 25 Terminate/frwd CRC of frames */ ++#define CMD_CFG_PAD_EN 0x00000020 /* 26 Frame padding removal */ ++#define CMD_CFG_PROMIS_EN 0x00000010 /* 27 Promiscuous operation enable */ ++#define CMD_CFG_WAN_MODE 0x00000008 /* 28 WAN mode enable */ ++#define CMD_CFG_RX_EN 0x00000002 /* 30 MAC receive path enable */ ++#define CMD_CFG_TX_EN 0x00000001 /* 31 MAC transmit path enable */ ++ ++/* Transmit FIFO Sections Register (TX_FIFO_SECTIONS) */ ++#define TX_FIFO_SECTIONS_TX_EMPTY_MASK 0xFFFF0000 ++#define TX_FIFO_SECTIONS_TX_AVAIL_MASK 0x0000FFFF ++#define TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G 0x00400000 ++#define TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G 0x00100000 ++#define TX_FIFO_SECTIONS_TX_EMPTY_PFC_10G 0x00360000 ++#define TX_FIFO_SECTIONS_TX_EMPTY_PFC_1G 0x00040000 ++#define TX_FIFO_SECTIONS_TX_AVAIL_10G 0x00000019 ++#define TX_FIFO_SECTIONS_TX_AVAIL_1G 0x00000020 ++#define TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G 0x00000060 ++ ++#define GET_TX_EMPTY_DEFAULT_VALUE(_val) \ ++_val &= ~TX_FIFO_SECTIONS_TX_EMPTY_MASK; \ ++((_val == TX_FIFO_SECTIONS_TX_AVAIL_10G) ? \ ++ (_val |= TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G) : \ ++ (_val |= TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G)); ++ ++#define GET_TX_EMPTY_PFC_VALUE(_val) \ ++_val &= ~TX_FIFO_SECTIONS_TX_EMPTY_MASK; \ ++((_val == TX_FIFO_SECTIONS_TX_AVAIL_10G) ? \ ++ (_val |= TX_FIFO_SECTIONS_TX_EMPTY_PFC_10G) : \ ++ (_val |= TX_FIFO_SECTIONS_TX_EMPTY_PFC_1G)); ++ ++/* Interface Mode Register (IF_MODE) */ ++#define IF_MODE_MASK 0x00000003 /* 30-31 Mask on i/f mode bits */ ++#define IF_MODE_XGMII 0x00000000 /* 30-31 XGMII (10G) interface */ ++#define IF_MODE_GMII 0x00000002 /* 30-31 GMII (1G) interface */ ++#define IF_MODE_RGMII 0x00000004 ++#define IF_MODE_RGMII_AUTO 0x00008000 ++#define IF_MODE_RGMII_1000 0x00004000 /* 10 - 1000Mbps RGMII */ ++#define IF_MODE_RGMII_100 0x00000000 /* 00 - 100Mbps RGMII */ ++#define IF_MODE_RGMII_10 0x00002000 /* 01 - 10Mbps RGMII */ ++#define IF_MODE_RGMII_SP_MASK 0x00006000 /* Setsp mask bits */ ++#define IF_MODE_RGMII_FD 0x00001000 /* Full duplex RGMII */ ++#define IF_MODE_HD 0x00000040 /* Half duplex operation */ ++ ++/* Hash table Control Register (HASHTABLE_CTRL) */ ++#define HASH_CTRL_MCAST_SHIFT 26 ++#define HASH_CTRL_MCAST_EN 0x00000100 /* 23 Mcast frame rx for hash */ ++#define HASH_CTRL_ADDR_MASK 0x0000003F /* 26-31 Hash table address code */ ++ ++#define GROUP_ADDRESS 0x0000010000000000LL /* MAC mcast indication */ ++#define HASH_TABLE_SIZE 64 /* Hash tbl size */ ++ ++/* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */ ++#define MEMAC_TX_IPG_LENGTH_MASK 0x0000003F ++ ++/* Statistics Configuration Register (STATN_CONFIG) */ ++#define STATS_CFG_CLR 0x00000004 /* 29 Reset all counters */ ++#define STATS_CFG_CLR_ON_RD 0x00000002 /* 30 Clear on read */ ++#define STATS_CFG_SATURATE 0x00000001 /* 31 Saturate at the maximum val */ ++ ++/* Interrupt Mask Register (IMASK) */ ++#define MEMAC_IMASK_MGI 0x40000000 /* 1 Magic pkt detect indication */ ++#define MEMAC_IMASK_TSECC_ER 0x20000000 /* 2 Timestamp FIFO ECC error evnt */ ++#define MEMAC_IMASK_TECC_ER 0x02000000 /* 6 Transmit frame ECC error evnt */ ++#define MEMAC_IMASK_RECC_ER 0x01000000 /* 7 Receive frame ECC error evnt */ ++ ++#define MEMAC_ALL_ERRS_IMASK \ ++ ((uint32_t)(MEMAC_IMASK_TSECC_ER | \ ++ MEMAC_IMASK_TECC_ER | \ ++ MEMAC_IMASK_RECC_ER | \ ++ MEMAC_IMASK_MGI)) ++ ++#define MEMAC_IEVNT_PCS 0x80000000 /* PCS (XG). Link sync (G) */ ++#define MEMAC_IEVNT_AN 0x40000000 /* Auto-negotiation */ ++#define MEMAC_IEVNT_LT 0x20000000 /* Link Training/New page */ ++#define MEMAC_IEVNT_MGI 0x00004000 /* Magic pkt detection */ ++#define MEMAC_IEVNT_TS_ECC_ER 0x00002000 /* Timestamp FIFO ECC error */ ++#define MEMAC_IEVNT_RX_FIFO_OVFL 0x00001000 /* Rx FIFO overflow */ ++#define MEMAC_IEVNT_TX_FIFO_UNFL 0x00000800 /* Tx FIFO underflow */ ++#define MEMAC_IEVNT_TX_FIFO_OVFL 0x00000400 /* Tx FIFO overflow */ ++#define MEMAC_IEVNT_TX_ECC_ER 0x00000200 /* Tx frame ECC error */ ++#define MEMAC_IEVNT_RX_ECC_ER 0x00000100 /* Rx frame ECC error */ ++#define MEMAC_IEVNT_LI_FAULT 0x00000080 /* Link Interruption flt */ ++#define MEMAC_IEVNT_RX_EMPTY 0x00000040 /* Rx FIFO empty */ ++#define MEMAC_IEVNT_TX_EMPTY 0x00000020 /* Tx FIFO empty */ ++#define MEMAC_IEVNT_RX_LOWP 0x00000010 /* Low Power Idle */ ++#define MEMAC_IEVNT_PHY_LOS 0x00000004 /* Phy loss of signal */ ++#define MEMAC_IEVNT_REM_FAULT 0x00000002 /* Remote fault (XGMII) */ ++#define MEMAC_IEVNT_LOC_FAULT 0x00000001 /* Local fault (XGMII) */ ++ ++enum memac_counters { ++ E_MEMAC_COUNTER_R64, ++ E_MEMAC_COUNTER_R127, ++ E_MEMAC_COUNTER_R255, ++ E_MEMAC_COUNTER_R511, ++ E_MEMAC_COUNTER_R1023, ++ E_MEMAC_COUNTER_R1518, ++ E_MEMAC_COUNTER_R1519X, ++ E_MEMAC_COUNTER_RFRG, ++ E_MEMAC_COUNTER_RJBR, ++ E_MEMAC_COUNTER_RDRP, ++ E_MEMAC_COUNTER_RALN, ++ E_MEMAC_COUNTER_TUND, ++ E_MEMAC_COUNTER_ROVR, ++ E_MEMAC_COUNTER_RXPF, ++ E_MEMAC_COUNTER_TXPF, ++ E_MEMAC_COUNTER_ROCT, ++ E_MEMAC_COUNTER_RMCA, ++ E_MEMAC_COUNTER_RBCA, ++ E_MEMAC_COUNTER_RPKT, ++ E_MEMAC_COUNTER_RUCA, ++ E_MEMAC_COUNTER_RERR, ++ E_MEMAC_COUNTER_TOCT, ++ E_MEMAC_COUNTER_TMCA, ++ E_MEMAC_COUNTER_TBCA, ++ E_MEMAC_COUNTER_TUCA, ++ E_MEMAC_COUNTER_TERR ++}; ++ ++#define DEFAULT_PAUSE_QUANTA 0xf000 ++#define DEFAULT_FRAME_LENGTH 0x600 ++#define DEFAULT_TX_IPG_LENGTH 12 ++ ++/* ++ * memory map ++ */ ++ ++struct mac_addr { ++ uint32_t mac_addr_l; /* Lower 32 bits of 48-bit MAC address */ ++ uint32_t mac_addr_u; /* Upper 16 bits of 48-bit MAC address */ ++}; ++ ++struct memac_regs { ++ /* General Control and Status */ ++ uint32_t res0000[2]; ++ uint32_t command_config; /* 0x008 Ctrl and cfg */ ++ struct mac_addr mac_addr0; /* 0x00C-0x010 MAC_ADDR_0...1 */ ++ uint32_t maxfrm; /* 0x014 Max frame length */ ++ uint32_t res0018[1]; ++ uint32_t rx_fifo_sections; /* Receive FIFO configuration reg */ ++ uint32_t tx_fifo_sections; /* Transmit FIFO configuration reg */ ++ uint32_t res0024[2]; ++ uint32_t hashtable_ctrl; /* 0x02C Hash table control */ ++ uint32_t res0030[4]; ++ uint32_t ievent; /* 0x040 Interrupt event */ ++ uint32_t tx_ipg_length; /* 0x044 Transmitter inter-packet-gap */ ++ uint32_t res0048; ++ uint32_t imask; /* 0x04C Interrupt mask */ ++ uint32_t res0050; ++ uint32_t pause_quanta[4]; /* 0x054 Pause quanta */ ++ uint32_t pause_thresh[4]; /* 0x064 Pause quanta threshold */ ++ uint32_t rx_pause_status; /* 0x074 Receive pause status */ ++ uint32_t res0078[2]; ++ struct mac_addr mac_addr[MEMAC_NUM_OF_PADDRS]; /* 0x80-0x0B4 mac padr */ ++ uint32_t lpwake_timer; /* 0x0B8 Low Power Wakeup Timer */ ++ uint32_t sleep_timer; /* 0x0BC Transmit EEE Low Power Timer */ ++ uint32_t res00c0[8]; ++ uint32_t statn_config; /* 0x0E0 Statistics configuration */ ++ uint32_t res00e4[7]; ++ /* Rx Statistics Counter */ ++ uint32_t reoct_l; ++ uint32_t reoct_u; ++ uint32_t roct_l; ++ uint32_t roct_u; ++ uint32_t raln_l; ++ uint32_t raln_u; ++ uint32_t rxpf_l; ++ uint32_t rxpf_u; ++ uint32_t rfrm_l; ++ uint32_t rfrm_u; ++ uint32_t rfcs_l; ++ uint32_t rfcs_u; ++ uint32_t rvlan_l; ++ uint32_t rvlan_u; ++ uint32_t rerr_l; ++ uint32_t rerr_u; ++ uint32_t ruca_l; ++ uint32_t ruca_u; ++ uint32_t rmca_l; ++ uint32_t rmca_u; ++ uint32_t rbca_l; ++ uint32_t rbca_u; ++ uint32_t rdrp_l; ++ uint32_t rdrp_u; ++ uint32_t rpkt_l; ++ uint32_t rpkt_u; ++ uint32_t rund_l; ++ uint32_t rund_u; ++ uint32_t r64_l; ++ uint32_t r64_u; ++ uint32_t r127_l; ++ uint32_t r127_u; ++ uint32_t r255_l; ++ uint32_t r255_u; ++ uint32_t r511_l; ++ uint32_t r511_u; ++ uint32_t r1023_l; ++ uint32_t r1023_u; ++ uint32_t r1518_l; ++ uint32_t r1518_u; ++ uint32_t r1519x_l; ++ uint32_t r1519x_u; ++ uint32_t rovr_l; ++ uint32_t rovr_u; ++ uint32_t rjbr_l; ++ uint32_t rjbr_u; ++ uint32_t rfrg_l; ++ uint32_t rfrg_u; ++ uint32_t rcnp_l; ++ uint32_t rcnp_u; ++ uint32_t rdrntp_l; ++ uint32_t rdrntp_u; ++ uint32_t res01d0[12]; ++ /* Tx Statistics Counter */ ++ uint32_t teoct_l; ++ uint32_t teoct_u; ++ uint32_t toct_l; ++ uint32_t toct_u; ++ uint32_t res0210[2]; ++ uint32_t txpf_l; ++ uint32_t txpf_u; ++ uint32_t tfrm_l; ++ uint32_t tfrm_u; ++ uint32_t tfcs_l; ++ uint32_t tfcs_u; ++ uint32_t tvlan_l; ++ uint32_t tvlan_u; ++ uint32_t terr_l; ++ uint32_t terr_u; ++ uint32_t tuca_l; ++ uint32_t tuca_u; ++ uint32_t tmca_l; ++ uint32_t tmca_u; ++ uint32_t tbca_l; ++ uint32_t tbca_u; ++ uint32_t res0258[2]; ++ uint32_t tpkt_l; ++ uint32_t tpkt_u; ++ uint32_t tund_l; ++ uint32_t tund_u; ++ uint32_t t64_l; ++ uint32_t t64_u; ++ uint32_t t127_l; ++ uint32_t t127_u; ++ uint32_t t255_l; ++ uint32_t t255_u; ++ uint32_t t511_l; ++ uint32_t t511_u; ++ uint32_t t1023_l; ++ uint32_t t1023_u; ++ uint32_t t1518_l; ++ uint32_t t1518_u; ++ uint32_t t1519x_l; ++ uint32_t t1519x_u; ++ uint32_t res02a8[6]; ++ uint32_t tcnp_l; ++ uint32_t tcnp_u; ++ uint32_t res02c8[14]; ++ /* Line Interface Control */ ++ uint32_t if_mode; /* 0x300 Interface Mode Control */ ++ uint32_t if_status; /* 0x304 Interface Status */ ++ uint32_t res0308[14]; ++ /* HiGig/2 */ ++ uint32_t hg_config; /* 0x340 Control and cfg */ ++ uint32_t res0344[3]; ++ uint32_t hg_pause_quanta; /* 0x350 Pause quanta */ ++ uint32_t res0354[3]; ++ uint32_t hg_pause_thresh; /* 0x360 Pause quanta threshold */ ++ uint32_t res0364[3]; ++ uint32_t hgrx_pause_status; /* 0x370 Receive pause status */ ++ uint32_t hg_fifos_status; /* 0x374 fifos status */ ++ uint32_t rhm; /* 0x378 rx messages counter */ ++ uint32_t thm; /* 0x37C tx messages counter */ ++}; ++ ++struct memac_cfg { ++ bool reset_on_init; ++ bool rx_error_discard; ++ bool pause_ignore; ++ bool pause_forward_enable; ++ bool no_length_check_enable; ++ bool cmd_frame_enable; ++ bool send_idle_enable; ++ bool wan_mode_enable; ++ bool promiscuous_mode_enable; ++ bool tx_addr_ins_enable; ++ bool loopback_enable; ++ bool lgth_check_nostdr; ++ bool time_stamp_enable; ++ bool pad_enable; ++ bool phy_tx_ena_on; ++ bool rx_sfd_any; ++ bool rx_pbl_fwd; ++ bool tx_pbl_fwd; ++ bool debug_mode; ++ bool wake_on_lan; ++ uint16_t max_frame_length; ++ uint16_t pause_quanta; ++ uint32_t tx_ipg_length; ++}; ++ ++ ++/** ++ * fman_memac_defconfig() - Get default MEMAC configuration ++ * @cfg: pointer to configuration structure. ++ * ++ * Call this function to obtain a default set of configuration values for ++ * initializing MEMAC. The user can overwrite any of the values before calling ++ * fman_memac_init(), if specific configuration needs to be applied. ++ */ ++void fman_memac_defconfig(struct memac_cfg *cfg); ++ ++int fman_memac_init(struct memac_regs *regs, ++ struct memac_cfg *cfg, ++ enum enet_interface enet_interface, ++ enum enet_speed enet_speed, ++ bool slow_10g_if, ++ uint32_t exceptions); ++ ++void fman_memac_enable(struct memac_regs *regs, bool apply_rx, bool apply_tx); ++ ++void fman_memac_disable(struct memac_regs *regs, bool apply_rx, bool apply_tx); ++ ++void fman_memac_set_promiscuous(struct memac_regs *regs, bool val); ++ ++void fman_memac_add_addr_in_paddr(struct memac_regs *regs, ++ uint8_t *adr, ++ uint8_t paddr_num); ++ ++void fman_memac_clear_addr_in_paddr(struct memac_regs *regs, ++ uint8_t paddr_num); ++ ++uint64_t fman_memac_get_counter(struct memac_regs *regs, ++ enum memac_counters reg_name); ++ ++void fman_memac_set_tx_pause_frames(struct memac_regs *regs, ++ uint8_t priority, uint16_t pauseTime, uint16_t threshTime); ++ ++uint16_t fman_memac_get_max_frame_len(struct memac_regs *regs); ++ ++void fman_memac_set_exception(struct memac_regs *regs, uint32_t val, ++ bool enable); ++ ++void fman_memac_reset_stat(struct memac_regs *regs); ++ ++void fman_memac_reset(struct memac_regs *regs); ++ ++void fman_memac_reset_filter_table(struct memac_regs *regs); ++ ++void fman_memac_set_hash_table_entry(struct memac_regs *regs, uint32_t crc); ++ ++void fman_memac_set_hash_table(struct memac_regs *regs, uint32_t val); ++ ++void fman_memac_set_rx_ignore_pause_frames(struct memac_regs *regs, ++ bool enable); ++ ++void fman_memac_set_wol(struct memac_regs *regs, bool enable); ++ ++uint32_t fman_memac_get_event(struct memac_regs *regs, uint32_t ev_mask); ++ ++void fman_memac_ack_event(struct memac_regs *regs, uint32_t ev_mask); ++ ++uint32_t fman_memac_get_interrupt_mask(struct memac_regs *regs); ++ ++void fman_memac_adjust_link(struct memac_regs *regs, ++ enum enet_interface iface_mode, ++ enum enet_speed speed, bool full_dx); ++ ++ ++ ++#endif /*__FSL_FMAN_MEMAC_H*/ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_memac_mii_acc.h b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_memac_mii_acc.h +new file mode 100755 +index 0000000..b430445 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_memac_mii_acc.h +@@ -0,0 +1,78 @@ ++/* ++ * Copyright 2008-2013 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 __FSL_FMAN_MEMAC_MII_ACC_H ++#define __FSL_FMAN_MEMAC_MII_ACC_H ++ ++#include "common/general.h" ++#include "fsl_enet.h" ++/* MII Management Registers */ ++#define MDIO_CFG_CLK_DIV_MASK 0x0080ff80 ++#define MDIO_CFG_CLK_DIV_SHIFT 7 ++#define MDIO_CFG_HOLD_MASK 0x0000001c ++#define MDIO_CFG_ENC45 0x00000040 ++#define MDIO_CFG_READ_ERR 0x00000002 ++#define MDIO_CFG_BSY 0x00000001 ++ ++#define MDIO_CTL_PHY_ADDR_SHIFT 5 ++#define MDIO_CTL_READ 0x00008000 ++ ++#define MDIO_DATA_BSY 0x80000000 ++ ++/*MEMAC Internal PHY Registers - SGMII */ ++#define PHY_SGMII_CR_PHY_RESET 0x8000 ++#define PHY_SGMII_CR_RESET_AN 0x0200 ++#define PHY_SGMII_CR_DEF_VAL 0x1140 ++#define PHY_SGMII_DEV_ABILITY_SGMII 0x4001 ++#define PHY_SGMII_DEV_ABILITY_1000X 0x01A0 ++#define PHY_SGMII_IF_MODE_AN 0x0002 ++#define PHY_SGMII_IF_MODE_SGMII 0x0001 ++#define PHY_SGMII_IF_MODE_1000X 0x0000 ++ ++/*----------------------------------------------------*/ ++/* MII Configuration Control Memory Map Registers */ ++/*----------------------------------------------------*/ ++struct memac_mii_access_mem_map { ++ uint32_t mdio_cfg; /* 0x030 */ ++ uint32_t mdio_ctrl; /* 0x034 */ ++ uint32_t mdio_data; /* 0x038 */ ++ uint32_t mdio_addr; /* 0x03c */ ++}; ++ ++int fman_memac_mii_read_phy_reg(struct memac_mii_access_mem_map *mii_regs, ++ uint8_t phy_addr, uint8_t reg, uint16_t *data, ++ enum enet_speed enet_speed); ++int fman_memac_mii_write_phy_reg(struct memac_mii_access_mem_map *mii_regs, ++ uint8_t phy_addr, uint8_t reg, uint16_t data, ++ enum enet_speed enet_speed); ++ ++#endif /* __MAC_API_MEMAC_MII_ACC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_port.h b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_port.h +new file mode 100755 +index 0000000..080a23e +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_port.h +@@ -0,0 +1,593 @@ ++/* ++ * Copyright 2008-2013 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 __FSL_FMAN_PORT_H ++#define __FSL_FMAN_PORT_H ++ ++#include "fsl_fman_sp.h" ++ ++/** @Collection Registers bit fields */ ++ ++/** @Description BMI defines */ ++#define BMI_EBD_EN 0x80000000 ++ ++#define BMI_PORT_CFG_EN 0x80000000 ++#define BMI_PORT_CFG_FDOVR 0x02000000 ++#define BMI_PORT_CFG_IM 0x01000000 ++ ++#define BMI_PORT_STATUS_BSY 0x80000000 ++ ++#define BMI_DMA_ATTR_SWP_SHIFT FMAN_SP_DMA_ATTR_SWP_SHIFT ++#define BMI_DMA_ATTR_IC_STASH_ON 0x10000000 ++#define BMI_DMA_ATTR_HDR_STASH_ON 0x04000000 ++#define BMI_DMA_ATTR_SG_STASH_ON 0x01000000 ++#define BMI_DMA_ATTR_WRITE_OPTIMIZE FMAN_SP_DMA_ATTR_WRITE_OPTIMIZE ++ ++#define BMI_RX_FIFO_PRI_ELEVATION_SHIFT 16 ++#define BMI_RX_FIFO_THRESHOLD_ETHE 0x80000000 ++ ++#define BMI_TX_FRAME_END_CS_IGNORE_SHIFT 24 ++#define BMI_RX_FRAME_END_CS_IGNORE_SHIFT 24 ++#define BMI_RX_FRAME_END_CUT_SHIFT 16 ++ ++#define BMI_IC_TO_EXT_SHIFT FMAN_SP_IC_TO_EXT_SHIFT ++#define BMI_IC_FROM_INT_SHIFT FMAN_SP_IC_FROM_INT_SHIFT ++ ++#define BMI_INT_BUF_MARG_SHIFT 28 ++#define BMI_EXT_BUF_MARG_START_SHIFT FMAN_SP_EXT_BUF_MARG_START_SHIFT ++ ++#define BMI_CMD_MR_LEAC 0x00200000 ++#define BMI_CMD_MR_SLEAC 0x00100000 ++#define BMI_CMD_MR_MA 0x00080000 ++#define BMI_CMD_MR_DEAS 0x00040000 ++#define BMI_CMD_RX_MR_DEF (BMI_CMD_MR_LEAC | \ ++ BMI_CMD_MR_SLEAC | \ ++ BMI_CMD_MR_MA | \ ++ BMI_CMD_MR_DEAS) ++#define BMI_CMD_TX_MR_DEF 0 ++#define BMI_CMD_OP_MR_DEF (BMI_CMD_MR_DEAS | \ ++ BMI_CMD_MR_MA) ++ ++#define BMI_CMD_ATTR_ORDER 0x80000000 ++#define BMI_CMD_ATTR_SYNC 0x02000000 ++#define BMI_CMD_ATTR_COLOR_SHIFT 26 ++ ++#define BMI_FIFO_PIPELINE_DEPTH_SHIFT 12 ++#define BMI_NEXT_ENG_FD_BITS_SHIFT 24 ++#define BMI_FRAME_END_CS_IGNORE_SHIFT 24 ++ ++#define BMI_COUNTERS_EN 0x80000000 ++ ++#define BMI_EXT_BUF_POOL_VALID FMAN_SP_EXT_BUF_POOL_VALID ++#define BMI_EXT_BUF_POOL_EN_COUNTER FMAN_SP_EXT_BUF_POOL_EN_COUNTER ++#define BMI_EXT_BUF_POOL_BACKUP FMAN_SP_EXT_BUF_POOL_BACKUP ++#define BMI_EXT_BUF_POOL_ID_SHIFT 16 ++#define BMI_EXT_BUF_POOL_ID_MASK 0x003F0000 ++#define BMI_POOL_DEP_NUM_OF_POOLS_SHIFT 16 ++ ++#define BMI_TX_FIFO_MIN_FILL_SHIFT 16 ++#define BMI_TX_FIFO_PIPELINE_DEPTH_SHIFT 12 ++ ++#define MAX_PERFORMANCE_TASK_COMP 64 ++#define MAX_PERFORMANCE_RX_QUEUE_COMP 64 ++#define MAX_PERFORMANCE_TX_QUEUE_COMP 8 ++#define MAX_PERFORMANCE_DMA_COMP 16 ++#define MAX_PERFORMANCE_FIFO_COMP 1024 ++ ++#define BMI_PERFORMANCE_TASK_COMP_SHIFT 24 ++#define BMI_PERFORMANCE_QUEUE_COMP_SHIFT 16 ++#define BMI_PERFORMANCE_DMA_COMP_SHIFT 12 ++ ++#define BMI_RATE_LIMIT_GRAN_TX 16000 /* In Kbps */ ++#define BMI_RATE_LIMIT_GRAN_OP 10000 /* In frames */ ++#define BMI_RATE_LIMIT_MAX_RATE_IN_GRAN_UNITS 1024 ++#define BMI_RATE_LIMIT_MAX_BURST_SIZE 1024 /* In KBytes */ ++#define BMI_RATE_LIMIT_MAX_BURST_SHIFT 16 ++#define BMI_RATE_LIMIT_HIGH_BURST_SIZE_GRAN 0x80000000 ++#define BMI_RATE_LIMIT_SCALE_TSBS_SHIFT 16 ++#define BMI_RATE_LIMIT_SCALE_EN 0x80000000 ++#define BMI_SG_DISABLE FMAN_SP_SG_DISABLE ++ ++/** @Description QMI defines */ ++#define QMI_PORT_CFG_EN 0x80000000 ++#define QMI_PORT_CFG_EN_COUNTERS 0x10000000 ++ ++#define QMI_PORT_STATUS_DEQ_TNUM_BSY 0x80000000 ++#define QMI_PORT_STATUS_DEQ_FD_BSY 0x20000000 ++ ++#define QMI_DEQ_CFG_PRI 0x80000000 ++#define QMI_DEQ_CFG_TYPE1 0x10000000 ++#define QMI_DEQ_CFG_TYPE2 0x20000000 ++#define QMI_DEQ_CFG_TYPE3 0x30000000 ++#define QMI_DEQ_CFG_PREFETCH_PARTIAL 0x01000000 ++#define QMI_DEQ_CFG_PREFETCH_FULL 0x03000000 ++#define QMI_DEQ_CFG_SP_MASK 0xf ++#define QMI_DEQ_CFG_SP_SHIFT 20 ++ ++ ++/** @Description General port defines */ ++#define FMAN_PORT_EXT_POOLS_NUM(fm_rev_maj) \ ++ (((fm_rev_maj) == 4) ? 4 : 8) ++#define FMAN_PORT_MAX_EXT_POOLS_NUM 8 ++#define FMAN_PORT_OBS_EXT_POOLS_NUM 2 ++#define FMAN_PORT_CG_MAP_NUM 8 ++#define FMAN_PORT_PRS_RESULT_WORDS_NUM 8 ++#define FMAN_PORT_BMI_FIFO_UNITS 0x100 ++#define FMAN_PORT_IC_OFFSET_UNITS 0x10 ++ ++ ++/** @Collection FM Port Register Map */ ++ ++/** @Description BMI Rx port register map */ ++struct fman_port_rx_bmi_regs { ++ uint32_t fmbm_rcfg; /**< Rx Configuration */ ++ uint32_t fmbm_rst; /**< Rx Status */ ++ uint32_t fmbm_rda; /**< Rx DMA attributes*/ ++ uint32_t fmbm_rfp; /**< Rx FIFO Parameters*/ ++ uint32_t fmbm_rfed; /**< Rx Frame End Data*/ ++ uint32_t fmbm_ricp; /**< Rx Internal Context Parameters*/ ++ uint32_t fmbm_rim; /**< Rx Internal Buffer Margins*/ ++ uint32_t fmbm_rebm; /**< Rx External Buffer Margins*/ ++ uint32_t fmbm_rfne; /**< Rx Frame Next Engine*/ ++ uint32_t fmbm_rfca; /**< Rx Frame Command Attributes.*/ ++ uint32_t fmbm_rfpne; /**< Rx Frame Parser Next Engine*/ ++ uint32_t fmbm_rpso; /**< Rx Parse Start Offset*/ ++ uint32_t fmbm_rpp; /**< Rx Policer Profile */ ++ uint32_t fmbm_rccb; /**< Rx Coarse Classification Base */ ++ uint32_t fmbm_reth; /**< Rx Excessive Threshold */ ++ uint32_t reserved003c[1]; /**< (0x03C 0x03F) */ ++ uint32_t fmbm_rprai[FMAN_PORT_PRS_RESULT_WORDS_NUM]; ++ /**< Rx Parse Results Array Init*/ ++ uint32_t fmbm_rfqid; /**< Rx Frame Queue ID*/ ++ uint32_t fmbm_refqid; /**< Rx Error Frame Queue ID*/ ++ uint32_t fmbm_rfsdm; /**< Rx Frame Status Discard Mask*/ ++ uint32_t fmbm_rfsem; /**< Rx Frame Status Error Mask*/ ++ uint32_t fmbm_rfene; /**< Rx Frame Enqueue Next Engine */ ++ uint32_t reserved0074[0x2]; /**< (0x074-0x07C) */ ++ uint32_t fmbm_rcmne; /**< Rx Frame Continuous Mode Next Engine */ ++ uint32_t reserved0080[0x20];/**< (0x080 0x0FF) */ ++ uint32_t fmbm_ebmpi[FMAN_PORT_MAX_EXT_POOLS_NUM]; ++ /**< Buffer Manager pool Information-*/ ++ uint32_t fmbm_acnt[FMAN_PORT_MAX_EXT_POOLS_NUM]; ++ /**< Allocate Counter-*/ ++ uint32_t reserved0130[8]; ++ /**< 0x130/0x140 - 0x15F reserved -*/ ++ uint32_t fmbm_rcgm[FMAN_PORT_CG_MAP_NUM]; ++ /**< Congestion Group Map*/ ++ uint32_t fmbm_mpd; /**< BM Pool Depletion */ ++ uint32_t reserved0184[0x1F]; /**< (0x184 0x1FF) */ ++ uint32_t fmbm_rstc; /**< Rx Statistics Counters*/ ++ uint32_t fmbm_rfrc; /**< Rx Frame Counter*/ ++ uint32_t fmbm_rfbc; /**< Rx Bad Frames Counter*/ ++ uint32_t fmbm_rlfc; /**< Rx Large Frames Counter*/ ++ uint32_t fmbm_rffc; /**< Rx Filter Frames Counter*/ ++ uint32_t fmbm_rfdc; /**< Rx Frame Discard Counter*/ ++ uint32_t fmbm_rfldec; /**< Rx Frames List DMA Error Counter*/ ++ uint32_t fmbm_rodc; /**< Rx Out of Buffers Discard nntr*/ ++ uint32_t fmbm_rbdc; /**< Rx Buffers Deallocate Counter*/ ++ uint32_t reserved0224[0x17]; /**< (0x224 0x27F) */ ++ uint32_t fmbm_rpc; /**< Rx Performance Counters*/ ++ uint32_t fmbm_rpcp; /**< Rx Performance Count Parameters*/ ++ uint32_t fmbm_rccn; /**< Rx Cycle Counter*/ ++ uint32_t fmbm_rtuc; /**< Rx Tasks Utilization Counter*/ ++ uint32_t fmbm_rrquc; /**< Rx Receive Queue Utilization cntr*/ ++ uint32_t fmbm_rduc; /**< Rx DMA Utilization Counter*/ ++ uint32_t fmbm_rfuc; /**< Rx FIFO Utilization Counter*/ ++ uint32_t fmbm_rpac; /**< Rx Pause Activation Counter*/ ++ uint32_t reserved02a0[0x18]; /**< (0x2A0 0x2FF) */ ++ uint32_t fmbm_rdbg; /**< Rx Debug-*/ ++}; ++ ++/** @Description BMI Tx port register map */ ++struct fman_port_tx_bmi_regs { ++ uint32_t fmbm_tcfg; /**< Tx Configuration */ ++ uint32_t fmbm_tst; /**< Tx Status */ ++ uint32_t fmbm_tda; /**< Tx DMA attributes */ ++ uint32_t fmbm_tfp; /**< Tx FIFO Parameters */ ++ uint32_t fmbm_tfed; /**< Tx Frame End Data */ ++ uint32_t fmbm_ticp; /**< Tx Internal Context Parameters */ ++ uint32_t fmbm_tfdne; /**< Tx Frame Dequeue Next Engine. */ ++ uint32_t fmbm_tfca; /**< Tx Frame Command attribute. */ ++ uint32_t fmbm_tcfqid; /**< Tx Confirmation Frame Queue ID. */ ++ uint32_t fmbm_tefqid; /**< Tx Frame Error Queue ID */ ++ uint32_t fmbm_tfene; /**< Tx Frame Enqueue Next Engine */ ++ uint32_t fmbm_trlmts; /**< Tx Rate Limiter Scale */ ++ uint32_t fmbm_trlmt; /**< Tx Rate Limiter */ ++ uint32_t reserved0034[0x0e]; /**< (0x034-0x6c) */ ++ uint32_t fmbm_tccb; /**< Tx Coarse Classification base */ ++ uint32_t fmbm_tfne; /**< Tx Frame Next Engine */ ++ uint32_t fmbm_tpfcm[0x02]; /**< Tx Priority based Flow Control (PFC) Mapping */ ++ uint32_t fmbm_tcmne; /**< Tx Frame Continuous Mode Next Engine */ ++ uint32_t reserved0080[0x60]; /**< (0x080-0x200) */ ++ uint32_t fmbm_tstc; /**< Tx Statistics Counters */ ++ uint32_t fmbm_tfrc; /**< Tx Frame Counter */ ++ uint32_t fmbm_tfdc; /**< Tx Frames Discard Counter */ ++ uint32_t fmbm_tfledc; /**< Tx Frame len error discard cntr */ ++ uint32_t fmbm_tfufdc; /**< Tx Frame unsprt frmt discard cntr*/ ++ uint32_t fmbm_tbdc; /**< Tx Buffers Deallocate Counter */ ++ uint32_t reserved0218[0x1A]; /**< (0x218-0x280) */ ++ uint32_t fmbm_tpc; /**< Tx Performance Counters*/ ++ uint32_t fmbm_tpcp; /**< Tx Performance Count Parameters*/ ++ uint32_t fmbm_tccn; /**< Tx Cycle Counter*/ ++ uint32_t fmbm_ttuc; /**< Tx Tasks Utilization Counter*/ ++ uint32_t fmbm_ttcquc; /**< Tx Transmit conf Q util Counter*/ ++ uint32_t fmbm_tduc; /**< Tx DMA Utilization Counter*/ ++ uint32_t fmbm_tfuc; /**< Tx FIFO Utilization Counter*/ ++}; ++ ++/** @Description BMI O/H port register map */ ++struct fman_port_oh_bmi_regs { ++ uint32_t fmbm_ocfg; /**< O/H Configuration */ ++ uint32_t fmbm_ost; /**< O/H Status */ ++ uint32_t fmbm_oda; /**< O/H DMA attributes */ ++ uint32_t fmbm_oicp; /**< O/H Internal Context Parameters */ ++ uint32_t fmbm_ofdne; /**< O/H Frame Dequeue Next Engine */ ++ uint32_t fmbm_ofne; /**< O/H Frame Next Engine */ ++ uint32_t fmbm_ofca; /**< O/H Frame Command Attributes. */ ++ uint32_t fmbm_ofpne; /**< O/H Frame Parser Next Engine */ ++ uint32_t fmbm_opso; /**< O/H Parse Start Offset */ ++ uint32_t fmbm_opp; /**< O/H Policer Profile */ ++ uint32_t fmbm_occb; /**< O/H Coarse Classification base */ ++ uint32_t fmbm_oim; /**< O/H Internal margins*/ ++ uint32_t fmbm_ofp; /**< O/H Fifo Parameters*/ ++ uint32_t fmbm_ofed; /**< O/H Frame End Data*/ ++ uint32_t reserved0030[2]; /**< (0x038 - 0x03F) */ ++ uint32_t fmbm_oprai[FMAN_PORT_PRS_RESULT_WORDS_NUM]; ++ /**< O/H Parse Results Array Initialization */ ++ uint32_t fmbm_ofqid; /**< O/H Frame Queue ID */ ++ uint32_t fmbm_oefqid; /**< O/H Error Frame Queue ID */ ++ uint32_t fmbm_ofsdm; /**< O/H Frame Status Discard Mask */ ++ uint32_t fmbm_ofsem; /**< O/H Frame Status Error Mask */ ++ uint32_t fmbm_ofene; /**< O/H Frame Enqueue Next Engine */ ++ uint32_t fmbm_orlmts; /**< O/H Rate Limiter Scale */ ++ uint32_t fmbm_orlmt; /**< O/H Rate Limiter */ ++ uint32_t fmbm_ocmne; /**< O/H Continuous Mode Next Engine */ ++ uint32_t reserved0080[0x20]; /**< 0x080 - 0x0FF Reserved */ ++ uint32_t fmbm_oebmpi[2]; /**< Buf Mngr Observed Pool Info */ ++ uint32_t reserved0108[0x16]; /**< 0x108 - 0x15F Reserved */ ++ uint32_t fmbm_ocgm[FMAN_PORT_CG_MAP_NUM]; /**< Observed Congestion Group Map */ ++ uint32_t fmbm_ompd; /**< Observed BMan Pool Depletion */ ++ uint32_t reserved0184[0x1F]; /**< 0x184 - 0x1FF Reserved */ ++ uint32_t fmbm_ostc; /**< O/H Statistics Counters */ ++ uint32_t fmbm_ofrc; /**< O/H Frame Counter */ ++ uint32_t fmbm_ofdc; /**< O/H Frames Discard Counter */ ++ uint32_t fmbm_ofledc; /**< O/H Frames Len Err Discard Cntr */ ++ uint32_t fmbm_ofufdc; /**< O/H Frames Unsprtd Discard Cutr */ ++ uint32_t fmbm_offc; /**< O/H Filter Frames Counter */ ++ uint32_t fmbm_ofwdc; /**< Rx Frames WRED Discard Counter */ ++ uint32_t fmbm_ofldec; /**< O/H Frames List DMA Error Cntr */ ++ uint32_t fmbm_obdc; /**< O/H Buffers Deallocate Counter */ ++ uint32_t reserved0218[0x17]; /**< (0x218 - 0x27F) */ ++ uint32_t fmbm_opc; /**< O/H Performance Counters */ ++ uint32_t fmbm_opcp; /**< O/H Performance Count Parameters */ ++ uint32_t fmbm_occn; /**< O/H Cycle Counter */ ++ uint32_t fmbm_otuc; /**< O/H Tasks Utilization Counter */ ++ uint32_t fmbm_oduc; /**< O/H DMA Utilization Counter */ ++ uint32_t fmbm_ofuc; /**< O/H FIFO Utilization Counter */ ++}; ++ ++/** @Description BMI port register map */ ++union fman_port_bmi_regs { ++ struct fman_port_rx_bmi_regs rx; ++ struct fman_port_tx_bmi_regs tx; ++ struct fman_port_oh_bmi_regs oh; ++}; ++ ++/** @Description QMI port register map */ ++struct fman_port_qmi_regs { ++ uint32_t fmqm_pnc; /**< PortID n Configuration Register */ ++ uint32_t fmqm_pns; /**< PortID n Status Register */ ++ uint32_t fmqm_pnts; /**< PortID n Task Status Register */ ++ uint32_t reserved00c[4]; /**< 0xn00C - 0xn01B */ ++ uint32_t fmqm_pnen; /**< PortID n Enqueue NIA Register */ ++ uint32_t fmqm_pnetfc; /**< PortID n Enq Total Frame Counter */ ++ uint32_t reserved024[2]; /**< 0xn024 - 0x02B */ ++ uint32_t fmqm_pndn; /**< PortID n Dequeue NIA Register */ ++ uint32_t fmqm_pndc; /**< PortID n Dequeue Config Register */ ++ uint32_t fmqm_pndtfc; /**< PortID n Dequeue tot Frame cntr */ ++ uint32_t fmqm_pndfdc; /**< PortID n Dequeue FQID Dflt Cntr */ ++ uint32_t fmqm_pndcc; /**< PortID n Dequeue Confirm Counter */ ++}; ++ ++ ++enum fman_port_dma_swap { ++ E_FMAN_PORT_DMA_NO_SWAP, /**< No swap, transfer data as is */ ++ E_FMAN_PORT_DMA_SWAP_LE, ++ /**< The transferred data should be swapped in PPC Little Endian mode */ ++ E_FMAN_PORT_DMA_SWAP_BE ++ /**< The transferred data should be swapped in Big Endian mode */ ++}; ++ ++/* Default port color */ ++enum fman_port_color { ++ E_FMAN_PORT_COLOR_GREEN, /**< Default port color is green */ ++ E_FMAN_PORT_COLOR_YELLOW, /**< Default port color is yellow */ ++ E_FMAN_PORT_COLOR_RED, /**< Default port color is red */ ++ E_FMAN_PORT_COLOR_OVERRIDE /**< Ignore color */ ++}; ++ ++/* QMI dequeue from the SP channel - types */ ++enum fman_port_deq_type { ++ E_FMAN_PORT_DEQ_BY_PRI, ++ /**< Priority precedence and Intra-Class scheduling */ ++ E_FMAN_PORT_DEQ_ACTIVE_FQ, ++ /**< Active FQ precedence and Intra-Class scheduling */ ++ E_FMAN_PORT_DEQ_ACTIVE_FQ_NO_ICS ++ /**< Active FQ precedence and override Intra-Class scheduling */ ++}; ++ ++/* QMI dequeue prefetch modes */ ++enum fman_port_deq_prefetch { ++ E_FMAN_PORT_DEQ_NO_PREFETCH, /**< No prefetch mode */ ++ E_FMAN_PORT_DEQ_PART_PREFETCH, /**< Partial prefetch mode */ ++ E_FMAN_PORT_DEQ_FULL_PREFETCH /**< Full prefetch mode */ ++}; ++ ++/* Parameters for defining performance counters behavior */ ++struct fman_port_perf_cnt_params { ++ uint8_t task_val; /**< Task compare value */ ++ uint8_t queue_val; ++ /**< Rx or Tx conf queue compare value (unused for O/H ports) */ ++ uint8_t dma_val; /**< Dma compare value */ ++ uint32_t fifo_val; /**< Fifo compare value (in bytes) */ ++}; ++ ++/** @Description FM Port configuration structure, used at init */ ++struct fman_port_cfg { ++ struct fman_port_perf_cnt_params perf_cnt_params; ++ /* BMI parameters */ ++ enum fman_port_dma_swap dma_swap_data; ++ bool dma_ic_stash_on; ++ bool dma_header_stash_on; ++ bool dma_sg_stash_on; ++ bool dma_write_optimize; ++ uint16_t ic_ext_offset; ++ uint8_t ic_int_offset; ++ uint16_t ic_size; ++ enum fman_port_color color; ++ bool sync_req; ++ bool discard_override; ++ uint8_t checksum_bytes_ignore; ++ uint8_t rx_cut_end_bytes; ++ uint32_t rx_pri_elevation; ++ uint32_t rx_fifo_thr; ++ uint8_t rx_fd_bits; ++ uint8_t int_buf_start_margin; ++ uint16_t ext_buf_start_margin; ++ uint16_t ext_buf_end_margin; ++ uint32_t tx_fifo_min_level; ++ uint32_t tx_fifo_low_comf_level; ++ uint8_t tx_fifo_deq_pipeline_depth; ++ bool stats_counters_enable; ++ bool perf_counters_enable; ++ /* QMI parameters */ ++ bool deq_high_pri; ++ enum fman_port_deq_type deq_type; ++ enum fman_port_deq_prefetch deq_prefetch_opt; ++ uint16_t deq_byte_cnt; ++ bool queue_counters_enable; ++ bool no_scatter_gather; ++ int errata_A006675; ++ int errata_A006320; ++ int excessive_threshold_register; ++ int fmbm_rebm_has_sgd; ++ int fmbm_tfne_has_features; ++ int qmi_deq_options_support; ++}; ++ ++enum fman_port_type { ++ E_FMAN_PORT_TYPE_OP = 0, ++ /**< Offline parsing port, shares id-s with ++ * host command, so must have exclusive id-s */ ++ E_FMAN_PORT_TYPE_RX, /**< 1G Rx port */ ++ E_FMAN_PORT_TYPE_RX_10G, /**< 10G Rx port */ ++ E_FMAN_PORT_TYPE_TX, /**< 1G Tx port */ ++ E_FMAN_PORT_TYPE_TX_10G, /**< 10G Tx port */ ++ E_FMAN_PORT_TYPE_DUMMY, ++ E_FMAN_PORT_TYPE_HC = E_FMAN_PORT_TYPE_DUMMY ++ /**< Host command port, shares id-s with ++ * offline parsing ports, so must have exclusive id-s */ ++}; ++ ++struct fman_port_params { ++ uint32_t discard_mask; ++ uint32_t err_mask; ++ uint32_t dflt_fqid; ++ uint32_t err_fqid; ++ uint8_t deq_sp; ++ bool dont_release_buf; ++}; ++ ++/* Port context - used by most API functions */ ++struct fman_port { ++ enum fman_port_type type; ++ uint8_t fm_rev_maj; ++ uint8_t fm_rev_min; ++ union fman_port_bmi_regs *bmi_regs; ++ struct fman_port_qmi_regs *qmi_regs; ++ bool im_en; ++ uint8_t ext_pools_num; ++}; ++ ++/** @Description External buffer pools configuration */ ++struct fman_port_bpools { ++ uint8_t count; /**< Num of pools to set up */ ++ bool counters_enable; /**< Enable allocate counters */ ++ uint8_t grp_bp_depleted_num; ++ /**< Number of depleted pools - if reached the BMI indicates ++ * the MAC to send a pause frame */ ++ struct { ++ uint8_t bpid; /**< BM pool ID */ ++ uint16_t size; ++ /**< Pool's size - must be in ascending order */ ++ bool is_backup; ++ /**< If this is a backup pool */ ++ bool grp_bp_depleted; ++ /**< Consider this buffer in multiple pools depletion criteria*/ ++ bool single_bp_depleted; ++ /**< Consider this buffer in single pool depletion criteria */ ++ bool pfc_priorities_en; ++ } bpool[FMAN_PORT_MAX_EXT_POOLS_NUM]; ++}; ++ ++enum fman_port_rate_limiter_scale_down { ++ E_FMAN_PORT_RATE_DOWN_NONE, ++ E_FMAN_PORT_RATE_DOWN_BY_2, ++ E_FMAN_PORT_RATE_DOWN_BY_4, ++ E_FMAN_PORT_RATE_DOWN_BY_8 ++}; ++ ++/* Rate limiter configuration */ ++struct fman_port_rate_limiter { ++ uint8_t count_1micro_bit; ++ bool high_burst_size_gran; ++ /**< Defines burst_size granularity for OP ports; when TRUE, ++ * burst_size below counts in frames, otherwise in 10^3 frames */ ++ uint16_t burst_size; ++ /**< Max burst size, in KBytes for Tx port, according to ++ * high_burst_size_gran definition for OP port */ ++ uint32_t rate; ++ /**< In Kbps for Tx port, in frames/sec for OP port */ ++ enum fman_port_rate_limiter_scale_down rate_factor; ++}; ++ ++/* BMI statistics counters */ ++enum fman_port_stats_counters { ++ E_FMAN_PORT_STATS_CNT_FRAME, ++ /**< Number of processed frames; valid for all ports */ ++ E_FMAN_PORT_STATS_CNT_DISCARD, ++ /**< For Rx ports - frames discarded by QMAN, for Tx or O/H ports - ++ * frames discarded due to DMA error; valid for all ports */ ++ E_FMAN_PORT_STATS_CNT_DEALLOC_BUF, ++ /**< Number of buffer deallocate operations; valid for all ports */ ++ E_FMAN_PORT_STATS_CNT_RX_BAD_FRAME, ++ /**< Number of bad Rx frames, like CRC error, Rx FIFO overflow etc; ++ * valid for Rx ports only */ ++ E_FMAN_PORT_STATS_CNT_RX_LARGE_FRAME, ++ /**< Number of Rx oversized frames, that is frames exceeding max frame ++ * size configured for the corresponding ETH controller; ++ * valid for Rx ports only */ ++ E_FMAN_PORT_STATS_CNT_RX_OUT_OF_BUF, ++ /**< Frames discarded due to lack of external buffers; valid for ++ * Rx ports only */ ++ E_FMAN_PORT_STATS_CNT_LEN_ERR, ++ /**< Frames discarded due to frame length error; valid for Tx and ++ * O/H ports only */ ++ E_FMAN_PORT_STATS_CNT_UNSUPPORTED_FORMAT, ++ /**< Frames discarded due to unsupported FD format; valid for Tx ++ * and O/H ports only */ ++ E_FMAN_PORT_STATS_CNT_FILTERED_FRAME, ++ /**< Number of frames filtered out by PCD module; valid for ++ * Rx and OP ports only */ ++ E_FMAN_PORT_STATS_CNT_DMA_ERR, ++ /**< Frames rejected by QMAN that were not able to release their ++ * buffers due to DMA error; valid for Rx and O/H ports only */ ++ E_FMAN_PORT_STATS_CNT_WRED_DISCARD ++ /**< Frames going through O/H port that were not able to to enter the ++ * return queue due to WRED algorithm; valid for O/H ports only */ ++}; ++ ++/* BMI performance counters */ ++enum fman_port_perf_counters { ++ E_FMAN_PORT_PERF_CNT_CYCLE, /**< Cycle counter */ ++ E_FMAN_PORT_PERF_CNT_TASK_UTIL, /**< Tasks utilization counter */ ++ E_FMAN_PORT_PERF_CNT_QUEUE_UTIL, ++ /**< For Rx ports - Rx queue utilization, for Tx ports - Tx conf queue ++ * utilization; not valid for O/H ports */ ++ E_FMAN_PORT_PERF_CNT_DMA_UTIL, /**< DMA utilization counter */ ++ E_FMAN_PORT_PERF_CNT_FIFO_UTIL, /**< FIFO utilization counter */ ++ E_FMAN_PORT_PERF_CNT_RX_PAUSE ++ /**< Number of cycles in which Rx pause activation control is on; ++ * valid for Rx ports only */ ++}; ++ ++/* QMI counters */ ++enum fman_port_qmi_counters { ++ E_FMAN_PORT_ENQ_TOTAL, /**< EnQ tot frame cntr */ ++ E_FMAN_PORT_DEQ_TOTAL, /**< DeQ tot frame cntr; invalid for Rx ports */ ++ E_FMAN_PORT_DEQ_FROM_DFLT, ++ /**< Dequeue from default FQID counter not valid for Rx ports */ ++ E_FMAN_PORT_DEQ_CONFIRM /**< DeQ confirm cntr invalid for Rx ports */ ++}; ++ ++ ++/** @Collection FM Port API */ ++void fman_port_defconfig(struct fman_port_cfg *cfg, enum fman_port_type type); ++int fman_port_init(struct fman_port *port, ++ struct fman_port_cfg *cfg, ++ struct fman_port_params *params); ++int fman_port_enable(struct fman_port *port); ++int fman_port_disable(const struct fman_port *port); ++int fman_port_set_bpools(const struct fman_port *port, ++ const struct fman_port_bpools *bp); ++int fman_port_set_rate_limiter(struct fman_port *port, ++ struct fman_port_rate_limiter *rate_limiter); ++int fman_port_delete_rate_limiter(struct fman_port *port); ++int fman_port_set_err_mask(struct fman_port *port, uint32_t err_mask); ++int fman_port_set_discard_mask(struct fman_port *port, uint32_t discard_mask); ++int fman_port_modify_rx_fd_bits(struct fman_port *port, ++ uint8_t rx_fd_bits, ++ bool add); ++int fman_port_set_perf_cnt_params(struct fman_port *port, ++ struct fman_port_perf_cnt_params *params); ++int fman_port_set_stats_cnt_mode(struct fman_port *port, bool enable); ++int fman_port_set_perf_cnt_mode(struct fman_port *port, bool enable); ++int fman_port_set_queue_cnt_mode(struct fman_port *port, bool enable); ++int fman_port_set_bpool_cnt_mode(struct fman_port *port, ++ uint8_t bpid, ++ bool enable); ++uint32_t fman_port_get_stats_counter(struct fman_port *port, ++ enum fman_port_stats_counters counter); ++void fman_port_set_stats_counter(struct fman_port *port, ++ enum fman_port_stats_counters counter, ++ uint32_t value); ++uint32_t fman_port_get_perf_counter(struct fman_port *port, ++ enum fman_port_perf_counters counter); ++void fman_port_set_perf_counter(struct fman_port *port, ++ enum fman_port_perf_counters counter, ++ uint32_t value); ++uint32_t fman_port_get_qmi_counter(struct fman_port *port, ++ enum fman_port_qmi_counters counter); ++void fman_port_set_qmi_counter(struct fman_port *port, ++ enum fman_port_qmi_counters counter, ++ uint32_t value); ++uint32_t fman_port_get_bpool_counter(struct fman_port *port, uint8_t bpid); ++void fman_port_set_bpool_counter(struct fman_port *port, ++ uint8_t bpid, ++ uint32_t value); ++int fman_port_add_congestion_grps(struct fman_port *port, ++ uint32_t grps_map[FMAN_PORT_CG_MAP_NUM]); ++int fman_port_remove_congestion_grps(struct fman_port *port, ++ uint32_t grps_map[FMAN_PORT_CG_MAP_NUM]); ++ ++ ++#endif /* __FSL_FMAN_PORT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_prs.h b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_prs.h +new file mode 100644 +index 0000000..b18997d +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_prs.h +@@ -0,0 +1,102 @@ ++/* ++ * Copyright 2008-2012 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 __FSL_FMAN_PRS_H ++#define __FSL_FMAN_PRS_H ++ ++#include "common/general.h" ++ ++#define FM_PCD_EX_PRS_DOUBLE_ECC 0x02000000 ++#define FM_PCD_EX_PRS_SINGLE_ECC 0x01000000 ++ ++#define FM_PCD_PRS_PPSC_ALL_PORTS 0xffff0000 ++#define FM_PCD_PRS_RPIMAC_EN 0x00000001 ++#define FM_PCD_PRS_PORT_IDLE_STS 0xffff0000 ++#define FM_PCD_PRS_SINGLE_ECC 0x00004000 ++#define FM_PCD_PRS_DOUBLE_ECC 0x00004000 ++#define PRS_MAX_CYCLE_LIMIT 8191 ++ ++#define DEFAULT_MAX_PRS_CYC_LIM 0 ++ ++struct fman_prs_regs { ++ uint32_t fmpr_rpclim; ++ uint32_t fmpr_rpimac; ++ uint32_t pmeec; ++ uint32_t res00c[5]; ++ uint32_t fmpr_pevr; ++ uint32_t fmpr_pever; ++ uint32_t res028; ++ uint32_t fmpr_perr; ++ uint32_t fmpr_perer; ++ uint32_t res034; ++ uint32_t res038[10]; ++ uint32_t fmpr_ppsc; ++ uint32_t res064; ++ uint32_t fmpr_pds; ++ uint32_t fmpr_l2rrs; ++ uint32_t fmpr_l3rrs; ++ uint32_t fmpr_l4rrs; ++ uint32_t fmpr_srrs; ++ uint32_t fmpr_l2rres; ++ uint32_t fmpr_l3rres; ++ uint32_t fmpr_l4rres; ++ uint32_t fmpr_srres; ++ uint32_t fmpr_spcs; ++ uint32_t fmpr_spscs; ++ uint32_t fmpr_hxscs; ++ uint32_t fmpr_mrcs; ++ uint32_t fmpr_mwcs; ++ uint32_t fmpr_mrscs; ++ uint32_t fmpr_mwscs; ++ uint32_t fmpr_fcscs; ++}; ++ ++struct fman_prs_cfg { ++ uint32_t port_id_stat; ++ uint16_t max_prs_cyc_lim; ++ uint32_t prs_exceptions; ++}; ++ ++uint32_t fman_prs_get_err_event(struct fman_prs_regs *regs, uint32_t ev_mask); ++uint32_t fman_prs_get_err_ev_mask(struct fman_prs_regs *regs); ++void fman_prs_ack_err_event(struct fman_prs_regs *regs, uint32_t event); ++uint32_t fman_prs_get_expt_event(struct fman_prs_regs *regs, uint32_t ev_mask); ++uint32_t fman_prs_get_expt_ev_mask(struct fman_prs_regs *regs); ++void fman_prs_ack_expt_event(struct fman_prs_regs *regs, uint32_t event); ++void fman_prs_defconfig(struct fman_prs_cfg *cfg); ++int fman_prs_init(struct fman_prs_regs *regs, struct fman_prs_cfg *cfg); ++void fman_prs_enable(struct fman_prs_regs *regs); ++void fman_prs_disable(struct fman_prs_regs *regs); ++int fman_prs_is_enabled(struct fman_prs_regs *regs); ++void fman_prs_set_stst_port_msk(struct fman_prs_regs *regs, uint32_t pid_msk); ++void fman_prs_set_stst(struct fman_prs_regs *regs, bool enable); ++#endif /* __FSL_FMAN_PRS_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_rtc.h b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_rtc.h +new file mode 100755 +index 0000000..f6b69a1 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_rtc.h +@@ -0,0 +1,449 @@ ++/* ++ * Copyright 2013 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 __FSL_FMAN_RTC_H ++#define __FSL_FMAN_RTC_H ++ ++#include "common/general.h" ++ ++/* FM RTC Registers definitions */ ++#define FMAN_RTC_TMR_CTRL_ALMP1 0x80000000 ++#define FMAN_RTC_TMR_CTRL_ALMP2 0x40000000 ++#define FMAN_RTC_TMR_CTRL_FS 0x10000000 ++#define FMAN_RTC_TMR_CTRL_PP1L 0x08000000 ++#define FMAN_RTC_TMR_CTRL_PP2L 0x04000000 ++#define FMAN_RTC_TMR_CTRL_TCLK_PERIOD_MASK 0x03FF0000 ++#define FMAN_RTC_TMR_CTRL_FRD 0x00004000 ++#define FMAN_RTC_TMR_CTRL_SLV 0x00002000 ++#define FMAN_RTC_TMR_CTRL_ETEP1 0x00000100 ++#define FMAN_RTC_TMR_CTRL_COPH 0x00000080 ++#define FMAN_RTC_TMR_CTRL_CIPH 0x00000040 ++#define FMAN_RTC_TMR_CTRL_TMSR 0x00000020 ++#define FMAN_RTC_TMR_CTRL_DBG 0x00000010 ++#define FMAN_RTC_TMR_CTRL_BYP 0x00000008 ++#define FMAN_RTC_TMR_CTRL_TE 0x00000004 ++#define FMAN_RTC_TMR_CTRL_CKSEL_OSC_CLK 0x00000003 ++#define FMAN_RTC_TMR_CTRL_CKSEL_MAC_CLK 0x00000001 ++#define FMAN_RTC_TMR_CTRL_CKSEL_EXT_CLK 0x00000000 ++#define FMAN_RTC_TMR_CTRL_TCLK_PERIOD_SHIFT 16 ++ ++#define FMAN_RTC_TMR_TEVENT_ETS2 0x02000000 ++#define FMAN_RTC_TMR_TEVENT_ETS1 0x01000000 ++#define FMAN_RTC_TMR_TEVENT_ALM2 0x00020000 ++#define FMAN_RTC_TMR_TEVENT_ALM1 0x00010000 ++#define FMAN_RTC_TMR_TEVENT_PP1 0x00000080 ++#define FMAN_RTC_TMR_TEVENT_PP2 0x00000040 ++#define FMAN_RTC_TMR_TEVENT_PP3 0x00000020 ++#define FMAN_RTC_TMR_TEVENT_ALL (FMAN_RTC_TMR_TEVENT_ETS2 |\ ++ FMAN_RTC_TMR_TEVENT_ETS1 |\ ++ FMAN_RTC_TMR_TEVENT_ALM2 |\ ++ FMAN_RTC_TMR_TEVENT_ALM1 |\ ++ FMAN_RTC_TMR_TEVENT_PP1 |\ ++ FMAN_RTC_TMR_TEVENT_PP2 |\ ++ FMAN_RTC_TMR_TEVENT_PP3) ++ ++#define FMAN_RTC_TMR_PRSC_OCK_MASK 0x0000FFFF ++ ++/**************************************************************************//** ++ @Description FM RTC Alarm Polarity Options. ++*//***************************************************************************/ ++enum fman_rtc_alarm_polarity { ++ E_FMAN_RTC_ALARM_POLARITY_ACTIVE_HIGH, /**< Active-high output polarity */ ++ E_FMAN_RTC_ALARM_POLARITY_ACTIVE_LOW /**< Active-low output polarity */ ++}; ++ ++/**************************************************************************//** ++ @Description FM RTC Trigger Polarity Options. ++*//***************************************************************************/ ++enum fman_rtc_trigger_polarity { ++ E_FMAN_RTC_TRIGGER_ON_RISING_EDGE, /**< Trigger on rising edge */ ++ E_FMAN_RTC_TRIGGER_ON_FALLING_EDGE /**< Trigger on falling edge */ ++}; ++ ++/**************************************************************************//** ++ @Description IEEE1588 Timer Module FM RTC Optional Clock Sources. ++*//***************************************************************************/ ++enum fman_src_clock { ++ E_FMAN_RTC_SOURCE_CLOCK_EXTERNAL, /**< external high precision timer ++ reference clock */ ++ E_FMAN_RTC_SOURCE_CLOCK_SYSTEM, /**< MAC system clock */ ++ E_FMAN_RTC_SOURCE_CLOCK_OSCILATOR /**< RTC clock oscilator */ ++}; ++ ++/* RTC default values */ ++#define DEFAULT_SRC_CLOCK E_FMAN_RTC_SOURCE_CLOCK_SYSTEM ++#define DEFAULT_INVERT_INPUT_CLK_PHASE FALSE ++#define DEFAULT_INVERT_OUTPUT_CLK_PHASE FALSE ++#define DEFAULT_ALARM_POLARITY E_FMAN_RTC_ALARM_POLARITY_ACTIVE_HIGH ++#define DEFAULT_TRIGGER_POLARITY E_FMAN_RTC_TRIGGER_ON_FALLING_EDGE ++#define DEFAULT_PULSE_REALIGN FALSE ++ ++#define FMAN_RTC_MAX_NUM_OF_ALARMS 3 ++#define FMAN_RTC_MAX_NUM_OF_PERIODIC_PULSES 4 ++#define FMAN_RTC_MAX_NUM_OF_EXT_TRIGGERS 3 ++ ++/**************************************************************************//** ++ @Description FM RTC timer alarm ++*//***************************************************************************/ ++struct t_tmr_alarm{ ++ uint32_t tmr_alarm_h; /**< */ ++ uint32_t tmr_alarm_l; /**< */ ++}; ++ ++/**************************************************************************//** ++ @Description FM RTC timer Ex trigger ++*//***************************************************************************/ ++struct t_tmr_ext_trigger{ ++ uint32_t tmr_etts_h; /**< */ ++ uint32_t tmr_etts_l; /**< */ ++}; ++ ++struct rtc_regs { ++ uint32_t tmr_id; /* 0x000 Module ID register */ ++ uint32_t tmr_id2; /* 0x004 Controller ID register */ ++ uint32_t reserved0008[30]; ++ uint32_t tmr_ctrl; /* 0x0080 timer control register */ ++ uint32_t tmr_tevent; /* 0x0084 timer event register */ ++ uint32_t tmr_temask; /* 0x0088 timer event mask register */ ++ uint32_t reserved008c[3]; ++ uint32_t tmr_cnt_h; /* 0x0098 timer counter high register */ ++ uint32_t tmr_cnt_l; /* 0x009c timer counter low register */ ++ uint32_t tmr_add; /* 0x00a0 timer drift compensation addend register */ ++ uint32_t tmr_acc; /* 0x00a4 timer accumulator register */ ++ uint32_t tmr_prsc; /* 0x00a8 timer prescale */ ++ uint32_t reserved00ac; ++ uint32_t tmr_off_h; /* 0x00b0 timer offset high */ ++ uint32_t tmr_off_l; /* 0x00b4 timer offset low */ ++ struct t_tmr_alarm tmr_alarm[FMAN_RTC_MAX_NUM_OF_ALARMS]; /* 0x00b8 timer ++ alarm */ ++ uint32_t tmr_fiper[FMAN_RTC_MAX_NUM_OF_PERIODIC_PULSES]; /* 0x00d0 timer ++ fixed period interval */ ++ struct t_tmr_ext_trigger tmr_etts[FMAN_RTC_MAX_NUM_OF_EXT_TRIGGERS]; ++ /* 0x00e0 time stamp general purpose external */ ++ uint32_t reserved00f0[4]; ++}; ++ ++struct rtc_cfg { ++ enum fman_src_clock src_clk; ++ uint32_t ext_src_clk_freq; ++ uint32_t rtc_freq_hz; ++ bool timer_slave_mode; ++ bool invert_input_clk_phase; ++ bool invert_output_clk_phase; ++ uint32_t events_mask; ++ bool bypass; /**< Indicates if frequency compensation ++ is bypassed */ ++ bool pulse_realign; ++ enum fman_rtc_alarm_polarity alarm_polarity[FMAN_RTC_MAX_NUM_OF_ALARMS]; ++ enum fman_rtc_trigger_polarity trigger_polarity ++ [FMAN_RTC_MAX_NUM_OF_EXT_TRIGGERS]; ++}; ++ ++/** ++ * fman_rtc_defconfig() - Get default RTC configuration ++ * @cfg: pointer to configuration structure. ++ * ++ * Call this function to obtain a default set of configuration values for ++ * initializing RTC. The user can overwrite any of the values before calling ++ * fman_rtc_init(), if specific configuration needs to be applied. ++ */ ++void fman_rtc_defconfig(struct rtc_cfg *cfg); ++ ++/** ++ * fman_rtc_get_events() - Get the events ++ * @regs: Pointer to RTC register block ++ * ++ * Returns: The events ++ */ ++uint32_t fman_rtc_get_events(struct rtc_regs *regs); ++ ++/** ++ * fman_rtc_get_interrupt_mask() - Get the events mask ++ * @regs: Pointer to RTC register block ++ * ++ * Returns: The events mask ++ */ ++uint32_t fman_rtc_get_interrupt_mask(struct rtc_regs *regs); ++ ++ ++/** ++ * fman_rtc_set_interrupt_mask() - Set the events mask ++ * @regs: Pointer to RTC register block ++ * @mask: The mask to set ++ */ ++void fman_rtc_set_interrupt_mask(struct rtc_regs *regs, uint32_t mask); ++ ++/** ++ * fman_rtc_get_event() - Check if specific events occurred ++ * @regs: Pointer to RTC register block ++ * @ev_mask: a mask of the events to check ++ * ++ * Returns: 0 if the events did not occur. Non zero if one of the events occurred ++ */ ++uint32_t fman_rtc_get_event(struct rtc_regs *regs, uint32_t ev_mask); ++ ++/** ++ * fman_rtc_check_and_clear_event() - Clear events which are on ++ * @regs: Pointer to RTC register block ++ * ++ * Returns: A mask of the events which were cleared ++ */ ++uint32_t fman_rtc_check_and_clear_event(struct rtc_regs *regs); ++ ++/** ++ * fman_rtc_ack_event() - Clear events ++ * @regs: Pointer to RTC register block ++ * @events: The events to disable ++ */ ++void fman_rtc_ack_event(struct rtc_regs *regs, uint32_t events); ++ ++/** ++ * fman_rtc_enable_interupt() - Enable events interrupts ++ * @regs: Pointer to RTC register block ++ * @mask: The events to disable ++ */ ++void fman_rtc_enable_interupt(struct rtc_regs *regs, uint32_t mask); ++ ++/** ++ * fman_rtc_disable_interupt() - Disable events interrupts ++ * @regs: Pointer to RTC register block ++ * @mask: The events to disable ++ */ ++void fman_rtc_disable_interupt(struct rtc_regs *regs, uint32_t mask); ++ ++/** ++ * fman_rtc_get_timer_ctrl() - Get the control register ++ * @regs: Pointer to RTC register block ++ * ++ * Returns: The control register value ++ */ ++uint32_t fman_rtc_get_timer_ctrl(struct rtc_regs *regs); ++ ++/** ++ * fman_rtc_set_timer_ctrl() - Set timer control register ++ * @regs: Pointer to RTC register block ++ * @val: The value to set ++ */ ++void fman_rtc_set_timer_ctrl(struct rtc_regs *regs, uint32_t val); ++ ++/** ++ * fman_rtc_get_frequency_compensation() - Get the frequency compensation ++ * @regs: Pointer to RTC register block ++ * ++ * Returns: The timer counter ++ */ ++uint32_t fman_rtc_get_frequency_compensation(struct rtc_regs *regs); ++ ++/** ++ * fman_rtc_set_frequency_compensation() - Set frequency compensation ++ * @regs: Pointer to RTC register block ++ * @val: The value to set ++ */ ++void fman_rtc_set_frequency_compensation(struct rtc_regs *regs, uint32_t val); ++ ++/** ++ * fman_rtc_get_trigger_stamp() - Get a trigger stamp ++ * @regs: Pointer to RTC register block ++ * @id: The id of the trigger stamp ++ * ++ * Returns: The time stamp ++ */ ++uint64_t fman_rtc_get_trigger_stamp(struct rtc_regs *regs, int id); ++ ++/** ++ * fman_rtc_set_timer_alarm_l() - Set timer alarm low register ++ * @regs: Pointer to RTC register block ++ * @index: The index of alarm to set ++ * @val: The value to set ++ */ ++void fman_rtc_set_timer_alarm_l(struct rtc_regs *regs, int index, ++ uint32_t val); ++ ++/** ++ * fman_rtc_set_timer_alarm() - Set timer alarm ++ * @regs: Pointer to RTC register block ++ * @index: The index of alarm to set ++ * @val: The value to set ++ */ ++void fman_rtc_set_timer_alarm(struct rtc_regs *regs, int index, int64_t val); ++ ++/** ++ * fman_rtc_set_timer_fiper() - Set timer fiper ++ * @regs: Pointer to RTC register block ++ * @index: The index of fiper to set ++ * @val: The value to set ++ */ ++void fman_rtc_set_timer_fiper(struct rtc_regs *regs, int index, uint32_t val); ++ ++/** ++ * fman_rtc_set_timer_offset() - Set timer offset ++ * @regs: Pointer to RTC register block ++ * @val: The value to set ++ */ ++void fman_rtc_set_timer_offset(struct rtc_regs *regs, int64_t val); ++ ++/** ++ * fman_rtc_get_timer() - Get the timer counter ++ * @regs: Pointer to RTC register block ++ * ++ * Returns: The timer counter ++ */ ++static inline uint64_t fman_rtc_get_timer(struct rtc_regs *regs) ++{ ++ uint64_t time; ++ /* TMR_CNT_L must be read first to get an accurate value */ ++ time = (uint64_t)ioread32be(®s->tmr_cnt_l); ++ time |= ((uint64_t)ioread32be(®s->tmr_cnt_h) << 32); ++ ++ return time; ++} ++ ++/** ++ * fman_rtc_set_timer() - Set timer counter ++ * @regs: Pointer to RTC register block ++ * @val: The value to set ++ */ ++static inline void fman_rtc_set_timer(struct rtc_regs *regs, int64_t val) ++{ ++ iowrite32be((uint32_t)val, ®s->tmr_cnt_l); ++ iowrite32be((uint32_t)(val >> 32), ®s->tmr_cnt_h); ++} ++ ++/** ++ * fman_rtc_timers_soft_reset() - Soft reset ++ * @regs: Pointer to RTC register block ++ * ++ * Resets all the timer registers and state machines for the 1588 IP and ++ * the attached client 1588 ++ */ ++void fman_rtc_timers_soft_reset(struct rtc_regs *regs); ++ ++/** ++ * fman_rtc_clear_external_trigger() - Clear an external trigger ++ * @regs: Pointer to RTC register block ++ * @id: The id of the trigger to clear ++ */ ++void fman_rtc_clear_external_trigger(struct rtc_regs *regs, int id); ++ ++/** ++ * fman_rtc_clear_periodic_pulse() - Clear periodic pulse ++ * @regs: Pointer to RTC register block ++ * @id: The id of the fiper to clear ++ */ ++void fman_rtc_clear_periodic_pulse(struct rtc_regs *regs, int id); ++ ++/** ++ * fman_rtc_enable() - Enable RTC hardware block ++ * @regs: Pointer to RTC register block ++ */ ++void fman_rtc_enable(struct rtc_regs *regs, bool reset_clock); ++ ++/** ++ * fman_rtc_is_enabled() - Is RTC hardware block enabled ++ * @regs: Pointer to RTC register block ++ * ++ * Return: TRUE if enabled ++ */ ++bool fman_rtc_is_enabled(struct rtc_regs *regs); ++ ++/** ++ * fman_rtc_disable() - Disable RTC hardware block ++ * @regs: Pointer to RTC register block ++ */ ++void fman_rtc_disable(struct rtc_regs *regs); ++ ++/** ++ * fman_rtc_init() - Init RTC hardware block ++ * @cfg: RTC configuration data ++ * @regs: Pointer to RTC register block ++ * @num_alarms: Number of alarms in RTC ++ * @num_fipers: Number of fipers in RTC ++ * @num_ext_triggers: Number of external triggers in RTC ++ * @freq_compensation: Frequency compensation ++ * @output_clock_divisor: Output clock divisor ++ * ++ * This function initializes RTC and applies basic configuration. ++ */ ++void fman_rtc_init(struct rtc_cfg *cfg, struct rtc_regs *regs, int num_alarms, ++ int num_fipers, int num_ext_triggers, bool init_freq_comp, ++ uint32_t freq_compensation, uint32_t output_clock_divisor); ++ ++/** ++ * fman_rtc_set_alarm() - Set an alarm ++ * @regs: Pointer to RTC register block ++ * @id: id of alarm ++ * @val: value to write ++ * @enable: should interrupt be enabled ++ */ ++void fman_rtc_set_alarm(struct rtc_regs *regs, int id, uint32_t val, bool enable); ++ ++/** ++ * fman_rtc_set_periodic_pulse() - Set an alarm ++ * @regs: Pointer to RTC register block ++ * @id: id of fiper ++ * @val: value to write ++ * @enable: should interrupt be enabled ++ */ ++void fman_rtc_set_periodic_pulse(struct rtc_regs *regs, int id, uint32_t val, ++ bool enable); ++ ++/** ++ * fman_rtc_set_ext_trigger() - Set an external trigger ++ * @regs: Pointer to RTC register block ++ * @id: id of trigger ++ * @enable: should interrupt be enabled ++ * @use_pulse_as_input: use the pulse as input ++ */ ++void fman_rtc_set_ext_trigger(struct rtc_regs *regs, int id, bool enable, ++ bool use_pulse_as_input); ++ ++struct fm_rtc_alarm_params { ++ uint8_t alarm_id; /**< 0 or 1 */ ++ uint64_t alarm_time; /**< In nanoseconds, the time when the ++ alarm should go off - must be a ++ multiple of the RTC period */ ++ void (*f_alarm_callback)(void* app, uint8_t id); /**< This routine will ++ be called when RTC reaches alarmTime */ ++ bool clear_on_expiration; /**< TRUE to turn off the alarm once ++ expired.*/ ++}; ++ ++struct fm_rtc_periodic_pulse_params { ++ uint8_t periodic_pulse_id; /**< 0 or 1 */ ++ uint64_t periodic_pulse_period; /**< In Nanoseconds. Must be a multiple ++ of the RTC period */ ++ void (*f_periodic_pulse_callback)(void* app, uint8_t id); /**< This ++ routine will be called every ++ periodicPulsePeriod. */ ++}; ++ ++#endif /* __FSL_FMAN_RTC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_sp.h b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_sp.h +new file mode 100755 +index 0000000..f8ef7d5 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_sp.h +@@ -0,0 +1,138 @@ ++/* ++ * Copyright 2013 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 __FSL_FMAN_SP_H ++#define __FSL_FMAN_SP_H ++ ++#include "common/general.h" ++#include "fsl_fman.h" ++ ++ ++struct fm_pcd_storage_profile_regs{ ++ uint32_t fm_sp_ebmpi[8]; ++ /*offset 0 - 0xc*/ ++ /**< Buffer Manager pool Information */ ++ ++ uint32_t fm_sp_acnt; /*offset 0x20*/ ++ uint32_t fm_sp_ebm; /*offset 0x24*/ ++ uint32_t fm_sp_da; /*offset 0x28*/ ++ uint32_t fm_sp_icp; /*offset 0x2c*/ ++ uint32_t fm_sp_mpd; /*offset 0x30*/ ++ uint32_t res1[2]; /*offset 0x34 - 0x38*/ ++ uint32_t fm_sp_spliodn; /*offset 0x3c*/ ++}; ++ ++/**************************************************************************//** ++ @Description structure for defining internal context copying ++*//***************************************************************************/ ++struct fman_sp_int_context_data_copy{ ++ uint16_t ext_buf_offset; /**< Offset in External buffer to which ++ internal context is copied to (Rx) ++ or taken from (Tx, Op). */ ++ uint8_t int_context_offset; /**< Offset within internal context to copy ++ from (Rx) or to copy to (Tx, Op).*/ ++ uint16_t size; /**< Internal offset size to be copied */ ++}; ++ ++/**************************************************************************//** ++ @Description struct for defining external buffer margins ++*//***************************************************************************/ ++struct fman_sp_buf_margins{ ++ uint16_t start_margins; /**< Number of bytes to be left at the ++ beginning of the external buffer (must be ++ divisible by 16) */ ++ uint16_t end_margins; /**< number of bytes to be left at the end of ++ the external buffer(must be divisible by 16)*/ ++}; ++ ++struct fm_storage_profile_params { ++ struct fman_ext_pools fm_ext_pools; ++ struct fman_backup_bm_pools backup_pools; ++ struct fman_sp_int_context_data_copy *int_context; ++ struct fman_sp_buf_margins *buf_margins; ++ enum fman_dma_swap_option dma_swap_data; ++ enum fman_dma_cache_option int_context_cache_attr; ++ enum fman_dma_cache_option header_cache_attr; ++ enum fman_dma_cache_option scatter_gather_cache_attr; ++ bool dma_write_optimize; ++ uint16_t liodn_offset; ++ bool no_scather_gather; ++ struct fman_buf_pool_depletion buf_pool_depletion; ++}; ++ ++/**************************************************************************//** ++ @Description Registers bit fields ++*//***************************************************************************/ ++#define FMAN_SP_EXT_BUF_POOL_EN_COUNTER 0x40000000 ++#define FMAN_SP_EXT_BUF_POOL_VALID 0x80000000 ++#define FMAN_SP_EXT_BUF_POOL_BACKUP 0x20000000 ++#define FMAN_SP_DMA_ATTR_WRITE_OPTIMIZE 0x00100000 ++#define FMAN_SP_SG_DISABLE 0x80000000 ++ ++/* shifts */ ++#define FMAN_SP_EXT_BUF_POOL_ID_SHIFT 16 ++#define FMAN_SP_POOL_DEP_NUM_OF_POOLS_SHIFT 16 ++#define FMAN_SP_EXT_BUF_MARG_START_SHIFT 16 ++#define FMAN_SP_EXT_BUF_MARG_END_SHIFT 0 ++#define FMAN_SP_DMA_ATTR_SWP_SHIFT 30 ++#define FMAN_SP_DMA_ATTR_IC_CACHE_SHIFT 28 ++#define FMAN_SP_DMA_ATTR_HDR_CACHE_SHIFT 26 ++#define FMAN_SP_DMA_ATTR_SG_CACHE_SHIFT 24 ++#define FMAN_SP_IC_TO_EXT_SHIFT 16 ++#define FMAN_SP_IC_FROM_INT_SHIFT 8 ++#define FMAN_SP_IC_SIZE_SHIFT 0 ++ ++/**************************************************************************//** ++ @Description defaults ++*//***************************************************************************/ ++#define DEFAULT_FMAN_SP_DMA_SWAP_DATA FMAN_DMA_NO_SWP ++#define DEFAULT_FMAN_SP_DMA_INT_CONTEXT_CACHE_ATTR FMAN_DMA_NO_STASH ++#define DEFAULT_FMAN_SP_DMA_HEADER_CACHE_ATTR FMAN_DMA_NO_STASH ++#define DEFAULT_FMAN_SP_DMA_SCATTER_GATHER_CACHE_ATTR FMAN_DMA_NO_STASH ++#define DEFAULT_FMAN_SP_DMA_WRITE_OPTIMIZE TRUE ++#define DEFAULT_FMAN_SP_NO_SCATTER_GATHER FALSE ++ ++void fman_vsp_defconfig(struct fm_storage_profile_params *cfg); ++ ++void fman_vsp_init(struct fm_pcd_storage_profile_regs *regs, ++ uint16_t index, struct fm_storage_profile_params *fm_vsp_params, ++ int port_max_num_of_ext_pools, int bm_max_num_of_pools, ++ int max_num_of_pfc_priorities); ++ ++uint32_t fman_vsp_get_statistics(struct fm_pcd_storage_profile_regs *regs, ++ uint16_t index); ++ ++void fman_vsp_set_statistics(struct fm_pcd_storage_profile_regs *regs, ++ uint16_t index, uint32_t value); ++ ++ ++#endif /* __FSL_FMAN_SP_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_tgec.h b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_tgec.h +new file mode 100644 +index 0000000..a037314 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/fsl_fman_tgec.h +@@ -0,0 +1,479 @@ ++/* ++ * Copyright 2008-2012 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 __FSL_FMAN_TGEC_H ++#define __FSL_FMAN_TGEC_H ++ ++#include "common/general.h" ++#include "fsl_enet.h" ++ ++ ++/* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */ ++#define TGEC_TX_IPG_LENGTH_MASK 0x000003ff ++ ++enum tgec_counters { ++ E_TGEC_COUNTER_R64, ++ E_TGEC_COUNTER_R127, ++ E_TGEC_COUNTER_R255, ++ E_TGEC_COUNTER_R511, ++ E_TGEC_COUNTER_R1023, ++ E_TGEC_COUNTER_R1518, ++ E_TGEC_COUNTER_R1519X, ++ E_TGEC_COUNTER_TRFRG, ++ E_TGEC_COUNTER_TRJBR, ++ E_TGEC_COUNTER_RDRP, ++ E_TGEC_COUNTER_RALN, ++ E_TGEC_COUNTER_TRUND, ++ E_TGEC_COUNTER_TROVR, ++ E_TGEC_COUNTER_RXPF, ++ E_TGEC_COUNTER_TXPF, ++ E_TGEC_COUNTER_ROCT, ++ E_TGEC_COUNTER_RMCA, ++ E_TGEC_COUNTER_RBCA, ++ E_TGEC_COUNTER_RPKT, ++ E_TGEC_COUNTER_RUCA, ++ E_TGEC_COUNTER_RERR, ++ E_TGEC_COUNTER_TOCT, ++ E_TGEC_COUNTER_TMCA, ++ E_TGEC_COUNTER_TBCA, ++ E_TGEC_COUNTER_TUCA, ++ E_TGEC_COUNTER_TERR ++}; ++ ++/* Command and Configuration Register (COMMAND_CONFIG) */ ++#define CMD_CFG_EN_TIMESTAMP 0x00100000 ++#define CMD_CFG_TX_ADDR_INS_SEL 0x00080000 ++#define CMD_CFG_NO_LEN_CHK 0x00020000 ++#define CMD_CFG_SEND_IDLE 0x00010000 ++#define CMD_CFG_RX_ER_DISC 0x00004000 ++#define CMD_CFG_CMD_FRM_EN 0x00002000 ++#define CMD_CFG_STAT_CLR 0x00001000 ++#define CMD_CFG_LOOPBACK_EN 0x00000400 ++#define CMD_CFG_TX_ADDR_INS 0x00000200 ++#define CMD_CFG_PAUSE_IGNORE 0x00000100 ++#define CMD_CFG_PAUSE_FWD 0x00000080 ++#define CMD_CFG_PROMIS_EN 0x00000010 ++#define CMD_CFG_WAN_MODE 0x00000008 ++#define CMD_CFG_RX_EN 0x00000002 ++#define CMD_CFG_TX_EN 0x00000001 ++ ++/* Interrupt Mask Register (IMASK) */ ++#define TGEC_IMASK_MDIO_SCAN_EVENT 0x00010000 ++#define TGEC_IMASK_MDIO_CMD_CMPL 0x00008000 ++#define TGEC_IMASK_REM_FAULT 0x00004000 ++#define TGEC_IMASK_LOC_FAULT 0x00002000 ++#define TGEC_IMASK_TX_ECC_ER 0x00001000 ++#define TGEC_IMASK_TX_FIFO_UNFL 0x00000800 ++#define TGEC_IMASK_TX_FIFO_OVFL 0x00000400 ++#define TGEC_IMASK_TX_ER 0x00000200 ++#define TGEC_IMASK_RX_FIFO_OVFL 0x00000100 ++#define TGEC_IMASK_RX_ECC_ER 0x00000080 ++#define TGEC_IMASK_RX_JAB_FRM 0x00000040 ++#define TGEC_IMASK_RX_OVRSZ_FRM 0x00000020 ++#define TGEC_IMASK_RX_RUNT_FRM 0x00000010 ++#define TGEC_IMASK_RX_FRAG_FRM 0x00000008 ++#define TGEC_IMASK_RX_LEN_ER 0x00000004 ++#define TGEC_IMASK_RX_CRC_ER 0x00000002 ++#define TGEC_IMASK_RX_ALIGN_ER 0x00000001 ++ ++#define TGEC_EVENTS_MASK \ ++ ((uint32_t)(TGEC_IMASK_MDIO_SCAN_EVENT | \ ++ TGEC_IMASK_MDIO_CMD_CMPL | \ ++ TGEC_IMASK_REM_FAULT | \ ++ TGEC_IMASK_LOC_FAULT | \ ++ TGEC_IMASK_TX_ECC_ER | \ ++ TGEC_IMASK_TX_FIFO_UNFL | \ ++ TGEC_IMASK_TX_FIFO_OVFL | \ ++ TGEC_IMASK_TX_ER | \ ++ TGEC_IMASK_RX_FIFO_OVFL | \ ++ TGEC_IMASK_RX_ECC_ER | \ ++ TGEC_IMASK_RX_JAB_FRM | \ ++ TGEC_IMASK_RX_OVRSZ_FRM | \ ++ TGEC_IMASK_RX_RUNT_FRM | \ ++ TGEC_IMASK_RX_FRAG_FRM | \ ++ TGEC_IMASK_RX_LEN_ER | \ ++ TGEC_IMASK_RX_CRC_ER | \ ++ TGEC_IMASK_RX_ALIGN_ER)) ++ ++/* Hashtable Control Register (HASHTABLE_CTRL) */ ++#define TGEC_HASH_MCAST_SHIFT 23 ++#define TGEC_HASH_MCAST_EN 0x00000200 ++#define TGEC_HASH_ADR_MSK 0x000001ff ++ ++#define DEFAULT_WAN_MODE_ENABLE FALSE ++#define DEFAULT_PROMISCUOUS_MODE_ENABLE FALSE ++#define DEFAULT_PAUSE_FORWARD_ENABLE FALSE ++#define DEFAULT_PAUSE_IGNORE FALSE ++#define DEFAULT_TX_ADDR_INS_ENABLE FALSE ++#define DEFAULT_LOOPBACK_ENABLE FALSE ++#define DEFAULT_CMD_FRAME_ENABLE FALSE ++#define DEFAULT_RX_ERROR_DISCARD FALSE ++#define DEFAULT_SEND_IDLE_ENABLE FALSE ++#define DEFAULT_NO_LENGTH_CHECK_ENABLE TRUE ++#define DEFAULT_LGTH_CHECK_NOSTDR FALSE ++#define DEFAULT_TIME_STAMP_ENABLE FALSE ++#define DEFAULT_TX_IPG_LENGTH 12 ++#define DEFAULT_MAX_FRAME_LENGTH 0x600 ++#define DEFAULT_PAUSE_QUANT 0xf000 ++ ++/* ++ * 10G memory map ++ */ ++struct tgec_regs { ++ uint32_t tgec_id; /* 0x000 Controller ID */ ++ uint32_t reserved001[1]; /* 0x004 */ ++ uint32_t command_config; /* 0x008 Control and configuration */ ++ uint32_t mac_addr_0; /* 0x00c Lower 32 bits of the MAC adr */ ++ uint32_t mac_addr_1; /* 0x010 Upper 16 bits of the MAC adr */ ++ uint32_t maxfrm; /* 0x014 Maximum frame length */ ++ uint32_t pause_quant; /* 0x018 Pause quanta */ ++ uint32_t rx_fifo_sections; /* 0x01c */ ++ uint32_t tx_fifo_sections; /* 0x020 */ ++ uint32_t rx_fifo_almost_f_e; /* 0x024 */ ++ uint32_t tx_fifo_almost_f_e; /* 0x028 */ ++ uint32_t hashtable_ctrl; /* 0x02c Hash table control*/ ++ uint32_t mdio_cfg_status; /* 0x030 */ ++ uint32_t mdio_command; /* 0x034 */ ++ uint32_t mdio_data; /* 0x038 */ ++ uint32_t mdio_regaddr; /* 0x03c */ ++ uint32_t status; /* 0x040 */ ++ uint32_t tx_ipg_len; /* 0x044 Transmitter inter-packet-gap */ ++ uint32_t mac_addr_2; /* 0x048 Lower 32 bits of 2nd MAC adr */ ++ uint32_t mac_addr_3; /* 0x04c Upper 16 bits of 2nd MAC adr */ ++ uint32_t rx_fifo_ptr_rd; /* 0x050 */ ++ uint32_t rx_fifo_ptr_wr; /* 0x054 */ ++ uint32_t tx_fifo_ptr_rd; /* 0x058 */ ++ uint32_t tx_fifo_ptr_wr; /* 0x05c */ ++ uint32_t imask; /* 0x060 Interrupt mask */ ++ uint32_t ievent; /* 0x064 Interrupt event */ ++ uint32_t udp_port; /* 0x068 Defines a UDP Port number */ ++ uint32_t type_1588v2; /* 0x06c Type field for 1588v2 */ ++ uint32_t reserved070[4]; /* 0x070 */ ++ /*10Ge Statistics Counter */ ++ uint32_t tfrm_u; /* 80 aFramesTransmittedOK */ ++ uint32_t tfrm_l; /* 84 aFramesTransmittedOK */ ++ uint32_t rfrm_u; /* 88 aFramesReceivedOK */ ++ uint32_t rfrm_l; /* 8c aFramesReceivedOK */ ++ uint32_t rfcs_u; /* 90 aFrameCheckSequenceErrors */ ++ uint32_t rfcs_l; /* 94 aFrameCheckSequenceErrors */ ++ uint32_t raln_u; /* 98 aAlignmentErrors */ ++ uint32_t raln_l; /* 9c aAlignmentErrors */ ++ uint32_t txpf_u; /* A0 aPAUSEMACCtrlFramesTransmitted */ ++ uint32_t txpf_l; /* A4 aPAUSEMACCtrlFramesTransmitted */ ++ uint32_t rxpf_u; /* A8 aPAUSEMACCtrlFramesReceived */ ++ uint32_t rxpf_l; /* Ac aPAUSEMACCtrlFramesReceived */ ++ uint32_t rlong_u; /* B0 aFrameTooLongErrors */ ++ uint32_t rlong_l; /* B4 aFrameTooLongErrors */ ++ uint32_t rflr_u; /* B8 aInRangeLengthErrors */ ++ uint32_t rflr_l; /* Bc aInRangeLengthErrors */ ++ uint32_t tvlan_u; /* C0 VLANTransmittedOK */ ++ uint32_t tvlan_l; /* C4 VLANTransmittedOK */ ++ uint32_t rvlan_u; /* C8 VLANReceivedOK */ ++ uint32_t rvlan_l; /* Cc VLANReceivedOK */ ++ uint32_t toct_u; /* D0 ifOutOctets */ ++ uint32_t toct_l; /* D4 ifOutOctets */ ++ uint32_t roct_u; /* D8 ifInOctets */ ++ uint32_t roct_l; /* Dc ifInOctets */ ++ uint32_t ruca_u; /* E0 ifInUcastPkts */ ++ uint32_t ruca_l; /* E4 ifInUcastPkts */ ++ uint32_t rmca_u; /* E8 ifInMulticastPkts */ ++ uint32_t rmca_l; /* Ec ifInMulticastPkts */ ++ uint32_t rbca_u; /* F0 ifInBroadcastPkts */ ++ uint32_t rbca_l; /* F4 ifInBroadcastPkts */ ++ uint32_t terr_u; /* F8 ifOutErrors */ ++ uint32_t terr_l; /* Fc ifOutErrors */ ++ uint32_t reserved100[2]; /* 100-108*/ ++ uint32_t tuca_u; /* 108 ifOutUcastPkts */ ++ uint32_t tuca_l; /* 10c ifOutUcastPkts */ ++ uint32_t tmca_u; /* 110 ifOutMulticastPkts */ ++ uint32_t tmca_l; /* 114 ifOutMulticastPkts */ ++ uint32_t tbca_u; /* 118 ifOutBroadcastPkts */ ++ uint32_t tbca_l; /* 11c ifOutBroadcastPkts */ ++ uint32_t rdrp_u; /* 120 etherStatsDropEvents */ ++ uint32_t rdrp_l; /* 124 etherStatsDropEvents */ ++ uint32_t reoct_u; /* 128 etherStatsOctets */ ++ uint32_t reoct_l; /* 12c etherStatsOctets */ ++ uint32_t rpkt_u; /* 130 etherStatsPkts */ ++ uint32_t rpkt_l; /* 134 etherStatsPkts */ ++ uint32_t trund_u; /* 138 etherStatsUndersizePkts */ ++ uint32_t trund_l; /* 13c etherStatsUndersizePkts */ ++ uint32_t r64_u; /* 140 etherStatsPkts64Octets */ ++ uint32_t r64_l; /* 144 etherStatsPkts64Octets */ ++ uint32_t r127_u; /* 148 etherStatsPkts65to127Octets */ ++ uint32_t r127_l; /* 14c etherStatsPkts65to127Octets */ ++ uint32_t r255_u; /* 150 etherStatsPkts128to255Octets */ ++ uint32_t r255_l; /* 154 etherStatsPkts128to255Octets */ ++ uint32_t r511_u; /* 158 etherStatsPkts256to511Octets */ ++ uint32_t r511_l; /* 15c etherStatsPkts256to511Octets */ ++ uint32_t r1023_u; /* 160 etherStatsPkts512to1023Octets */ ++ uint32_t r1023_l; /* 164 etherStatsPkts512to1023Octets */ ++ uint32_t r1518_u; /* 168 etherStatsPkts1024to1518Octets */ ++ uint32_t r1518_l; /* 16c etherStatsPkts1024to1518Octets */ ++ uint32_t r1519x_u; /* 170 etherStatsPkts1519toX */ ++ uint32_t r1519x_l; /* 174 etherStatsPkts1519toX */ ++ uint32_t trovr_u; /* 178 etherStatsOversizePkts */ ++ uint32_t trovr_l; /* 17c etherStatsOversizePkts */ ++ uint32_t trjbr_u; /* 180 etherStatsJabbers */ ++ uint32_t trjbr_l; /* 184 etherStatsJabbers */ ++ uint32_t trfrg_u; /* 188 etherStatsFragments */ ++ uint32_t trfrg_l; /* 18C etherStatsFragments */ ++ uint32_t rerr_u; /* 190 ifInErrors */ ++ uint32_t rerr_l; /* 194 ifInErrors */ ++}; ++ ++/** ++ * struct tgec_cfg - TGEC configuration ++ * ++ * @rx_error_discard: Receive Erroneous Frame Discard Enable. When set to 1 ++ * any frame received with an error is discarded in the ++ * Core and not forwarded to the Client interface. ++ * When set to 0 (Reset value), erroneous Frames are ++ * forwarded to the Client interface with ff_rx_err ++ * asserted. ++ * @pause_ignore: Ignore Pause Frame Quanta. If set to 1 received pause ++ * frames are ignored by the MAC. When set to 0 ++ * (Reset value) the transmit process is stopped for the ++ * amount of time specified in the pause quanta received ++ * within a pause frame. ++ * @pause_forward_enable: ++ * Terminate / Forward Pause Frames. If set to 1 pause ++ * frames are forwarded to the user application. When set ++ * to 0 (Reset value) pause frames are terminated and ++ * discarded within the MAC. ++ * @no_length_check_enable: ++ * Payload Length Check Disable. When set to 0 ++ * (Reset value), the Core checks the frame's payload ++ * length with the Frame Length/Type field, when set to 1 ++ * the payload length check is disabled. ++ * @cmd_frame_enable: Enables reception of all command frames. When set to 1 ++ * all Command Frames are accepted, when set to 0 ++ * (Reset Value) only Pause Frames are accepted and all ++ * other Command Frames are rejected. ++ * @send_idle_enable: Force Idle Generation. When set to 1, the MAC ++ * permanently sends XGMII Idle sequences even when faults ++ * are received. ++ * @wan_mode_enable: WAN Mode Enable. Sets WAN mode (1) or LAN mode ++ * (0, default) of operation. ++ * @promiscuous_mode_enable: ++ * Enables MAC promiscuous operation. When set to 1, all ++ * frames are received without any MAC address filtering, ++ * when set to 0 (Reset value) Unicast Frames with a ++ * destination address not matching the Core MAC Address ++ * (MAC Address programmed in Registers MAC_ADDR_0 and ++ * MAC_ADDR_1 or the MAC address programmed in Registers ++ * MAC_ADDR_2 and MAC_ADDR_3) are rejected. ++ * @tx_addr_ins_enable: Set Source MAC Address on Transmit. If set to 1 the ++ * MAC overwrites the source MAC address received from the ++ * Client Interface with one of the MAC addresses. If set ++ * to 0 (Reset value), the source MAC address from the ++ * Client Interface is transmitted unmodified to the line. ++ * @loopback_enable: PHY Interface Loopback. When set to 1, the signal ++ * loop_ena is set to '1', when set to 0 (Reset value) ++ * the signal loop_ena is set to 0. ++ * @lgth_check_nostdr: The Core interprets the Length/Type field differently ++ * depending on the value of this Bit ++ * @time_stamp_enable: This bit selects between enabling and disabling the ++ * IEEE 1588 functionality. 1: IEEE 1588 is enabled ++ * 0: IEEE 1588 is disabled ++ * @max_frame_length: Maximum supported received frame length. ++ * The 10GEC MAC supports reception of any frame size up ++ * to 16,352 bytes (0x3FE0). Typical settings are ++ * 0x05EE (1,518 bytes) for standard frames. ++ * Default setting is 0x0600 (1,536 bytes). ++ * Received frames that exceed this stated maximum ++ * are truncated. ++ * @pause_quant: Pause quanta value used with transmitted pause frames. ++ * Each quanta represents a 512 bit-times. ++ * @tx_ipg_length: Transmit Inter-Packet-Gap (IPG) value. A 6-bit value: ++ * Depending on LAN or WAN mode of operation the value has ++ * the following meaning: - LAN Mode: Number of octets in ++ * steps of 4. Valid values are 8, 12, 16, ... 100. DIC is ++ * fully supported (see 10.6.1 page 49) for any setting. A ++ * default of 12 (reset value) must be set to conform to ++ * IEEE802.3ae. Warning: When set to 8, PCS layers may not ++ * be able to perform clock rate compensation. - WAN Mode: ++ * Stretch factor. Valid values are 4..15. The stretch ++ * factor is calculated as (value+1)*8. A default of 12 ++ * (reset value) must be set to conform to IEEE 802.3ae ++ * (i.e. 13*8=104). A larger value shrinks the IPG ++ * (increasing bandwidth). ++ * ++ * This structure contains basic TGEC configuration and must be passed to ++ * fman_tgec_init() function. A default set of configuration values can be ++ * obtained by calling fman_tgec_defconfig(). ++ */ ++struct tgec_cfg { ++ bool rx_error_discard; ++ bool pause_ignore; ++ bool pause_forward_enable; ++ bool no_length_check_enable; ++ bool cmd_frame_enable; ++ bool send_idle_enable; ++ bool wan_mode_enable; ++ bool promiscuous_mode_enable; ++ bool tx_addr_ins_enable; ++ bool loopback_enable; ++ bool lgth_check_nostdr; ++ bool time_stamp_enable; ++ uint16_t max_frame_length; ++ uint16_t pause_quant; ++ uint32_t tx_ipg_length; ++ bool skip_fman11_workaround; ++}; ++ ++ ++void fman_tgec_defconfig(struct tgec_cfg *cfg); ++ ++/** ++ * fman_tgec_init() - Init tgec hardware block ++ * @regs: Pointer to tgec register block ++ * @cfg: tgec configuration data ++ * @exceptions_mask: initial exceptions mask ++ * ++ * This function initializes the tgec controller and applies its ++ * basic configuration. ++ * ++ * Returns: 0 if successful, an error code otherwise. ++ */ ++ ++int fman_tgec_init(struct tgec_regs *regs, struct tgec_cfg *cfg, ++ uint32_t exception_mask); ++ ++void fman_tgec_enable(struct tgec_regs *regs, bool apply_rx, bool apply_tx); ++ ++void fman_tgec_disable(struct tgec_regs *regs, bool apply_rx, bool apply_tx); ++ ++uint32_t fman_tgec_get_revision(struct tgec_regs *regs); ++ ++void fman_tgec_set_mac_address(struct tgec_regs *regs, uint8_t *macaddr); ++ ++void fman_tgec_set_promiscuous(struct tgec_regs *regs, bool val); ++ ++/** ++ * fman_tgec_reset_stat() - Completely resets all TGEC HW counters ++ * @regs: Pointer to TGEC register block ++ */ ++void fman_tgec_reset_stat(struct tgec_regs *regs); ++ ++/** ++ * fman_tgec_get_counter() - Reads TGEC HW counters ++ * @regs: Pointer to TGEC register block ++ * @reg_name: Counter name according to the appropriate enum ++ * ++ * Returns: Required counter value ++ */ ++uint64_t fman_tgec_get_counter(struct tgec_regs *regs, ++ enum tgec_counters reg_name); ++ ++/** ++ * fman_tgec_set_hash_table() - Sets the Hashtable Control Register ++ * @regs: Pointer to TGEC register block ++ * @value: Value to be written in Hashtable Control Register ++ */ ++void fman_tgec_set_hash_table(struct tgec_regs *regs, uint32_t value); ++ ++/** ++ * fman_tgec_set_tx_pause_frames() - Sets the Pause Quanta Register ++ * @regs: Pointer to TGEC register block ++ * @pause_time: Pause quanta value used with transmitted pause frames. ++ * Each quanta represents a 512 bit-times ++ */ ++void fman_tgec_set_tx_pause_frames(struct tgec_regs *regs, uint16_t pause_time); ++ ++/** ++ * fman_tgec_set_rx_ignore_pause_frames() - Changes the policy WRT pause frames ++ * @regs: Pointer to TGEC register block ++ * @en: Ignore/Respond to pause frame quanta ++ * ++ * Sets the value of PAUSE_IGNORE field in the COMMAND_CONFIG Register ++ * 0 - MAC stops transmit process for the duration specified ++ * in the Pause frame quanta of a received Pause frame. ++ * 1 - MAC ignores received Pause frames. ++ */ ++void fman_tgec_set_rx_ignore_pause_frames(struct tgec_regs *regs, bool en); ++ ++/** ++ * fman_tgec_enable_1588_time_stamp() - change timestamp functionality ++ * @regs: Pointer to TGEC register block ++ * @en: enable/disable timestamp functionality ++ * ++ * Sets the value of EN_TIMESTAMP field in the COMMAND_CONFIG Register ++ * IEEE 1588 timestamp functionality control: ++ * 0 disabled, 1 enabled ++ */ ++ ++void fman_tgec_enable_1588_time_stamp(struct tgec_regs *regs, bool en); ++ ++uint32_t fman_tgec_get_event(struct tgec_regs *regs, uint32_t ev_mask); ++ ++void fman_tgec_ack_event(struct tgec_regs *regs, uint32_t ev_mask); ++ ++uint32_t fman_tgec_get_interrupt_mask(struct tgec_regs *regs); ++ ++/** ++ * fman_tgec_add_addr_in_paddr() - Sets additional exact match MAC address ++ * @regs: Pointer to TGEC register block ++ * @addr_ptr: Pointer to 6-byte array containing the MAC address ++ * ++ * Sets the additional station MAC address ++ */ ++void fman_tgec_add_addr_in_paddr(struct tgec_regs *regs, uint8_t *addr_ptr); ++ ++void fman_tgec_clear_addr_in_paddr(struct tgec_regs *regs); ++ ++void fman_tgec_enable_interrupt(struct tgec_regs *regs, uint32_t ev_mask); ++ ++void fman_tgec_disable_interrupt(struct tgec_regs *regs, uint32_t ev_mask); ++ ++void fman_tgec_reset_filter_table(struct tgec_regs *regs); ++ ++void fman_tgec_set_hash_table_entry(struct tgec_regs *regs, uint32_t crc); ++ ++ ++/** ++ * fman_tgec_get_max_frame_len() - Returns the maximum frame length value ++ * @regs: Pointer to TGEC register block ++ */ ++uint16_t fman_tgec_get_max_frame_len(struct tgec_regs *regs); ++ ++/** ++ * fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007() - Initialize the ++ * main tgec configuration parameters ++ * @regs: Pointer to TGEC register block ++ * ++ * TODO ++ */ ++void fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007(struct tgec_regs ++ *regs); ++ ++ ++#endif /* __FSL_FMAN_TGEC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3H/dpaa_integration_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3H/dpaa_integration_ext.h +new file mode 100644 +index 0000000..38ed441 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3H/dpaa_integration_ext.h +@@ -0,0 +1,290 @@ ++/* ++ * Copyright 2012 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. ++ */ ++ ++/** ++ ++ @File dpaa_integration_ext.h ++ ++ @Description T4240 FM external definitions and structures. ++*//***************************************************************************/ ++#ifndef __DPAA_INTEGRATION_EXT_H ++#define __DPAA_INTEGRATION_EXT_H ++ ++#include "std_ext.h" ++ ++ ++#define DPAA_VERSION 11 ++ ++/**************************************************************************//** ++ @Description DPAA SW Portals Enumeration. ++*//***************************************************************************/ ++typedef enum ++{ ++ e_DPAA_SWPORTAL0 = 0, ++ e_DPAA_SWPORTAL1, ++ e_DPAA_SWPORTAL2, ++ e_DPAA_SWPORTAL3, ++ e_DPAA_SWPORTAL4, ++ e_DPAA_SWPORTAL5, ++ e_DPAA_SWPORTAL6, ++ e_DPAA_SWPORTAL7, ++ e_DPAA_SWPORTAL8, ++ e_DPAA_SWPORTAL9, ++ e_DPAA_SWPORTAL10, ++ e_DPAA_SWPORTAL11, ++ e_DPAA_SWPORTAL12, ++ e_DPAA_SWPORTAL13, ++ e_DPAA_SWPORTAL14, ++ e_DPAA_SWPORTAL15, ++ e_DPAA_SWPORTAL16, ++ e_DPAA_SWPORTAL17, ++ e_DPAA_SWPORTAL18, ++ e_DPAA_SWPORTAL19, ++ e_DPAA_SWPORTAL20, ++ e_DPAA_SWPORTAL21, ++ e_DPAA_SWPORTAL22, ++ e_DPAA_SWPORTAL23, ++ e_DPAA_SWPORTAL24, ++ e_DPAA_SWPORTAL_DUMMY_LAST ++} e_DpaaSwPortal; ++ ++/**************************************************************************//** ++ @Description DPAA Direct Connect Portals Enumeration. ++*//***************************************************************************/ ++typedef enum ++{ ++ e_DPAA_DCPORTAL0 = 0, ++ e_DPAA_DCPORTAL1, ++ e_DPAA_DCPORTAL2, ++ e_DPAA_DCPORTAL_DUMMY_LAST ++} e_DpaaDcPortal; ++ ++#define DPAA_MAX_NUM_OF_SW_PORTALS e_DPAA_SWPORTAL_DUMMY_LAST ++#define DPAA_MAX_NUM_OF_DC_PORTALS e_DPAA_DCPORTAL_DUMMY_LAST ++ ++/***************************************************************************** ++ QMan INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define QM_MAX_NUM_OF_POOL_CHANNELS 15 /**< Total number of channels, dedicated and pool */ ++#define QM_MAX_NUM_OF_WQ 8 /**< Number of work queues per channel */ ++#define QM_MAX_NUM_OF_CGS 256 /**< Congestion groups number */ ++#define QM_MAX_NUM_OF_FQIDS (16 * MEGABYTE) ++ /**< FQIDs range - 24 bits */ ++ ++/**************************************************************************//** ++ @Description Work Queue Channel assignments in QMan. ++*//***************************************************************************/ ++typedef enum ++{ ++ e_QM_FQ_CHANNEL_SWPORTAL0 = 0x0, /**< Dedicated channels serviced by software portals 0 to 24 */ ++ e_QM_FQ_CHANNEL_SWPORTAL1, ++ e_QM_FQ_CHANNEL_SWPORTAL2, ++ e_QM_FQ_CHANNEL_SWPORTAL3, ++ e_QM_FQ_CHANNEL_SWPORTAL4, ++ e_QM_FQ_CHANNEL_SWPORTAL5, ++ e_QM_FQ_CHANNEL_SWPORTAL6, ++ e_QM_FQ_CHANNEL_SWPORTAL7, ++ e_QM_FQ_CHANNEL_SWPORTAL8, ++ e_QM_FQ_CHANNEL_SWPORTAL9, ++ e_QM_FQ_CHANNEL_SWPORTAL10, ++ e_QM_FQ_CHANNEL_SWPORTAL11, ++ e_QM_FQ_CHANNEL_SWPORTAL12, ++ e_QM_FQ_CHANNEL_SWPORTAL13, ++ e_QM_FQ_CHANNEL_SWPORTAL14, ++ e_QM_FQ_CHANNEL_SWPORTAL15, ++ e_QM_FQ_CHANNEL_SWPORTAL16, ++ e_QM_FQ_CHANNEL_SWPORTAL17, ++ e_QM_FQ_CHANNEL_SWPORTAL18, ++ e_QM_FQ_CHANNEL_SWPORTAL19, ++ e_QM_FQ_CHANNEL_SWPORTAL20, ++ e_QM_FQ_CHANNEL_SWPORTAL21, ++ e_QM_FQ_CHANNEL_SWPORTAL22, ++ e_QM_FQ_CHANNEL_SWPORTAL23, ++ e_QM_FQ_CHANNEL_SWPORTAL24, ++ ++ e_QM_FQ_CHANNEL_POOL1 = 0x401, /**< Pool channels that can be serviced by any of the software portals */ ++ e_QM_FQ_CHANNEL_POOL2, ++ e_QM_FQ_CHANNEL_POOL3, ++ e_QM_FQ_CHANNEL_POOL4, ++ e_QM_FQ_CHANNEL_POOL5, ++ e_QM_FQ_CHANNEL_POOL6, ++ e_QM_FQ_CHANNEL_POOL7, ++ e_QM_FQ_CHANNEL_POOL8, ++ e_QM_FQ_CHANNEL_POOL9, ++ e_QM_FQ_CHANNEL_POOL10, ++ e_QM_FQ_CHANNEL_POOL11, ++ e_QM_FQ_CHANNEL_POOL12, ++ e_QM_FQ_CHANNEL_POOL13, ++ e_QM_FQ_CHANNEL_POOL14, ++ e_QM_FQ_CHANNEL_POOL15, ++ ++ e_QM_FQ_CHANNEL_FMAN0_SP0 = 0x800, /**< Dedicated channels serviced by Direct Connect Portal 0: ++ connected to FMan 0; assigned in incrementing order to ++ each sub-portal (SP) in the portal */ ++ e_QM_FQ_CHANNEL_FMAN0_SP1, ++ e_QM_FQ_CHANNEL_FMAN0_SP2, ++ e_QM_FQ_CHANNEL_FMAN0_SP3, ++ e_QM_FQ_CHANNEL_FMAN0_SP4, ++ e_QM_FQ_CHANNEL_FMAN0_SP5, ++ e_QM_FQ_CHANNEL_FMAN0_SP6, ++ e_QM_FQ_CHANNEL_FMAN0_SP7, ++ e_QM_FQ_CHANNEL_FMAN0_SP8, ++ e_QM_FQ_CHANNEL_FMAN0_SP9, ++ e_QM_FQ_CHANNEL_FMAN0_SP10, ++ e_QM_FQ_CHANNEL_FMAN0_SP11, ++ e_QM_FQ_CHANNEL_FMAN0_SP12, ++ e_QM_FQ_CHANNEL_FMAN0_SP13, ++ e_QM_FQ_CHANNEL_FMAN0_SP14, ++ e_QM_FQ_CHANNEL_FMAN0_SP15, ++ ++ e_QM_FQ_CHANNEL_RMAN_SP0 = 0x820, /**< Dedicated channels serviced by Direct Connect Portal 1: connected to RMan */ ++ e_QM_FQ_CHANNEL_RMAN_SP1, ++ ++ e_QM_FQ_CHANNEL_CAAM = 0x840 /**< Dedicated channel serviced by Direct Connect Portal 2: ++ connected to SEC */ ++} e_QmFQChannel; ++ ++/***************************************************************************** ++ BMan INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define BM_MAX_NUM_OF_POOLS 64 /**< Number of buffers pools */ ++ ++/***************************************************************************** ++ SEC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define SEC_NUM_OF_DECOS 3 ++#define SEC_ALL_DECOS_MASK 0x00000003 ++ ++ ++/***************************************************************************** ++ FM INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define INTG_MAX_NUM_OF_FM 2 ++/* Ports defines */ ++#define FM_MAX_NUM_OF_1G_MACS 6 ++#define FM_MAX_NUM_OF_10G_MACS 2 ++#define FM_MAX_NUM_OF_MACS (FM_MAX_NUM_OF_1G_MACS + FM_MAX_NUM_OF_10G_MACS) ++#define FM_MAX_NUM_OF_OH_PORTS 6 ++ ++#define FM_MAX_NUM_OF_1G_RX_PORTS FM_MAX_NUM_OF_1G_MACS ++#define FM_MAX_NUM_OF_10G_RX_PORTS FM_MAX_NUM_OF_10G_MACS ++#define FM_MAX_NUM_OF_RX_PORTS (FM_MAX_NUM_OF_10G_RX_PORTS + FM_MAX_NUM_OF_1G_RX_PORTS) ++ ++#define FM_MAX_NUM_OF_1G_TX_PORTS FM_MAX_NUM_OF_1G_MACS ++#define FM_MAX_NUM_OF_10G_TX_PORTS FM_MAX_NUM_OF_10G_MACS ++#define FM_MAX_NUM_OF_TX_PORTS (FM_MAX_NUM_OF_10G_TX_PORTS + FM_MAX_NUM_OF_1G_TX_PORTS) ++ ++#define FM_PORT_MAX_NUM_OF_EXT_POOLS 4 /**< Number of external BM pools per Rx port */ ++#define FM_PORT_NUM_OF_CONGESTION_GRPS 256 /**< Total number of congestion groups in QM */ ++#define FM_MAX_NUM_OF_SUB_PORTALS 16 ++#define FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS 0 ++ ++#define FM_VSP_MAX_NUM_OF_ENTRIES 64 ++#define FM_MAX_NUM_OF_PFC_PRIORITIES 8 ++ ++/* RAMs defines */ ++#define FM_MURAM_SIZE (384 * KILOBYTE) ++#define FM_IRAM_SIZE(major, minor) (64 * KILOBYTE) ++#define FM_NUM_OF_CTRL 4 ++ ++/* PCD defines */ ++#define FM_PCD_PLCR_NUM_ENTRIES 256 /**< Total number of policer profiles */ ++#define FM_PCD_KG_NUM_OF_SCHEMES 32 /**< Total number of KG schemes */ ++#define FM_PCD_MAX_NUM_OF_CLS_PLANS 256 /**< Number of classification plan entries. */ ++#define FM_PCD_PRS_SW_PATCHES_SIZE 0x00000600 /**< Number of bytes saved for patches */ ++#define FM_PCD_SW_PRS_SIZE 0x00000800 /**< Total size of SW parser area */ ++ ++/* RTC defines */ ++#define FM_RTC_NUM_OF_ALARMS 2 /**< RTC number of alarms */ ++#define FM_RTC_NUM_OF_PERIODIC_PULSES 3 /**< RTC number of periodic pulses */ ++#define FM_RTC_NUM_OF_EXT_TRIGGERS 2 /**< RTC number of external triggers */ ++ ++/* QMI defines */ ++#define QMI_MAX_NUM_OF_TNUMS 64 ++#define QMI_DEF_TNUMS_THRESH 32 ++/* FPM defines */ ++#define FM_NUM_OF_FMAN_CTRL_EVENT_REGS 4 ++ ++/* DMA defines */ ++#define DMA_THRESH_MAX_COMMQ 83 ++#define DMA_THRESH_MAX_BUF 127 ++ ++/* BMI defines */ ++#define BMI_MAX_NUM_OF_TASKS 128 ++#define BMI_MAX_NUM_OF_DMAS 84 ++ ++#define BMI_MAX_FIFO_SIZE (FM_MURAM_SIZE) ++#define PORT_MAX_WEIGHT 16 ++ ++#define FM_CHECK_PORT_RESTRICTIONS(__validPorts, __newPortIndx) TRUE ++ ++/* Unique T4240 */ ++#define FM_OP_OPEN_DMA_MIN_LIMIT ++#define FM_NO_RESTRICT_ON_ACCESS_RSRC ++#define FM_NO_OP_OBSERVED_POOLS ++#define FM_FRAME_END_PARAMS_FOR_OP ++#define FM_DEQ_PIPELINE_PARAMS_FOR_OP ++#define FM_QMI_NO_SINGLE_ECC_EXCEPTION ++ ++#define FM_NO_GUARANTEED_RESET_VALUES ++ ++/* FM errata */ ++#define FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 ++#define FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 ++#define FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 ++#define FM_OP_NO_VSP_NO_RELEASE_ERRATA_FMAN_A006675 ++#define FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981 ++ ++#define FM_BCB_ERRATA_BMI_SW001 ++#define FM_LEN_CHECK_ERRATA_FMAN_SW002 ++#define FM_AID_MODE_NO_TNUM_SW005 /* refer to pdm TKT068794 - only support of port_id on aid */ ++#define FM_ERROR_VSP_NO_MATCH_SW006 /* refer to pdm TKT174304 - no match between errorQ and VSP */ ++ ++/***************************************************************************** ++ RMan INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define RM_MAX_NUM_OF_IB 4 /**< Number of inbound blocks */ ++#define RM_NUM_OF_IBCU 8 /**< NUmber of classification units in an inbound block */ ++ ++/* RMan erratas */ ++#define RM_ERRONEOUS_ACK_ERRATA_RMAN_A006756 ++ ++/***************************************************************************** ++ FM MACSEC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define NUM_OF_RX_SC 16 ++#define NUM_OF_TX_SC 16 ++ ++#define NUM_OF_SA_PER_RX_SC 2 ++#define NUM_OF_SA_PER_TX_SC 2 ++ ++#endif /* __DPAA_INTEGRATION_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3H/part_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3H/part_ext.h +new file mode 100644 +index 0000000..0d62dd1 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3H/part_ext.h +@@ -0,0 +1,71 @@ ++/* ++ * Copyright 2012 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. ++ */ ++ ++/**************************************************************************//** ++ ++ @File part_ext.h ++ ++ @Description Definitions for the part (integration) module. ++*//***************************************************************************/ ++ ++#ifndef __PART_EXT_H ++#define __PART_EXT_H ++ ++#include "std_ext.h" ++#include "part_integration_ext.h" ++ ++#if !(defined(P1023) || \ ++ defined(P2041) || \ ++ defined(P3041) || \ ++ defined(P4080) || \ ++ defined(P5020) || \ ++ defined(P5040) || \ ++ defined(B4860) || \ ++ defined(T4240)) ++#error "unable to proceed without chip-definition" ++#endif ++ ++ ++/**************************************************************************//* ++ @Description Part data structure - must be contained in any integration ++ data structure. ++*//***************************************************************************/ ++typedef struct t_Part ++{ ++ uintptr_t (* f_GetModuleBase)(t_Handle h_Part, e_ModuleId moduleId); ++ /**< Returns the address of the module's memory map base. */ ++ e_ModuleId (* f_GetModuleIdByBase)(t_Handle h_Part, uintptr_t baseAddress); ++ /**< Returns the module's ID according to its memory map base. */ ++} t_Part; ++ ++ ++#endif /* __PART_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3H/part_integration_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3H/part_integration_ext.h +new file mode 100644 +index 0000000..3254c76 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3H/part_integration_ext.h +@@ -0,0 +1,304 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/** ++ ++ @File part_integration_ext.h ++ ++ @Description T4240 external definitions and structures. ++*//***************************************************************************/ ++#ifndef __PART_INTEGRATION_EXT_H ++#define __PART_INTEGRATION_EXT_H ++ ++#include "std_ext.h" ++#include "ddr_std_ext.h" ++#include "enet_ext.h" ++#include "dpaa_integration_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group T4240_chip_id T4240 Application Programming Interface ++ ++ @Description T4240 Chip functions,definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++#define CORE_E6500 ++ ++#define INTG_MAX_NUM_OF_CORES 24 ++ ++ ++/**************************************************************************//** ++ @Description Module types. ++*//***************************************************************************/ ++typedef enum e_ModuleId ++{ ++ e_MODULE_ID_DUART_1 = 0, ++ e_MODULE_ID_DUART_2, ++ e_MODULE_ID_DUART_3, ++ e_MODULE_ID_DUART_4, ++ e_MODULE_ID_LAW, ++ e_MODULE_ID_IFC, ++ e_MODULE_ID_PAMU, ++ e_MODULE_ID_QM, /**< Queue manager module */ ++ e_MODULE_ID_BM, /**< Buffer manager module */ ++ e_MODULE_ID_QM_CE_PORTAL_0, ++ e_MODULE_ID_QM_CI_PORTAL_0, ++ e_MODULE_ID_QM_CE_PORTAL_1, ++ e_MODULE_ID_QM_CI_PORTAL_1, ++ e_MODULE_ID_QM_CE_PORTAL_2, ++ e_MODULE_ID_QM_CI_PORTAL_2, ++ e_MODULE_ID_QM_CE_PORTAL_3, ++ e_MODULE_ID_QM_CI_PORTAL_3, ++ e_MODULE_ID_QM_CE_PORTAL_4, ++ e_MODULE_ID_QM_CI_PORTAL_4, ++ e_MODULE_ID_QM_CE_PORTAL_5, ++ e_MODULE_ID_QM_CI_PORTAL_5, ++ e_MODULE_ID_QM_CE_PORTAL_6, ++ e_MODULE_ID_QM_CI_PORTAL_6, ++ e_MODULE_ID_QM_CE_PORTAL_7, ++ e_MODULE_ID_QM_CI_PORTAL_7, ++ e_MODULE_ID_QM_CE_PORTAL_8, ++ e_MODULE_ID_QM_CI_PORTAL_8, ++ e_MODULE_ID_QM_CE_PORTAL_9, ++ e_MODULE_ID_QM_CI_PORTAL_9, ++ e_MODULE_ID_BM_CE_PORTAL_0, ++ e_MODULE_ID_BM_CI_PORTAL_0, ++ e_MODULE_ID_BM_CE_PORTAL_1, ++ e_MODULE_ID_BM_CI_PORTAL_1, ++ e_MODULE_ID_BM_CE_PORTAL_2, ++ e_MODULE_ID_BM_CI_PORTAL_2, ++ e_MODULE_ID_BM_CE_PORTAL_3, ++ e_MODULE_ID_BM_CI_PORTAL_3, ++ e_MODULE_ID_BM_CE_PORTAL_4, ++ e_MODULE_ID_BM_CI_PORTAL_4, ++ e_MODULE_ID_BM_CE_PORTAL_5, ++ e_MODULE_ID_BM_CI_PORTAL_5, ++ e_MODULE_ID_BM_CE_PORTAL_6, ++ e_MODULE_ID_BM_CI_PORTAL_6, ++ e_MODULE_ID_BM_CE_PORTAL_7, ++ e_MODULE_ID_BM_CI_PORTAL_7, ++ e_MODULE_ID_BM_CE_PORTAL_8, ++ e_MODULE_ID_BM_CI_PORTAL_8, ++ e_MODULE_ID_BM_CE_PORTAL_9, ++ e_MODULE_ID_BM_CI_PORTAL_9, ++ e_MODULE_ID_FM, /**< Frame manager module */ ++ e_MODULE_ID_FM_RTC, /**< FM Real-Time-Clock */ ++ e_MODULE_ID_FM_MURAM, /**< FM Multi-User-RAM */ ++ e_MODULE_ID_FM_BMI, /**< FM BMI block */ ++ e_MODULE_ID_FM_QMI, /**< FM QMI block */ ++ e_MODULE_ID_FM_PARSER, /**< FM parser block */ ++ e_MODULE_ID_FM_PORT_HO1, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO2, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO3, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO4, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO5, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO6, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO7, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_1GRx1, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx2, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx3, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx4, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx5, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx6, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_10GRx1, /**< FM Rx 10G MAC port block */ ++ e_MODULE_ID_FM_PORT_10GRx2, /**< FM Rx 10G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx1, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx2, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx3, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx4, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx5, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx6, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_10GTx1, /**< FM Tx 10G MAC port block */ ++ e_MODULE_ID_FM_PORT_10GTx2, /**< FM Tx 10G MAC port block */ ++ e_MODULE_ID_FM_PLCR, /**< FM Policer */ ++ e_MODULE_ID_FM_KG, /**< FM Keygen */ ++ e_MODULE_ID_FM_DMA, /**< FM DMA */ ++ e_MODULE_ID_FM_FPM, /**< FM FPM */ ++ e_MODULE_ID_FM_IRAM, /**< FM Instruction-RAM */ ++ e_MODULE_ID_FM_1GMDIO, /**< FM 1G MDIO MAC */ ++ e_MODULE_ID_FM_10GMDIO, /**< FM 10G MDIO */ ++ e_MODULE_ID_FM_PRS_IRAM, /**< FM SW-parser Instruction-RAM */ ++ e_MODULE_ID_FM_1GMAC1, /**< FM 1G MAC #1 */ ++ e_MODULE_ID_FM_1GMAC2, /**< FM 1G MAC #2 */ ++ e_MODULE_ID_FM_1GMAC3, /**< FM 1G MAC #3 */ ++ e_MODULE_ID_FM_1GMAC4, /**< FM 1G MAC #4 */ ++ e_MODULE_ID_FM_1GMAC5, /**< FM 1G MAC #5 */ ++ e_MODULE_ID_FM_1GMAC6, /**< FM 1G MAC #6 */ ++ e_MODULE_ID_FM_10GMAC1, /**< FM 10G MAC */ ++ e_MODULE_ID_FM_10GMAC2, /**< FM 10G MAC */ ++ ++ e_MODULE_ID_SEC_GEN, /**< SEC 4.0 General registers */ ++ e_MODULE_ID_SEC_QI, /**< SEC 4.0 QI registers */ ++ e_MODULE_ID_SEC_JQ0, /**< SEC 4.0 JQ-0 registers */ ++ e_MODULE_ID_SEC_JQ1, /**< SEC 4.0 JQ-1 registers */ ++ e_MODULE_ID_SEC_JQ2, /**< SEC 4.0 JQ-2 registers */ ++ e_MODULE_ID_SEC_JQ3, /**< SEC 4.0 JQ-3 registers */ ++ e_MODULE_ID_SEC_RTIC, /**< SEC 4.0 RTIC registers */ ++ e_MODULE_ID_SEC_DECO0_CCB0, /**< SEC 4.0 DECO-0/CCB-0 registers */ ++ e_MODULE_ID_SEC_DECO1_CCB1, /**< SEC 4.0 DECO-1/CCB-1 registers */ ++ e_MODULE_ID_SEC_DECO2_CCB2, /**< SEC 4.0 DECO-2/CCB-2 registers */ ++ e_MODULE_ID_SEC_DECO3_CCB3, /**< SEC 4.0 DECO-3/CCB-3 registers */ ++ e_MODULE_ID_SEC_DECO4_CCB4, /**< SEC 4.0 DECO-4/CCB-4 registers */ ++ ++ e_MODULE_ID_PIC, /**< PIC */ ++ e_MODULE_ID_GPIO, /**< GPIO */ ++ e_MODULE_ID_SERDES, /**< SERDES */ ++ e_MODULE_ID_CPC_1, /**< CoreNet-Platform-Cache 1 */ ++ e_MODULE_ID_CPC_2, /**< CoreNet-Platform-Cache 2 */ ++ ++ e_MODULE_ID_SRIO_PORTS, /**< RapidIO controller */ ++ ++ e_MODULE_ID_DUMMY_LAST ++} e_ModuleId; ++ ++#define NUM_OF_MODULES e_MODULE_ID_DUMMY_LAST ++ ++#if 0 /* using unified values */ ++/***************************************************************************** ++ INTEGRATION-SPECIFIC MODULE CODES ++******************************************************************************/ ++#define MODULE_UNKNOWN 0x00000000 ++#define MODULE_MEM 0x00010000 ++#define MODULE_MM 0x00020000 ++#define MODULE_CORE 0x00030000 ++#define MODULE_T4240 0x00040000 ++#define MODULE_T4240_PLATFORM 0x00050000 ++#define MODULE_PM 0x00060000 ++#define MODULE_MMU 0x00070000 ++#define MODULE_PIC 0x00080000 ++#define MODULE_CPC 0x00090000 ++#define MODULE_DUART 0x000a0000 ++#define MODULE_SERDES 0x000b0000 ++#define MODULE_PIO 0x000c0000 ++#define MODULE_QM 0x000d0000 ++#define MODULE_BM 0x000e0000 ++#define MODULE_SEC 0x000f0000 ++#define MODULE_LAW 0x00100000 ++#define MODULE_LBC 0x00110000 ++#define MODULE_PAMU 0x00120000 ++#define MODULE_FM 0x00130000 ++#define MODULE_FM_MURAM 0x00140000 ++#define MODULE_FM_PCD 0x00150000 ++#define MODULE_FM_RTC 0x00160000 ++#define MODULE_FM_MAC 0x00170000 ++#define MODULE_FM_PORT 0x00180000 ++#define MODULE_FM_SP 0x00190000 ++#define MODULE_DPA_PORT 0x001a0000 ++#define MODULE_MII 0x001b0000 ++#define MODULE_I2C 0x001c0000 ++#define MODULE_DMA 0x001d0000 ++#define MODULE_DDR 0x001e0000 ++#define MODULE_ESPI 0x001f0000 ++#define MODULE_DPAA_IPSEC 0x00200000 ++#endif /* using unified values */ ++ ++/***************************************************************************** ++ PAMU INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define PAMU_NUM_OF_PARTITIONS 4 ++ ++/***************************************************************************** ++ LAW INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define LAW_NUM_OF_WINDOWS 32 ++#define LAW_MIN_WINDOW_SIZE 0x0000000000001000LL /**< 4 Kbytes */ ++#define LAW_MAX_WINDOW_SIZE 0x0000010000000000LL /**< 1 Tbytes for 40-bit address space */ ++ ++ ++/***************************************************************************** ++ LBC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++/**************************************************************************//** ++ @Group lbc_exception_grp LBC Exception Unit ++ ++ @Description LBC Exception unit API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Anchor lbc_exbm ++ ++ @Collection LBC Errors Bit Mask ++ ++ These errors are reported through the exceptions callback.. ++ The values can be or'ed in any combination in the errors mask ++ parameter of the errors report structure. ++ ++ These errors can also be passed as a bit-mask to ++ LBC_EnableErrorChecking() or LBC_DisableErrorChecking(), ++ for enabling or disabling error checking. ++ @{ ++*//***************************************************************************/ ++#define LBC_ERR_BUS_MONITOR 0x80000000 /**< Bus monitor error */ ++#define LBC_ERR_PARITY_ECC 0x20000000 /**< Parity error for GPCM/UPM */ ++#define LBC_ERR_WRITE_PROTECT 0x04000000 /**< Write protection error */ ++#define LBC_ERR_CHIP_SELECT 0x00080000 /**< Unrecognized chip select */ ++ ++#define LBC_ERR_ALL (LBC_ERR_BUS_MONITOR | LBC_ERR_PARITY_ECC | \ ++ LBC_ERR_WRITE_PROTECT | LBC_ERR_CHIP_SELECT) ++ /**< All possible errors */ ++/* @} */ ++/** @} */ /* end of lbc_exception_grp group */ ++ ++#define LBC_INCORRECT_ERROR_REPORT_ERRATA ++ ++#define LBC_NUM_OF_BANKS 8 ++#define LBC_MAX_CS_SIZE 0x0000000100000000LL /* Up to 4G memory block size */ ++#define LBC_PARITY_SUPPORT ++#define LBC_ADDRESS_HOLD_TIME_CTRL ++#define LBC_HIGH_CLK_DIVIDERS ++#define LBC_FCM_AVAILABLE ++ ++/***************************************************************************** ++ GPIO INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define GPIO_PORT_OFFSET_0x1000 ++ ++#define GPIO_NUM_OF_PORTS 3 /**< Number of ports in GPIO module; ++ Each port contains up to 32 I/O pins. */ ++ ++#define GPIO_VALID_PIN_MASKS \ ++ { /* Port A */ 0xFFFFFFFF, \ ++ /* Port B */ 0xFFFFFFFF, \ ++ /* Port C */ 0xFFFFFFFF } ++ ++#define GPIO_VALID_INTR_MASKS \ ++ { /* Port A */ 0xFFFFFFFF, \ ++ /* Port B */ 0xFFFFFFFF, \ ++ /* Port C */ 0xFFFFFFFF } ++ ++ ++ ++#endif /* __PART_INTEGRATION_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3L/dpaa_integration_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3L/dpaa_integration_ext.h +new file mode 100644 +index 0000000..594527e +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3L/dpaa_integration_ext.h +@@ -0,0 +1,292 @@ ++/* ++ * Copyright 2012 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. ++ */ ++ ++/** ++ ++ @File dpaa_integration_ext.h ++ ++ @Description T4240 FM external definitions and structures. ++*//***************************************************************************/ ++#ifndef __DPAA_INTEGRATION_EXT_H ++#define __DPAA_INTEGRATION_EXT_H ++ ++#include "std_ext.h" ++ ++ ++#define DPAA_VERSION 11 ++ ++/**************************************************************************//** ++ @Description DPAA SW Portals Enumeration. ++*//***************************************************************************/ ++typedef enum ++{ ++ e_DPAA_SWPORTAL0 = 0, ++ e_DPAA_SWPORTAL1, ++ e_DPAA_SWPORTAL2, ++ e_DPAA_SWPORTAL3, ++ e_DPAA_SWPORTAL4, ++ e_DPAA_SWPORTAL5, ++ e_DPAA_SWPORTAL6, ++ e_DPAA_SWPORTAL7, ++ e_DPAA_SWPORTAL8, ++ e_DPAA_SWPORTAL9, ++ e_DPAA_SWPORTAL10, ++ e_DPAA_SWPORTAL11, ++ e_DPAA_SWPORTAL12, ++ e_DPAA_SWPORTAL13, ++ e_DPAA_SWPORTAL14, ++ e_DPAA_SWPORTAL15, ++ e_DPAA_SWPORTAL16, ++ e_DPAA_SWPORTAL17, ++ e_DPAA_SWPORTAL18, ++ e_DPAA_SWPORTAL19, ++ e_DPAA_SWPORTAL20, ++ e_DPAA_SWPORTAL21, ++ e_DPAA_SWPORTAL22, ++ e_DPAA_SWPORTAL23, ++ e_DPAA_SWPORTAL24, ++ e_DPAA_SWPORTAL_DUMMY_LAST ++} e_DpaaSwPortal; ++ ++/**************************************************************************//** ++ @Description DPAA Direct Connect Portals Enumeration. ++*//***************************************************************************/ ++typedef enum ++{ ++ e_DPAA_DCPORTAL0 = 0, ++ e_DPAA_DCPORTAL1, ++ e_DPAA_DCPORTAL2, ++ e_DPAA_DCPORTAL_DUMMY_LAST ++} e_DpaaDcPortal; ++ ++#define DPAA_MAX_NUM_OF_SW_PORTALS e_DPAA_SWPORTAL_DUMMY_LAST ++#define DPAA_MAX_NUM_OF_DC_PORTALS e_DPAA_DCPORTAL_DUMMY_LAST ++ ++/***************************************************************************** ++ QMan INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define QM_MAX_NUM_OF_POOL_CHANNELS 15 /**< Total number of channels, dedicated and pool */ ++#define QM_MAX_NUM_OF_WQ 8 /**< Number of work queues per channel */ ++#define QM_MAX_NUM_OF_CGS 256 /**< Congestion groups number */ ++#define QM_MAX_NUM_OF_FQIDS (16 * MEGABYTE) ++ /**< FQIDs range - 24 bits */ ++ ++/**************************************************************************//** ++ @Description Work Queue Channel assignments in QMan. ++*//***************************************************************************/ ++typedef enum ++{ ++ e_QM_FQ_CHANNEL_SWPORTAL0 = 0x0, /**< Dedicated channels serviced by software portals 0 to 24 */ ++ e_QM_FQ_CHANNEL_SWPORTAL1, ++ e_QM_FQ_CHANNEL_SWPORTAL2, ++ e_QM_FQ_CHANNEL_SWPORTAL3, ++ e_QM_FQ_CHANNEL_SWPORTAL4, ++ e_QM_FQ_CHANNEL_SWPORTAL5, ++ e_QM_FQ_CHANNEL_SWPORTAL6, ++ e_QM_FQ_CHANNEL_SWPORTAL7, ++ e_QM_FQ_CHANNEL_SWPORTAL8, ++ e_QM_FQ_CHANNEL_SWPORTAL9, ++ e_QM_FQ_CHANNEL_SWPORTAL10, ++ e_QM_FQ_CHANNEL_SWPORTAL11, ++ e_QM_FQ_CHANNEL_SWPORTAL12, ++ e_QM_FQ_CHANNEL_SWPORTAL13, ++ e_QM_FQ_CHANNEL_SWPORTAL14, ++ e_QM_FQ_CHANNEL_SWPORTAL15, ++ e_QM_FQ_CHANNEL_SWPORTAL16, ++ e_QM_FQ_CHANNEL_SWPORTAL17, ++ e_QM_FQ_CHANNEL_SWPORTAL18, ++ e_QM_FQ_CHANNEL_SWPORTAL19, ++ e_QM_FQ_CHANNEL_SWPORTAL20, ++ e_QM_FQ_CHANNEL_SWPORTAL21, ++ e_QM_FQ_CHANNEL_SWPORTAL22, ++ e_QM_FQ_CHANNEL_SWPORTAL23, ++ e_QM_FQ_CHANNEL_SWPORTAL24, ++ ++ e_QM_FQ_CHANNEL_POOL1 = 0x401, /**< Pool channels that can be serviced by any of the software portals */ ++ e_QM_FQ_CHANNEL_POOL2, ++ e_QM_FQ_CHANNEL_POOL3, ++ e_QM_FQ_CHANNEL_POOL4, ++ e_QM_FQ_CHANNEL_POOL5, ++ e_QM_FQ_CHANNEL_POOL6, ++ e_QM_FQ_CHANNEL_POOL7, ++ e_QM_FQ_CHANNEL_POOL8, ++ e_QM_FQ_CHANNEL_POOL9, ++ e_QM_FQ_CHANNEL_POOL10, ++ e_QM_FQ_CHANNEL_POOL11, ++ e_QM_FQ_CHANNEL_POOL12, ++ e_QM_FQ_CHANNEL_POOL13, ++ e_QM_FQ_CHANNEL_POOL14, ++ e_QM_FQ_CHANNEL_POOL15, ++ ++ e_QM_FQ_CHANNEL_FMAN0_SP0 = 0x800, /**< Dedicated channels serviced by Direct Connect Portal 0: ++ connected to FMan 0; assigned in incrementing order to ++ each sub-portal (SP) in the portal */ ++ e_QM_FQ_CHANNEL_FMAN0_SP1, ++ e_QM_FQ_CHANNEL_FMAN0_SP2, ++ e_QM_FQ_CHANNEL_FMAN0_SP3, ++ e_QM_FQ_CHANNEL_FMAN0_SP4, ++ e_QM_FQ_CHANNEL_FMAN0_SP5, ++ e_QM_FQ_CHANNEL_FMAN0_SP6, ++ e_QM_FQ_CHANNEL_FMAN0_SP7, ++ e_QM_FQ_CHANNEL_FMAN0_SP8, ++ e_QM_FQ_CHANNEL_FMAN0_SP9, ++ e_QM_FQ_CHANNEL_FMAN0_SP10, ++ e_QM_FQ_CHANNEL_FMAN0_SP11, ++ e_QM_FQ_CHANNEL_FMAN0_SP12, ++ e_QM_FQ_CHANNEL_FMAN0_SP13, ++ e_QM_FQ_CHANNEL_FMAN0_SP14, ++ e_QM_FQ_CHANNEL_FMAN0_SP15, ++ ++ e_QM_FQ_CHANNEL_RMAN_SP0 = 0x820, /**< Dedicated channels serviced by Direct Connect Portal 1: connected to RMan */ ++ e_QM_FQ_CHANNEL_RMAN_SP1, ++ ++ e_QM_FQ_CHANNEL_CAAM = 0x840 /**< Dedicated channel serviced by Direct Connect Portal 2: ++ connected to SEC */ ++} e_QmFQChannel; ++ ++/***************************************************************************** ++ BMan INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define BM_MAX_NUM_OF_POOLS 64 /**< Number of buffers pools */ ++ ++/***************************************************************************** ++ SEC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define SEC_NUM_OF_DECOS 3 ++#define SEC_ALL_DECOS_MASK 0x00000003 ++ ++ ++/***************************************************************************** ++ FM INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define INTG_MAX_NUM_OF_FM 1 ++/* Ports defines */ ++#define FM_MAX_NUM_OF_1G_MACS 5 ++#define FM_MAX_NUM_OF_10G_MACS 1 ++#define FM_MAX_NUM_OF_MACS (FM_MAX_NUM_OF_1G_MACS + FM_MAX_NUM_OF_10G_MACS) ++#define FM_MAX_NUM_OF_OH_PORTS 4 ++ ++#define FM_MAX_NUM_OF_1G_RX_PORTS FM_MAX_NUM_OF_1G_MACS ++#define FM_MAX_NUM_OF_10G_RX_PORTS FM_MAX_NUM_OF_10G_MACS ++#define FM_MAX_NUM_OF_RX_PORTS (FM_MAX_NUM_OF_10G_RX_PORTS + FM_MAX_NUM_OF_1G_RX_PORTS) ++ ++#define FM_MAX_NUM_OF_1G_TX_PORTS FM_MAX_NUM_OF_1G_MACS ++#define FM_MAX_NUM_OF_10G_TX_PORTS FM_MAX_NUM_OF_10G_MACS ++#define FM_MAX_NUM_OF_TX_PORTS (FM_MAX_NUM_OF_10G_TX_PORTS + FM_MAX_NUM_OF_1G_TX_PORTS) ++ ++#define FM_MAX_NUM_OF_MACSECS 1 /* Should be updated */ ++ ++#define FM_PORT_MAX_NUM_OF_EXT_POOLS 4 /**< Number of external BM pools per Rx port */ ++#define FM_PORT_NUM_OF_CONGESTION_GRPS 256 /**< Total number of congestion groups in QM */ ++#define FM_MAX_NUM_OF_SUB_PORTALS 16 ++#define FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS 0 ++ ++#define FM_VSP_MAX_NUM_OF_ENTRIES 32 ++#define FM_MAX_NUM_OF_PFC_PRIORITIES 8 ++ ++/* RAMs defines */ ++#define FM_MURAM_SIZE (192 * KILOBYTE) ++#define FM_IRAM_SIZE(major, minor) \ ++ (((major == 6) && ((minor == 4) )) ? (64 * KILOBYTE) : (32 * KILOBYTE)) ++#define FM_NUM_OF_CTRL 2 ++ ++/* PCD defines */ ++#define FM_PCD_PLCR_NUM_ENTRIES 256 /**< Total number of policer profiles */ ++#define FM_PCD_KG_NUM_OF_SCHEMES 32 /**< Total number of KG schemes */ ++#define FM_PCD_MAX_NUM_OF_CLS_PLANS 256 /**< Number of classification plan entries. */ ++#define FM_PCD_PRS_SW_PATCHES_SIZE 0x00000600 /**< Number of bytes saved for patches */ ++#define FM_PCD_SW_PRS_SIZE 0x00000800 /**< Total size of SW parser area */ ++ ++/* RTC defines */ ++#define FM_RTC_NUM_OF_ALARMS 2 /**< RTC number of alarms */ ++#define FM_RTC_NUM_OF_PERIODIC_PULSES 3 /**< RTC number of periodic pulses */ ++#define FM_RTC_NUM_OF_EXT_TRIGGERS 2 /**< RTC number of external triggers */ ++ ++/* QMI defines */ ++#define QMI_MAX_NUM_OF_TNUMS 64 ++#define QMI_DEF_TNUMS_THRESH 32 ++/* FPM defines */ ++#define FM_NUM_OF_FMAN_CTRL_EVENT_REGS 4 ++ ++/* DMA defines */ ++#define DMA_THRESH_MAX_COMMQ 83 ++#define DMA_THRESH_MAX_BUF 127 ++ ++/* BMI defines */ ++#define BMI_MAX_NUM_OF_TASKS 64 ++#define BMI_MAX_NUM_OF_DMAS 32 ++ ++#define BMI_MAX_FIFO_SIZE (FM_MURAM_SIZE) ++#define PORT_MAX_WEIGHT 16 ++ ++#define FM_CHECK_PORT_RESTRICTIONS(__validPorts, __newPortIndx) TRUE ++ ++/* Unique T4240 */ ++#define FM_OP_OPEN_DMA_MIN_LIMIT ++#define FM_NO_RESTRICT_ON_ACCESS_RSRC ++#define FM_NO_OP_OBSERVED_POOLS ++#define FM_FRAME_END_PARAMS_FOR_OP ++#define FM_DEQ_PIPELINE_PARAMS_FOR_OP ++#define FM_QMI_NO_SINGLE_ECC_EXCEPTION ++ ++#define FM_NO_GUARANTEED_RESET_VALUES ++ ++/* FM errata */ ++#define FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 ++#define FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 ++#define FM_OP_NO_VSP_NO_RELEASE_ERRATA_FMAN_A006675 ++#define FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981 ++ ++#define FM_BCB_ERRATA_BMI_SW001 ++#define FM_LEN_CHECK_ERRATA_FMAN_SW002 ++#define FM_AID_MODE_NO_TNUM_SW005 /* refer to pdm TKT068794 - only support of port_id on aid */ ++#define FM_ERROR_VSP_NO_MATCH_SW006 /* refer to pdm TKT174304 - no match between errorQ and VSP */ ++ ++/***************************************************************************** ++ RMan INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define RM_MAX_NUM_OF_IB 4 /**< Number of inbound blocks */ ++#define RM_NUM_OF_IBCU 8 /**< NUmber of classification units in an inbound block */ ++ ++/* RMan erratas */ ++#define RM_ERRONEOUS_ACK_ERRATA_RMAN_A006756 ++ ++/***************************************************************************** ++ FM MACSEC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define NUM_OF_RX_SC 16 ++#define NUM_OF_TX_SC 16 ++ ++#define NUM_OF_SA_PER_RX_SC 2 ++#define NUM_OF_SA_PER_TX_SC 2 ++ ++#endif /* __DPAA_INTEGRATION_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3L/part_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3L/part_ext.h +new file mode 100644 +index 0000000..ba9732e +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3L/part_ext.h +@@ -0,0 +1,59 @@ ++/* ++ * Copyright 2012 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. ++ */ ++ ++/**************************************************************************//** ++ ++ @File part_ext.h ++ ++ @Description Definitions for the part (integration) module. ++*//***************************************************************************/ ++ ++#ifndef __PART_EXT_H ++#define __PART_EXT_H ++ ++#include "std_ext.h" ++#include "part_integration_ext.h" ++ ++/**************************************************************************//* ++ @Description Part data structure - must be contained in any integration ++ data structure. ++*//***************************************************************************/ ++typedef struct t_Part ++{ ++ uintptr_t (* f_GetModuleBase)(t_Handle h_Part, e_ModuleId moduleId); ++ /**< Returns the address of the module's memory map base. */ ++ e_ModuleId (* f_GetModuleIdByBase)(t_Handle h_Part, uintptr_t baseAddress); ++ /**< Returns the module's ID according to its memory map base. */ ++} t_Part; ++ ++ ++#endif /* __PART_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3L/part_integration_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3L/part_integration_ext.h +new file mode 100644 +index 0000000..3254c76 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/FMANV3L/part_integration_ext.h +@@ -0,0 +1,304 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/** ++ ++ @File part_integration_ext.h ++ ++ @Description T4240 external definitions and structures. ++*//***************************************************************************/ ++#ifndef __PART_INTEGRATION_EXT_H ++#define __PART_INTEGRATION_EXT_H ++ ++#include "std_ext.h" ++#include "ddr_std_ext.h" ++#include "enet_ext.h" ++#include "dpaa_integration_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group T4240_chip_id T4240 Application Programming Interface ++ ++ @Description T4240 Chip functions,definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++#define CORE_E6500 ++ ++#define INTG_MAX_NUM_OF_CORES 24 ++ ++ ++/**************************************************************************//** ++ @Description Module types. ++*//***************************************************************************/ ++typedef enum e_ModuleId ++{ ++ e_MODULE_ID_DUART_1 = 0, ++ e_MODULE_ID_DUART_2, ++ e_MODULE_ID_DUART_3, ++ e_MODULE_ID_DUART_4, ++ e_MODULE_ID_LAW, ++ e_MODULE_ID_IFC, ++ e_MODULE_ID_PAMU, ++ e_MODULE_ID_QM, /**< Queue manager module */ ++ e_MODULE_ID_BM, /**< Buffer manager module */ ++ e_MODULE_ID_QM_CE_PORTAL_0, ++ e_MODULE_ID_QM_CI_PORTAL_0, ++ e_MODULE_ID_QM_CE_PORTAL_1, ++ e_MODULE_ID_QM_CI_PORTAL_1, ++ e_MODULE_ID_QM_CE_PORTAL_2, ++ e_MODULE_ID_QM_CI_PORTAL_2, ++ e_MODULE_ID_QM_CE_PORTAL_3, ++ e_MODULE_ID_QM_CI_PORTAL_3, ++ e_MODULE_ID_QM_CE_PORTAL_4, ++ e_MODULE_ID_QM_CI_PORTAL_4, ++ e_MODULE_ID_QM_CE_PORTAL_5, ++ e_MODULE_ID_QM_CI_PORTAL_5, ++ e_MODULE_ID_QM_CE_PORTAL_6, ++ e_MODULE_ID_QM_CI_PORTAL_6, ++ e_MODULE_ID_QM_CE_PORTAL_7, ++ e_MODULE_ID_QM_CI_PORTAL_7, ++ e_MODULE_ID_QM_CE_PORTAL_8, ++ e_MODULE_ID_QM_CI_PORTAL_8, ++ e_MODULE_ID_QM_CE_PORTAL_9, ++ e_MODULE_ID_QM_CI_PORTAL_9, ++ e_MODULE_ID_BM_CE_PORTAL_0, ++ e_MODULE_ID_BM_CI_PORTAL_0, ++ e_MODULE_ID_BM_CE_PORTAL_1, ++ e_MODULE_ID_BM_CI_PORTAL_1, ++ e_MODULE_ID_BM_CE_PORTAL_2, ++ e_MODULE_ID_BM_CI_PORTAL_2, ++ e_MODULE_ID_BM_CE_PORTAL_3, ++ e_MODULE_ID_BM_CI_PORTAL_3, ++ e_MODULE_ID_BM_CE_PORTAL_4, ++ e_MODULE_ID_BM_CI_PORTAL_4, ++ e_MODULE_ID_BM_CE_PORTAL_5, ++ e_MODULE_ID_BM_CI_PORTAL_5, ++ e_MODULE_ID_BM_CE_PORTAL_6, ++ e_MODULE_ID_BM_CI_PORTAL_6, ++ e_MODULE_ID_BM_CE_PORTAL_7, ++ e_MODULE_ID_BM_CI_PORTAL_7, ++ e_MODULE_ID_BM_CE_PORTAL_8, ++ e_MODULE_ID_BM_CI_PORTAL_8, ++ e_MODULE_ID_BM_CE_PORTAL_9, ++ e_MODULE_ID_BM_CI_PORTAL_9, ++ e_MODULE_ID_FM, /**< Frame manager module */ ++ e_MODULE_ID_FM_RTC, /**< FM Real-Time-Clock */ ++ e_MODULE_ID_FM_MURAM, /**< FM Multi-User-RAM */ ++ e_MODULE_ID_FM_BMI, /**< FM BMI block */ ++ e_MODULE_ID_FM_QMI, /**< FM QMI block */ ++ e_MODULE_ID_FM_PARSER, /**< FM parser block */ ++ e_MODULE_ID_FM_PORT_HO1, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO2, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO3, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO4, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO5, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO6, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO7, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_1GRx1, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx2, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx3, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx4, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx5, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx6, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_10GRx1, /**< FM Rx 10G MAC port block */ ++ e_MODULE_ID_FM_PORT_10GRx2, /**< FM Rx 10G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx1, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx2, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx3, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx4, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx5, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx6, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_10GTx1, /**< FM Tx 10G MAC port block */ ++ e_MODULE_ID_FM_PORT_10GTx2, /**< FM Tx 10G MAC port block */ ++ e_MODULE_ID_FM_PLCR, /**< FM Policer */ ++ e_MODULE_ID_FM_KG, /**< FM Keygen */ ++ e_MODULE_ID_FM_DMA, /**< FM DMA */ ++ e_MODULE_ID_FM_FPM, /**< FM FPM */ ++ e_MODULE_ID_FM_IRAM, /**< FM Instruction-RAM */ ++ e_MODULE_ID_FM_1GMDIO, /**< FM 1G MDIO MAC */ ++ e_MODULE_ID_FM_10GMDIO, /**< FM 10G MDIO */ ++ e_MODULE_ID_FM_PRS_IRAM, /**< FM SW-parser Instruction-RAM */ ++ e_MODULE_ID_FM_1GMAC1, /**< FM 1G MAC #1 */ ++ e_MODULE_ID_FM_1GMAC2, /**< FM 1G MAC #2 */ ++ e_MODULE_ID_FM_1GMAC3, /**< FM 1G MAC #3 */ ++ e_MODULE_ID_FM_1GMAC4, /**< FM 1G MAC #4 */ ++ e_MODULE_ID_FM_1GMAC5, /**< FM 1G MAC #5 */ ++ e_MODULE_ID_FM_1GMAC6, /**< FM 1G MAC #6 */ ++ e_MODULE_ID_FM_10GMAC1, /**< FM 10G MAC */ ++ e_MODULE_ID_FM_10GMAC2, /**< FM 10G MAC */ ++ ++ e_MODULE_ID_SEC_GEN, /**< SEC 4.0 General registers */ ++ e_MODULE_ID_SEC_QI, /**< SEC 4.0 QI registers */ ++ e_MODULE_ID_SEC_JQ0, /**< SEC 4.0 JQ-0 registers */ ++ e_MODULE_ID_SEC_JQ1, /**< SEC 4.0 JQ-1 registers */ ++ e_MODULE_ID_SEC_JQ2, /**< SEC 4.0 JQ-2 registers */ ++ e_MODULE_ID_SEC_JQ3, /**< SEC 4.0 JQ-3 registers */ ++ e_MODULE_ID_SEC_RTIC, /**< SEC 4.0 RTIC registers */ ++ e_MODULE_ID_SEC_DECO0_CCB0, /**< SEC 4.0 DECO-0/CCB-0 registers */ ++ e_MODULE_ID_SEC_DECO1_CCB1, /**< SEC 4.0 DECO-1/CCB-1 registers */ ++ e_MODULE_ID_SEC_DECO2_CCB2, /**< SEC 4.0 DECO-2/CCB-2 registers */ ++ e_MODULE_ID_SEC_DECO3_CCB3, /**< SEC 4.0 DECO-3/CCB-3 registers */ ++ e_MODULE_ID_SEC_DECO4_CCB4, /**< SEC 4.0 DECO-4/CCB-4 registers */ ++ ++ e_MODULE_ID_PIC, /**< PIC */ ++ e_MODULE_ID_GPIO, /**< GPIO */ ++ e_MODULE_ID_SERDES, /**< SERDES */ ++ e_MODULE_ID_CPC_1, /**< CoreNet-Platform-Cache 1 */ ++ e_MODULE_ID_CPC_2, /**< CoreNet-Platform-Cache 2 */ ++ ++ e_MODULE_ID_SRIO_PORTS, /**< RapidIO controller */ ++ ++ e_MODULE_ID_DUMMY_LAST ++} e_ModuleId; ++ ++#define NUM_OF_MODULES e_MODULE_ID_DUMMY_LAST ++ ++#if 0 /* using unified values */ ++/***************************************************************************** ++ INTEGRATION-SPECIFIC MODULE CODES ++******************************************************************************/ ++#define MODULE_UNKNOWN 0x00000000 ++#define MODULE_MEM 0x00010000 ++#define MODULE_MM 0x00020000 ++#define MODULE_CORE 0x00030000 ++#define MODULE_T4240 0x00040000 ++#define MODULE_T4240_PLATFORM 0x00050000 ++#define MODULE_PM 0x00060000 ++#define MODULE_MMU 0x00070000 ++#define MODULE_PIC 0x00080000 ++#define MODULE_CPC 0x00090000 ++#define MODULE_DUART 0x000a0000 ++#define MODULE_SERDES 0x000b0000 ++#define MODULE_PIO 0x000c0000 ++#define MODULE_QM 0x000d0000 ++#define MODULE_BM 0x000e0000 ++#define MODULE_SEC 0x000f0000 ++#define MODULE_LAW 0x00100000 ++#define MODULE_LBC 0x00110000 ++#define MODULE_PAMU 0x00120000 ++#define MODULE_FM 0x00130000 ++#define MODULE_FM_MURAM 0x00140000 ++#define MODULE_FM_PCD 0x00150000 ++#define MODULE_FM_RTC 0x00160000 ++#define MODULE_FM_MAC 0x00170000 ++#define MODULE_FM_PORT 0x00180000 ++#define MODULE_FM_SP 0x00190000 ++#define MODULE_DPA_PORT 0x001a0000 ++#define MODULE_MII 0x001b0000 ++#define MODULE_I2C 0x001c0000 ++#define MODULE_DMA 0x001d0000 ++#define MODULE_DDR 0x001e0000 ++#define MODULE_ESPI 0x001f0000 ++#define MODULE_DPAA_IPSEC 0x00200000 ++#endif /* using unified values */ ++ ++/***************************************************************************** ++ PAMU INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define PAMU_NUM_OF_PARTITIONS 4 ++ ++/***************************************************************************** ++ LAW INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define LAW_NUM_OF_WINDOWS 32 ++#define LAW_MIN_WINDOW_SIZE 0x0000000000001000LL /**< 4 Kbytes */ ++#define LAW_MAX_WINDOW_SIZE 0x0000010000000000LL /**< 1 Tbytes for 40-bit address space */ ++ ++ ++/***************************************************************************** ++ LBC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++/**************************************************************************//** ++ @Group lbc_exception_grp LBC Exception Unit ++ ++ @Description LBC Exception unit API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Anchor lbc_exbm ++ ++ @Collection LBC Errors Bit Mask ++ ++ These errors are reported through the exceptions callback.. ++ The values can be or'ed in any combination in the errors mask ++ parameter of the errors report structure. ++ ++ These errors can also be passed as a bit-mask to ++ LBC_EnableErrorChecking() or LBC_DisableErrorChecking(), ++ for enabling or disabling error checking. ++ @{ ++*//***************************************************************************/ ++#define LBC_ERR_BUS_MONITOR 0x80000000 /**< Bus monitor error */ ++#define LBC_ERR_PARITY_ECC 0x20000000 /**< Parity error for GPCM/UPM */ ++#define LBC_ERR_WRITE_PROTECT 0x04000000 /**< Write protection error */ ++#define LBC_ERR_CHIP_SELECT 0x00080000 /**< Unrecognized chip select */ ++ ++#define LBC_ERR_ALL (LBC_ERR_BUS_MONITOR | LBC_ERR_PARITY_ECC | \ ++ LBC_ERR_WRITE_PROTECT | LBC_ERR_CHIP_SELECT) ++ /**< All possible errors */ ++/* @} */ ++/** @} */ /* end of lbc_exception_grp group */ ++ ++#define LBC_INCORRECT_ERROR_REPORT_ERRATA ++ ++#define LBC_NUM_OF_BANKS 8 ++#define LBC_MAX_CS_SIZE 0x0000000100000000LL /* Up to 4G memory block size */ ++#define LBC_PARITY_SUPPORT ++#define LBC_ADDRESS_HOLD_TIME_CTRL ++#define LBC_HIGH_CLK_DIVIDERS ++#define LBC_FCM_AVAILABLE ++ ++/***************************************************************************** ++ GPIO INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define GPIO_PORT_OFFSET_0x1000 ++ ++#define GPIO_NUM_OF_PORTS 3 /**< Number of ports in GPIO module; ++ Each port contains up to 32 I/O pins. */ ++ ++#define GPIO_VALID_PIN_MASKS \ ++ { /* Port A */ 0xFFFFFFFF, \ ++ /* Port B */ 0xFFFFFFFF, \ ++ /* Port C */ 0xFFFFFFFF } ++ ++#define GPIO_VALID_INTR_MASKS \ ++ { /* Port A */ 0xFFFFFFFF, \ ++ /* Port B */ 0xFFFFFFFF, \ ++ /* Port C */ 0xFFFFFFFF } ++ ++ ++ ++#endif /* __PART_INTEGRATION_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P1023/dpaa_integration_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P1023/dpaa_integration_ext.h +new file mode 100644 +index 0000000..7b5390d +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P1023/dpaa_integration_ext.h +@@ -0,0 +1,213 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/** ++ ++ @File dpaa_integration_ext.h ++ ++ @Description P1023 FM external definitions and structures. ++*//***************************************************************************/ ++#ifndef __DPAA_INTEGRATION_EXT_H ++#define __DPAA_INTEGRATION_EXT_H ++ ++#include "std_ext.h" ++ ++ ++#define DPAA_VERSION 10 ++ ++typedef enum e_DpaaSwPortal { ++ e_DPAA_SWPORTAL0 = 0, ++ e_DPAA_SWPORTAL1, ++ e_DPAA_SWPORTAL2, ++ e_DPAA_SWPORTAL_DUMMY_LAST ++} e_DpaaSwPortal; ++ ++typedef enum { ++ e_DPAA_DCPORTAL0 = 0, ++ e_DPAA_DCPORTAL2, ++ e_DPAA_DCPORTAL_DUMMY_LAST ++} e_DpaaDcPortal; ++ ++#define DPAA_MAX_NUM_OF_SW_PORTALS e_DPAA_SWPORTAL_DUMMY_LAST ++#define DPAA_MAX_NUM_OF_DC_PORTALS e_DPAA_DCPORTAL_DUMMY_LAST ++ ++/***************************************************************************** ++ QMAN INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define QM_MAX_NUM_OF_POOL_CHANNELS 3 ++#define QM_MAX_NUM_OF_WQ 8 ++#define QM_MAX_NUM_OF_SWP_AS 2 ++#define QM_MAX_NUM_OF_CGS 64 ++#define QM_MAX_NUM_OF_FQIDS (16*MEGABYTE) ++ ++typedef enum { ++ e_QM_FQ_CHANNEL_SWPORTAL0 = 0, ++ e_QM_FQ_CHANNEL_SWPORTAL1, ++ e_QM_FQ_CHANNEL_SWPORTAL2, ++ ++ e_QM_FQ_CHANNEL_POOL1 = 0x21, ++ e_QM_FQ_CHANNEL_POOL2, ++ e_QM_FQ_CHANNEL_POOL3, ++ ++ e_QM_FQ_CHANNEL_FMAN0_SP0 = 0x40, ++ e_QM_FQ_CHANNEL_FMAN0_SP1, ++ e_QM_FQ_CHANNEL_FMAN0_SP2, ++ e_QM_FQ_CHANNEL_FMAN0_SP3, ++ e_QM_FQ_CHANNEL_FMAN0_SP4, ++ e_QM_FQ_CHANNEL_FMAN0_SP5, ++ e_QM_FQ_CHANNEL_FMAN0_SP6, ++ ++ ++ e_QM_FQ_CHANNEL_CAAM = 0x80 ++} e_QmFQChannel; ++ ++/***************************************************************************** ++ BMAN INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define BM_MAX_NUM_OF_POOLS 8 ++ ++/***************************************************************************** ++ SEC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define SEC_NUM_OF_DECOS 2 ++#define SEC_ALL_DECOS_MASK 0x00000003 ++#define SEC_RNGB ++#define SEC_NO_ESP_TRAILER_REMOVAL ++ ++/***************************************************************************** ++ FM INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define INTG_MAX_NUM_OF_FM 1 ++ ++/* Ports defines */ ++#define FM_MAX_NUM_OF_1G_MACS 2 ++#define FM_MAX_NUM_OF_10G_MACS 0 ++#define FM_MAX_NUM_OF_MACS (FM_MAX_NUM_OF_1G_MACS + FM_MAX_NUM_OF_10G_MACS) ++#define FM_MAX_NUM_OF_OH_PORTS 5 ++ ++#define FM_MAX_NUM_OF_1G_RX_PORTS FM_MAX_NUM_OF_1G_MACS ++#define FM_MAX_NUM_OF_10G_RX_PORTS FM_MAX_NUM_OF_10G_MACS ++#define FM_MAX_NUM_OF_RX_PORTS (FM_MAX_NUM_OF_10G_RX_PORTS + FM_MAX_NUM_OF_1G_RX_PORTS) ++ ++#define FM_MAX_NUM_OF_1G_TX_PORTS FM_MAX_NUM_OF_1G_MACS ++#define FM_MAX_NUM_OF_10G_TX_PORTS FM_MAX_NUM_OF_10G_MACS ++#define FM_MAX_NUM_OF_TX_PORTS (FM_MAX_NUM_OF_10G_TX_PORTS + FM_MAX_NUM_OF_1G_TX_PORTS) ++ ++#define FM_MAX_NUM_OF_MACSECS 1 ++ ++#define FM_MACSEC_SUPPORT ++ ++#define FM_LOW_END_RESTRICTION /* prevents the use of TX port 1 with OP port 0 */ ++ ++#define FM_PORT_MAX_NUM_OF_EXT_POOLS 4 /**< Number of external BM pools per Rx port */ ++#define FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS 2 /**< Number of Offline parsing port external BM pools per Rx port */ ++#define FM_PORT_NUM_OF_CONGESTION_GRPS 32 /**< Total number of congestion groups in QM */ ++#define FM_MAX_NUM_OF_SUB_PORTALS 7 ++ ++/* Rams defines */ ++#define FM_MURAM_SIZE (64*KILOBYTE) ++#define FM_IRAM_SIZE(major, minor) (32 * KILOBYTE) ++#define FM_NUM_OF_CTRL 2 ++ ++/* PCD defines */ ++#define FM_PCD_PLCR_NUM_ENTRIES 32 /**< Total number of policer profiles */ ++#define FM_PCD_KG_NUM_OF_SCHEMES 16 /**< Total number of KG schemes */ ++#define FM_PCD_MAX_NUM_OF_CLS_PLANS 128 /**< Number of classification plan entries. */ ++#define FM_PCD_PRS_SW_PATCHES_SIZE 0x00000240 /**< Number of bytes saved for patches */ ++#define FM_PCD_SW_PRS_SIZE 0x00000800 /**< Total size of SW parser area */ ++ ++/* RTC defines */ ++#define FM_RTC_NUM_OF_ALARMS 2 ++#define FM_RTC_NUM_OF_PERIODIC_PULSES 2 ++#define FM_RTC_NUM_OF_EXT_TRIGGERS 2 ++ ++/* QMI defines */ ++#define QMI_MAX_NUM_OF_TNUMS 15 ++ ++/* FPM defines */ ++#define FM_NUM_OF_FMAN_CTRL_EVENT_REGS 4 ++ ++/* DMA defines */ ++#define DMA_THRESH_MAX_COMMQ 15 ++#define DMA_THRESH_MAX_BUF 7 ++ ++/* BMI defines */ ++#define BMI_MAX_NUM_OF_TASKS 64 ++#define BMI_MAX_NUM_OF_DMAS 16 ++#define BMI_MAX_FIFO_SIZE (FM_MURAM_SIZE) ++#define PORT_MAX_WEIGHT 4 ++ ++/***************************************************************************** ++ FM MACSEC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define NUM_OF_RX_SC 16 ++#define NUM_OF_TX_SC 16 ++ ++#define NUM_OF_SA_PER_RX_SC 2 ++#define NUM_OF_SA_PER_TX_SC 2 ++ ++/**************************************************************************//** ++ @Description Enum for inter-module interrupts registration ++*//***************************************************************************/ ++ ++/* 1023 unique features */ ++#define FM_QMI_NO_ECC_EXCEPTIONS ++#define FM_CSI_CFED_LIMIT ++#define FM_PEDANTIC_DMA ++#define FM_QMI_NO_DEQ_OPTIONS_SUPPORT ++#define FM_FIFO_ALLOCATION_ALG ++#define FM_DEQ_PIPELINE_PARAMS_FOR_OP ++#define FM_HAS_TOTAL_DMAS ++#define FM_KG_NO_IPPID_SUPPORT ++#define FM_NO_GUARANTEED_RESET_VALUES ++#define FM_MAC_RESET ++ ++/* FM erratas */ ++#define FM_RX_PREAM_4_ERRATA_DTSEC_A001 ++#define FM_MAGIC_PACKET_UNRECOGNIZED_ERRATA_DTSEC2 /* No implementation, Out of LLD scope */ ++ ++#define FM_DEBUG_TRACE_FMAN_A004 /* No implementation, Out of LLD scope */ ++#define FM_INT_BUF_LEAK_FMAN_A005 /* No implementation, Out of LLD scope. App must avoid S/G */ ++ ++#define FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 ++ ++/* #define FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */ ++ ++/* ++TKT056919 - axi12axi0 can hang if read request follows the single byte write on the very next cycle ++TKT038900 - FM dma lockup occur due to AXI slave protocol violation ++*/ ++#define FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 ++ ++ ++#endif /* __DPAA_INTEGRATION_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P1023/part_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P1023/part_ext.h +new file mode 100644 +index 0000000..6814d5f +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P1023/part_ext.h +@@ -0,0 +1,82 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/**************************************************************************//** ++ ++ @File part_ext.h ++ ++ @Description Definitions for the part (integration) module. ++*//***************************************************************************/ ++ ++#ifndef __PART_EXT_H ++#define __PART_EXT_H ++ ++#include "std_ext.h" ++#include "part_integration_ext.h" ++ ++ ++#if !(defined(MPC8306) || \ ++ defined(MPC8309) || \ ++ defined(MPC834x) || \ ++ defined(MPC836x) || \ ++ defined(MPC832x) || \ ++ defined(MPC837x) || \ ++ defined(MPC8568) || \ ++ defined(MPC8569) || \ ++ defined(P1020) || \ ++ defined(P1021) || \ ++ defined(P1022) || \ ++ defined(P1023) || \ ++ defined(P2020) || \ ++ defined(P3041) || \ ++ defined(P4080) || \ ++ defined(P5020) || \ ++ defined(MSC814x)) ++#error "unable to proceed without chip-definition" ++#endif ++ ++ ++/**************************************************************************//* ++ @Description Part data structure - must be contained in any integration ++ data structure. ++*//***************************************************************************/ ++typedef struct t_Part ++{ ++ uint64_t (* f_GetModuleBase)(t_Handle h_Part, e_ModuleId moduleId); ++ /**< Returns the address of the module's memory map base. */ ++ e_ModuleId (* f_GetModuleIdByBase)(t_Handle h_Part, uint64_t baseAddress); ++ /**< Returns the module's ID according to its memory map base. */ ++} t_Part; ++ ++ ++#endif /* __PART_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P1023/part_integration_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P1023/part_integration_ext.h +new file mode 100644 +index 0000000..e838283 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P1023/part_integration_ext.h +@@ -0,0 +1,635 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++/**************************************************************************//** ++ @File part_integration_ext.h ++ ++ @Description P1023 external definitions and structures. ++*//***************************************************************************/ ++#ifndef __PART_INTEGRATION_EXT_H ++#define __PART_INTEGRATION_EXT_H ++ ++#include "std_ext.h" ++#include "dpaa_integration_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group 1023_chip_id P1023 Application Programming Interface ++ ++ @Description P1023 Chip functions,definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++#define INTG_MAX_NUM_OF_CORES 2 ++ ++ ++/**************************************************************************//** ++ @Description Module types. ++*//***************************************************************************/ ++typedef enum e_ModuleId ++{ ++ e_MODULE_ID_LAW, /**< Local Access module */ ++ e_MODULE_ID_ECM, /**< e500 Coherency Module */ ++ e_MODULE_ID_DDR, /**< DDR memory controller */ ++ e_MODULE_ID_I2C_1, /**< I2C 1 */ ++ e_MODULE_ID_I2C_2, /**< I2C 1 */ ++ e_MODULE_ID_DUART_1, /**< DUART module 1 */ ++ e_MODULE_ID_DUART_2, /**< DUART module 2 */ ++ e_MODULE_ID_LBC, /**< Local bus memory controller module */ ++ e_MODULE_ID_PCIE_1, /**< PCI Express 1 controller module */ ++ e_MODULE_ID_PCIE_ATMU_1, /**< PCI 1 ATMU Window */ ++ e_MODULE_ID_PCIE_2, /**< PCI Express 2 controller module */ ++ e_MODULE_ID_PCIE_ATMU_2, /**< PCI 2 ATMU Window */ ++ e_MODULE_ID_PCIE_3, /**< PCI Express 3 controller module */ ++ e_MODULE_ID_PCIE_ATMU_3, /**< PCI 3 ATMU Window */ ++ e_MODULE_ID_MSI, /**< MSI registers */ ++ e_MODULE_ID_L2_SRAM, /**< L2/SRAM Memory-Mapped controller module */ ++ e_MODULE_ID_DMA_1, /**< DMA controller 1 */ ++ e_MODULE_ID_DMA_2, /**< DMA controller 2 */ ++ e_MODULE_ID_EPIC, /**< Programmable interrupt controller */ ++ e_MODULE_ID_ESPI, /**< ESPI module */ ++ e_MODULE_ID_GPIO, /**< General Purpose I/O */ ++ e_MODULE_ID_SEC_GEN, /**< SEC 4.0 General registers */ ++ e_MODULE_ID_SEC_QI, /**< SEC 4.0 QI registers */ ++ e_MODULE_ID_SEC_JQ0, /**< SEC 4.0 JQ-0 registers */ ++ e_MODULE_ID_SEC_JQ1, /**< SEC 4.0 JQ-1 registers */ ++ e_MODULE_ID_SEC_JQ2, /**< SEC 4.0 JQ-2 registers */ ++ e_MODULE_ID_SEC_JQ3, /**< SEC 4.0 JQ-3 registers */ ++ e_MODULE_ID_SEC_RTIC, /**< SEC 4.0 RTIC registers */ ++ e_MODULE_ID_SEC_DECO0_CCB0, /**< SEC 4.0 DECO-0/CCB-0 registers */ ++ e_MODULE_ID_SEC_DECO1_CCB1, /**< SEC 4.0 DECO-1/CCB-1 registers */ ++ e_MODULE_ID_SEC_DECO2_CCB2, /**< SEC 4.0 DECO-2/CCB-2 registers */ ++ e_MODULE_ID_SEC_DECO3_CCB3, /**< SEC 4.0 DECO-3/CCB-3 registers */ ++ e_MODULE_ID_SEC_DECO4_CCB4, /**< SEC 4.0 DECO-4/CCB-4 registers */ ++ e_MODULE_ID_USB_DR_1, /**< USB 2.0 module 1 */ ++ e_MODULE_ID_USB_DR_2, /**< USB 2.0 module 2 */ ++ e_MODULE_ID_ETSEC_MII_MNG, /**< MII MNG registers */ ++ e_MODULE_ID_ETSEC_1, /**< ETSEC module 1 */ ++ e_MODULE_ID_ETSEC_2, /**< ETSEC module 2 */ ++ e_MODULE_ID_GUTS, /**< Serial DMA */ ++ e_MODULE_ID_PM, /**< Performance Monitor module */ ++ e_MODULE_ID_QM, /**< Queue manager module */ ++ e_MODULE_ID_BM, /**< Buffer manager module */ ++ e_MODULE_ID_QM_CE_PORTAL, ++ e_MODULE_ID_QM_CI_PORTAL, ++ e_MODULE_ID_BM_CE_PORTAL, ++ e_MODULE_ID_BM_CI_PORTAL, ++ e_MODULE_ID_FM, /**< Frame manager #1 module */ ++ e_MODULE_ID_FM_RTC, /**< FM Real-Time-Clock */ ++ e_MODULE_ID_FM_MURAM, /**< FM Multi-User-RAM */ ++ e_MODULE_ID_FM_BMI, /**< FM BMI block */ ++ e_MODULE_ID_FM_QMI, /**< FM QMI block */ ++ e_MODULE_ID_FM_PRS, /**< FM parser block */ ++ e_MODULE_ID_FM_PORT_HO0, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO1, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO2, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO3, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO4, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_1GRx0, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx1, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx0, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx1, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PLCR, /**< FM Policer */ ++ e_MODULE_ID_FM_KG, /**< FM Keygen */ ++ e_MODULE_ID_FM_DMA, /**< FM DMA */ ++ e_MODULE_ID_FM_FPM, /**< FM FPM */ ++ e_MODULE_ID_FM_IRAM, /**< FM Instruction-RAM */ ++ e_MODULE_ID_FM_1GMDIO0, /**< FM 1G MDIO MAC 0*/ ++ e_MODULE_ID_FM_1GMDIO1, /**< FM 1G MDIO MAC 1*/ ++ e_MODULE_ID_FM_PRS_IRAM, /**< FM SW-parser Instruction-RAM */ ++ e_MODULE_ID_FM_RISC0, /**< FM risc #0 */ ++ e_MODULE_ID_FM_RISC1, /**< FM risc #1 */ ++ e_MODULE_ID_FM_1GMAC0, /**< FM 1G MAC #0 */ ++ e_MODULE_ID_FM_1GMAC1, /**< FM 1G MAC #1 */ ++ e_MODULE_ID_FM_MACSEC, /**< FM MACSEC */ ++ ++ e_MODULE_ID_DUMMY_LAST ++} e_ModuleId; ++ ++#define NUM_OF_MODULES e_MODULE_ID_DUMMY_LAST ++ ++ ++#define P1023_OFFSET_LAW 0x00000C08 ++#define P1023_OFFSET_ECM 0x00001000 ++#define P1023_OFFSET_DDR 0x00002000 ++#define P1023_OFFSET_I2C1 0x00003000 ++#define P1023_OFFSET_I2C2 0x00003100 ++#define P1023_OFFSET_DUART1 0x00004500 ++#define P1023_OFFSET_DUART2 0x00004600 ++#define P1023_OFFSET_LBC 0x00005000 ++#define P1023_OFFSET_ESPI 0x00007000 ++#define P1023_OFFSET_PCIE2 0x00009000 ++#define P1023_OFFSET_PCIE2_ATMU 0x00009C00 ++#define P1023_OFFSET_PCIE1 0x0000A000 ++#define P1023_OFFSET_PCIE1_ATMU 0x0000AC00 ++#define P1023_OFFSET_PCIE3 0x0000B000 ++#define P1023_OFFSET_PCIE3_ATMU 0x0000BC00 ++#define P1023_OFFSET_DMA2 0x0000C100 ++#define P1023_OFFSET_GPIO 0x0000F000 ++#define P1023_OFFSET_L2_SRAM 0x00020000 ++#define P1023_OFFSET_DMA1 0x00021100 ++#define P1023_OFFSET_USB1 0x00022000 ++#define P1023_OFFSET_SEC_GEN 0x00030000 ++#define P1023_OFFSET_SEC_JQ0 0x00031000 ++#define P1023_OFFSET_SEC_JQ1 0x00032000 ++#define P1023_OFFSET_SEC_JQ2 0x00033000 ++#define P1023_OFFSET_SEC_JQ3 0x00034000 ++#define P1023_OFFSET_SEC_RTIC 0x00036000 ++#define P1023_OFFSET_SEC_QI 0x00037000 ++#define P1023_OFFSET_SEC_DECO0_CCB0 0x00038000 ++#define P1023_OFFSET_SEC_DECO1_CCB1 0x00039000 ++#define P1023_OFFSET_SEC_DECO2_CCB2 0x0003a000 ++#define P1023_OFFSET_SEC_DECO3_CCB3 0x0003b000 ++#define P1023_OFFSET_SEC_DECO4_CCB4 0x0003c000 ++#define P1023_OFFSET_PIC 0x00040000 ++#define P1023_OFFSET_MSI 0x00041600 ++#define P1023_OFFSET_AXI 0x00081000 ++#define P1023_OFFSET_QM 0x00088000 ++#define P1023_OFFSET_BM 0x0008A000 ++#define P1022_OFFSET_PM 0x000E1000 ++ ++#define P1023_OFFSET_GUTIL 0x000E0000 ++#define P1023_OFFSET_PM 0x000E1000 ++#define P1023_OFFSET_DEBUG 0x000E2000 ++#define P1023_OFFSET_SERDES 0x000E3000 ++#define P1023_OFFSET_ROM 0x000F0000 ++#define P1023_OFFSET_FM 0x00100000 ++ ++#define P1023_OFFSET_FM_MURAM (P1023_OFFSET_FM + 0x00000000) ++#define P1023_OFFSET_FM_BMI (P1023_OFFSET_FM + 0x00080000) ++#define P1023_OFFSET_FM_QMI (P1023_OFFSET_FM + 0x00080400) ++#define P1023_OFFSET_FM_PRS (P1023_OFFSET_FM + 0x00080800) ++#define P1023_OFFSET_FM_PORT_HO0 (P1023_OFFSET_FM + 0x00081000) ++#define P1023_OFFSET_FM_PORT_HO1 (P1023_OFFSET_FM + 0x00082000) ++#define P1023_OFFSET_FM_PORT_HO2 (P1023_OFFSET_FM + 0x00083000) ++#define P1023_OFFSET_FM_PORT_HO3 (P1023_OFFSET_FM + 0x00084000) ++#define P1023_OFFSET_FM_PORT_HO4 (P1023_OFFSET_FM + 0x00085000) ++#define P1023_OFFSET_FM_PORT_1GRX0 (P1023_OFFSET_FM + 0x00088000) ++#define P1023_OFFSET_FM_PORT_1GRX1 (P1023_OFFSET_FM + 0x00089000) ++#define P1023_OFFSET_FM_PORT_1GTX0 (P1023_OFFSET_FM + 0x000A8000) ++#define P1023_OFFSET_FM_PORT_1GTX1 (P1023_OFFSET_FM + 0x000A9000) ++#define P1023_OFFSET_FM_PLCR (P1023_OFFSET_FM + 0x000C0000) ++#define P1023_OFFSET_FM_KG (P1023_OFFSET_FM + 0x000C1000) ++#define P1023_OFFSET_FM_DMA (P1023_OFFSET_FM + 0x000C2000) ++#define P1023_OFFSET_FM_FPM (P1023_OFFSET_FM + 0x000C3000) ++#define P1023_OFFSET_FM_IRAM (P1023_OFFSET_FM + 0x000C4000) ++#define P1023_OFFSET_FM_PRS_IRAM (P1023_OFFSET_FM + 0x000C7000) ++#define P1023_OFFSET_FM_RISC0 (P1023_OFFSET_FM + 0x000D0000) ++#define P1023_OFFSET_FM_RISC1 (P1023_OFFSET_FM + 0x000D0400) ++#define P1023_OFFSET_FM_MACSEC (P1023_OFFSET_FM + 0x000D8000) ++#define P1023_OFFSET_FM_1GMAC0 (P1023_OFFSET_FM + 0x000E0000) ++#define P1023_OFFSET_FM_1GMDIO0 (P1023_OFFSET_FM + 0x000E1120) ++#define P1023_OFFSET_FM_1GMAC1 (P1023_OFFSET_FM + 0x000E2000) ++#define P1023_OFFSET_FM_1GMDIO1 (P1023_OFFSET_FM + 0x000E3000) ++#define P1023_OFFSET_FM_RTC (P1023_OFFSET_FM + 0x000FE000) ++ ++/* Offsets relative to QM or BM portals base */ ++#define P1023_OFFSET_PORTALS_CE_AREA 0x00000000 /* cache enabled area */ ++#define P1023_OFFSET_PORTALS_CI_AREA 0x00100000 /* cache inhibited area */ ++ ++#define P1023_OFFSET_PORTALS_CE(portal) (P1023_OFFSET_PORTALS_CE_AREA + 0x4000 * (portal)) ++#define P1023_OFFSET_PORTALS_CI(portal) (P1023_OFFSET_PORTALS_CI_AREA + 0x1000 * (portal)) ++ ++/**************************************************************************//** ++ @Description Transaction source ID (for memory controllers error reporting). ++*//***************************************************************************/ ++typedef enum e_TransSrc ++{ ++ e_TRANS_SRC_PCIE_2 = 0x01, /**< PCIe port 2 */ ++ e_TRANS_SRC_PCIE_1 = 0x02, /**< PCIe port 1 */ ++ e_TRANS_SRC_PCIE_3 = 0x03, /**< PCIe port 3 */ ++ e_TRANS_SRC_LBC = 0x04, /**< Enhanced local bus */ ++ e_TRANS_SRC_DPAA_SW_PORTALS = 0x0E, /**< DPAA software portals or SRAM */ ++ e_TRANS_SRC_DDR = 0x0F, /**< DDR controller */ ++ e_TRANS_SRC_CORE_INS_FETCH = 0x10, /**< Processor (instruction) */ ++ e_TRANS_SRC_CORE_DATA = 0x11, /**< Processor (data) */ ++ e_TRANS_SRC_DMA = 0x15 /**< DMA */ ++} e_TransSrc; ++ ++/**************************************************************************//** ++ @Description Local Access Window Target interface ID ++*//***************************************************************************/ ++typedef enum e_P1023LawTargetId ++{ ++ e_P1023_LAW_TARGET_PCIE_2 = 0x01, /**< PCI Express 2 target interface */ ++ e_P1023_LAW_TARGET_PCIE_1 = 0x02, /**< PCI Express 1 target interface */ ++ e_P1023_LAW_TARGET_PCIE_3 = 0x03, /**< PCI Express 3 target interface */ ++ e_P1023_LAW_TARGET_LBC = 0x04, /**< Local bus target interface */ ++ e_P1023_LAW_TARGET_QM_PORTALS = 0x0E, /**< Queue Manager Portals */ ++ e_P1023_LAW_TARGET_BM_PORTALS = 0x0E, /**< Buffer Manager Portals */ ++ e_P1023_LAW_TARGET_SRAM = 0x0E, /**< SRAM scratchpad */ ++ e_P1023_LAW_TARGET_DDR = 0x0F, /**< DDR target interface */ ++ e_P1023_LAW_TARGET_NONE = 0xFF /**< Invalid target interface */ ++} e_P1023LawTargetId; ++ ++ ++/**************************************************************************//** ++ @Group 1023_init_grp P1023 Initialization Unit ++ ++ @Description P1023 initialization unit API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description Part ID and revision number ++*//***************************************************************************/ ++typedef enum e_P1023DeviceName ++{ ++ e_P1023_REV_INVALID = 0x00000000, /**< Invalid revision */ ++ e_SC1023_REV_1_0 = (int)0x80FC0010, /**< SC1023 rev 1.0 */ ++ e_SC1023_REV_1_1 = (int)0x80FC0011, /**< SC1023 rev 1.1 */ ++ e_P1023_REV_1_0 = (int)0x80FE0010, /**< P1023 rev 1.0 with security */ ++ e_P1023_REV_1_1 = (int)0x80FE0011, /**< P1023 rev 1.1 with security */ ++ e_P1017_REV_1_1 = (int)0x80FF0011, /**< P1017 rev 1.1 with security */ ++ e_P1023_REV_1_0_NO_SEC = (int)0x80F60010, /**< P1023 rev 1.0 without security */ ++ e_P1023_REV_1_1_NO_SEC = (int)0x80F60011, /**< P1023 rev 1.1 without security */ ++ e_P1017_REV_1_1_NO_SEC = (int)0x80F70011 /**< P1017 rev 1.1 without security */ ++} e_P1023DeviceName; ++ ++/**************************************************************************//** ++ @Description structure representing P1023 initialization parameters ++*//***************************************************************************/ ++typedef struct t_P1023Params ++{ ++ uintptr_t ccsrBaseAddress; /**< CCSR base address (virtual) */ ++ uintptr_t bmPortalsBaseAddress; /**< Portals base address (virtual) */ ++ uintptr_t qmPortalsBaseAddress; /**< Portals base address (virtual) */ ++} t_P1023Params; ++ ++/**************************************************************************//** ++ @Function P1023_ConfigAndInit ++ ++ @Description General initiation of the chip registers. ++ ++ @Param[in] p_P1023Params - A pointer to data structure of parameters ++ ++ @Return A handle to the P1023 data structure. ++*//***************************************************************************/ ++t_Handle P1023_ConfigAndInit(t_P1023Params *p_P1023Params); ++ ++/**************************************************************************//** ++ @Function P1023_Free ++ ++ @Description Free all resources. ++ ++ @Param h_P1023 - (In) The handle of the initialized P1023 object. ++ ++ @Return E_OK on success; Other value otherwise. ++*//***************************************************************************/ ++t_Error P1023_Free(t_Handle h_P1023); ++ ++/**************************************************************************//** ++ @Function P1023_GetRevInfo ++ ++ @Description This routine enables access to chip and revision information. ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ ++ @Return Part ID and revision. ++*//***************************************************************************/ ++e_P1023DeviceName P1023_GetRevInfo(uintptr_t gutilBase); ++ ++/**************************************************************************//** ++ @Function P1023_GetE500Factor ++ ++ @Description Returns E500 core clock multiplication factor. ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ @Param[in] coreId - Id of the requested core. ++ @Param[out] p_E500MulFactor - Returns E500 to CCB multification factor. ++ @Param[out] p_E500DivFactor - Returns E500 to CCB division factor. ++ ++ @Return E_OK on success; Other value otherwise. ++* ++*//***************************************************************************/ ++t_Error P1023_GetE500Factor(uintptr_t gutilBase, ++ uint32_t coreId, ++ uint32_t *p_E500MulFactor, ++ uint32_t *p_E500DivFactor); ++ ++/**************************************************************************//** ++ @Function P1023_GetFmFactor ++ ++ @Description returns FM multiplication factors. (This value is returned using ++ two parameters to avoid using float parameter). ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ @Param[out] p_FmMulFactor - returns E500 to CCB multification factor. ++ @Param[out] p_FmDivFactor - returns E500 to CCB division factor. ++ ++ @Return E_OK on success; Other value otherwise. ++*//***************************************************************************/ ++t_Error P1023_GetFmFactor(uintptr_t gutilBase, uint32_t *p_FmMulFactor, uint32_t *p_FmDivFactor); ++ ++/**************************************************************************//** ++ @Function P1023_GetCcbFactor ++ ++ @Description returns system multiplication factor. ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ ++ @Return System multiplication factor. ++*//***************************************************************************/ ++uint32_t P1023_GetCcbFactor(uintptr_t gutilBase); ++ ++#if 0 ++/**************************************************************************//** ++ @Function P1023_GetDdrFactor ++ ++ @Description returns the multiplication factor of the clock in for the DDR clock . ++ Note: assumes the ddr_in_clk is identical to the sys_in_clk ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ @Param p_DdrMulFactor - returns DDR in clk multification factor. ++ @Param p_DdrDivFactor - returns DDR division factor. ++ ++ @Return E_OK on success; Other value otherwise.. ++*//***************************************************************************/ ++t_Error P1023_GetDdrFactor( uintptr_t gutilBase, ++ uint32_t *p_DdrMulFactor, ++ uint32_t *p_DdrDivFactor); ++ ++/**************************************************************************//** ++ @Function P1023_GetDdrType ++ ++ @Description returns the multiplication factor of the clock in for the DDR clock . ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ @Param p_DdrType - (Out) returns DDR type DDR1/DDR2/DDR3. ++ ++ @Return E_OK on success; Other value otherwise. ++*//***************************************************************************/ ++t_Error P1023_GetDdrType(uintptr_t gutilBase, e_DdrType *p_DdrType ); ++#endif ++ ++/** @} */ /* end of 1023_init_grp group */ ++/** @} */ /* end of 1023_grp group */ ++ ++#define CORE_E500V2 ++ ++#if 0 /* using unified values */ ++/***************************************************************************** ++ INTEGRATION-SPECIFIC MODULE CODES ++******************************************************************************/ ++#define MODULE_UNKNOWN 0x00000000 ++#define MODULE_MEM 0x00010000 ++#define MODULE_MM 0x00020000 ++#define MODULE_CORE 0x00030000 ++#define MODULE_P1023 0x00040000 ++#define MODULE_MII 0x00050000 ++#define MODULE_PM 0x00060000 ++#define MODULE_MMU 0x00070000 ++#define MODULE_PIC 0x00080000 ++#define MODULE_L2_CACHE 0x00090000 ++#define MODULE_DUART 0x000a0000 ++#define MODULE_SERDES 0x000b0000 ++#define MODULE_PIO 0x000c0000 ++#define MODULE_QM 0x000d0000 ++#define MODULE_BM 0x000e0000 ++#define MODULE_SEC 0x000f0000 ++#define MODULE_FM 0x00100000 ++#define MODULE_FM_MURAM 0x00110000 ++#define MODULE_FM_PCD 0x00120000 ++#define MODULE_FM_RTC 0x00130000 ++#define MODULE_FM_MAC 0x00140000 ++#define MODULE_FM_PORT 0x00150000 ++#define MODULE_FM_MACSEC 0x00160000 ++#define MODULE_FM_MACSEC_SECY 0x00170000 ++#define MODULE_FM_SP 0x00280000 ++#define MODULE_ECM 0x00190000 ++#define MODULE_DMA 0x001a0000 ++#define MODULE_DDR 0x001b0000 ++#define MODULE_LAW 0x001c0000 ++#define MODULE_LBC 0x001d0000 ++#define MODULE_I2C 0x001e0000 ++#define MODULE_ESPI 0x001f0000 ++#define MODULE_PCI 0x00200000 ++#define MODULE_DPA_PORT 0x00210000 ++#define MODULE_USB 0x00220000 ++#endif /* using unified values */ ++ ++/***************************************************************************** ++ LBC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++/**************************************************************************//** ++ @Group lbc_exception_grp LBC Exception Unit ++ ++ @Description LBC Exception unit API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Anchor lbc_exbm ++ ++ @Collection LBC Errors Bit Mask ++ ++ These errors are reported through the exceptions callback.. ++ The values can be or'ed in any combination in the errors mask ++ parameter of the errors report structure. ++ ++ These errors can also be passed as a bit-mask to ++ LBC_EnableErrorChecking() or LBC_DisableErrorChecking(), ++ for enabling or disabling error checking. ++ @{ ++*//***************************************************************************/ ++#define LBC_ERR_BUS_MONITOR 0x80000000 /**< Bus monitor error */ ++#define LBC_ERR_PARITY_ECC 0x20000000 /**< Parity error for GPCM/UPM */ ++#define LBC_ERR_WRITE_PROTECT 0x04000000 /**< Write protection error */ ++#define LBC_ERR_CHIP_SELECT 0x00080000 /**< Unrecognized chip select */ ++ ++#define LBC_ERR_ALL (LBC_ERR_BUS_MONITOR | LBC_ERR_PARITY_ECC | \ ++ LBC_ERR_WRITE_PROTECT | LBC_ERR_CHIP_SELECT) ++ /**< All possible errors */ ++/* @} */ ++/** @} */ /* end of lbc_exception_grp group */ ++ ++#define LBC_NUM_OF_BANKS 2 ++#define LBC_MAX_CS_SIZE 0x0000000100000000LL ++#define LBC_ATOMIC_OPERATION_SUPPORT ++#define LBC_PARITY_SUPPORT ++#define LBC_ADDRESS_SHIFT_SUPPORT ++#define LBC_ADDRESS_HOLD_TIME_CTRL ++#define LBC_HIGH_CLK_DIVIDERS ++#define LBC_FCM_AVAILABLE ++ ++ ++/***************************************************************************** ++ LAW INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define LAW_ARCH_CCB ++#define LAW_NUM_OF_WINDOWS 12 ++#define LAW_MIN_WINDOW_SIZE 0x0000000000001000LL /**< 4KB */ ++#define LAW_MAX_WINDOW_SIZE 0x0000001000000000LL /**< 32GB */ ++ ++ ++/***************************************************************************** ++ SPI INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define SPI_NUM_OF_CONTROLLERS 1 ++ ++/***************************************************************************** ++ PCI/PCIe INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++ ++#define PCI_MAX_INBOUND_WINDOWS_NUM 4 ++#define PCI_MAX_OUTBOUND_WINDOWS_NUM 5 ++ ++/**************************************************************************//** ++ @Description Target interface of an inbound window ++*//***************************************************************************/ ++typedef enum e_PciTargetInterface ++{ ++ e_PCI_TARGET_PCIE_2 = 0x1, /**< PCI Express target interface 2 */ ++ e_PCI_TARGET_PCIE_1 = 0x2, /**< PCI Express target interface 1 */ ++ e_PCI_TARGET_PCIE_3 = 0x3, /**< PCI Express target interface 3 */ ++ e_PCI_TARGET_LOCAL_MEMORY = 0xF /**< Local Memory (DDR SDRAM, Local Bus, SRAM) target interface */ ++ ++} e_PciTargetInterface; ++ ++/***************************************************************************** ++ DDR INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define DDR_NUM_OF_VALID_CS 2 ++ ++/***************************************************************************** ++ SEC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define SEC_ERRATA_STAT_REGS_UNUSABLE ++ ++/***************************************************************************** ++ DMA INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define DMA_NUM_OF_CONTROLLERS 2 ++ ++ ++ ++ ++/***************************************************************************** ++ 1588 INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define PTP_V2 ++ ++/**************************************************************************//** ++ @Function P1023_GetMuxControlReg ++ ++ @Description Returns the value of PMUXCR (Alternate Function Signal Multiplex ++ Control Register) ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ ++ @Return Value of PMUXCR ++*//***************************************************************************/ ++uint32_t P1023_GetMuxControlReg(uintptr_t gutilBase); ++ ++/**************************************************************************//** ++ @Function P1023_SetMuxControlReg ++ ++ @Description Sets the value of PMUXCR (Alternate Function Signal Multiplex ++ Control Register) ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ @Param[in] val - the new value for PMUXCR. ++ ++ @Return None ++*//***************************************************************************/ ++void P1023_SetMuxControlReg(uintptr_t gutilBase, uint32_t val); ++ ++/**************************************************************************//** ++ @Function P1023_GetDeviceDisableStatusRegister ++ ++ @Description Returns the value of DEVDISR (Device Disable Register) ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ ++ @Return Value of DEVDISR ++*//***************************************************************************/ ++uint32_t P1023_GetDeviceDisableStatusRegister(uintptr_t gutilBase); ++ ++/**************************************************************************//** ++ @Function P1023_GetPorDeviceStatusRegister ++ ++ @Description Returns the value of POR Device Status Register ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ ++ @Return POR Device Status Register ++*//***************************************************************************/ ++uint32_t P1023_GetPorDeviceStatusRegister(uintptr_t gutilBase); ++ ++/**************************************************************************//** ++ @Function P1023_GetPorBootModeStatusRegister ++ ++ @Description Returns the value of POR Boot Mode Status Register ++ ++ @Param[in] gutilBase - Base address of P1023 GUTIL registers. ++ ++ @Return POR Boot Mode Status Register value ++*//***************************************************************************/ ++uint32_t P1023_GetPorBootModeStatusRegister(uintptr_t gutilBase); ++ ++ ++#define PORDEVSR_SGMII1_DIS 0x10000000 ++#define PORDEVSR_SGMII2_DIS 0x08000000 ++#define PORDEVSR_ECP1 0x02000000 ++#define PORDEVSR_IO_SEL 0x00780000 ++#define PORDEVSR_IO_SEL_SHIFT 19 ++#define PORBMSR_HA 0x00070000 ++#define PORBMSR_HA_SHIFT 16 ++ ++#define DEVDISR_QM_BM 0x80000000 ++#define DEVDISR_FM 0x40000000 ++#define DEVDISR_PCIE1 0x20000000 ++#define DEVDISR_MAC_SEC 0x10000000 ++#define DEVDISR_ELBC 0x08000000 ++#define DEVDISR_PCIE2 0x04000000 ++#define DEVDISR_PCIE3 0x02000000 ++#define DEVDISR_CAAM 0x01000000 ++#define DEVDISR_USB0 0x00800000 ++#define DEVDISR_1588 0x00020000 ++#define DEVDISR_CORE0 0x00008000 ++#define DEVDISR_TB0 0x00004000 ++#define DEVDISR_CORE1 0x00002000 ++#define DEVDISR_TB1 0x00001000 ++#define DEVDISR_DMA1 0x00000400 ++#define DEVDISR_DMA2 0x00000200 ++#define DEVDISR_DDR 0x00000010 ++#define DEVDISR_TSEC1 0x00000080 ++#define DEVDISR_TSEC2 0x00000040 ++#define DEVDISR_SPI 0x00000008 ++#define DEVDISR_I2C 0x00000004 ++#define DEVDISR_DUART 0x00000002 ++ ++ ++#endif /* __PART_INTEGRATION_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P3040_P4080_P5020/dpaa_integration_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P3040_P4080_P5020/dpaa_integration_ext.h +new file mode 100644 +index 0000000..6e2b925 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P3040_P4080_P5020/dpaa_integration_ext.h +@@ -0,0 +1,276 @@ ++/* Copyright (c) 2009-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++/**************************************************************************//** ++ @File dpaa_integration_ext.h ++ ++ @Description P3040/P4080/P5020 FM external definitions and structures. ++*//***************************************************************************/ ++#ifndef __DPAA_INTEGRATION_EXT_H ++#define __DPAA_INTEGRATION_EXT_H ++ ++#include "std_ext.h" ++ ++ ++#define DPAA_VERSION 10 ++ ++typedef enum { ++ e_DPAA_SWPORTAL0 = 0, ++ e_DPAA_SWPORTAL1, ++ e_DPAA_SWPORTAL2, ++ e_DPAA_SWPORTAL3, ++ e_DPAA_SWPORTAL4, ++ e_DPAA_SWPORTAL5, ++ e_DPAA_SWPORTAL6, ++ e_DPAA_SWPORTAL7, ++ e_DPAA_SWPORTAL8, ++ e_DPAA_SWPORTAL9, ++ e_DPAA_SWPORTAL_DUMMY_LAST ++} e_DpaaSwPortal; ++ ++typedef enum { ++ e_DPAA_DCPORTAL0 = 0, ++ e_DPAA_DCPORTAL1, ++ e_DPAA_DCPORTAL2, ++ e_DPAA_DCPORTAL3, ++ e_DPAA_DCPORTAL4, ++ e_DPAA_DCPORTAL_DUMMY_LAST ++} e_DpaaDcPortal; ++ ++#define DPAA_MAX_NUM_OF_SW_PORTALS e_DPAA_SWPORTAL_DUMMY_LAST ++#define DPAA_MAX_NUM_OF_DC_PORTALS e_DPAA_DCPORTAL_DUMMY_LAST ++ ++/***************************************************************************** ++ QMan INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define QM_MAX_NUM_OF_POOL_CHANNELS 15 /**< Total number of channels, dedicated and pool */ ++#define QM_MAX_NUM_OF_WQ 8 /**< Number of work queues per channel */ ++#define QM_MAX_NUM_OF_SWP_AS 4 ++#define QM_MAX_NUM_OF_CGS 256 /**< Number of congestion groups */ ++#define QM_MAX_NUM_OF_FQIDS (16 * MEGABYTE) /**< FQIDs range - 24 bits */ ++ ++/**************************************************************************//** ++ @Description Work Queue Channel assignments in QMan. ++*//***************************************************************************/ ++typedef enum ++{ ++ e_QM_FQ_CHANNEL_SWPORTAL0 = 0, /**< Dedicated channels serviced by software portals 0 to 9 */ ++ e_QM_FQ_CHANNEL_SWPORTAL1, ++ e_QM_FQ_CHANNEL_SWPORTAL2, ++ e_QM_FQ_CHANNEL_SWPORTAL3, ++ e_QM_FQ_CHANNEL_SWPORTAL4, ++ e_QM_FQ_CHANNEL_SWPORTAL5, ++ e_QM_FQ_CHANNEL_SWPORTAL6, ++ e_QM_FQ_CHANNEL_SWPORTAL7, ++ e_QM_FQ_CHANNEL_SWPORTAL8, ++ e_QM_FQ_CHANNEL_SWPORTAL9, ++ ++ e_QM_FQ_CHANNEL_POOL1 = 0x21, /**< Pool channels that can be serviced by any of the software portals */ ++ e_QM_FQ_CHANNEL_POOL2, ++ e_QM_FQ_CHANNEL_POOL3, ++ e_QM_FQ_CHANNEL_POOL4, ++ e_QM_FQ_CHANNEL_POOL5, ++ e_QM_FQ_CHANNEL_POOL6, ++ e_QM_FQ_CHANNEL_POOL7, ++ e_QM_FQ_CHANNEL_POOL8, ++ e_QM_FQ_CHANNEL_POOL9, ++ e_QM_FQ_CHANNEL_POOL10, ++ e_QM_FQ_CHANNEL_POOL11, ++ e_QM_FQ_CHANNEL_POOL12, ++ e_QM_FQ_CHANNEL_POOL13, ++ e_QM_FQ_CHANNEL_POOL14, ++ e_QM_FQ_CHANNEL_POOL15, ++ ++ e_QM_FQ_CHANNEL_FMAN0_SP0 = 0x40, /**< Dedicated channels serviced by Direct Connect Portal 0: ++ connected to FMan 0; assigned in incrementing order to ++ each sub-portal (SP) in the portal */ ++ e_QM_FQ_CHANNEL_FMAN0_SP1, ++ e_QM_FQ_CHANNEL_FMAN0_SP2, ++ e_QM_FQ_CHANNEL_FMAN0_SP3, ++ e_QM_FQ_CHANNEL_FMAN0_SP4, ++ e_QM_FQ_CHANNEL_FMAN0_SP5, ++ e_QM_FQ_CHANNEL_FMAN0_SP6, ++ e_QM_FQ_CHANNEL_FMAN0_SP7, ++ e_QM_FQ_CHANNEL_FMAN0_SP8, ++ e_QM_FQ_CHANNEL_FMAN0_SP9, ++ e_QM_FQ_CHANNEL_FMAN0_SP10, ++ e_QM_FQ_CHANNEL_FMAN0_SP11, ++/* difference between 5020 and 4080 :) */ ++ e_QM_FQ_CHANNEL_FMAN1_SP0 = 0x60, ++ e_QM_FQ_CHANNEL_FMAN1_SP1, ++ e_QM_FQ_CHANNEL_FMAN1_SP2, ++ e_QM_FQ_CHANNEL_FMAN1_SP3, ++ e_QM_FQ_CHANNEL_FMAN1_SP4, ++ e_QM_FQ_CHANNEL_FMAN1_SP5, ++ e_QM_FQ_CHANNEL_FMAN1_SP6, ++ e_QM_FQ_CHANNEL_FMAN1_SP7, ++ e_QM_FQ_CHANNEL_FMAN1_SP8, ++ e_QM_FQ_CHANNEL_FMAN1_SP9, ++ e_QM_FQ_CHANNEL_FMAN1_SP10, ++ e_QM_FQ_CHANNEL_FMAN1_SP11, ++ ++ e_QM_FQ_CHANNEL_CAAM = 0x80, /**< Dedicated channel serviced by Direct Connect Portal 2: ++ connected to SEC 4.x */ ++ ++ e_QM_FQ_CHANNEL_PME = 0xA0, /**< Dedicated channel serviced by Direct Connect Portal 3: ++ connected to PME */ ++ e_QM_FQ_CHANNEL_RAID = 0xC0 /**< Dedicated channel serviced by Direct Connect Portal 4: ++ connected to RAID */ ++} e_QmFQChannel; ++ ++/***************************************************************************** ++ BMan INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define BM_MAX_NUM_OF_POOLS 64 /**< Number of buffers pools */ ++ ++ ++/***************************************************************************** ++ FM INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define INTG_MAX_NUM_OF_FM 2 ++ ++/* Ports defines */ ++#define FM_MAX_NUM_OF_1G_MACS 5 ++#define FM_MAX_NUM_OF_10G_MACS 1 ++#define FM_MAX_NUM_OF_MACS (FM_MAX_NUM_OF_1G_MACS + FM_MAX_NUM_OF_10G_MACS) ++#define FM_MAX_NUM_OF_OH_PORTS 7 ++ ++#define FM_MAX_NUM_OF_1G_RX_PORTS FM_MAX_NUM_OF_1G_MACS ++#define FM_MAX_NUM_OF_10G_RX_PORTS FM_MAX_NUM_OF_10G_MACS ++#define FM_MAX_NUM_OF_RX_PORTS (FM_MAX_NUM_OF_10G_RX_PORTS + FM_MAX_NUM_OF_1G_RX_PORTS) ++ ++#define FM_MAX_NUM_OF_1G_TX_PORTS FM_MAX_NUM_OF_1G_MACS ++#define FM_MAX_NUM_OF_10G_TX_PORTS FM_MAX_NUM_OF_10G_MACS ++#define FM_MAX_NUM_OF_TX_PORTS (FM_MAX_NUM_OF_10G_TX_PORTS + FM_MAX_NUM_OF_1G_TX_PORTS) ++ ++#define FM_PORT_MAX_NUM_OF_EXT_POOLS 8 /**< Number of external BM pools per Rx port */ ++#define FM_PORT_NUM_OF_CONGESTION_GRPS 256 /**< Total number of congestion groups in QM */ ++#define FM_MAX_NUM_OF_SUB_PORTALS 12 ++#define FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS 0 ++ ++/* Rams defines */ ++#define FM_MURAM_SIZE (160*KILOBYTE) ++#define FM_IRAM_SIZE(major, minor) (64 * KILOBYTE) ++#define FM_NUM_OF_CTRL 2 ++ ++/* PCD defines */ ++#define FM_PCD_PLCR_NUM_ENTRIES 256 /**< Total number of policer profiles */ ++#define FM_PCD_KG_NUM_OF_SCHEMES 32 /**< Total number of KG schemes */ ++#define FM_PCD_MAX_NUM_OF_CLS_PLANS 256 /**< Number of classification plan entries. */ ++#define FM_PCD_PRS_SW_PATCHES_SIZE 0x00000200 /**< Number of bytes saved for patches */ ++#define FM_PCD_SW_PRS_SIZE 0x00000800 /**< Total size of SW parser area */ ++ ++/* RTC defines */ ++#define FM_RTC_NUM_OF_ALARMS 2 /**< RTC number of alarms */ ++#define FM_RTC_NUM_OF_PERIODIC_PULSES 2 /**< RTC number of periodic pulses */ ++#define FM_RTC_NUM_OF_EXT_TRIGGERS 2 /**< RTC number of external triggers */ ++ ++/* QMI defines */ ++#define QMI_MAX_NUM_OF_TNUMS 64 ++#define QMI_DEF_TNUMS_THRESH 48 ++ ++/* FPM defines */ ++#define FM_NUM_OF_FMAN_CTRL_EVENT_REGS 4 ++ ++/* DMA defines */ ++#define DMA_THRESH_MAX_COMMQ 31 ++#define DMA_THRESH_MAX_BUF 127 ++ ++/* BMI defines */ ++#define BMI_MAX_NUM_OF_TASKS 128 ++#define BMI_MAX_NUM_OF_DMAS 32 ++#define BMI_MAX_FIFO_SIZE (FM_MURAM_SIZE) ++#define PORT_MAX_WEIGHT 16 ++ ++ ++#define FM_CHECK_PORT_RESTRICTIONS(__validPorts, __newPortIndx) TRUE ++ ++/* p4080-rev1 unique features */ ++#define QM_CGS_NO_FRAME_MODE ++ ++/* p4080 unique features */ ++#define FM_NO_DISPATCH_RAM_ECC ++#define FM_NO_WATCHDOG ++#define FM_NO_TNUM_AGING ++#define FM_KG_NO_BYPASS_FQID_GEN ++#define FM_KG_NO_BYPASS_PLCR_PROFILE_GEN ++#define FM_NO_BACKUP_POOLS ++#define FM_NO_OP_OBSERVED_POOLS ++#define FM_NO_ADVANCED_RATE_LIMITER ++#define FM_NO_OP_OBSERVED_CGS ++#define FM_HAS_TOTAL_DMAS ++#define FM_KG_NO_IPPID_SUPPORT ++#define FM_NO_GUARANTEED_RESET_VALUES ++#define FM_MAC_RESET ++ ++/* FM erratas */ ++#define FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 ++#define FM_TX_SHORT_FRAME_BAD_TS_ERRATA_10GMAC_A006 /* No implementation, Out of LLD scope */ ++#define FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007 ++#define FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008 ++#define FM_TX_INVALID_ECC_ERRATA_10GMAC_A009 /* Out of LLD scope, user may disable ECC exceptions using FM_DisableRamsEcc */ ++#define FM_BAD_VLAN_DETECT_ERRATA_10GMAC_A010 ++ ++#define FM_RX_PREAM_4_ERRATA_DTSEC_A001 ++#define FM_GRS_ERRATA_DTSEC_A002 ++#define FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 ++#define FM_GTS_ERRATA_DTSEC_A004 ++#define FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012 ++#define FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 ++#define FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 ++ ++#define FM_MAGIC_PACKET_UNRECOGNIZED_ERRATA_DTSEC2 /* No implementation, Out of LLD scope */ ++#define FM_TX_LOCKUP_ERRATA_DTSEC6 ++ ++#define FM_HC_DEF_FQID_ONLY_ERRATA_FMAN_A003 /* Implemented by ucode */ ++#define FM_DEBUG_TRACE_FMAN_A004 /* No implementation, Out of LLD scope */ ++ ++#define FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 ++ ++#define FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005 ++ ++#define FM_LEN_CHECK_ERRATA_FMAN_SW002 ++ ++#define FM_NO_CTXA_COPY_ERRATA_FMAN_SW001 ++#define FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004 ++ ++/***************************************************************************** ++ FM MACSEC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define NUM_OF_RX_SC 16 ++#define NUM_OF_TX_SC 16 ++ ++#define NUM_OF_SA_PER_RX_SC 2 ++#define NUM_OF_SA_PER_TX_SC 2 ++ ++ ++#endif /* __DPAA_INTEGRATION_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P3040_P4080_P5020/part_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P3040_P4080_P5020/part_ext.h +new file mode 100644 +index 0000000..512f0ba +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P3040_P4080_P5020/part_ext.h +@@ -0,0 +1,83 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/**************************************************************************//** ++ ++ @File part_ext.h ++ ++ @Description Definitions for the part (integration) module. ++*//***************************************************************************/ ++ ++#ifndef __PART_EXT_H ++#define __PART_EXT_H ++ ++#include "std_ext.h" ++#include "part_integration_ext.h" ++ ++ ++#if !(defined(MPC8306) || \ ++ defined(MPC8309) || \ ++ defined(MPC834x) || \ ++ defined(MPC836x) || \ ++ defined(MPC832x) || \ ++ defined(MPC837x) || \ ++ defined(MPC8568) || \ ++ defined(MPC8569) || \ ++ defined(P1020) || \ ++ defined(P1021) || \ ++ defined(P1022) || \ ++ defined(P1023) || \ ++ defined(P2020) || \ ++ defined(P2040) || \ ++ defined(P3041) || \ ++ defined(P4080) || \ ++ defined(SC4080) || \ ++ defined(P5020) || \ ++ defined(MSC814x)) ++#error "unable to proceed without chip-definition" ++#endif /* !(defined(MPC834x) || ... */ ++ ++ ++/**************************************************************************//* ++ @Description Part data structure - must be contained in any integration ++ data structure. ++*//***************************************************************************/ ++typedef struct t_Part ++{ ++ uintptr_t (* f_GetModuleBase)(t_Handle h_Part, e_ModuleId moduleId); ++ /**< Returns the address of the module's memory map base. */ ++ e_ModuleId (* f_GetModuleIdByBase)(t_Handle h_Part, uintptr_t baseAddress); ++ /**< Returns the module's ID according to its memory map base. */ ++} t_Part; ++ ++ ++#endif /* __PART_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P3040_P4080_P5020/part_integration_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P3040_P4080_P5020/part_integration_ext.h +new file mode 100644 +index 0000000..03c59b8 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/P3040_P4080_P5020/part_integration_ext.h +@@ -0,0 +1,336 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++/**************************************************************************//** ++ @File part_integration_ext.h ++ ++ @Description P3040/P4080/P5020 external definitions and structures. ++*//***************************************************************************/ ++#ifndef __PART_INTEGRATION_EXT_H ++#define __PART_INTEGRATION_EXT_H ++ ++#include "std_ext.h" ++#include "dpaa_integration_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group P3040/P4080/P5020_chip_id P5020 Application Programming Interface ++ ++ @Description P3040/P4080/P5020 Chip functions,definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++#define CORE_E500MC ++ ++#define INTG_MAX_NUM_OF_CORES 1 ++ ++ ++/**************************************************************************//** ++ @Description Module types. ++*//***************************************************************************/ ++typedef enum e_ModuleId ++{ ++ e_MODULE_ID_DUART_1 = 0, ++ e_MODULE_ID_DUART_2, ++ e_MODULE_ID_DUART_3, ++ e_MODULE_ID_DUART_4, ++ e_MODULE_ID_LAW, ++ e_MODULE_ID_LBC, ++ e_MODULE_ID_PAMU, ++ e_MODULE_ID_QM, /**< Queue manager module */ ++ e_MODULE_ID_BM, /**< Buffer manager module */ ++ e_MODULE_ID_QM_CE_PORTAL_0, ++ e_MODULE_ID_QM_CI_PORTAL_0, ++ e_MODULE_ID_QM_CE_PORTAL_1, ++ e_MODULE_ID_QM_CI_PORTAL_1, ++ e_MODULE_ID_QM_CE_PORTAL_2, ++ e_MODULE_ID_QM_CI_PORTAL_2, ++ e_MODULE_ID_QM_CE_PORTAL_3, ++ e_MODULE_ID_QM_CI_PORTAL_3, ++ e_MODULE_ID_QM_CE_PORTAL_4, ++ e_MODULE_ID_QM_CI_PORTAL_4, ++ e_MODULE_ID_QM_CE_PORTAL_5, ++ e_MODULE_ID_QM_CI_PORTAL_5, ++ e_MODULE_ID_QM_CE_PORTAL_6, ++ e_MODULE_ID_QM_CI_PORTAL_6, ++ e_MODULE_ID_QM_CE_PORTAL_7, ++ e_MODULE_ID_QM_CI_PORTAL_7, ++ e_MODULE_ID_QM_CE_PORTAL_8, ++ e_MODULE_ID_QM_CI_PORTAL_8, ++ e_MODULE_ID_QM_CE_PORTAL_9, ++ e_MODULE_ID_QM_CI_PORTAL_9, ++ e_MODULE_ID_BM_CE_PORTAL_0, ++ e_MODULE_ID_BM_CI_PORTAL_0, ++ e_MODULE_ID_BM_CE_PORTAL_1, ++ e_MODULE_ID_BM_CI_PORTAL_1, ++ e_MODULE_ID_BM_CE_PORTAL_2, ++ e_MODULE_ID_BM_CI_PORTAL_2, ++ e_MODULE_ID_BM_CE_PORTAL_3, ++ e_MODULE_ID_BM_CI_PORTAL_3, ++ e_MODULE_ID_BM_CE_PORTAL_4, ++ e_MODULE_ID_BM_CI_PORTAL_4, ++ e_MODULE_ID_BM_CE_PORTAL_5, ++ e_MODULE_ID_BM_CI_PORTAL_5, ++ e_MODULE_ID_BM_CE_PORTAL_6, ++ e_MODULE_ID_BM_CI_PORTAL_6, ++ e_MODULE_ID_BM_CE_PORTAL_7, ++ e_MODULE_ID_BM_CI_PORTAL_7, ++ e_MODULE_ID_BM_CE_PORTAL_8, ++ e_MODULE_ID_BM_CI_PORTAL_8, ++ e_MODULE_ID_BM_CE_PORTAL_9, ++ e_MODULE_ID_BM_CI_PORTAL_9, ++ e_MODULE_ID_FM1, /**< Frame manager #1 module */ ++ e_MODULE_ID_FM1_RTC, /**< FM Real-Time-Clock */ ++ e_MODULE_ID_FM1_MURAM, /**< FM Multi-User-RAM */ ++ e_MODULE_ID_FM1_BMI, /**< FM BMI block */ ++ e_MODULE_ID_FM1_QMI, /**< FM QMI block */ ++ e_MODULE_ID_FM1_PRS, /**< FM parser block */ ++ e_MODULE_ID_FM1_PORT_HO0, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM1_PORT_HO1, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM1_PORT_HO2, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM1_PORT_HO3, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM1_PORT_HO4, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM1_PORT_HO5, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM1_PORT_HO6, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM1_PORT_1GRx0, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GRx1, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GRx2, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GRx3, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GRx4, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_10GRx0, /**< FM Rx 10G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GTx0, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GTx1, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GTx2, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GTx3, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_1GTx4, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM1_PORT_10GTx0, /**< FM Tx 10G MAC port block */ ++ e_MODULE_ID_FM1_PLCR, /**< FM Policer */ ++ e_MODULE_ID_FM1_KG, /**< FM Keygen */ ++ e_MODULE_ID_FM1_DMA, /**< FM DMA */ ++ e_MODULE_ID_FM1_FPM, /**< FM FPM */ ++ e_MODULE_ID_FM1_IRAM, /**< FM Instruction-RAM */ ++ e_MODULE_ID_FM1_1GMDIO0, /**< FM 1G MDIO MAC 0*/ ++ e_MODULE_ID_FM1_1GMDIO1, /**< FM 1G MDIO MAC 1*/ ++ e_MODULE_ID_FM1_1GMDIO2, /**< FM 1G MDIO MAC 2*/ ++ e_MODULE_ID_FM1_1GMDIO3, /**< FM 1G MDIO MAC 3*/ ++ e_MODULE_ID_FM1_10GMDIO, /**< FM 10G MDIO */ ++ e_MODULE_ID_FM1_PRS_IRAM, /**< FM SW-parser Instruction-RAM */ ++ e_MODULE_ID_FM1_1GMAC0, /**< FM 1G MAC #0 */ ++ e_MODULE_ID_FM1_1GMAC1, /**< FM 1G MAC #1 */ ++ e_MODULE_ID_FM1_1GMAC2, /**< FM 1G MAC #2 */ ++ e_MODULE_ID_FM1_1GMAC3, /**< FM 1G MAC #3 */ ++ e_MODULE_ID_FM1_10GMAC0, /**< FM 10G MAC #0 */ ++ ++ e_MODULE_ID_FM2, /**< Frame manager #2 module */ ++ e_MODULE_ID_FM2_RTC, /**< FM Real-Time-Clock */ ++ e_MODULE_ID_FM2_MURAM, /**< FM Multi-User-RAM */ ++ e_MODULE_ID_FM2_BMI, /**< FM BMI block */ ++ e_MODULE_ID_FM2_QMI, /**< FM QMI block */ ++ e_MODULE_ID_FM2_PRS, /**< FM parser block */ ++ e_MODULE_ID_FM2_PORT_HO0, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM2_PORT_HO1, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM2_PORT_HO2, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM2_PORT_HO3, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM2_PORT_HO4, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM2_PORT_HO5, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM2_PORT_HO6, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM2_PORT_1GRx0, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM2_PORT_1GRx1, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM2_PORT_1GRx2, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM2_PORT_1GRx3, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM2_PORT_10GRx0, /**< FM Rx 10G MAC port block */ ++ e_MODULE_ID_FM2_PORT_1GTx0, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM2_PORT_1GTx1, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM2_PORT_1GTx2, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM2_PORT_1GTx3, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM2_PORT_10GTx0, /**< FM Tx 10G MAC port block */ ++ e_MODULE_ID_FM2_PLCR, /**< FM Policer */ ++ e_MODULE_ID_FM2_KG, /**< FM Keygen */ ++ e_MODULE_ID_FM2_DMA, /**< FM DMA */ ++ e_MODULE_ID_FM2_FPM, /**< FM FPM */ ++ e_MODULE_ID_FM2_IRAM, /**< FM Instruction-RAM */ ++ e_MODULE_ID_FM2_1GMDIO0, /**< FM 1G MDIO MAC 0*/ ++ e_MODULE_ID_FM2_1GMDIO1, /**< FM 1G MDIO MAC 1*/ ++ e_MODULE_ID_FM2_1GMDIO2, /**< FM 1G MDIO MAC 2*/ ++ e_MODULE_ID_FM2_1GMDIO3, /**< FM 1G MDIO MAC 3*/ ++ e_MODULE_ID_FM2_10GMDIO, /**< FM 10G MDIO */ ++ e_MODULE_ID_FM2_PRS_IRAM, /**< FM SW-parser Instruction-RAM */ ++ e_MODULE_ID_FM2_1GMAC0, /**< FM 1G MAC #0 */ ++ e_MODULE_ID_FM2_1GMAC1, /**< FM 1G MAC #1 */ ++ e_MODULE_ID_FM2_1GMAC2, /**< FM 1G MAC #2 */ ++ e_MODULE_ID_FM2_1GMAC3, /**< FM 1G MAC #3 */ ++ e_MODULE_ID_FM2_10GMAC0, /**< FM 10G MAC #0 */ ++ ++ e_MODULE_ID_SEC_GEN, /**< SEC 4.0 General registers */ ++ e_MODULE_ID_SEC_QI, /**< SEC 4.0 QI registers */ ++ e_MODULE_ID_SEC_JQ0, /**< SEC 4.0 JQ-0 registers */ ++ e_MODULE_ID_SEC_JQ1, /**< SEC 4.0 JQ-1 registers */ ++ e_MODULE_ID_SEC_JQ2, /**< SEC 4.0 JQ-2 registers */ ++ e_MODULE_ID_SEC_JQ3, /**< SEC 4.0 JQ-3 registers */ ++ e_MODULE_ID_SEC_RTIC, /**< SEC 4.0 RTIC registers */ ++ e_MODULE_ID_SEC_DECO0_CCB0, /**< SEC 4.0 DECO-0/CCB-0 registers */ ++ e_MODULE_ID_SEC_DECO1_CCB1, /**< SEC 4.0 DECO-1/CCB-1 registers */ ++ e_MODULE_ID_SEC_DECO2_CCB2, /**< SEC 4.0 DECO-2/CCB-2 registers */ ++ e_MODULE_ID_SEC_DECO3_CCB3, /**< SEC 4.0 DECO-3/CCB-3 registers */ ++ e_MODULE_ID_SEC_DECO4_CCB4, /**< SEC 4.0 DECO-4/CCB-4 registers */ ++ ++ e_MODULE_ID_MPIC, /**< MPIC */ ++ e_MODULE_ID_GPIO, /**< GPIO */ ++ e_MODULE_ID_SERDES, /**< SERDES */ ++ e_MODULE_ID_CPC_1, /**< CoreNet-Platform-Cache 1 */ ++ e_MODULE_ID_CPC_2, /**< CoreNet-Platform-Cache 2 */ ++ ++ e_MODULE_ID_SRIO_PORTS, /**< RapidIO controller */ ++ e_MODULE_ID_SRIO_MU, /**< RapidIO messaging unit module */ ++ ++ e_MODULE_ID_DUMMY_LAST ++} e_ModuleId; ++ ++#define NUM_OF_MODULES e_MODULE_ID_DUMMY_LAST ++ ++#if 0 /* using unified values */ ++/***************************************************************************** ++ INTEGRATION-SPECIFIC MODULE CODES ++******************************************************************************/ ++#define MODULE_UNKNOWN 0x00000000 ++#define MODULE_MEM 0x00010000 ++#define MODULE_MM 0x00020000 ++#define MODULE_CORE 0x00030000 ++#define MODULE_CHIP 0x00040000 ++#define MODULE_PLTFRM 0x00050000 ++#define MODULE_PM 0x00060000 ++#define MODULE_MMU 0x00070000 ++#define MODULE_PIC 0x00080000 ++#define MODULE_CPC 0x00090000 ++#define MODULE_DUART 0x000a0000 ++#define MODULE_SERDES 0x000b0000 ++#define MODULE_PIO 0x000c0000 ++#define MODULE_QM 0x000d0000 ++#define MODULE_BM 0x000e0000 ++#define MODULE_SEC 0x000f0000 ++#define MODULE_LAW 0x00100000 ++#define MODULE_LBC 0x00110000 ++#define MODULE_PAMU 0x00120000 ++#define MODULE_FM 0x00130000 ++#define MODULE_FM_MURAM 0x00140000 ++#define MODULE_FM_PCD 0x00150000 ++#define MODULE_FM_RTC 0x00160000 ++#define MODULE_FM_MAC 0x00170000 ++#define MODULE_FM_PORT 0x00180000 ++#define MODULE_FM_SP 0x00190000 ++#define MODULE_DPA_PORT 0x001a0000 ++#define MODULE_MII 0x001b0000 ++#define MODULE_I2C 0x001c0000 ++#define MODULE_DMA 0x001d0000 ++#define MODULE_DDR 0x001e0000 ++#define MODULE_ESPI 0x001f0000 ++#define MODULE_DPAA_IPSEC 0x00200000 ++#endif /* using unified values */ ++ ++/***************************************************************************** ++ PAMU INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define PAMU_NUM_OF_PARTITIONS 5 ++ ++#define PAMU_PICS_AVICS_ERRATA_PAMU3 ++ ++/***************************************************************************** ++ LAW INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define LAW_NUM_OF_WINDOWS 32 ++#define LAW_MIN_WINDOW_SIZE 0x0000000000001000LL /**< 4KB */ ++#define LAW_MAX_WINDOW_SIZE 0x0000002000000000LL /**< 64GB */ ++ ++ ++/***************************************************************************** ++ LBC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++/**************************************************************************//** ++ @Group lbc_exception_grp LBC Exception Unit ++ ++ @Description LBC Exception unit API functions, definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Anchor lbc_exbm ++ ++ @Collection LBC Errors Bit Mask ++ ++ These errors are reported through the exceptions callback.. ++ The values can be or'ed in any combination in the errors mask ++ parameter of the errors report structure. ++ ++ These errors can also be passed as a bit-mask to ++ LBC_EnableErrorChecking() or LBC_DisableErrorChecking(), ++ for enabling or disabling error checking. ++ @{ ++*//***************************************************************************/ ++#define LBC_ERR_BUS_MONITOR 0x80000000 /**< Bus monitor error */ ++#define LBC_ERR_PARITY_ECC 0x20000000 /**< Parity error for GPCM/UPM */ ++#define LBC_ERR_WRITE_PROTECT 0x04000000 /**< Write protection error */ ++#define LBC_ERR_ATOMIC_WRITE 0x00800000 /**< Atomic write error */ ++#define LBC_ERR_ATOMIC_READ 0x00400000 /**< Atomic read error */ ++#define LBC_ERR_CHIP_SELECT 0x00080000 /**< Unrecognized chip select */ ++ ++#define LBC_ERR_ALL (LBC_ERR_BUS_MONITOR | LBC_ERR_PARITY_ECC | \ ++ LBC_ERR_WRITE_PROTECT | LBC_ERR_ATOMIC_WRITE | \ ++ LBC_ERR_ATOMIC_READ | LBC_ERR_CHIP_SELECT) ++ /**< All possible errors */ ++/* @} */ ++/** @} */ /* end of lbc_exception_grp group */ ++ ++#define LBC_INCORRECT_ERROR_REPORT_ERRATA ++ ++#define LBC_NUM_OF_BANKS 8 ++#define LBC_MAX_CS_SIZE 0x0000000100000000LL ++#define LBC_ATOMIC_OPERATION_SUPPORT ++#define LBC_PARITY_SUPPORT ++#define LBC_ADDRESS_HOLD_TIME_CTRL ++#define LBC_HIGH_CLK_DIVIDERS ++#define LBC_FCM_AVAILABLE ++ ++/***************************************************************************** ++ GPIO INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define GPIO_NUM_OF_PORTS 1 /**< Number of ports in GPIO module; ++ Each port contains up to 32 i/O pins. */ ++ ++#define GPIO_VALID_PIN_MASKS \ ++ { /* Port A */ 0xFFFFFFFF } ++ ++#define GPIO_VALID_INTR_MASKS \ ++ { /* Port A */ 0xFFFFFFFF } ++ ++#endif /* __PART_INTEGRATION_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/math_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/math_ext.h +new file mode 100644 +index 0000000..bff428d +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/math_ext.h +@@ -0,0 +1,99 @@ ++/* ++ * Copyright 2008-2012 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 __MATH_EXT_H ++#define __MATH_EXT_H ++ ++ ++#if defined(NCSW_LINUX) && defined(__KERNEL__) ++#include ++ ++#elif defined(__MWERKS__) ++#define LOW(x) ( sizeof(x)==8 ? *(1+(int32_t*)&x) : (*(int32_t*)&x)) ++#define HIGH(x) (*(int32_t*)&x) ++#define ULOW(x) ( sizeof(x)==8 ? *(1+(uint32_t*)&x) : (*(uint32_t*)&x)) ++#define UHIGH(x) (*(uint32_t*)&x) ++ ++static const double big = 1.0e300; ++ ++/* Macro for checking if a number is a power of 2 */ ++static __inline__ double ceil(double x) ++{ ++ int32_t i0,i1,j0; /*- cc 020130 -*/ ++ uint32_t i,j; /*- cc 020130 -*/ ++ i0 = HIGH(x); ++ i1 = LOW(x); ++ j0 = ((i0>>20)&0x7ff)-0x3ff; ++ if(j0<20) { ++ if(j0<0) { /* raise inexact if x != 0 */ ++ if(big+x>0.0) {/* return 0*sign(x) if |x|<1 */ ++ if(i0<0) {i0=0x80000000;i1=0;} ++ else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;} ++ } ++ } else { ++ i = (uint32_t)(0x000fffff)>>j0; ++ if(((i0&i)|i1)==0) return x; /* x is integral */ ++ if(big+x>0.0) { /* raise inexact flag */ ++ if(i0>0) i0 += (0x00100000)>>j0; ++ i0 &= (~i); i1=0; ++ } ++ } ++ } else if (j0>51) { ++ if(j0==0x400) return x+x; /* inf or NaN */ ++ else return x; /* x is integral */ ++ } else { ++ i = ((uint32_t)(0xffffffff))>>(j0-20); /*- cc 020130 -*/ ++ if((i1&i)==0) return x; /* x is integral */ ++ if(big+x>0.0) { /* raise inexact flag */ ++ if(i0>0) { ++ if(j0==20) i0+=1; ++ else { ++ j = (uint32_t)(i1 + (1<<(52-j0))); ++ if(j ++#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */ ++ ++ ++#endif /* __MATH_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/ncsw_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/ncsw_ext.h +new file mode 100644 +index 0000000..8de7f5c +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/ncsw_ext.h +@@ -0,0 +1,435 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File ncsw_ext.h ++ ++ @Description General NetCommSw Standard Definitions ++*//***************************************************************************/ ++ ++#ifndef __NCSW_EXT_H ++#define __NCSW_EXT_H ++ ++ ++#include "memcpy_ext.h" ++ ++#define WRITE_BLOCK IOMemSet32 /* include memcpy_ext.h */ ++#define COPY_BLOCK Mem2IOCpy32 /* include memcpy_ext.h */ ++ ++#define PTR_TO_UINT(_ptr) ((uintptr_t)(_ptr)) ++#define UINT_TO_PTR(_val) ((void*)(uintptr_t)(_val)) ++ ++#define PTR_MOVE(_ptr, _offset) (void*)((uint8_t*)(_ptr) + (_offset)) ++ ++ ++#define WRITE_UINT8_UINT24(arg, data08, data24) \ ++ WRITE_UINT32(arg,((uint32_t)(data08)<<24)|((uint32_t)(data24)&0x00FFFFFF)) ++#define WRITE_UINT24_UINT8(arg, data24, data08) \ ++ WRITE_UINT32(arg,((uint32_t)(data24)<< 8)|((uint32_t)(data08)&0x000000FF)) ++ ++/* Little-Endian access macros */ ++ ++#define WRITE_UINT16_LE(arg, data) \ ++ WRITE_UINT16((arg), SwapUint16(data)) ++ ++#define WRITE_UINT32_LE(arg, data) \ ++ WRITE_UINT32((arg), SwapUint32(data)) ++ ++#define WRITE_UINT64_LE(arg, data) \ ++ WRITE_UINT64((arg), SwapUint64(data)) ++ ++#define GET_UINT16_LE(arg) \ ++ SwapUint16(GET_UINT16(arg)) ++ ++#define GET_UINT32_LE(arg) \ ++ SwapUint32(GET_UINT32(arg)) ++ ++#define GET_UINT64_LE(arg) \ ++ SwapUint64(GET_UINT64(arg)) ++ ++/* Write and Read again macros */ ++#define WRITE_UINT_SYNC(size, arg, data) \ ++ do { \ ++ WRITE_UINT##size((arg), (data)); \ ++ CORE_MemoryBarrier(); \ ++ } while (0) ++ ++#define WRITE_UINT8_SYNC(arg, data) WRITE_UINT_SYNC(8, (arg), (data)) ++ ++#define WRITE_UINT16_SYNC(arg, data) WRITE_UINT_SYNC(16, (arg), (data)) ++#define WRITE_UINT32_SYNC(arg, data) WRITE_UINT_SYNC(32, (arg), (data)) ++ ++#define MAKE_UINT64(high32, low32) (((uint64_t)high32 << 32) | (low32)) ++ ++ ++/*----------------------*/ ++/* Miscellaneous macros */ ++/*----------------------*/ ++ ++#define UNUSED(_x) ((void)(_x)) ++ ++#define KILOBYTE 0x400UL /* 1024 */ ++#define MEGABYTE (KILOBYTE * KILOBYTE) /* 1024*1024 */ ++#define GIGABYTE ((uint64_t)(KILOBYTE * MEGABYTE)) /* 1024*1024*1024 */ ++#define TERABYTE ((uint64_t)(KILOBYTE * GIGABYTE)) /* 1024*1024*1024*1024 */ ++ ++#ifndef NO_IRQ ++#define NO_IRQ (0) ++#endif ++#define NCSW_MASTER_ID (0) ++ ++/* Macro for checking if a number is a power of 2 */ ++#define POWER_OF_2(n) (!((n) & ((n)-1))) ++ ++/* Macro for calculating log of base 2 */ ++#define LOG2(num, log2Num) \ ++ do \ ++ { \ ++ uint64_t tmp = (num); \ ++ log2Num = 0; \ ++ while (tmp > 1) \ ++ { \ ++ log2Num++; \ ++ tmp >>= 1; \ ++ } \ ++ } while (0) ++ ++#define NEXT_POWER_OF_2(_num, _nextPow) \ ++do \ ++{ \ ++ if (POWER_OF_2(_num)) \ ++ _nextPow = (_num); \ ++ else \ ++ { \ ++ uint64_t tmp = (_num); \ ++ _nextPow = 1; \ ++ while (tmp) \ ++ { \ ++ _nextPow <<= 1; \ ++ tmp >>= 1; \ ++ } \ ++ } \ ++} while (0) ++ ++/* Ceiling division - not the fastest way, but safer in terms of overflow */ ++#define DIV_CEIL(x,y) (((x)/(y)) + ((((((x)/(y)))*(y)) == (x)) ? 0 : 1)) ++ ++/* Round up a number to be a multiple of a second number */ ++#define ROUND_UP(x,y) ((((x) + (y) - 1) / (y)) * (y)) ++ ++/* Timing macro for converting usec units to number of ticks. */ ++/* (number of usec * clock_Hz) / 1,000,000) - since */ ++/* clk is in MHz units, no division needed. */ ++#define USEC_TO_CLK(usec,clk) ((usec) * (clk)) ++#define CYCLES_TO_USEC(cycles,clk) ((cycles) / (clk)) ++ ++/* Timing macros for converting between nsec units and number of clocks. */ ++#define NSEC_TO_CLK(nsec,clk) DIV_CEIL(((nsec) * (clk)), 1000) ++#define CYCLES_TO_NSEC(cycles,clk) (((cycles) * 1000) / (clk)) ++ ++/* Timing macros for converting between psec units and number of clocks. */ ++#define PSEC_TO_CLK(psec,clk) DIV_CEIL(((psec) * (clk)), 1000000) ++#define CYCLES_TO_PSEC(cycles,clk) (((cycles) * 1000000) / (clk)) ++ ++/* Min, Max macros */ ++#define MIN(a,b) ((a) < (b) ? (a) : (b)) ++#define MAX(a,b) ((a) > (b) ? (a) : (b)) ++#define IN_RANGE(min,val,max) ((min)<=(val) && (val)<=(max)) ++ ++#define ABS(a) ((a<0)?(a*-1):a) ++ ++#if !(defined(ARRAY_SIZE)) ++#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) ++#endif /* !defined(ARRAY_SIZE) */ ++ ++ ++/* possible alignments */ ++#define HALF_WORD_ALIGNMENT 2 ++#define WORD_ALIGNMENT 4 ++#define DOUBLE_WORD_ALIGNMENT 8 ++#define BURST_ALIGNMENT 32 ++ ++#define HALF_WORD_ALIGNED 0x00000001 ++#define WORD_ALIGNED 0x00000003 ++#define DOUBLE_WORD_ALIGNED 0x00000007 ++#define BURST_ALIGNED 0x0000001f ++#ifndef IS_ALIGNED ++#define IS_ALIGNED(n,align) (!((uint32_t)(n) & (align - 1))) ++#endif /* IS_ALIGNED */ ++ ++ ++#define LAST_BUF 1 ++#define FIRST_BUF 2 ++#define SINGLE_BUF (LAST_BUF | FIRST_BUF) ++#define MIDDLE_BUF 4 ++ ++#define ARRAY_END -1 ++ ++#define ILLEGAL_BASE (~0) ++ ++#define BUF_POSITION(first, last) state[(!!(last))<<1 | !!(first)] ++#define DECLARE_POSITION static uint8_t state[4] = { (uint8_t)MIDDLE_BUF, (uint8_t)FIRST_BUF, (uint8_t)LAST_BUF, (uint8_t)SINGLE_BUF }; ++ ++ ++/**************************************************************************//** ++ @Description Timers operation mode ++*//***************************************************************************/ ++typedef enum e_TimerMode ++{ ++ e_TIMER_MODE_INVALID = 0, ++ e_TIMER_MODE_FREE_RUN, /**< Free run - counter continues to increase ++ after reaching the reference value. */ ++ e_TIMER_MODE_PERIODIC, /**< Periodic - counter restarts counting from 0 ++ after reaching the reference value. */ ++ e_TIMER_MODE_SINGLE /**< Single (one-shot) - counter stops counting ++ after reaching the reference value. */ ++} e_TimerMode; ++ ++ ++/**************************************************************************//** ++ @Description Enumeration (bit flags) of communication modes (Transmit, ++ receive or both). ++*//***************************************************************************/ ++typedef enum e_CommMode ++{ ++ e_COMM_MODE_NONE = 0, /**< No transmit/receive communication */ ++ e_COMM_MODE_RX = 1, /**< Only receive communication */ ++ e_COMM_MODE_TX = 2, /**< Only transmit communication */ ++ e_COMM_MODE_RX_AND_TX = 3 /**< Both transmit and receive communication */ ++} e_CommMode; ++ ++/**************************************************************************//** ++ @Description General Diagnostic Mode ++*//***************************************************************************/ ++typedef enum e_DiagMode ++{ ++ e_DIAG_MODE_NONE = 0, /**< Normal operation; no diagnostic mode */ ++ e_DIAG_MODE_CTRL_LOOPBACK, /**< Loopback in the controller */ ++ e_DIAG_MODE_CHIP_LOOPBACK, /**< Loopback in the chip but not in the ++ controller; e.g. IO-pins, SerDes, etc. */ ++ e_DIAG_MODE_PHY_LOOPBACK, /**< Loopback in the external PHY */ ++ e_DIAG_MODE_EXT_LOOPBACK, /**< Loopback in the external line (beyond the PHY) */ ++ e_DIAG_MODE_CTRL_ECHO, /**< Echo incoming data by the controller */ ++ e_DIAG_MODE_PHY_ECHO /**< Echo incoming data by the PHY */ ++} e_DiagMode; ++ ++/**************************************************************************//** ++ @Description Possible RxStore callback responses. ++*//***************************************************************************/ ++typedef enum e_RxStoreResponse ++{ ++ e_RX_STORE_RESPONSE_PAUSE /**< Pause invoking callback with received data; ++ in polling mode, start again invoking callback ++ only next time user invokes the receive routine; ++ in interrupt mode, start again invoking callback ++ only next time a receive event triggers an interrupt; ++ in all cases, received data that are pending are not ++ lost, rather, their processing is temporarily deferred; ++ in all cases, received data are processed in the order ++ in which they were received. */ ++ , e_RX_STORE_RESPONSE_CONTINUE /**< Continue invoking callback with received data. */ ++} e_RxStoreResponse; ++ ++ ++/**************************************************************************//** ++ @Description General Handle ++*//***************************************************************************/ ++typedef void * t_Handle; /**< handle, used as object's descriptor */ ++ ++/**************************************************************************//** ++ @Description MUTEX type ++*//***************************************************************************/ ++typedef uint32_t t_Mutex; ++ ++/**************************************************************************//** ++ @Description Error Code. ++ ++ The high word of the error code is the code of the software ++ module (driver). The low word is the error type (e_ErrorType). ++ To get the values from the error code, use GET_ERROR_TYPE() ++ and GET_ERROR_MODULE(). ++*//***************************************************************************/ ++typedef uint32_t t_Error; ++ ++/**************************************************************************//** ++ @Description General prototype of interrupt service routine (ISR). ++ ++ @Param[in] handle - Optional handle of the module handling the interrupt. ++ ++ @Return None ++ *//***************************************************************************/ ++typedef void (t_Isr)(t_Handle handle); ++ ++/**************************************************************************//** ++ @Anchor mem_attr ++ ++ @Collection Memory Attributes ++ ++ Various attributes of memory partitions. These values may be ++ or'ed together to create a mask of all memory attributes. ++ @{ ++*//***************************************************************************/ ++#define MEMORY_ATTR_CACHEABLE 0x00000001 ++ /**< Memory is cacheable */ ++#define MEMORY_ATTR_QE_2ND_BUS_ACCESS 0x00000002 ++ /**< Memory can be accessed by QUICC Engine ++ through its secondary bus interface */ ++ ++/* @} */ ++ ++ ++/**************************************************************************//** ++ @Function t_GetBufFunction ++ ++ @Description User callback function called by driver to get data buffer. ++ ++ User provides this function. Driver invokes it. ++ ++ @Param[in] h_BufferPool - A handle to buffer pool manager ++ @Param[out] p_BufContextHandle - Returns the user's private context that ++ should be associated with the buffer ++ ++ @Return Pointer to data buffer, NULL if error ++ *//***************************************************************************/ ++typedef uint8_t * (t_GetBufFunction)(t_Handle h_BufferPool, ++ t_Handle *p_BufContextHandle); ++ ++/**************************************************************************//** ++ @Function t_PutBufFunction ++ ++ @Description User callback function called by driver to return data buffer. ++ ++ User provides this function. Driver invokes it. ++ ++ @Param[in] h_BufferPool - A handle to buffer pool manager ++ @Param[in] p_Buffer - A pointer to buffer to return ++ @Param[in] h_BufContext - The user's private context associated with ++ the returned buffer ++ ++ @Return E_OK on success; Error code otherwise ++ *//***************************************************************************/ ++typedef t_Error (t_PutBufFunction)(t_Handle h_BufferPool, ++ uint8_t *p_Buffer, ++ t_Handle h_BufContext); ++ ++/**************************************************************************//** ++ @Function t_PhysToVirt ++ ++ @Description Translates a physical address to the matching virtual address. ++ ++ @Param[in] addr - The physical address to translate. ++ ++ @Return Virtual address. ++*//***************************************************************************/ ++typedef void * t_PhysToVirt(physAddress_t addr); ++ ++/**************************************************************************//** ++ @Function t_VirtToPhys ++ ++ @Description Translates a virtual address to the matching physical address. ++ ++ @Param[in] addr - The virtual address to translate. ++ ++ @Return Physical address. ++*//***************************************************************************/ ++typedef physAddress_t t_VirtToPhys(void *addr); ++ ++/**************************************************************************//** ++ @Description Buffer Pool Information Structure. ++*//***************************************************************************/ ++typedef struct t_BufferPoolInfo ++{ ++ t_Handle h_BufferPool; /**< A handle to the buffer pool manager */ ++ t_GetBufFunction *f_GetBuf; /**< User callback to get a free buffer */ ++ t_PutBufFunction *f_PutBuf; /**< User callback to return a buffer */ ++ uint16_t bufferSize; /**< Buffer size (in bytes) */ ++ ++ t_PhysToVirt *f_PhysToVirt; /**< User callback to translate pool buffers ++ physical addresses to virtual addresses */ ++ t_VirtToPhys *f_VirtToPhys; /**< User callback to translate pool buffers ++ virtual addresses to physical addresses */ ++} t_BufferPoolInfo; ++ ++ ++/**************************************************************************//** ++ @Description User callback function called by driver when transmit completed. ++ ++ User provides this function. Driver invokes it. ++ ++ @Param[in] h_App - Application's handle, as was provided to the ++ driver by the user ++ @Param[in] queueId - Transmit queue ID ++ @Param[in] p_Data - Pointer to the data buffer ++ @Param[in] h_BufContext - The user's private context associated with ++ the given data buffer ++ @Param[in] status - Transmit status and errors ++ @Param[in] flags - Driver-dependent information ++ *//***************************************************************************/ ++typedef void (t_TxConfFunction)(t_Handle h_App, ++ uint32_t queueId, ++ uint8_t *p_Data, ++ t_Handle h_BufContext, ++ uint16_t status, ++ uint32_t flags); ++ ++/**************************************************************************//** ++ @Description User callback function called by driver with receive data. ++ ++ User provides this function. Driver invokes it. ++ ++ @Param[in] h_App - Application's handle, as was provided to the ++ driver by the user ++ @Param[in] queueId - Receive queue ID ++ @Param[in] p_Data - Pointer to the buffer with received data ++ @Param[in] h_BufContext - The user's private context associated with ++ the given data buffer ++ @Param[in] length - Length of received data ++ @Param[in] status - Receive status and errors ++ @Param[in] position - Position of buffer in frame ++ @Param[in] flags - Driver-dependent information ++ ++ @Retval e_RX_STORE_RESPONSE_CONTINUE - order the driver to continue Rx ++ operation for all ready data. ++ @Retval e_RX_STORE_RESPONSE_PAUSE - order the driver to stop Rx operation. ++ *//***************************************************************************/ ++typedef e_RxStoreResponse (t_RxStoreFunction)(t_Handle h_App, ++ uint32_t queueId, ++ uint8_t *p_Data, ++ t_Handle h_BufContext, ++ uint32_t length, ++ uint16_t status, ++ uint8_t position, ++ uint32_t flags); ++ ++ ++#endif /* __NCSW_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/net_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/net_ext.h +new file mode 100644 +index 0000000..8f3bc36 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/net_ext.h +@@ -0,0 +1,430 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File net_ext.h ++ ++ @Description This file contains common and general netcomm headers definitions. ++*//***************************************************************************/ ++#ifndef __NET_EXT_H ++#define __NET_EXT_H ++ ++#include "std_ext.h" ++ ++ ++typedef uint8_t headerFieldPpp_t; ++ ++#define NET_HEADER_FIELD_PPP_PID (1) ++#define NET_HEADER_FIELD_PPP_COMPRESSED (NET_HEADER_FIELD_PPP_PID << 1) ++#define NET_HEADER_FIELD_PPP_ALL_FIELDS ((NET_HEADER_FIELD_PPP_PID << 2) - 1) ++ ++ ++typedef uint8_t headerFieldPppoe_t; ++ ++#define NET_HEADER_FIELD_PPPoE_VER (1) ++#define NET_HEADER_FIELD_PPPoE_TYPE (NET_HEADER_FIELD_PPPoE_VER << 1) ++#define NET_HEADER_FIELD_PPPoE_CODE (NET_HEADER_FIELD_PPPoE_VER << 2) ++#define NET_HEADER_FIELD_PPPoE_SID (NET_HEADER_FIELD_PPPoE_VER << 3) ++#define NET_HEADER_FIELD_PPPoE_LEN (NET_HEADER_FIELD_PPPoE_VER << 4) ++#define NET_HEADER_FIELD_PPPoE_SESSION (NET_HEADER_FIELD_PPPoE_VER << 5) ++#define NET_HEADER_FIELD_PPPoE_PID (NET_HEADER_FIELD_PPPoE_VER << 6) ++#define NET_HEADER_FIELD_PPPoE_ALL_FIELDS ((NET_HEADER_FIELD_PPPoE_VER << 7) - 1) ++ ++#define NET_HEADER_FIELD_PPPMUX_PID (1) ++#define NET_HEADER_FIELD_PPPMUX_CKSUM (NET_HEADER_FIELD_PPPMUX_PID << 1) ++#define NET_HEADER_FIELD_PPPMUX_COMPRESSED (NET_HEADER_FIELD_PPPMUX_PID << 2) ++#define NET_HEADER_FIELD_PPPMUX_ALL_FIELDS ((NET_HEADER_FIELD_PPPMUX_PID << 3) - 1) ++ ++#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF (1) ++#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_LXT (NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 1) ++#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_LEN (NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 2) ++#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_PID (NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 3) ++#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_USE_PID (NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 4) ++#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_ALL_FIELDS ((NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 5) - 1) ++ ++ ++typedef uint8_t headerFieldEth_t; ++ ++#define NET_HEADER_FIELD_ETH_DA (1) ++#define NET_HEADER_FIELD_ETH_SA (NET_HEADER_FIELD_ETH_DA << 1) ++#define NET_HEADER_FIELD_ETH_LENGTH (NET_HEADER_FIELD_ETH_DA << 2) ++#define NET_HEADER_FIELD_ETH_TYPE (NET_HEADER_FIELD_ETH_DA << 3) ++#define NET_HEADER_FIELD_ETH_FINAL_CKSUM (NET_HEADER_FIELD_ETH_DA << 4) ++#define NET_HEADER_FIELD_ETH_PADDING (NET_HEADER_FIELD_ETH_DA << 5) ++#define NET_HEADER_FIELD_ETH_ALL_FIELDS ((NET_HEADER_FIELD_ETH_DA << 6) - 1) ++ ++#define NET_HEADER_FIELD_ETH_ADDR_SIZE 6 ++ ++typedef uint16_t headerFieldIp_t; ++ ++#define NET_HEADER_FIELD_IP_VER (1) ++#define NET_HEADER_FIELD_IP_DSCP (NET_HEADER_FIELD_IP_VER << 2) ++#define NET_HEADER_FIELD_IP_ECN (NET_HEADER_FIELD_IP_VER << 3) ++#define NET_HEADER_FIELD_IP_PROTO (NET_HEADER_FIELD_IP_VER << 4) ++ ++#define NET_HEADER_FIELD_IP_PROTO_SIZE 1 ++ ++typedef uint16_t headerFieldIpv4_t; ++ ++#define NET_HEADER_FIELD_IPv4_VER (1) ++#define NET_HEADER_FIELD_IPv4_HDR_LEN (NET_HEADER_FIELD_IPv4_VER << 1) ++#define NET_HEADER_FIELD_IPv4_TOS (NET_HEADER_FIELD_IPv4_VER << 2) ++#define NET_HEADER_FIELD_IPv4_TOTAL_LEN (NET_HEADER_FIELD_IPv4_VER << 3) ++#define NET_HEADER_FIELD_IPv4_ID (NET_HEADER_FIELD_IPv4_VER << 4) ++#define NET_HEADER_FIELD_IPv4_FLAG_D (NET_HEADER_FIELD_IPv4_VER << 5) ++#define NET_HEADER_FIELD_IPv4_FLAG_M (NET_HEADER_FIELD_IPv4_VER << 6) ++#define NET_HEADER_FIELD_IPv4_OFFSET (NET_HEADER_FIELD_IPv4_VER << 7) ++#define NET_HEADER_FIELD_IPv4_TTL (NET_HEADER_FIELD_IPv4_VER << 8) ++#define NET_HEADER_FIELD_IPv4_PROTO (NET_HEADER_FIELD_IPv4_VER << 9) ++#define NET_HEADER_FIELD_IPv4_CKSUM (NET_HEADER_FIELD_IPv4_VER << 10) ++#define NET_HEADER_FIELD_IPv4_SRC_IP (NET_HEADER_FIELD_IPv4_VER << 11) ++#define NET_HEADER_FIELD_IPv4_DST_IP (NET_HEADER_FIELD_IPv4_VER << 12) ++#define NET_HEADER_FIELD_IPv4_OPTS (NET_HEADER_FIELD_IPv4_VER << 13) ++#define NET_HEADER_FIELD_IPv4_OPTS_COUNT (NET_HEADER_FIELD_IPv4_VER << 14) ++#define NET_HEADER_FIELD_IPv4_ALL_FIELDS ((NET_HEADER_FIELD_IPv4_VER << 15) - 1) ++ ++#define NET_HEADER_FIELD_IPv4_ADDR_SIZE 4 ++#define NET_HEADER_FIELD_IPv4_PROTO_SIZE 1 ++ ++ ++typedef uint8_t headerFieldIpv6_t; ++ ++#define NET_HEADER_FIELD_IPv6_VER (1) ++#define NET_HEADER_FIELD_IPv6_TC (NET_HEADER_FIELD_IPv6_VER << 1) ++#define NET_HEADER_FIELD_IPv6_SRC_IP (NET_HEADER_FIELD_IPv6_VER << 2) ++#define NET_HEADER_FIELD_IPv6_DST_IP (NET_HEADER_FIELD_IPv6_VER << 3) ++#define NET_HEADER_FIELD_IPv6_NEXT_HDR (NET_HEADER_FIELD_IPv6_VER << 4) ++#define NET_HEADER_FIELD_IPv6_FL (NET_HEADER_FIELD_IPv6_VER << 5) ++#define NET_HEADER_FIELD_IPv6_HOP_LIMIT (NET_HEADER_FIELD_IPv6_VER << 6) ++#define NET_HEADER_FIELD_IPv6_ALL_FIELDS ((NET_HEADER_FIELD_IPv6_VER << 7) - 1) ++ ++#define NET_HEADER_FIELD_IPv6_ADDR_SIZE 16 ++#define NET_HEADER_FIELD_IPv6_NEXT_HDR_SIZE 1 ++ ++#define NET_HEADER_FIELD_ICMP_TYPE (1) ++#define NET_HEADER_FIELD_ICMP_CODE (NET_HEADER_FIELD_ICMP_TYPE << 1) ++#define NET_HEADER_FIELD_ICMP_CKSUM (NET_HEADER_FIELD_ICMP_TYPE << 2) ++#define NET_HEADER_FIELD_ICMP_ID (NET_HEADER_FIELD_ICMP_TYPE << 3) ++#define NET_HEADER_FIELD_ICMP_SQ_NUM (NET_HEADER_FIELD_ICMP_TYPE << 4) ++#define NET_HEADER_FIELD_ICMP_ALL_FIELDS ((NET_HEADER_FIELD_ICMP_TYPE << 5) - 1) ++ ++#define NET_HEADER_FIELD_ICMP_CODE_SIZE 1 ++#define NET_HEADER_FIELD_ICMP_TYPE_SIZE 1 ++ ++#define NET_HEADER_FIELD_IGMP_VERSION (1) ++#define NET_HEADER_FIELD_IGMP_TYPE (NET_HEADER_FIELD_IGMP_VERSION << 1) ++#define NET_HEADER_FIELD_IGMP_CKSUM (NET_HEADER_FIELD_IGMP_VERSION << 2) ++#define NET_HEADER_FIELD_IGMP_DATA (NET_HEADER_FIELD_IGMP_VERSION << 3) ++#define NET_HEADER_FIELD_IGMP_ALL_FIELDS ((NET_HEADER_FIELD_IGMP_VERSION << 4) - 1) ++ ++ ++typedef uint16_t headerFieldTcp_t; ++ ++#define NET_HEADER_FIELD_TCP_PORT_SRC (1) ++#define NET_HEADER_FIELD_TCP_PORT_DST (NET_HEADER_FIELD_TCP_PORT_SRC << 1) ++#define NET_HEADER_FIELD_TCP_SEQ (NET_HEADER_FIELD_TCP_PORT_SRC << 2) ++#define NET_HEADER_FIELD_TCP_ACK (NET_HEADER_FIELD_TCP_PORT_SRC << 3) ++#define NET_HEADER_FIELD_TCP_OFFSET (NET_HEADER_FIELD_TCP_PORT_SRC << 4) ++#define NET_HEADER_FIELD_TCP_FLAGS (NET_HEADER_FIELD_TCP_PORT_SRC << 5) ++#define NET_HEADER_FIELD_TCP_WINDOW (NET_HEADER_FIELD_TCP_PORT_SRC << 6) ++#define NET_HEADER_FIELD_TCP_CKSUM (NET_HEADER_FIELD_TCP_PORT_SRC << 7) ++#define NET_HEADER_FIELD_TCP_URGPTR (NET_HEADER_FIELD_TCP_PORT_SRC << 8) ++#define NET_HEADER_FIELD_TCP_OPTS (NET_HEADER_FIELD_TCP_PORT_SRC << 9) ++#define NET_HEADER_FIELD_TCP_OPTS_COUNT (NET_HEADER_FIELD_TCP_PORT_SRC << 10) ++#define NET_HEADER_FIELD_TCP_ALL_FIELDS ((NET_HEADER_FIELD_TCP_PORT_SRC << 11) - 1) ++ ++#define NET_HEADER_FIELD_TCP_PORT_SIZE 2 ++ ++ ++typedef uint8_t headerFieldSctp_t; ++ ++#define NET_HEADER_FIELD_SCTP_PORT_SRC (1) ++#define NET_HEADER_FIELD_SCTP_PORT_DST (NET_HEADER_FIELD_SCTP_PORT_SRC << 1) ++#define NET_HEADER_FIELD_SCTP_VER_TAG (NET_HEADER_FIELD_SCTP_PORT_SRC << 2) ++#define NET_HEADER_FIELD_SCTP_CKSUM (NET_HEADER_FIELD_SCTP_PORT_SRC << 3) ++#define NET_HEADER_FIELD_SCTP_ALL_FIELDS ((NET_HEADER_FIELD_SCTP_PORT_SRC << 4) - 1) ++ ++#define NET_HEADER_FIELD_SCTP_PORT_SIZE 2 ++ ++typedef uint8_t headerFieldDccp_t; ++ ++#define NET_HEADER_FIELD_DCCP_PORT_SRC (1) ++#define NET_HEADER_FIELD_DCCP_PORT_DST (NET_HEADER_FIELD_DCCP_PORT_SRC << 1) ++#define NET_HEADER_FIELD_DCCP_ALL_FIELDS ((NET_HEADER_FIELD_DCCP_PORT_SRC << 2) - 1) ++ ++#define NET_HEADER_FIELD_DCCP_PORT_SIZE 2 ++ ++ ++typedef uint8_t headerFieldUdp_t; ++ ++#define NET_HEADER_FIELD_UDP_PORT_SRC (1) ++#define NET_HEADER_FIELD_UDP_PORT_DST (NET_HEADER_FIELD_UDP_PORT_SRC << 1) ++#define NET_HEADER_FIELD_UDP_LEN (NET_HEADER_FIELD_UDP_PORT_SRC << 2) ++#define NET_HEADER_FIELD_UDP_CKSUM (NET_HEADER_FIELD_UDP_PORT_SRC << 3) ++#define NET_HEADER_FIELD_UDP_ALL_FIELDS ((NET_HEADER_FIELD_UDP_PORT_SRC << 4) - 1) ++ ++#define NET_HEADER_FIELD_UDP_PORT_SIZE 2 ++ ++typedef uint8_t headerFieldUdpLite_t; ++ ++#define NET_HEADER_FIELD_UDP_LITE_PORT_SRC (1) ++#define NET_HEADER_FIELD_UDP_LITE_PORT_DST (NET_HEADER_FIELD_UDP_LITE_PORT_SRC << 1) ++#define NET_HEADER_FIELD_UDP_LITE_ALL_FIELDS ((NET_HEADER_FIELD_UDP_LITE_PORT_SRC << 2) - 1) ++ ++#define NET_HEADER_FIELD_UDP_LITE_PORT_SIZE 2 ++ ++typedef uint8_t headerFieldUdpEncapEsp_t; ++ ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC (1) ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 1) ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 2) ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 3) ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 4) ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 5) ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_ALL_FIELDS ((NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 6) - 1) ++ ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SIZE 2 ++#define NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI_SIZE 4 ++ ++#define NET_HEADER_FIELD_IPHC_CID (1) ++#define NET_HEADER_FIELD_IPHC_CID_TYPE (NET_HEADER_FIELD_IPHC_CID << 1) ++#define NET_HEADER_FIELD_IPHC_HCINDEX (NET_HEADER_FIELD_IPHC_CID << 2) ++#define NET_HEADER_FIELD_IPHC_GEN (NET_HEADER_FIELD_IPHC_CID << 3) ++#define NET_HEADER_FIELD_IPHC_D_BIT (NET_HEADER_FIELD_IPHC_CID << 4) ++#define NET_HEADER_FIELD_IPHC_ALL_FIELDS ((NET_HEADER_FIELD_IPHC_CID << 5) - 1) ++ ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE (1) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_FLAGS (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 1) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_LENGTH (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 2) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_TSN (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 3) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_STREAM_ID (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 4) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_STREAM_SQN (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 5) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_PAYLOAD_PID (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 6) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_UNORDERED (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 7) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_BEGGINING (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 8) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_END (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 9) ++#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_ALL_FIELDS ((NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 10) - 1) ++ ++#define NET_HEADER_FIELD_L2TPv2_TYPE_BIT (1) ++#define NET_HEADER_FIELD_L2TPv2_LENGTH_BIT (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 1) ++#define NET_HEADER_FIELD_L2TPv2_SEQUENCE_BIT (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 2) ++#define NET_HEADER_FIELD_L2TPv2_OFFSET_BIT (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 3) ++#define NET_HEADER_FIELD_L2TPv2_PRIORITY_BIT (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 4) ++#define NET_HEADER_FIELD_L2TPv2_VERSION (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 5) ++#define NET_HEADER_FIELD_L2TPv2_LEN (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 6) ++#define NET_HEADER_FIELD_L2TPv2_TUNNEL_ID (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 7) ++#define NET_HEADER_FIELD_L2TPv2_SESSION_ID (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 8) ++#define NET_HEADER_FIELD_L2TPv2_NS (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 9) ++#define NET_HEADER_FIELD_L2TPv2_NR (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 10) ++#define NET_HEADER_FIELD_L2TPv2_OFFSET_SIZE (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 11) ++#define NET_HEADER_FIELD_L2TPv2_FIRST_BYTE (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 12) ++#define NET_HEADER_FIELD_L2TPv2_ALL_FIELDS ((NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 13) - 1) ++ ++#define NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT (1) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_LENGTH_BIT (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 1) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_SEQUENCE_BIT (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 2) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_VERSION (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 3) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_LENGTH (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 4) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_CONTROL (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 5) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_SENT (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 6) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_RECV (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 7) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_FIRST_BYTE (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 8) ++#define NET_HEADER_FIELD_L2TPv3_CTRL_ALL_FIELDS ((NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 9) - 1) ++ ++#define NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT (1) ++#define NET_HEADER_FIELD_L2TPv3_SESS_VERSION (NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT << 1) ++#define NET_HEADER_FIELD_L2TPv3_SESS_ID (NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT << 2) ++#define NET_HEADER_FIELD_L2TPv3_SESS_COOKIE (NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT << 3) ++#define NET_HEADER_FIELD_L2TPv3_SESS_ALL_FIELDS ((NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT << 4) - 1) ++ ++ ++typedef uint8_t headerFieldVlan_t; ++ ++#define NET_HEADER_FIELD_VLAN_VPRI (1) ++#define NET_HEADER_FIELD_VLAN_CFI (NET_HEADER_FIELD_VLAN_VPRI << 1) ++#define NET_HEADER_FIELD_VLAN_VID (NET_HEADER_FIELD_VLAN_VPRI << 2) ++#define NET_HEADER_FIELD_VLAN_LENGTH (NET_HEADER_FIELD_VLAN_VPRI << 3) ++#define NET_HEADER_FIELD_VLAN_TYPE (NET_HEADER_FIELD_VLAN_VPRI << 4) ++#define NET_HEADER_FIELD_VLAN_ALL_FIELDS ((NET_HEADER_FIELD_VLAN_VPRI << 5) - 1) ++ ++#define NET_HEADER_FIELD_VLAN_TCI (NET_HEADER_FIELD_VLAN_VPRI | \ ++ NET_HEADER_FIELD_VLAN_CFI | \ ++ NET_HEADER_FIELD_VLAN_VID) ++ ++ ++typedef uint8_t headerFieldLlc_t; ++ ++#define NET_HEADER_FIELD_LLC_DSAP (1) ++#define NET_HEADER_FIELD_LLC_SSAP (NET_HEADER_FIELD_LLC_DSAP << 1) ++#define NET_HEADER_FIELD_LLC_CTRL (NET_HEADER_FIELD_LLC_DSAP << 2) ++#define NET_HEADER_FIELD_LLC_ALL_FIELDS ((NET_HEADER_FIELD_LLC_DSAP << 3) - 1) ++ ++#define NET_HEADER_FIELD_NLPID_NLPID (1) ++#define NET_HEADER_FIELD_NLPID_ALL_FIELDS ((NET_HEADER_FIELD_NLPID_NLPID << 1) - 1) ++ ++ ++typedef uint8_t headerFieldSnap_t; ++ ++#define NET_HEADER_FIELD_SNAP_OUI (1) ++#define NET_HEADER_FIELD_SNAP_PID (NET_HEADER_FIELD_SNAP_OUI << 1) ++#define NET_HEADER_FIELD_SNAP_ALL_FIELDS ((NET_HEADER_FIELD_SNAP_OUI << 2) - 1) ++ ++ ++typedef uint8_t headerFieldLlcSnap_t; ++ ++#define NET_HEADER_FIELD_LLC_SNAP_TYPE (1) ++#define NET_HEADER_FIELD_LLC_SNAP_ALL_FIELDS ((NET_HEADER_FIELD_LLC_SNAP_TYPE << 1) - 1) ++ ++#define NET_HEADER_FIELD_ARP_HTYPE (1) ++#define NET_HEADER_FIELD_ARP_PTYPE (NET_HEADER_FIELD_ARP_HTYPE << 1) ++#define NET_HEADER_FIELD_ARP_HLEN (NET_HEADER_FIELD_ARP_HTYPE << 2) ++#define NET_HEADER_FIELD_ARP_PLEN (NET_HEADER_FIELD_ARP_HTYPE << 3) ++#define NET_HEADER_FIELD_ARP_OPER (NET_HEADER_FIELD_ARP_HTYPE << 4) ++#define NET_HEADER_FIELD_ARP_SHA (NET_HEADER_FIELD_ARP_HTYPE << 5) ++#define NET_HEADER_FIELD_ARP_SPA (NET_HEADER_FIELD_ARP_HTYPE << 6) ++#define NET_HEADER_FIELD_ARP_THA (NET_HEADER_FIELD_ARP_HTYPE << 7) ++#define NET_HEADER_FIELD_ARP_TPA (NET_HEADER_FIELD_ARP_HTYPE << 8) ++#define NET_HEADER_FIELD_ARP_ALL_FIELDS ((NET_HEADER_FIELD_ARP_HTYPE << 9) - 1) ++ ++#define NET_HEADER_FIELD_RFC2684_LLC (1) ++#define NET_HEADER_FIELD_RFC2684_NLPID (NET_HEADER_FIELD_RFC2684_LLC << 1) ++#define NET_HEADER_FIELD_RFC2684_OUI (NET_HEADER_FIELD_RFC2684_LLC << 2) ++#define NET_HEADER_FIELD_RFC2684_PID (NET_HEADER_FIELD_RFC2684_LLC << 3) ++#define NET_HEADER_FIELD_RFC2684_VPN_OUI (NET_HEADER_FIELD_RFC2684_LLC << 4) ++#define NET_HEADER_FIELD_RFC2684_VPN_IDX (NET_HEADER_FIELD_RFC2684_LLC << 5) ++#define NET_HEADER_FIELD_RFC2684_ALL_FIELDS ((NET_HEADER_FIELD_RFC2684_LLC << 6) - 1) ++ ++#define NET_HEADER_FIELD_USER_DEFINED_SRCPORT (1) ++#define NET_HEADER_FIELD_USER_DEFINED_PCDID (NET_HEADER_FIELD_USER_DEFINED_SRCPORT << 1) ++#define NET_HEADER_FIELD_USER_DEFINED_ALL_FIELDS ((NET_HEADER_FIELD_USER_DEFINED_SRCPORT << 2) - 1) ++ ++#define NET_HEADER_FIELD_PAYLOAD_BUFFER (1) ++#define NET_HEADER_FIELD_PAYLOAD_SIZE (NET_HEADER_FIELD_PAYLOAD_BUFFER << 1) ++#define NET_HEADER_FIELD_MAX_FRM_SIZE (NET_HEADER_FIELD_PAYLOAD_BUFFER << 2) ++#define NET_HEADER_FIELD_MIN_FRM_SIZE (NET_HEADER_FIELD_PAYLOAD_BUFFER << 3) ++#define NET_HEADER_FIELD_PAYLOAD_TYPE (NET_HEADER_FIELD_PAYLOAD_BUFFER << 4) ++#define NET_HEADER_FIELD_FRAME_SIZE (NET_HEADER_FIELD_PAYLOAD_BUFFER << 5) ++#define NET_HEADER_FIELD_PAYLOAD_ALL_FIELDS ((NET_HEADER_FIELD_PAYLOAD_BUFFER << 6) - 1) ++ ++ ++typedef uint8_t headerFieldGre_t; ++ ++#define NET_HEADER_FIELD_GRE_TYPE (1) ++#define NET_HEADER_FIELD_GRE_ALL_FIELDS ((NET_HEADER_FIELD_GRE_TYPE << 1) - 1) ++ ++ ++typedef uint8_t headerFieldMinencap_t; ++ ++#define NET_HEADER_FIELD_MINENCAP_SRC_IP (1) ++#define NET_HEADER_FIELD_MINENCAP_DST_IP (NET_HEADER_FIELD_MINENCAP_SRC_IP << 1) ++#define NET_HEADER_FIELD_MINENCAP_TYPE (NET_HEADER_FIELD_MINENCAP_SRC_IP << 2) ++#define NET_HEADER_FIELD_MINENCAP_ALL_FIELDS ((NET_HEADER_FIELD_MINENCAP_SRC_IP << 3) - 1) ++ ++ ++typedef uint8_t headerFieldIpsecAh_t; ++ ++#define NET_HEADER_FIELD_IPSEC_AH_SPI (1) ++#define NET_HEADER_FIELD_IPSEC_AH_NH (NET_HEADER_FIELD_IPSEC_AH_SPI << 1) ++#define NET_HEADER_FIELD_IPSEC_AH_ALL_FIELDS ((NET_HEADER_FIELD_IPSEC_AH_SPI << 2) - 1) ++ ++ ++typedef uint8_t headerFieldIpsecEsp_t; ++ ++#define NET_HEADER_FIELD_IPSEC_ESP_SPI (1) ++#define NET_HEADER_FIELD_IPSEC_ESP_SEQUENCE_NUM (NET_HEADER_FIELD_IPSEC_ESP_SPI << 1) ++#define NET_HEADER_FIELD_IPSEC_ESP_ALL_FIELDS ((NET_HEADER_FIELD_IPSEC_ESP_SPI << 2) - 1) ++ ++#define NET_HEADER_FIELD_IPSEC_ESP_SPI_SIZE 4 ++ ++ ++typedef uint8_t headerFieldMpls_t; ++ ++#define NET_HEADER_FIELD_MPLS_LABEL_STACK (1) ++#define NET_HEADER_FIELD_MPLS_LABEL_STACK_ALL_FIELDS ((NET_HEADER_FIELD_MPLS_LABEL_STACK << 1) - 1) ++ ++ ++typedef uint8_t headerFieldMacsec_t; ++ ++#define NET_HEADER_FIELD_MACSEC_SECTAG (1) ++#define NET_HEADER_FIELD_MACSEC_ALL_FIELDS ((NET_HEADER_FIELD_MACSEC_SECTAG << 1) - 1) ++ ++ ++typedef enum { ++ HEADER_TYPE_NONE = 0, ++ HEADER_TYPE_PAYLOAD, ++ HEADER_TYPE_ETH, ++ HEADER_TYPE_VLAN, ++ HEADER_TYPE_IPv4, ++ HEADER_TYPE_IPv6, ++ HEADER_TYPE_IP, ++ HEADER_TYPE_TCP, ++ HEADER_TYPE_UDP, ++ HEADER_TYPE_UDP_LITE, ++ HEADER_TYPE_IPHC, ++ HEADER_TYPE_SCTP, ++ HEADER_TYPE_SCTP_CHUNK_DATA, ++ HEADER_TYPE_PPPoE, ++ HEADER_TYPE_PPP, ++ HEADER_TYPE_PPPMUX, ++ HEADER_TYPE_PPPMUX_SUBFRAME, ++ HEADER_TYPE_L2TPv2, ++ HEADER_TYPE_L2TPv3_CTRL, ++ HEADER_TYPE_L2TPv3_SESS, ++ HEADER_TYPE_LLC, ++ HEADER_TYPE_LLC_SNAP, ++ HEADER_TYPE_NLPID, ++ HEADER_TYPE_SNAP, ++ HEADER_TYPE_MPLS, ++ HEADER_TYPE_IPSEC_AH, ++ HEADER_TYPE_IPSEC_ESP, ++ HEADER_TYPE_UDP_ENCAP_ESP, /* RFC 3948 */ ++ HEADER_TYPE_MACSEC, ++ HEADER_TYPE_GRE, ++ HEADER_TYPE_MINENCAP, ++ HEADER_TYPE_DCCP, ++ HEADER_TYPE_ICMP, ++ HEADER_TYPE_IGMP, ++ HEADER_TYPE_ARP, ++ HEADER_TYPE_CAPWAP, ++ HEADER_TYPE_CAPWAP_DTLS, ++ HEADER_TYPE_RFC2684, ++ HEADER_TYPE_USER_DEFINED_L2, ++ HEADER_TYPE_USER_DEFINED_L3, ++ HEADER_TYPE_USER_DEFINED_L4, ++ HEADER_TYPE_USER_DEFINED_SHIM1, ++ HEADER_TYPE_USER_DEFINED_SHIM2, ++ MAX_HEADER_TYPE_COUNT ++} e_NetHeaderType; ++ ++ ++#endif /* __NET_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/std_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/std_ext.h +new file mode 100644 +index 0000000..d91e6fd +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/std_ext.h +@@ -0,0 +1,48 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File std_ext.h ++ ++ @Description General Standard Definitions ++*//***************************************************************************/ ++ ++#ifndef __STD_EXT_H ++#define __STD_EXT_H ++ ++ ++#include "types_ext.h" ++#include "ncsw_ext.h" ++ ++ ++#endif /* __STD_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/stdarg_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/stdarg_ext.h +new file mode 100644 +index 0000000..3c8bb0a +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/stdarg_ext.h +@@ -0,0 +1,49 @@ ++/* ++ * Copyright 2008-2012 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 __STDARG_EXT_H ++#define __STDARG_EXT_H ++ ++ ++#if defined(NCSW_LINUX) && defined(__KERNEL__) ++#include ++ ++#else ++#include ++ ++#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */ ++ ++#include "std_ext.h" ++ ++ ++#endif /* __STDARG_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/stdlib_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/stdlib_ext.h +new file mode 100644 +index 0000000..a47860c +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/stdlib_ext.h +@@ -0,0 +1,162 @@ ++/* ++ * Copyright 2008-2012 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 __STDLIB_EXT_H ++#define __STDLIB_EXT_H ++ ++ ++#if (defined(NCSW_LINUX)) && defined(__KERNEL__) ++#include "stdarg_ext.h" ++#include "std_ext.h" ++ ++ ++/** ++ * strtoul - convert a string to an uint32_t ++ * @cp: The start of the string ++ * @endp: A pointer to the end of the parsed string will be placed here ++ * @base: The number base to use ++ */ ++uint32_t strtoul(const char *cp,char **endp,uint32_t base); ++ ++/** ++ * strtol - convert a string to a int32_t ++ * @cp: The start of the string ++ * @endp: A pointer to the end of the parsed string will be placed here ++ * @base: The number base to use ++ */ ++long strtol(const char *cp,char **endp,uint32_t base); ++ ++/** ++ * strtoull - convert a string to an uint64_t ++ * @cp: The start of the string ++ * @endp: A pointer to the end of the parsed string will be placed here ++ * @base: The number base to use ++ */ ++uint64_t strtoull(const char *cp,char **endp,uint32_t base); ++ ++/** ++ * strtoll - convert a string to a int64 long ++ * @cp: The start of the string ++ * @endp: A pointer to the end of the parsed string will be placed here ++ * @base: The number base to use ++ */ ++long long strtoll(const char *cp,char **endp,uint32_t base); ++ ++/** ++ * atoi - convert a character to a int ++ * @s: The start of the string ++ */ ++int atoi(const char *s); ++ ++/** ++ * strnlen - Find the length of a length-limited string ++ * @s: The string to be sized ++ * @count: The maximum number of bytes to search ++ */ ++size_t strnlen(const char * s, size_t count); ++ ++/** ++ * strlen - Find the length of a string ++ * @s: The string to be sized ++ */ ++size_t strlen(const char * s); ++ ++/** ++ * strtok - Split a string into tokens ++ * @s: The string to be searched ++ * @ct: The characters to search for ++ * ++ * WARNING: strtok is deprecated, use strsep instead. ++ */ ++char * strtok(char * s,const char * ct); ++ ++/** ++ * strncpy - Copy a length-limited, %NUL-terminated string ++ * @dest: Where to copy the string to ++ * @src: Where to copy the string from ++ * @count: The maximum number of bytes to copy ++ * ++ * Note that unlike userspace strncpy, this does not %NUL-pad the buffer. ++ * However, the result is not %NUL-terminated if the source exceeds ++ * @count bytes. ++ */ ++char * strncpy(char * dest,const char *src,size_t count); ++ ++/** ++ * strcpy - Copy a %NUL terminated string ++ * @dest: Where to copy the string to ++ * @src: Where to copy the string from ++ */ ++char * strcpy(char * dest,const char *src); ++ ++/** ++ * vsscanf - Unformat a buffer into a list of arguments ++ * @buf: input buffer ++ * @fmt: format of buffer ++ * @args: arguments ++ */ ++int vsscanf(const char * buf, const char * fmt, va_list args); ++ ++/** ++ * vsnprintf - Format a string and place it in a buffer ++ * @buf: The buffer to place the result into ++ * @size: The size of the buffer, including the trailing null space ++ * @fmt: The format string to use ++ * @args: Arguments for the format string ++ * ++ * Call this function if you are already dealing with a va_list. ++ * You probably want snprintf instead. ++ */ ++int vsnprintf(char *buf, size_t size, const char *fmt, va_list args); ++ ++/** ++ * vsprintf - Format a string and place it in a buffer ++ * @buf: The buffer to place the result into ++ * @fmt: The format string to use ++ * @args: Arguments for the format string ++ * ++ * Call this function if you are already dealing with a va_list. ++ * You probably want sprintf instead. ++ */ ++int vsprintf(char *buf, const char *fmt, va_list args); ++ ++#else ++#include ++#include ++#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */ ++ ++#include "std_ext.h" ++ ++ ++#endif /* __STDLIB_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/string_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/string_ext.h +new file mode 100644 +index 0000000..a5c6c7e +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/string_ext.h +@@ -0,0 +1,56 @@ ++/* ++ * Copyright 2008-2012 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 __STRING_EXT_H ++#define __STRING_EXT_H ++ ++ ++#if defined(NCSW_LINUX) && defined(__KERNEL__) ++#include ++#include ++extern char * strtok ( char * str, const char * delimiters ); ++ ++#elif defined(__KERNEL__) ++#include "linux/types.h" ++#include "linux/posix_types.h" ++#include "linux/string.h" ++ ++#else ++#include ++ ++#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */ ++ ++#include "std_ext.h" ++ ++ ++#endif /* __STRING_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/types_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/types_ext.h +new file mode 100644 +index 0000000..fd900e2 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/types_ext.h +@@ -0,0 +1,104 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File types_ext.h ++ ++ @Description General types Standard Definitions ++*//***************************************************************************/ ++ ++#ifndef __TYPES_EXT_H ++#define __TYPES_EXT_H ++ ++#if defined(NCSW_LINUX) ++#include "types_linux.h" ++ ++#elif defined(NCSW_VXWORKS) ++#include "types_vxworks.h" ++ ++#elif defined(__GNUC__) && defined(__cplusplus) ++#include "types_bb_gpp.h" ++ ++#elif defined(__GNUC__) ++#include "types_bb_gcc.h" ++ ++#elif defined(__ghs__) ++#include "types_ghs.h" ++ ++#else ++#include "types_dflt.h" ++#endif /* defined (__ROCOO__) */ ++ ++static __inline__ void TypesChecker(void) ++{ ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(push,1) ++#endif /* defined(__MWERKS__) && ... */ ++ _Packed struct strct { ++ __volatile__ int vi; ++ } _PackedType; ++#if defined(__MWERKS__) && !defined(__GNUC__) ++#pragma pack(pop) ++#endif /* defined(__MWERKS__) && ... */ ++ size_t size = 0; ++ bool tr = TRUE, fls = FALSE; ++ struct strct *p_Struct = NULL; ++ physAddress_t addr = 0x100; ++ ++ tr = fls; ++ p_Struct = p_Struct; ++ size++; ++ if (tr) size++; ++ ++ WRITE_UINT8(*((uint8_t*)((size_t)(addr))), ++ GET_UINT8(*((uint8_t*)((size_t)(addr))))); ++ ++ WRITE_UINT8(*((uint8_t*)((size_t)(UINT8_MAX))), ++ GET_UINT8(*((uint8_t*)((size_t)(UINT8_MAX))))); ++ WRITE_UINT16(*((uint16_t*)((size_t)(UINT16_MAX))), ++ GET_UINT16(*((uint16_t*)((size_t)(UINT16_MAX))))); ++ WRITE_UINT32(*((uint32_t*)((size_t)(UINT32_MAX))), ++ GET_UINT32(*((uint32_t*)((size_t)(UINT32_MAX))))); ++ WRITE_UINT64(*((uint64_t*)((size_t)(UINT64_MAX))), ++ GET_UINT64(*((uint64_t*)((size_t)(UINT64_MAX))))); ++ WRITE_UINT8(*((uint8_t*)((size_t)(INT8_MAX))), ++ GET_UINT8(*((uint8_t*)((size_t)(INT8_MIN))))); ++ WRITE_UINT16(*((uint16_t*)((size_t)(INT16_MAX))), ++ GET_UINT16(*((uint16_t*)((size_t)(INT16_MIN))))); ++ WRITE_UINT32(*((uint32_t*)((size_t)(INT32_MAX))), ++ GET_UINT32(*((uint32_t*)((size_t)(INT32_MIN))))); ++ WRITE_UINT64(*((uint64_t*)((size_t)(INT64_MAX))), ++ GET_UINT64(*((uint64_t*)((size_t)(INT64_MIN))))); ++} ++ ++#endif /* __TYPES_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/xx_common.h b/drivers/net/ethernet/freescale/sdk_fman/inc/xx_common.h +new file mode 100644 +index 0000000..8e81094 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/xx_common.h +@@ -0,0 +1,56 @@ ++/* ++ * Copyright 2012 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File debug_ext.h ++ ++ @Description Debug mode definitions. ++*//***************************************************************************/ ++ ++#ifndef __XX_COMMON_H ++#define __XX_COMMON_H ++ ++/***************************************************************************** ++ * UNIFIED MODULE CODES ++ *****************************************************************************/ ++#define MODULE_UNKNOWN 0x00000000 ++#define MODULE_FM 0x00010000 ++#define MODULE_FM_MURAM 0x00020000 ++#define MODULE_FM_PCD 0x00030000 ++#define MODULE_FM_RTC 0x00040000 ++#define MODULE_FM_MAC 0x00050000 ++#define MODULE_FM_PORT 0x00060000 ++#define MODULE_MM 0x00070000 ++#define MODULE_FM_SP 0x00080000 ++#define MODULE_FM_MACSEC 0x00090000 ++#endif /* __XX_COMMON_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/xx_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/xx_ext.h +new file mode 100644 +index 0000000..21b62d0 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/xx_ext.h +@@ -0,0 +1,791 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File xx_ext.h ++ ++ @Description Prototypes, externals and typedefs for system-supplied ++ (external) routines ++*//***************************************************************************/ ++ ++#ifndef __XX_EXT_H ++#define __XX_EXT_H ++ ++#include "std_ext.h" ++#include "xx_common.h" ++#include "part_ext.h" ++ ++ ++ ++/**************************************************************************//** ++ @Group xx_id XX Interface (System call hooks) ++ ++ @Description Prototypes, externals and typedefs for system-supplied ++ (external) routines ++ ++ @{ ++*//***************************************************************************/ ++ ++#ifdef DEBUG_XX_MALLOC ++void * XX_MallocDebug(uint32_t size, char *fname, int line); ++ ++void * XX_MallocSmartDebug(uint32_t size, ++ int memPartitionId, ++ uint32_t alignment, ++ char *fname, ++ int line); ++ ++#define XX_Malloc(sz) \ ++ XX_MallocDebug((sz), __FILE__, __LINE__) ++ ++#define XX_MallocSmart(sz, memt, al) \ ++ XX_MallocSmartDebug((sz), (memt), (al), __FILE__, __LINE__) ++ ++#else /* not DEBUG_XX_MALLOC */ ++/**************************************************************************//** ++ @Function XX_Malloc ++ ++ @Description allocates contiguous block of memory. ++ ++ @Param[in] size - Number of bytes to allocate. ++ ++ @Return The address of the newly allocated block on success, NULL on failure. ++*//***************************************************************************/ ++void * XX_Malloc(uint32_t size); ++ ++/**************************************************************************//** ++ @Function XX_MallocSmart ++ ++ @Description Allocates contiguous block of memory in a specified ++ alignment and from the specified segment. ++ ++ @Param[in] size - Number of bytes to allocate. ++ @Param[in] memPartitionId - Memory partition ID; The value zero must ++ be mapped to the default heap partition. ++ @Param[in] alignment - Required memory alignment (in bytes). ++ ++ @Return The address of the newly allocated block on success, NULL on failure. ++*//***************************************************************************/ ++void * XX_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment); ++#endif /* not DEBUG_XX_MALLOC */ ++ ++/**************************************************************************//** ++ @Function XX_FreeSmart ++ ++ @Description Frees the memory block pointed to by "p". ++ Only for memory allocated by XX_MallocSmart ++ ++ @Param[in] p_Memory - pointer to the memory block. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_FreeSmart(void *p_Memory); ++ ++/**************************************************************************//** ++ @Function XX_Free ++ ++ @Description frees the memory block pointed to by "p". ++ ++ @Param[in] p_Memory - pointer to the memory block. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_Free(void *p_Memory); ++ ++/**************************************************************************//** ++ @Function XX_Print ++ ++ @Description print a string. ++ ++ @Param[in] str - string to print. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_Print(char *str, ...); ++ ++/**************************************************************************//** ++ @Function XX_SetIntr ++ ++ @Description Set an interrupt service routine for a specific interrupt source. ++ ++ @Param[in] irq - Interrupt ID (system-specific number). ++ @Param[in] f_Isr - Callback routine that will be called when the interrupt occurs. ++ @Param[in] handle - The argument for the user callback routine. ++ ++ @Return E_OK on success; error code otherwise.. ++*//***************************************************************************/ ++t_Error XX_SetIntr(int irq, t_Isr *f_Isr, t_Handle handle); ++ ++/**************************************************************************//** ++ @Function XX_FreeIntr ++ ++ @Description Free a specific interrupt and a specific callback routine. ++ ++ @Param[in] irq - Interrupt ID (system-specific number). ++ ++ @Return E_OK on success; error code otherwise.. ++*//***************************************************************************/ ++t_Error XX_FreeIntr(int irq); ++ ++/**************************************************************************//** ++ @Function XX_EnableIntr ++ ++ @Description Enable a specific interrupt. ++ ++ @Param[in] irq - Interrupt ID (system-specific number). ++ ++ @Return E_OK on success; error code otherwise.. ++*//***************************************************************************/ ++t_Error XX_EnableIntr(int irq); ++ ++/**************************************************************************//** ++ @Function XX_DisableIntr ++ ++ @Description Disable a specific interrupt. ++ ++ @Param[in] irq - Interrupt ID (system-specific number). ++ ++ @Return E_OK on success; error code otherwise.. ++*//***************************************************************************/ ++t_Error XX_DisableIntr(int irq); ++ ++/**************************************************************************//** ++ @Function XX_DisableAllIntr ++ ++ @Description Disable all interrupts by masking them at the CPU. ++ ++ @Return A value that represents the interrupts state before the ++ operation, and should be passed to the matching ++ XX_RestoreAllIntr() call. ++*//***************************************************************************/ ++uint32_t XX_DisableAllIntr(void); ++ ++/**************************************************************************//** ++ @Function XX_RestoreAllIntr ++ ++ @Description Restore previous state of interrupts level at the CPU. ++ ++ @Param[in] flags - A value that represents the interrupts state to restore, ++ as returned by the matching call for XX_DisableAllIntr(). ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_RestoreAllIntr(uint32_t flags); ++ ++ ++/**************************************************************************//** ++ @Function XX_Exit ++ ++ @Description Stop execution and report status (where it is applicable) ++ ++ @Param[in] status - exit status ++*//***************************************************************************/ ++void XX_Exit(int status); ++ ++ ++/*****************************************************************************/ ++/* Tasklet Service Routines */ ++/*****************************************************************************/ ++typedef t_Handle t_TaskletHandle; ++ ++/**************************************************************************//** ++ @Function XX_InitTasklet ++ ++ @Description Create and initialize a tasklet object. ++ ++ @Param[in] routine - A routine to be ran as a tasklet. ++ @Param[in] data - An argument to pass to the tasklet. ++ ++ @Return Tasklet handle is returned on success. NULL is returned otherwise. ++*//***************************************************************************/ ++t_TaskletHandle XX_InitTasklet (void (*routine)(void *), void *data); ++ ++/**************************************************************************//** ++ @Function XX_FreeTasklet ++ ++ @Description Free a tasklet object. ++ ++ @Param[in] h_Tasklet - A handle to a tasklet to be free. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_FreeTasklet (t_TaskletHandle h_Tasklet); ++ ++/**************************************************************************//** ++ @Function XX_ScheduleTask ++ ++ @Description Schedule a tasklet object. ++ ++ @Param[in] h_Tasklet - A handle to a tasklet to be scheduled. ++ @Param[in] immediate - Indicate whether to schedule this tasklet on ++ the immediate queue or on the delayed one. ++ ++ @Return 0 - on success. Error code - otherwise. ++*//***************************************************************************/ ++int XX_ScheduleTask(t_TaskletHandle h_Tasklet, int immediate); ++ ++/**************************************************************************//** ++ @Function XX_FlushScheduledTasks ++ ++ @Description Flush all tasks there are in the scheduled tasks queue. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_FlushScheduledTasks(void); ++ ++/**************************************************************************//** ++ @Function XX_TaskletIsQueued ++ ++ @Description Check if task is queued. ++ ++ @Param[in] h_Tasklet - A handle to a tasklet to be scheduled. ++ ++ @Return 1 - task is queued. 0 - otherwise. ++*//***************************************************************************/ ++int XX_TaskletIsQueued(t_TaskletHandle h_Tasklet); ++ ++/**************************************************************************//** ++ @Function XX_SetTaskletData ++ ++ @Description Set data to a scheduled task. Used to change data of already ++ scheduled task. ++ ++ @Param[in] h_Tasklet - A handle to a tasklet to be scheduled. ++ @Param[in] data - Data to be set. ++*//***************************************************************************/ ++void XX_SetTaskletData(t_TaskletHandle h_Tasklet, t_Handle data); ++ ++/**************************************************************************//** ++ @Function XX_GetTaskletData ++ ++ @Description Get the data of scheduled task. ++ ++ @Param[in] h_Tasklet - A handle to a tasklet to be scheduled. ++ ++ @Return handle to the data of the task. ++*//***************************************************************************/ ++t_Handle XX_GetTaskletData(t_TaskletHandle h_Tasklet); ++ ++/**************************************************************************//** ++ @Function XX_BottomHalf ++ ++ @Description Bottom half implementation, invoked by the interrupt handler. ++ ++ This routine handles all bottom-half tasklets with interrupts ++ enabled. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_BottomHalf(void); ++ ++ ++/*****************************************************************************/ ++/* Spinlock Service Routines */ ++/*****************************************************************************/ ++ ++/**************************************************************************//** ++ @Function XX_InitSpinlock ++ ++ @Description Creates a spinlock. ++ ++ @Return Spinlock handle is returned on success; NULL otherwise. ++*//***************************************************************************/ ++t_Handle XX_InitSpinlock(void); ++ ++/**************************************************************************//** ++ @Function XX_FreeSpinlock ++ ++ @Description Frees the memory allocated for the spinlock creation. ++ ++ @Param[in] h_Spinlock - A handle to a spinlock. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_FreeSpinlock(t_Handle h_Spinlock); ++ ++/**************************************************************************//** ++ @Function XX_LockSpinlock ++ ++ @Description Locks a spinlock. ++ ++ @Param[in] h_Spinlock - A handle to a spinlock. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_LockSpinlock(t_Handle h_Spinlock); ++ ++/**************************************************************************//** ++ @Function XX_UnlockSpinlock ++ ++ @Description Unlocks a spinlock. ++ ++ @Param[in] h_Spinlock - A handle to a spinlock. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_UnlockSpinlock(t_Handle h_Spinlock); ++ ++/**************************************************************************//** ++ @Function XX_LockIntrSpinlock ++ ++ @Description Locks a spinlock (interrupt safe). ++ ++ @Param[in] h_Spinlock - A handle to a spinlock. ++ ++ @Return A value that represents the interrupts state before the ++ operation, and should be passed to the matching ++ XX_UnlockIntrSpinlock() call. ++*//***************************************************************************/ ++uint32_t XX_LockIntrSpinlock(t_Handle h_Spinlock); ++ ++/**************************************************************************//** ++ @Function XX_UnlockIntrSpinlock ++ ++ @Description Unlocks a spinlock (interrupt safe). ++ ++ @Param[in] h_Spinlock - A handle to a spinlock. ++ @Param[in] intrFlags - A value that represents the interrupts state to ++ restore, as returned by the matching call for ++ XX_LockIntrSpinlock(). ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_UnlockIntrSpinlock(t_Handle h_Spinlock, uint32_t intrFlags); ++ ++ ++/*****************************************************************************/ ++/* Timers Service Routines */ ++/*****************************************************************************/ ++ ++/**************************************************************************//** ++ @Function XX_CurrentTime ++ ++ @Description Returns current system time. ++ ++ @Return Current system time (in milliseconds). ++*//***************************************************************************/ ++uint32_t XX_CurrentTime(void); ++ ++/**************************************************************************//** ++ @Function XX_CreateTimer ++ ++ @Description Creates a timer. ++ ++ @Return Timer handle is returned on success; NULL otherwise. ++*//***************************************************************************/ ++t_Handle XX_CreateTimer(void); ++ ++/**************************************************************************//** ++ @Function XX_FreeTimer ++ ++ @Description Frees the memory allocated for the timer creation. ++ ++ @Param[in] h_Timer - A handle to a timer. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_FreeTimer(t_Handle h_Timer); ++ ++/**************************************************************************//** ++ @Function XX_StartTimer ++ ++ @Description Starts a timer. ++ ++ The user can select to start the timer as periodic timer or as ++ one-shot timer. The user should provide a callback routine that ++ will be called when the timer expires. ++ ++ @Param[in] h_Timer - A handle to a timer. ++ @Param[in] msecs - Timer expiration period (in milliseconds). ++ @Param[in] periodic - TRUE for a periodic timer; ++ FALSE for a one-shot timer.. ++ @Param[in] f_TimerExpired - A callback routine to be called when the ++ timer expires. ++ @Param[in] h_Arg - The argument to pass in the timer-expired ++ callback routine. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_StartTimer(t_Handle h_Timer, ++ uint32_t msecs, ++ bool periodic, ++ void (*f_TimerExpired)(t_Handle h_Arg), ++ t_Handle h_Arg); ++ ++/**************************************************************************//** ++ @Function XX_StopTimer ++ ++ @Description Frees the memory allocated for the timer creation. ++ ++ @Param[in] h_Timer - A handle to a timer. ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_StopTimer(t_Handle h_Timer); ++ ++/**************************************************************************//** ++ @Function XX_ModTimer ++ ++ @Description Updates the expiration time of a timer. ++ ++ This routine adds the given time to the current system time, ++ and sets this value as the new expiration time of the timer. ++ ++ @Param[in] h_Timer - A handle to a timer. ++ @Param[in] msecs - The new interval until timer expiration ++ (in milliseconds). ++ ++ @Return None. ++*//***************************************************************************/ ++void XX_ModTimer(t_Handle h_Timer, uint32_t msecs); ++ ++/**************************************************************************//** ++ @Function XX_Sleep ++ ++ @Description Non-busy wait until the desired time (in milliseconds) has passed. ++ ++ @Param[in] msecs - The requested sleep time (in milliseconds). ++ ++ @Return Zero if the requested time has elapsed; Otherwise, the value ++ returned will be the unslept amount) in milliseconds. ++ ++ @Cautions This routine enables interrupts during its wait time. ++*//***************************************************************************/ ++uint32_t XX_Sleep(uint32_t msecs); ++ ++/**************************************************************************//** ++ @Function XX_UDelay ++ ++ @Description Busy-wait until the desired time (in microseconds) has passed. ++ ++ @Param[in] usecs - The requested delay time (in microseconds). ++ ++ @Return None. ++ ++ @Cautions It is highly unrecommended to call this routine during interrupt ++ time, because the system time may not be updated properly during ++ the delay loop. The behavior of this routine during interrupt ++ time is unexpected. ++*//***************************************************************************/ ++void XX_UDelay(uint32_t usecs); ++ ++ ++/*****************************************************************************/ ++/* Other Service Routines */ ++/*****************************************************************************/ ++ ++/**************************************************************************//** ++ @Function XX_PhysToVirt ++ ++ @Description Translates a physical address to the matching virtual address. ++ ++ @Param[in] addr - The physical address to translate. ++ ++ @Return Virtual address. ++*//***************************************************************************/ ++void * XX_PhysToVirt(physAddress_t addr); ++ ++/**************************************************************************//** ++ @Function XX_VirtToPhys ++ ++ @Description Translates a virtual address to the matching physical address. ++ ++ @Param[in] addr - The virtual address to translate. ++ ++ @Return Physical address. ++*//***************************************************************************/ ++physAddress_t XX_VirtToPhys(void *addr); ++ ++ ++/**************************************************************************//** ++ @Group xx_ipc XX Inter-Partition-Communication API ++ ++ @Description The following API is to be used when working with multiple ++ partitions configuration. ++ ++ @{ ++*//***************************************************************************/ ++ ++#define XX_IPC_MAX_ADDR_NAME_LENGTH 16 /**< Maximum length of an endpoint name string; ++ The IPC service can use this constant to limit ++ the storage space for IPC endpoint names. */ ++ ++ ++/**************************************************************************//** ++ @Function t_IpcMsgCompletion ++ ++ @Description Callback function used upon IPC non-blocking transaction completion ++ to return message buffer to the caller and to forward reply if available. ++ ++ This callback function may be attached by the source endpoint to any outgoing ++ IPC message to indicate a non-blocking send (see also XX_IpcSendMessage() routine). ++ Upon completion of an IPC transaction (consisting of a message and an optional reply), ++ the IPC service invokes this callback routine to return the message buffer to the sender ++ and to provide the received reply, if requested. ++ ++ User provides this function. Driver invokes it. ++ ++ @Param[in] h_Module - Abstract handle to the sending module - the same handle as was passed ++ in the XX_IpcSendMessage() function; This handle is typically used to point ++ to the internal data structure of the source endpoint. ++ @Param[in] p_Msg - Pointer to original (sent) message buffer; ++ The source endpoint can free (or reuse) this buffer when message ++ completion callback is called. ++ @Param[in] p_Reply - Pointer to (received) reply buffer; ++ This pointer is the same as was provided by the source endpoint in ++ XX_IpcSendMessage(). ++ @Param[in] replyLength - Length (in bytes) of actual data in the reply buffer. ++ @Param[in] status - Completion status - E_OK or failure indication, e.g. IPC transaction completion ++ timeout. ++ ++ @Return None ++ *//***************************************************************************/ ++typedef void (t_IpcMsgCompletion)(t_Handle h_Module, ++ uint8_t *p_Msg, ++ uint8_t *p_Reply, ++ uint32_t replyLength, ++ t_Error status); ++ ++/**************************************************************************//** ++ @Function t_IpcMsgHandler ++ ++ @Description Callback function used as IPC message handler. ++ ++ The IPC service invokes message handlers for each IPC message received. ++ The actual function pointer should be registered by each destination endpoint ++ via the XX_IpcRegisterMsgHandler() routine. ++ ++ User provides this function. Driver invokes it. ++ ++ @Param[in] h_Module - Abstract handle to the message handling module - the same handle as ++ was passed in the XX_IpcRegisterMsgHandler() function; this handle is ++ typically used to point to the internal data structure of the destination ++ endpoint. ++ @Param[in] p_Msg - Pointer to message buffer with data received from peer. ++ @Param[in] msgLength - Length (in bytes) of message data. ++ @Param[in] p_Reply - Pointer to reply buffer, to be filled by the message handler and then sent ++ by the IPC service; ++ The reply buffer is allocated by the IPC service with size equals to the ++ replyLength parameter provided in message handler registration (see ++ XX_IpcRegisterMsgHandler() function); ++ If replyLength was initially specified as zero during message handler registration, ++ the IPC service may set this pointer to NULL and assume that a reply is not needed; ++ The IPC service is also responsible for freeing the reply buffer after the ++ reply has been sent or dismissed. ++ @Param[in,out] p_ReplyLength - Pointer to reply length, which has a dual role in this function: ++ [In] equals the replyLength parameter provided in message handler ++ registration (see XX_IpcRegisterMsgHandler() function), and ++ [Out] should be updated by message handler to the actual reply length; if ++ this value is set to zero, the IPC service must assume that a reply should ++ not be sent; ++ Note: If p_Reply is not NULL, p_ReplyLength must not be NULL as well. ++ ++ @Return E_OK on success; Error code otherwise. ++ *//***************************************************************************/ ++typedef t_Error (t_IpcMsgHandler)(t_Handle h_Module, ++ uint8_t *p_Msg, ++ uint32_t msgLength, ++ uint8_t *p_Reply, ++ uint32_t *p_ReplyLength); ++ ++/**************************************************************************//** ++ @Function XX_IpcRegisterMsgHandler ++ ++ @Description IPC mailbox registration. ++ ++ This function is used for registering an IPC message handler in the IPC service. ++ This function is called by each destination endpoint to indicate that it is ready ++ to handle incoming messages. The IPC service invokes the message handler upon receiving ++ a message addressed to the specified destination endpoint. ++ ++ @Param[in] addr - The address name string associated with the destination endpoint; ++ This address must be unique across the IPC service domain to ensure ++ correct message routing. ++ @Param[in] f_MsgHandler - Pointer to the message handler callback for processing incoming ++ message; invoked by the IPC service upon receiving a message ++ addressed to the destination endpoint specified by the addr ++ parameter. ++ @Param[in] h_Module - Abstract handle to the message handling module, passed unchanged ++ to f_MsgHandler callback function. ++ @Param[in] replyLength - The maximal data length (in bytes) of any reply that the specified message handler ++ may generate; the IPC service provides the message handler with buffer ++ for reply according to the length specified here (refer also to the description ++ of #t_IpcMsgHandler callback function type); ++ This size shall be zero if the message handler never generates replies. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error XX_IpcRegisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH], ++ t_IpcMsgHandler *f_MsgHandler, ++ t_Handle h_Module, ++ uint32_t replyLength); ++ ++/**************************************************************************//** ++ @Function XX_IpcUnregisterMsgHandler ++ ++ @Description Release IPC mailbox routine. ++ ++ This function is used for unregistering an IPC message handler from the IPC service. ++ This function is called by each destination endpoint to indicate that it is no longer ++ capable of handling incoming messages. ++ ++ @Param[in] addr - The address name string associated with the destination endpoint; ++ This address is the same as was used when the message handler was ++ registered via XX_IpcRegisterMsgHandler(). ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error XX_IpcUnregisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH]); ++ ++/**************************************************************************//** ++ @Function XX_IpcInitSession ++ ++ @Description This function is used for creating an IPC session between the source endpoint ++ and the destination endpoint. ++ ++ The actual implementation and representation of a session is left for the IPC service. ++ The function returns an abstract handle to the created session. This handle shall be used ++ by the source endpoint in subsequent calls to XX_IpcSendMessage(). ++ The IPC service assumes that before this function is called, no messages are sent from ++ the specified source endpoint to the specified destination endpoint. ++ ++ The IPC service may use a connection-oriented approach or a connectionless approach (or both) ++ as described below. ++ ++ @par Connection-Oriented Approach ++ ++ The IPC service may implement a session in a connection-oriented approach - when this function is called, ++ the IPC service should take the necessary steps to bring up a source-to-destination channel for messages ++ and a destination-to-source channel for replies. The returned handle should represent the internal ++ representation of these channels. ++ ++ @par Connectionless Approach ++ ++ The IPC service may implement a session in a connectionless approach - when this function is called, the ++ IPC service should not perform any particular steps, but it must store the pair of source and destination ++ addresses in some session representation and return it as a handle. When XX_IpcSendMessage() shall be ++ called, the IPC service may use this handle to provide the necessary identifiers for routing the messages ++ through the connectionless medium. ++ ++ @Param[in] destAddr - The address name string associated with the destination endpoint. ++ @Param[in] srcAddr - The address name string associated with the source endpoint. ++ ++ @Return Abstract handle to the initialized session, or NULL on error. ++*//***************************************************************************/ ++t_Handle XX_IpcInitSession(char destAddr[XX_IPC_MAX_ADDR_NAME_LENGTH], ++ char srcAddr[XX_IPC_MAX_ADDR_NAME_LENGTH]); ++ ++/**************************************************************************//** ++ @Function XX_IpcFreeSession ++ ++ @Description This function is used for terminating an existing IPC session between a source endpoint ++ and a destination endpoint. ++ ++ The IPC service assumes that after this function is called, no messages shall be sent from ++ the associated source endpoint to the associated destination endpoint. ++ ++ @Param[in] h_Session - Abstract handle to the IPC session - the same handle as was originally ++ returned by the XX_IpcInitSession() function. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error XX_IpcFreeSession(t_Handle h_Session); ++ ++/**************************************************************************//** ++ @Function XX_IpcSendMessage ++ ++ @Description IPC message send routine. ++ ++ This function may be used by a source endpoint to send an IPC message to a destination ++ endpoint. The source endpoint cannot send a message to the destination endpoint without ++ first initiating a session with that destination endpoint via XX_IpcInitSession() routine. ++ ++ The source endpoint must provide the buffer pointer and length of the outgoing message. ++ Optionally, it may also provide a buffer for an expected reply. In the latter case, the ++ transaction is not considered complete by the IPC service until the reply has been received. ++ If the source endpoint does not provide a reply buffer, the transaction is considered ++ complete after the message has been sent. The source endpoint must keep the message (and ++ optional reply) buffers valid until the transaction is complete. ++ ++ @par Non-blocking mode ++ ++ The source endpoint may request a non-blocking send by providing a non-NULL pointer to a message ++ completion callback function (f_Completion). Upon completion of the IPC transaction (consisting of a ++ message and an optional reply), the IPC service invokes this callback routine to return the message ++ buffer to the sender and to provide the received reply, if requested. ++ ++ @par Blocking mode ++ ++ The source endpoint may request a blocking send by setting f_Completion to NULL. The function is ++ expected to block until the IPC transaction is complete - either the reply has been received or (if no reply ++ was requested) the message has been sent. ++ ++ @Param[in] h_Session - Abstract handle to the IPC session - the same handle as was originally ++ returned by the XX_IpcInitSession() function. ++ @Param[in] p_Msg - Pointer to message buffer to send. ++ @Param[in] msgLength - Length (in bytes) of actual data in the message buffer. ++ @Param[in] p_Reply - Pointer to reply buffer - if this buffer is not NULL, the IPC service ++ fills this buffer with the received reply data; ++ In blocking mode, the reply data must be valid when the function returns; ++ In non-blocking mode, the reply data is valid when f_Completion is called; ++ If this pointer is NULL, no reply is expected. ++ @Param[in,out] p_ReplyLength - Pointer to reply length, which has a dual role in this function: ++ [In] specifies the maximal length (in bytes) of the reply buffer pointed by ++ p_Reply, and ++ [Out] in non-blocking mode this value is updated by the IPC service to the ++ actual reply length (in bytes). ++ @Param[in] f_Completion - Pointer to a completion callback to be used in non-blocking send mode; ++ The completion callback is invoked by the IPC service upon ++ completion of the IPC transaction (consisting of a message and an optional ++ reply); ++ If this pointer is NULL, the function is expected to block until the IPC ++ transaction is complete. ++ @Param[in] h_Arg - Abstract handle to the sending module; passed unchanged to the f_Completion ++ callback function as the first argument. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error XX_IpcSendMessage(t_Handle h_Session, ++ uint8_t *p_Msg, ++ uint32_t msgLength, ++ uint8_t *p_Reply, ++ uint32_t *p_ReplyLength, ++ t_IpcMsgCompletion *f_Completion, ++ t_Handle h_Arg); ++ ++ ++/** @} */ /* end of xx_ipc group */ ++/** @} */ /* end of xx_id group */ ++ ++ ++#endif /* __XX_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk b/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk +new file mode 100644 +index 0000000..b1fde53 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk +@@ -0,0 +1,47 @@ ++# ++# Makefile config for the Freescale NetcommSW ++# ++NET_DPA = $(srctree)/drivers/net ++DRV_DPA = $(srctree)/drivers/net/ethernet/freescale/sdk_dpaa ++FMAN = $(srctree)/drivers/net/ethernet/freescale/sdk_fman ++ ++ifeq ("$(CONFIG_FMAN_P3040_P4080_P5020)", "y") ++ccflags-y +=-include $(FMAN)/p3040_4080_5020_dflags.h ++endif ++ifeq ("$(CONFIG_FMAN_P1023)", "y") ++ccflags-y +=-include $(FMAN)/p1023_dflags.h ++endif ++ifdef CONFIG_FMAN_V3H ++ccflags-y +=-include $(FMAN)/fmanv3h_dflags.h ++endif ++ifdef CONFIG_FMAN_V3L ++ccflags-y +=-include $(FMAN)/fmanv3l_dflags.h ++endif ++ ++ccflags-y += -I$(DRV_DPA)/ ++ccflags-y += -I$(FMAN)/inc ++ccflags-y += -I$(FMAN)/inc/cores ++ccflags-y += -I$(FMAN)/inc/etc ++ccflags-y += -I$(FMAN)/inc/Peripherals ++ccflags-y += -I$(FMAN)/inc/flib ++ ++ifeq ("$(CONFIG_FMAN_P3040_P4080_P5020)", "y") ++ccflags-y += -I$(FMAN)/inc/integrations/P3040_P4080_P5020 ++endif ++ifeq ("$(CONFIG_FMAN_P1023)", "y") ++ccflags-y += -I$(FMAN)/inc/integrations/P1023 ++endif ++ifdef CONFIG_FMAN_V3H ++ccflags-y += -I$(FMAN)/inc/integrations/FMANV3H ++endif ++ifdef CONFIG_FMAN_V3L ++ccflags-y += -I$(FMAN)/inc/integrations/FMANV3L ++endif ++ ++ccflags-y += -I$(FMAN)/src/inc ++ccflags-y += -I$(FMAN)/src/inc/system ++ccflags-y += -I$(FMAN)/src/inc/wrapper ++ccflags-y += -I$(FMAN)/src/inc/xx ++ccflags-y += -I$(srctree)/include/uapi/linux/fmd ++ccflags-y += -I$(srctree)/include/uapi/linux/fmd/Peripherals ++ccflags-y += -I$(srctree)/include/uapi/linux/fmd/integrations +diff --git a/drivers/net/ethernet/freescale/sdk_fman/p1023_dflags.h b/drivers/net/ethernet/freescale/sdk_fman/p1023_dflags.h +new file mode 100644 +index 0000000..b48819d +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/p1023_dflags.h +@@ -0,0 +1,65 @@ ++/* ++ * Copyright 2008-2012 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 __dflags_h ++#define __dflags_h ++ ++ ++#define NCSW_LINUX ++#if 0 ++#define DEBUG ++#endif ++ ++#define P1023 ++#define NCSW_PPC_CORE ++ ++#define DEBUG_ERRORS 1 ++ ++#if defined(DEBUG) ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_INFO ++ ++#define DEBUG_XX_MALLOC ++#define DEBUG_MEM_LEAKS ++ ++#else ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_WARNING ++#endif /* (DEBUG) */ ++ ++#define REPORT_EVENTS 1 ++#define EVENT_GLOBAL_LEVEL REPORT_LEVEL_MINOR ++ ++#ifdef CONFIG_P4080_SIM ++#error "Do not define CONFIG_P4080_SIM..." ++#endif ++ ++ ++#endif /* __dflags_h */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/p3040_4080_5020_dflags.h b/drivers/net/ethernet/freescale/sdk_fman/p3040_4080_5020_dflags.h +new file mode 100644 +index 0000000..7438974 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/p3040_4080_5020_dflags.h +@@ -0,0 +1,62 @@ ++/* ++ * Copyright 2008-2012 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 __dflags_h ++#define __dflags_h ++ ++ ++#define NCSW_LINUX ++ ++#define P4080 ++#define NCSW_PPC_CORE ++ ++#define DEBUG_ERRORS 1 ++ ++#if defined(DEBUG) ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_INFO ++ ++#define DEBUG_XX_MALLOC ++#define DEBUG_MEM_LEAKS ++ ++#else ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_WARNING ++#endif /* (DEBUG) */ ++ ++#define REPORT_EVENTS 1 ++#define EVENT_GLOBAL_LEVEL REPORT_LEVEL_MINOR ++ ++#ifdef CONFIG_P4080_SIM ++#define SIMULATOR ++#endif /* CONFIG_P4080_SIM */ ++ ++ ++#endif /* __dflags_h */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/Makefile b/drivers/net/ethernet/freescale/sdk_fman/src/Makefile +new file mode 100644 +index 0000000..49405d0 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/Makefile +@@ -0,0 +1,11 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++ccflags-y += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk ++# ++obj-y += system/ ++obj-y += wrapper/ ++obj-y += xx/ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/inc/system/sys_ext.h b/drivers/net/ethernet/freescale/sdk_fman/src/inc/system/sys_ext.h +new file mode 100644 +index 0000000..20f27d2 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/inc/system/sys_ext.h +@@ -0,0 +1,118 @@ ++/* ++ * Copyright 2008-2012 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 __SYS_EXT_H ++#define __SYS_EXT_H ++ ++#include "std_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group sys_grp System Interfaces ++ ++ @Description Linux system programming interfaces. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group sys_gen_grp System General Interface ++ ++ @Description General definitions, structures and routines of the linux ++ system programming interface. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Collection Macros for Advanced Configuration Requests ++ @{ ++*//***************************************************************************/ ++#define SYS_MAX_ADV_CONFIG_ARGS 4 ++ /**< Maximum number of arguments in ++ an advanced configuration entry */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Description System Object Advanced Configuration Entry ++ ++ This structure represents a single request for an advanced ++ configuration call on the initialized object. An array of such ++ requests may be contained in the settings structure of the ++ corresponding object. ++ ++ The maximum number of arguments is limited to #SYS_MAX_ADV_CONFIG_ARGS. ++*//***************************************************************************/ ++typedef struct t_SysObjectAdvConfigEntry ++{ ++ void *p_Function; /**< Pointer to advanced configuration routine */ ++ ++ uintptr_t args[SYS_MAX_ADV_CONFIG_ARGS]; ++ /**< Array of arguments for the specified routine; ++ All arguments should be casted to uint32_t. */ ++} t_SysObjectAdvConfigEntry; ++ ++ ++/** @} */ /* end of sys_gen_grp */ ++/** @} */ /* end of sys_grp */ ++ ++#define NCSW_PARAMS(_num, _params) ADV_CONFIG_PARAMS_##_num _params ++ ++#define ADV_CONFIG_PARAMS_1(_type) \ ++ , (_type)p_Entry->args[0] ++ ++#define SET_ADV_CONFIG_ARGS_1(_arg0) \ ++ p_Entry->args[0] = (uintptr_t )(_arg0); \ ++ ++#define ARGS(_num, _params) SET_ADV_CONFIG_ARGS_##_num _params ++ ++#define ADD_ADV_CONFIG_START(_p_Entries, _maxEntries) \ ++ { \ ++ t_SysObjectAdvConfigEntry *p_Entry; \ ++ t_SysObjectAdvConfigEntry *p_Entrys = (_p_Entries); \ ++ int i=0, max = (_maxEntries); \ ++ ++#define ADD_ADV_CONFIG_END \ ++ } ++ ++#define ADV_CONFIG_CHECK_START(_p_Entry) \ ++ { \ ++ t_SysObjectAdvConfigEntry *p_Entry = _p_Entry; \ ++ t_Error errCode; \ ++ ++#define ADV_CONFIG_CHECK(_handle, _func, _params) \ ++ if (p_Entry->p_Function == _func) \ ++ { \ ++ errCode = _func(_handle _params); \ ++ } else ++ ++#endif /* __SYS_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/inc/system/sys_io_ext.h b/drivers/net/ethernet/freescale/sdk_fman/src/inc/system/sys_io_ext.h +new file mode 100644 +index 0000000..d6aa9d4 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/inc/system/sys_io_ext.h +@@ -0,0 +1,46 @@ ++/* ++ * Copyright 2008-2012 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 __SYS_IO_EXT_H ++#define __SYS_IO_EXT_H ++ ++#include "std_ext.h" ++#include "error_ext.h" ++ ++ ++t_Error SYS_RegisterIoMap (uint64_t virtAddr, uint64_t physAddr, uint32_t size); ++t_Error SYS_UnregisterIoMap (uint64_t virtAddr); ++uint64_t SYS_PhysToVirt (uint64_t addr); ++uint64_t SYS_VirtToPhys (uint64_t addr); ++ ++ ++#endif /* __SYS_IO_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/inc/types_linux.h b/drivers/net/ethernet/freescale/sdk_fman/src/inc/types_linux.h +new file mode 100644 +index 0000000..ac15d66 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/inc/types_linux.h +@@ -0,0 +1,200 @@ ++/* ++ * Copyright 2008-2012 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 __TYPES_LINUX_H__ ++#define __TYPES_LINUX_H__ ++ ++#include ++ ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#include ++#endif /* MODVERSIONS */ ++ ++#include ++#include ++#include ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) ++ #error "This kernel is probably not supported!!!" ++#elif (!((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) || \ ++ (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27)) || \ ++ (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,30)))) ++ #warning "This kernel is probably not supported!!! You may need to add some fixes." ++#endif /* LINUX_VERSION_CODE */ ++ ++ ++typedef float float_t; /* Single precision floating point */ ++typedef double double_t; /* Double precision floating point */ ++ ++ ++#define _Packed ++#define _PackedType __attribute__ ((packed)) ++ ++typedef phys_addr_t physAddress_t; ++ ++#define UINT8_MAX 0xFF ++#define UINT8_MIN 0 ++#define UINT16_MAX 0xFFFF ++#define UINT16_MIN 0 ++#define UINT32_MAX 0xFFFFFFFF ++#define UINT32_MIN 0 ++#define UINT64_MAX 0xFFFFFFFFFFFFFFFFLL ++#define UINT64_MIN 0 ++#define INT8_MAX 0x7F ++#define INT8_MIN 0x80 ++#define INT16_MAX 0x7FFF ++#define INT16_MIN 0x8000 ++#define INT32_MAX 0x7FFFFFFF ++#define INT32_MIN 0x80000000 ++#define INT64_MAX 0x7FFFFFFFFFFFFFFFLL ++#define INT64_MIN 0x8000000000000000LL ++ ++#define ON 1 ++#define OFF 0 ++ ++#define FALSE false ++#define TRUE true ++ ++ ++/************************/ ++/* memory access macros */ ++/************************/ ++#define GET_UINT8(arg) *(volatile uint8_t *)(&(arg)) ++#define GET_UINT16(arg) in_be16(&(arg))//*(volatile uint16_t*)(&(arg)) ++#define GET_UINT32(arg) in_be32(&(arg))//*(volatile uint32_t*)(&(arg)) ++#define GET_UINT64(arg) *(volatile uint64_t*)(&(arg)) ++ ++#ifdef VERBOSE_WRITE ++void XX_Print(char *str, ...); ++#define WRITE_UINT8(arg, data) \ ++ do { XX_Print("ADDR: 0x%08x, VAL: 0x%02x\r\n", (uint32_t)&(arg), (data)); *(volatile uint8_t *)(&(arg)) = (data); } while (0) ++#define WRITE_UINT16(arg, data) \ ++ do { XX_Print("ADDR: 0x%08x, VAL: 0x%04x\r\n", (uint32_t)&(arg), (data)); out_be16(&(arg), data); /* *(volatile uint16_t*)(&(arg)) = (data);*/ } while (0) ++#define WRITE_UINT32(arg, data) \ ++ do { XX_Print("ADDR: 0x%08x, VAL: 0x%08x\r\n", (uint32_t)&(arg), (data)); out_be32(&(arg), data); /* *(volatile uint32_t*)(&(arg)) = (data);*/ } while (0) ++#define WRITE_UINT64(arg, data) \ ++ do { XX_Print("ADDR: 0x%08x, VAL: 0x%016llx\r\n", (uint32_t)&(arg), (data)); *(volatile uint64_t*)(&(arg)) = (data); } while (0) ++ ++#else /* not VERBOSE_WRITE */ ++#define WRITE_UINT8(arg, data) *(volatile uint8_t *)(&(arg)) = (data) ++#define WRITE_UINT16(arg, data) out_be16(&(arg), data)//*(volatile uint16_t*)(&(arg)) = (data) ++#define WRITE_UINT32(arg, data) out_be32(&(arg), data)//*(volatile unsigned int *)(&(arg)) = (data) ++#define WRITE_UINT64(arg, data) *(volatile uint64_t*)(&(arg)) = (data) ++#endif /* not VERBOSE_WRITE */ ++ ++ ++/*****************************************************************************/ ++/* General stuff */ ++/*****************************************************************************/ ++#ifdef ARRAY_SIZE ++#undef ARRAY_SIZE ++#endif /* ARRAY_SIZE */ ++ ++#ifdef MAJOR ++#undef MAJOR ++#endif /* MAJOR */ ++ ++#ifdef MINOR ++#undef MINOR ++#endif /* MINOR */ ++ ++#ifdef QE_SIZEOF_BD ++#undef QE_SIZEOF_BD ++#endif /* QE_SIZEOF_BD */ ++ ++#ifdef BD_BUFFER_CLEAR ++#undef BD_BUFFER_CLEAR ++#endif /* BD_BUFFER_CLEAR */ ++ ++#ifdef BD_BUFFER ++#undef BD_BUFFER ++#endif /* BD_BUFFER */ ++ ++#ifdef BD_STATUS_AND_LENGTH_SET ++#undef BD_STATUS_AND_LENGTH_SET ++#endif /* BD_STATUS_AND_LENGTH_SET */ ++ ++#ifdef BD_STATUS_AND_LENGTH ++#undef BD_STATUS_AND_LENGTH ++#endif /* BD_STATUS_AND_LENGTH */ ++ ++#ifdef BD_BUFFER_ARG ++#undef BD_BUFFER_ARG ++#endif /* BD_BUFFER_ARG */ ++ ++#ifdef BD_GET_NEXT ++#undef BD_GET_NEXT ++#endif /* BD_GET_NEXT */ ++ ++#ifdef QE_SDEBCR_BA_MASK ++#undef QE_SDEBCR_BA_MASK ++#endif /* QE_SDEBCR_BA_MASK */ ++ ++#ifdef BD_BUFFER_SET ++#undef BD_BUFFER_SET ++#endif /* BD_BUFFER_SET */ ++ ++#ifdef UPGCR_PROTOCOL ++#undef UPGCR_PROTOCOL ++#endif /* UPGCR_PROTOCOL */ ++ ++#ifdef UPGCR_TMS ++#undef UPGCR_TMS ++#endif /* UPGCR_TMS */ ++ ++#ifdef UPGCR_RMS ++#undef UPGCR_RMS ++#endif /* UPGCR_RMS */ ++ ++#ifdef UPGCR_ADDR ++#undef UPGCR_ADDR ++#endif /* UPGCR_ADDR */ ++ ++#ifdef UPGCR_DIAG ++#undef UPGCR_DIAG ++#endif /* UPGCR_DIAG */ ++ ++#ifdef NCSW_PARAMS ++#undef NCSW_PARAMS ++#endif /* NCSW_PARAMS */ ++ ++#ifdef NO_IRQ ++#undef NO_IRQ ++#endif /* NO_IRQ */ ++ ++#define PRINT_LINE XX_Print("%s:\n %s [%d]\n",__FILE__,__FUNCTION__,__LINE__); ++ ++ ++#endif /* __TYPES_LINUX_H__ */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/inc/wrapper/fsl_fman_test.h b/drivers/net/ethernet/freescale/sdk_fman/src/inc/wrapper/fsl_fman_test.h +new file mode 100644 +index 0000000..0466a47 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/inc/wrapper/fsl_fman_test.h +@@ -0,0 +1,84 @@ ++/* Copyright (c) 2008-2011 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++/****************************************************************************** ++ @File fsl_fman_test.h ++ ++ @Description ++*//***************************************************************************/ ++ ++#ifndef __FSL_FMAN_TEST_H ++#define __FSL_FMAN_TEST_H ++ ++#include ++#include /* raw_smp_processor_id() */ ++ ++//#define FMT_K_DBG ++//#define FMT_K_DBG_RUNTIME ++ ++#define _fmt_prk(stage, format, arg...) \ ++ printk(stage "fmt (cpu:%u): " format, raw_smp_processor_id(), ##arg) ++ ++#define _fmt_inf(format, arg...) _fmt_prk(KERN_INFO, format, ##arg) ++#define _fmt_wrn(format, arg...) _fmt_prk(KERN_WARNING, format, ##arg) ++#define _fmt_err(format, arg...) _fmt_prk(KERN_ERR, format, ##arg) ++ ++/* there are two macros for debugging: for runtime and generic. ++ * Helps when the runtime functions are not targeted for debugging, ++ * thus all the unnecessary information will be skipped. ++ */ ++/* used for generic debugging */ ++#if defined(FMT_K_DBG) ++ #define _fmt_dbg(format, arg...) \ ++ printk("fmt [%s:%u](cpu:%u) - " format, \ ++ __func__, __LINE__, raw_smp_processor_id(), ##arg) ++#else ++# define _fmt_dbg(arg...) ++#endif ++ ++/* used for debugging runtime functions */ ++#if defined(FMT_K_DBG_RUNTIME) ++ #define _fmt_dbgr(format, arg...) \ ++ printk("fmt [%s:%u](cpu:%u) - " format, \ ++ __func__, __LINE__, raw_smp_processor_id(), ##arg) ++#else ++# define _fmt_dbgr(arg...) ++#endif ++ ++#define FMT_RX_ERR_Q 0xffffffff ++#define FMT_RX_DFLT_Q 0xfffffffe ++#define FMT_TX_ERR_Q 0xfffffffd ++#define FMT_TX_CONF_Q 0xfffffffc ++ ++#define FMAN_TEST_MAX_TX_FQS 8 ++ ++#endif /* __FSL_FMAN_TEST_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/inc/wrapper/lnxwrp_exp_sym.h b/drivers/net/ethernet/freescale/sdk_fman/src/inc/wrapper/lnxwrp_exp_sym.h +new file mode 100644 +index 0000000..13c61d2 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/inc/wrapper/lnxwrp_exp_sym.h +@@ -0,0 +1,127 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++/* ++ @File lnxwrp_exp_sym.h ++ @Description FMan exported routines ++*/ ++ ++#ifndef __LNXWRP_EXP_SYM_H ++#define __LNXWRP_EXP_SYM_H ++ ++#include "fm_port_ext.h" ++#include "fm_pcd_ext.h" ++#include "fm_mac_ext.h" ++ ++ ++/* FMAN Port exported routines */ ++EXPORT_SYMBOL(FM_PORT_Disable); ++EXPORT_SYMBOL(FM_PORT_Enable); ++EXPORT_SYMBOL(FM_PORT_SetPCD); ++ ++/* Runtime PCD exported routines */ ++EXPORT_SYMBOL(FM_PCD_Enable); ++EXPORT_SYMBOL(FM_PCD_Disable); ++EXPORT_SYMBOL(FM_PCD_GetCounter); ++EXPORT_SYMBOL(FM_PCD_PrsLoadSw); ++EXPORT_SYMBOL(FM_PCD_KgSetDfltValue); ++EXPORT_SYMBOL(FM_PCD_KgSetAdditionalDataAfterParsing); ++EXPORT_SYMBOL(FM_PCD_SetException); ++EXPORT_SYMBOL(FM_PCD_ModifyCounter); ++EXPORT_SYMBOL(FM_PCD_SetPlcrStatistics); ++EXPORT_SYMBOL(FM_PCD_SetPrsStatistics); ++EXPORT_SYMBOL(FM_PCD_ForceIntr); ++EXPORT_SYMBOL(FM_PCD_HcTxConf); ++ ++EXPORT_SYMBOL(FM_PCD_NetEnvCharacteristicsSet); ++EXPORT_SYMBOL(FM_PCD_NetEnvCharacteristicsDelete); ++EXPORT_SYMBOL(FM_PCD_KgSchemeSet); ++EXPORT_SYMBOL(FM_PCD_KgSchemeDelete); ++EXPORT_SYMBOL(FM_PCD_KgSchemeGetCounter); ++EXPORT_SYMBOL(FM_PCD_KgSchemeSetCounter); ++EXPORT_SYMBOL(FM_PCD_CcRootBuild); ++EXPORT_SYMBOL(FM_PCD_CcRootDelete); ++EXPORT_SYMBOL(FM_PCD_MatchTableSet); ++EXPORT_SYMBOL(FM_PCD_MatchTableDelete); ++EXPORT_SYMBOL(FM_PCD_CcRootModifyNextEngine); ++EXPORT_SYMBOL(FM_PCD_MatchTableModifyNextEngine); ++EXPORT_SYMBOL(FM_PCD_MatchTableFindNModifyNextEngine); ++EXPORT_SYMBOL(FM_PCD_MatchTableModifyMissNextEngine); ++EXPORT_SYMBOL(FM_PCD_MatchTableRemoveKey); ++EXPORT_SYMBOL(FM_PCD_MatchTableFindNRemoveKey); ++EXPORT_SYMBOL(FM_PCD_MatchTableAddKey); ++EXPORT_SYMBOL(FM_PCD_MatchTableModifyKeyAndNextEngine); ++EXPORT_SYMBOL(FM_PCD_MatchTableFindNModifyKeyAndNextEngine); ++EXPORT_SYMBOL(FM_PCD_MatchTableModifyKey); ++EXPORT_SYMBOL(FM_PCD_MatchTableFindNModifyKey); ++EXPORT_SYMBOL(FM_PCD_MatchTableGetIndexedHashBucket); ++EXPORT_SYMBOL(FM_PCD_MatchTableGetNextEngine); ++EXPORT_SYMBOL(FM_PCD_MatchTableGetKeyCounter); ++EXPORT_SYMBOL(FM_PCD_MatchTableGetKeyStatistics); ++EXPORT_SYMBOL(FM_PCD_MatchTableFindNGetKeyStatistics); ++EXPORT_SYMBOL(FM_PCD_MatchTableGetMissStatistics); ++EXPORT_SYMBOL(FM_PCD_HashTableGetMissStatistics); ++EXPORT_SYMBOL(FM_PCD_HashTableSet); ++EXPORT_SYMBOL(FM_PCD_HashTableDelete); ++EXPORT_SYMBOL(FM_PCD_HashTableAddKey); ++EXPORT_SYMBOL(FM_PCD_HashTableRemoveKey); ++EXPORT_SYMBOL(FM_PCD_HashTableModifyNextEngine); ++EXPORT_SYMBOL(FM_PCD_HashTableModifyMissNextEngine); ++EXPORT_SYMBOL(FM_PCD_HashTableGetMissNextEngine); ++EXPORT_SYMBOL(FM_PCD_HashTableFindNGetKeyStatistics); ++EXPORT_SYMBOL(FM_PCD_PlcrProfileSet); ++EXPORT_SYMBOL(FM_PCD_PlcrProfileDelete); ++EXPORT_SYMBOL(FM_PCD_PlcrProfileGetCounter); ++EXPORT_SYMBOL(FM_PCD_PlcrProfileSetCounter); ++EXPORT_SYMBOL(FM_PCD_ManipNodeSet); ++EXPORT_SYMBOL(FM_PCD_ManipNodeDelete); ++EXPORT_SYMBOL(FM_PCD_ManipGetStatistics); ++EXPORT_SYMBOL(FM_PCD_ManipNodeReplace); ++#if (DPAA_VERSION >= 11) ++EXPORT_SYMBOL(FM_PCD_FrmReplicSetGroup); ++EXPORT_SYMBOL(FM_PCD_FrmReplicDeleteGroup); ++EXPORT_SYMBOL(FM_PCD_FrmReplicAddMember); ++EXPORT_SYMBOL(FM_PCD_FrmReplicRemoveMember); ++#endif /* DPAA_VERSION >= 11 */ ++ ++#ifdef FM_CAPWAP_SUPPORT ++EXPORT_SYMBOL(FM_PCD_StatisticsSetNode); ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++EXPORT_SYMBOL(FM_PCD_SetAdvancedOffloadSupport); ++ ++/* FMAN MAC exported routines */ ++EXPORT_SYMBOL(FM_MAC_GetStatistics); ++ ++EXPORT_SYMBOL(FM_GetSpecialOperationCoding); ++ ++#endif /* __LNXWRP_EXP_SYM_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/inc/wrapper/lnxwrp_fm_ext.h b/drivers/net/ethernet/freescale/sdk_fman/src/inc/wrapper/lnxwrp_fm_ext.h +new file mode 100644 +index 0000000..a72c867 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/inc/wrapper/lnxwrp_fm_ext.h +@@ -0,0 +1,163 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/****************************************************************************** ++ @File lnxwrp_fm_ext.h ++ ++ @Description TODO ++*//***************************************************************************/ ++ ++#ifndef __LNXWRP_FM_EXT_H ++#define __LNXWRP_FM_EXT_H ++ ++#include "std_ext.h" ++#include "sys_ext.h" ++#include "fm_ext.h" ++#include "fm_muram_ext.h" ++#include "fm_pcd_ext.h" ++#include "fm_port_ext.h" ++#include "fm_mac_ext.h" ++#include "fm_rtc_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group FM_LnxKern_grp Frame Manager Linux wrapper API ++ ++ @Description FM API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_LnxKern_init_grp Initialization Unit ++ ++ @Description Initialization Unit ++ ++ Initialization Flow: ++ Initialization of the FM Module will be carried out by the Linux ++ kernel according to the following sequence: ++ a. Calling the initialization routine with no parameters. ++ b. The driver will register to the Device-Tree. ++ c. The Linux Device-Tree will initiate a call to the driver for ++ initialization. ++ d. The driver will read the appropriate information from the Device-Tree ++ e. [Optional] Calling the advance initialization routines to change ++ driver's defaults. ++ f. Initialization of the device will be automatically upon using it. ++ ++ @{ ++*//***************************************************************************/ ++ ++typedef struct t_WrpFmDevSettings ++{ ++ t_FmParams param; ++ t_SysObjectAdvConfigEntry *advConfig; ++} t_WrpFmDevSettings; ++ ++typedef struct t_WrpFmPcdDevSettings ++{ ++ t_FmPcdParams param; ++ t_SysObjectAdvConfigEntry *advConfig; ++} t_WrpFmPcdDevSettings; ++ ++typedef struct t_WrpFmPortDevSettings ++{ ++ bool frag_enabled; ++ t_FmPortParams param; ++ t_SysObjectAdvConfigEntry *advConfig; ++} t_WrpFmPortDevSettings; ++ ++typedef struct t_WrpFmMacDevSettings ++{ ++ t_FmMacParams param; ++ t_SysObjectAdvConfigEntry *advConfig; ++} t_WrpFmMacDevSettings; ++ ++ ++/**************************************************************************//** ++ @Function LNXWRP_FM_Init ++ ++ @Description Initialize the FM linux wrapper. ++ ++ @Return A handle (descriptor) of the newly created FM Linux wrapper ++ structure. ++*//***************************************************************************/ ++t_Handle LNXWRP_FM_Init(void); ++ ++/**************************************************************************//** ++ @Function LNXWRP_FM_Free ++ ++ @Description Free the FM linux wrapper. ++ ++ @Param[in] h_LnxWrpFm - A handle to the FM linux wrapper. ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++t_Error LNXWRP_FM_Free(t_Handle h_LnxWrpFm); ++ ++/**************************************************************************//** ++ @Function LNXWRP_FM_GetMacHandle ++ ++ @Description Get the FM-MAC LLD handle from the FM linux wrapper. ++ ++ @Param[in] h_LnxWrpFm - A handle to the FM linux wrapper. ++ @Param[in] fmId - Index of the FM device to get the MAC handle from. ++ @Param[in] macId - Index of the mac handle. ++ ++ @Return A handle of the LLD compressor. ++*//***************************************************************************/ ++t_Handle LNXWRP_FM_GetMacHandle(t_Handle h_LnxWrpFm, uint8_t fmId, uint8_t macId); ++ ++#ifdef CONFIG_FSL_SDK_FMAN_TEST ++t_Handle LNXWRP_FM_TEST_Init(void); ++t_Error LNXWRP_FM_TEST_Free(t_Handle h_FmTestLnxWrp); ++#endif /* CONFIG_FSL_SDK_FMAN_TEST */ ++ ++/** @} */ /* end of FM_LnxKern_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group FM_LnxKern_ctrl_grp Control Unit ++ ++ @Description Control Unit ++ ++ TODO ++ @{ ++*//***************************************************************************/ ++ ++#include "lnxwrp_fsl_fman.h" ++ ++/** @} */ /* end of FM_LnxKern_ctrl_grp group */ ++/** @} */ /* end of FM_LnxKern_grp group */ ++ ++ ++#endif /* __LNXWRP_FM_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/inc/wrapper/lnxwrp_fsl_fman.h b/drivers/net/ethernet/freescale/sdk_fman/src/inc/wrapper/lnxwrp_fsl_fman.h +new file mode 100644 +index 0000000..f068499 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/inc/wrapper/lnxwrp_fsl_fman.h +@@ -0,0 +1,919 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/****************************************************************************** ++ @File lnxwrp_fsl_fman.h ++ ++ @Description Linux internal kernel API ++*//***************************************************************************/ ++ ++#ifndef __LNXWRP_FSL_FMAN_H ++#define __LNXWRP_FSL_FMAN_H ++ ++#include ++#include /* struct device */ ++#include /* struct qman_fq */ ++#include "dpaa_integration_ext.h" ++#include "fm_port_ext.h" ++#include "fm_mac_ext.h" ++#include "fm_macsec_ext.h" ++#include "fm_rtc_ext.h" ++ ++/**************************************************************************//** ++ @Group FM_LnxKern_grp Frame Manager Linux wrapper API ++ ++ @Description FM API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group FM_LnxKern_ctrl_grp Control Unit ++ ++ @Description Control Unit ++ ++ Internal Kernel Control Unit API ++ @{ ++*//***************************************************************************/ ++ ++/*****************************************************************************/ ++/* Internal Linux kernel routines */ ++/*****************************************************************************/ ++ ++/**************************************************************************//** ++ @Description MACSEC Exceptions wrapper ++*//***************************************************************************/ ++typedef enum fm_macsec_exception { ++ SINGLE_BIT_ECC = e_FM_MACSEC_EX_SINGLE_BIT_ECC, ++ MULTI_BIT_ECC = e_FM_MACSEC_EX_MULTI_BIT_ECC ++} fm_macsec_exception; ++ ++/**************************************************************************//** ++ @Description Unknown sci frame treatment wrapper ++*//***************************************************************************/ ++typedef enum fm_macsec_unknown_sci_frame_treatment { ++ SCI_DISCARD_BOTH = e_FM_MACSEC_UNKNOWN_SCI_FRAME_TREATMENT_DISCARD_BOTH, ++ SCI_DISCARD_UNCTRL_DELIVER_DISCARD_CTRL = \ ++ e_FM_MACSEC_UNKNOWN_SCI_FRAME_TREATMENT_DISCARD_UNCONTROLLED_DELIVER_OR_DISCARD_CONTROLLED, ++ SCI_DELIVER_UNCTRL_DISCARD_CTRL = \ ++ e_FM_MACSEC_UNKNOWN_SCI_FRAME_TREATMENT_DELIVER_UNCONTROLLED_DISCARD_CONTROLLED, ++ SCI_DELIVER_DISCARD_UNCTRL_DELIVER_DISCARD_CTRL = \ ++ e_FM_MACSEC_UNKNOWN_SCI_FRAME_TREATMENT_DELIVER_OR_DISCARD_UNCONTROLLED_DELIVER_OR_DISCARD_CONTROLLED ++} fm_macsec_unknown_sci_frame_treatment; ++ ++/**************************************************************************//** ++ @Description Untag frame treatment wrapper ++*//***************************************************************************/ ++typedef enum fm_macsec_untag_frame_treatment { ++ UNTAG_DELIVER_UNCTRL_DISCARD_CTRL = \ ++ e_FM_MACSEC_UNTAG_FRAME_TREATMENT_DELIVER_UNCONTROLLED_DISCARD_CONTROLLED, ++ UNTAG_DISCARD_BOTH = e_FM_MACSEC_UNTAG_FRAME_TREATMENT_DISCARD_BOTH, ++ UNTAG_DISCARD_UNCTRL_DELIVER_CTRL_UNMODIFIED = \ ++ e_FM_MACSEC_UNTAG_FRAME_TREATMENT_DISCARD_UNCONTROLLED_DELIVER_CONTROLLED_UNMODIFIED ++} fm_macsec_untag_frame_treatment; ++ ++/**************************************************************************//** ++ at Description MACSEC SECY Cipher Suite wrapper ++*//***************************************************************************/ ++typedef enum fm_macsec_secy_cipher_suite { ++ SECY_GCM_AES_128 = e_FM_MACSEC_SECY_GCM_AES_128, /**< GCM-AES-128 */ ++#if (DPAA_VERSION >= 11) ++ SECY_GCM_AES_256 = e_FM_MACSEC_SECY_GCM_AES_256 /**< GCM-AES-256 */ ++#endif /* (DPAA_VERSION >= 11) */ ++} fm_macsec_secy_cipher_suite; ++ ++/**************************************************************************//** ++ @Description MACSEC SECY Exceptions wrapper ++*//***************************************************************************/ ++typedef enum fm_macsec_secy_exception { ++ SECY_EX_FRAME_DISCARDED = e_FM_MACSEC_SECY_EX_FRAME_DISCARDED ++} fm_macsec_secy_exception; ++ ++/**************************************************************************//** ++ @Description MACSEC SECY Events wrapper ++*//***************************************************************************/ ++typedef enum fm_macsec_secy_event { ++ SECY_EV_NEXT_PN = e_FM_MACSEC_SECY_EV_NEXT_PN ++} fm_macsec_secy_event; ++ ++/**************************************************************************//** ++ @Description Valid frame behaviors wrapper ++*//***************************************************************************/ ++typedef enum fm_macsec_valid_frame_behavior { ++ VALID_FRAME_BEHAVIOR_DISABLE = e_FM_MACSEC_VALID_FRAME_BEHAVIOR_DISABLE, ++ VALID_FRAME_BEHAVIOR_CHECK = e_FM_MACSEC_VALID_FRAME_BEHAVIOR_CHECK, ++ VALID_FRAME_BEHAVIOR_STRICT = e_FM_MACSEC_VALID_FRAME_BEHAVIOR_STRICT ++} fm_macsec_valid_frame_behavior; ++ ++/**************************************************************************//** ++ @Description SCI insertion modes wrapper ++*//***************************************************************************/ ++typedef enum fm_macsec_sci_insertion_mode { ++ SCI_INSERTION_MODE_EXPLICIT_SECTAG = \ ++ e_FM_MACSEC_SCI_INSERTION_MODE_EXPLICIT_SECTAG, ++ SCI_INSERTION_MODE_EXPLICIT_MAC_SA = \ ++ e_FM_MACSEC_SCI_INSERTION_MODE_EXPLICIT_MAC_SA, ++ SCI_INSERTION_MODE_IMPLICT_PTP = e_FM_MACSEC_SCI_INSERTION_MODE_IMPLICT_PTP ++} fm_macsec_sci_insertion_mode; ++ ++typedef macsecSAKey_t macsec_sa_key_t; ++typedef macsecSCI_t macsec_sci_t; ++typedef macsecAN_t macsec_an_t; ++typedef t_Handle handle_t; ++ ++/**************************************************************************//** ++ @Function fm_macsec_secy_exception_callback wrapper ++ @Description Exceptions user callback routine, will be called upon an ++ exception passing the exception identification. ++ @Param[in] app_h A handle to an application layer object; This handle ++ will be passed by the driver upon calling this callback. ++ @Param[in] exception The exception. ++*//***************************************************************************/ ++typedef void (fm_macsec_secy_exception_callback) (handle_t app_h, ++ fm_macsec_secy_exception exception); ++ ++/**************************************************************************//** ++ @Function fm_macsec_secy_event_callback wrapper ++ @Description Events user callback routine, will be called upon an ++ event passing the event identification. ++ @Param[in] app_h A handle to an application layer object; This handle ++ will be passed by the driver upon calling this callback. ++ @Param[in] event The event. ++*//***************************************************************************/ ++typedef void (fm_macsec_secy_event_callback) (handle_t app_h, ++ fm_macsec_secy_event event); ++ ++/**************************************************************************//** ++ @Function fm_macsec_exception_callback wrapper ++ @Description Exceptions user callback routine, will be called upon an ++ exception passing the exception identification. ++ @Param[in] app_h A handle to an application layer object; This handle ++ will be passed by the driver upon calling this callback. ++ @Param[in] exception The exception. ++*//***************************************************************************/ ++typedef void (fm_macsec_exception_callback) (handle_t app_h, ++ fm_macsec_exception exception); ++ ++/**************************************************************************//** ++ @Description MACSEC SecY SC Params wrapper ++*//***************************************************************************/ ++struct fm_macsec_secy_sc_params { ++ macsec_sci_t sci; ++ fm_macsec_secy_cipher_suite cipher_suite; ++}; ++ ++/**************************************************************************//** ++ @Description FM MACSEC SecY config input wrapper ++*//***************************************************************************/ ++struct fm_macsec_secy_params { ++ handle_t fm_macsec_h; ++ struct fm_macsec_secy_sc_params tx_sc_params; ++ uint32_t num_receive_channels; ++ fm_macsec_secy_exception_callback *exception_f; ++ fm_macsec_secy_event_callback *event_f; ++ handle_t app_h; ++}; ++ ++/**************************************************************************//** ++ @Description FM MACSEC config input wrapper ++*//***************************************************************************/ ++struct fm_macsec_params { ++ handle_t fm_h; ++ bool guest_mode; ++ ++ union { ++ struct { ++ uint8_t fm_mac_id; ++ } guest_params; ++ ++ struct { ++ uintptr_t base_addr; ++ handle_t fm_mac_h; ++ fm_macsec_exception_callback *exception_f; ++ handle_t app_h; ++ } non_guest_params; ++ }; ++ ++}; ++ ++/**************************************************************************//** ++ @Description FM device opaque structure used for type checking ++*//***************************************************************************/ ++struct fm; ++ ++/**************************************************************************//** ++ @Description FM MAC device opaque structure used for type checking ++*//***************************************************************************/ ++struct fm_mac_dev; ++ ++/**************************************************************************//** ++ @Description FM MACSEC device opaque structure used for type checking ++*//***************************************************************************/ ++struct fm_macsec_dev; ++struct fm_macsec_secy_dev; ++ ++/**************************************************************************//** ++ @Description A structure .., ++*//***************************************************************************/ ++struct fm_port; ++ ++typedef int (*alloc_pcd_fqids)(struct device *dev, uint32_t num, ++ uint8_t alignment, uint32_t *base_fqid); ++ ++typedef int (*free_pcd_fqids)(struct device *dev, uint32_t base_fqid); ++ ++struct fm_port_pcd_param { ++ alloc_pcd_fqids cba; ++ free_pcd_fqids cbf; ++ struct device *dev; ++}; ++ ++/**************************************************************************//** ++ @Description A structure of information about each of the external ++ buffer pools used by the port, ++*//***************************************************************************/ ++struct fm_port_pool_param { ++ uint8_t id; /**< External buffer pool id */ ++ uint16_t size; /**< External buffer pool buffer size */ ++}; ++ ++/**************************************************************************//** ++ @Description structure for additional port parameters ++*//***************************************************************************/ ++struct fm_port_params { ++ uint32_t errq; /**< Error Queue Id. */ ++ uint32_t defq; /**< For Tx and HC - Default Confirmation queue, ++ 0 means no Tx conf for processed frames. ++ For Rx and OP - default Rx queue. */ ++ uint8_t num_pools; /**< Number of pools use by this port */ ++ struct fm_port_pool_param pool_param[FM_PORT_MAX_NUM_OF_EXT_POOLS]; ++ /**< Parameters for each pool */ ++ uint16_t priv_data_size; /**< Area that user may save for his own ++ need (E.g. save the SKB) */ ++ bool parse_results; /**< Put the parser-results in the Rx/Tx buffer */ ++ bool hash_results; /**< Put the hash-results in the Rx/Tx buffer */ ++ bool time_stamp; /**< Put the time-stamp in the Rx/Tx buffer */ ++ bool frag_enable; /**< Fragmentation support, for OP only */ ++ uint16_t data_align; /**< value for selecting a data alignment (must be a power of 2); ++ if write optimization is used, must be >= 16. */ ++ uint8_t manip_extra_space; /**< Maximum extra size needed (insertion-size minus removal-size); ++ Note that this field impacts the size of the buffer-prefix ++ (i.e. it pushes the data offset); */ ++}; ++ ++/**************************************************************************//** ++ @Function fm_bind ++ ++ @Description Bind to a specific FM device. ++ ++ @Param[in] fm_dev - the OF handle of the FM device. ++ ++ @Return A handle of the FM device. ++ ++ @Cautions Allowed only after the port was created. ++*//***************************************************************************/ ++struct fm *fm_bind(struct device *fm_dev); ++ ++/**************************************************************************//** ++ @Function fm_unbind ++ ++ @Description Un-bind from a specific FM device. ++ ++ @Param[in] fm - A handle of the FM device. ++ ++ @Cautions Allowed only after the port was created. ++*//***************************************************************************/ ++void fm_unbind(struct fm *fm); ++ ++void *fm_get_handle(struct fm *fm); ++void *fm_get_rtc_handle(struct fm *fm); ++struct resource *fm_get_mem_region(struct fm *fm); ++ ++/**************************************************************************//** ++ @Function fm_port_bind ++ ++ @Description Bind to a specific FM-port device (may be Rx or Tx port). ++ ++ @Param[in] fm_port_dev - the OF handle of the FM port device. ++ ++ @Return A handle of the FM port device. ++ ++ @Cautions Allowed only after the port was created. ++*//***************************************************************************/ ++struct fm_port *fm_port_bind(struct device *fm_port_dev); ++ ++/**************************************************************************//** ++ @Function fm_port_unbind ++ ++ @Description Un-bind from a specific FM-port device (may be Rx or Tx port). ++ ++ @Param[in] port - A handle of the FM port device. ++ ++ @Cautions Allowed only after the port was created. ++*//***************************************************************************/ ++void fm_port_unbind(struct fm_port *port); ++ ++/**************************************************************************//** ++ @Function fm_set_rx_port_params ++ ++ @Description Configure parameters for a specific Rx FM-port device. ++ ++ @Param[in] port - A handle of the FM port device. ++ @Param[in] params - Rx port parameters ++ ++ @Cautions Allowed only after the port is binded. ++*//***************************************************************************/ ++void fm_set_rx_port_params(struct fm_port *port, ++ struct fm_port_params *params); ++ ++/**************************************************************************//** ++ @Function fm_port_pcd_bind ++ ++ @Description Bind as a listener on a port PCD. ++ ++ @Param[in] port - A handle of the FM port device. ++ @Param[in] params - PCD port parameters ++ ++ @Cautions Allowed only after the port is binded. ++*//***************************************************************************/ ++void fm_port_pcd_bind (struct fm_port *port, struct fm_port_pcd_param *params); ++ ++/**************************************************************************//** ++ @Function fm_port_get_buff_layout_ext_params ++ ++ @Description Get data_align and manip_extra_space from the device tree ++ chosen node if applied. ++ This function will only update these two parameters. ++ When this port has no such parameters in the device tree ++ values will be set to 0. ++ ++ @Param[in] port - A handle of the FM port device. ++ @Param[in] params - PCD port parameters ++ ++ @Cautions Allowed only after the port is binded. ++*//***************************************************************************/ ++void fm_port_get_buff_layout_ext_params(struct fm_port *port, struct fm_port_params *params); ++ ++/**************************************************************************//** ++ @Function fm_get_tx_port_channel ++ ++ @Description Get qman-channel number for this Tx port. ++ ++ @Param[in] port - A handle of the FM port device. ++ ++ @Return qman-channel number for this Tx port. ++ ++ @Cautions Allowed only after the port is binded. ++*//***************************************************************************/ ++uint16_t fm_get_tx_port_channel(struct fm_port *port); ++ ++/**************************************************************************//** ++ @Function fm_set_tx_port_params ++ ++ @Description Configure parameters for a specific Tx FM-port device ++ ++ @Param[in] port - A handle of the FM port device. ++ @Param[in] params - Tx port parameters ++ ++ @Cautions Allowed only after the port is binded. ++*//***************************************************************************/ ++void fm_set_tx_port_params(struct fm_port *port, struct fm_port_params *params); ++ ++ ++/**************************************************************************//** ++ @Function fm_mac_set_handle ++ ++ @Description Set mac handle ++ ++ @Param[in] h_lnx_wrp_fm_dev - A handle of the LnxWrp FM device. ++ @Param[in] h_fm_mac - A handle of the LnxWrp FM MAC device. ++ @Param[in] mac_id - MAC id. ++*//***************************************************************************/ ++void fm_mac_set_handle(t_Handle h_lnx_wrp_fm_dev, t_Handle h_fm_mac, ++ int mac_id); ++ ++/**************************************************************************//** ++ @Function fm_port_enable ++ ++ @Description Enable specific FM-port device (may be Rx or Tx port). ++ ++ @Param[in] port - A handle of the FM port device. ++ ++ @Cautions Allowed only after the port is initialized. ++*//***************************************************************************/ ++int fm_port_enable(struct fm_port *port); ++ ++/**************************************************************************//** ++ @Function fm_port_disable ++ ++ @Description Disable specific FM-port device (may be Rx or Tx port). ++ ++ @Param[in] port - A handle of the FM port device. ++ ++ @Cautions Allowed only after the port is initialized. ++*//***************************************************************************/ ++int fm_port_disable(struct fm_port *port); ++ ++void *fm_port_get_handle(const struct fm_port *port); ++ ++u64 *fm_port_get_buffer_time_stamp(const struct fm_port *port, ++ const void *data); ++ ++/**************************************************************************//** ++ @Function fm_port_get_base_address ++ ++ @Description Get base address of this port. Useful for accessing ++ port-specific registers (i.e., not common ones). ++ ++ @Param[in] port - A handle of the FM port device. ++ ++ @Param[out] base_addr - The port's base addr (virtual address). ++*//***************************************************************************/ ++void fm_port_get_base_addr(const struct fm_port *port, uint64_t *base_addr); ++ ++/**************************************************************************//** ++ @Function fm_mutex_lock ++ ++ @Description Lock function required before any FMD/LLD call. ++*//***************************************************************************/ ++void fm_mutex_lock(void); ++ ++/**************************************************************************//** ++ @Function fm_mutex_unlock ++ ++ @Description Unlock function required after any FMD/LLD call. ++*//***************************************************************************/ ++void fm_mutex_unlock(void); ++ ++/**************************************************************************//** ++ @Function fm_get_max_frm ++ ++ @Description Get the maximum frame size ++*//***************************************************************************/ ++int fm_get_max_frm(void); ++ ++/**************************************************************************//** ++ @Function fm_get_rx_extra_headroom ++ ++ @Description Get the extra headroom size ++*//***************************************************************************/ ++int fm_get_rx_extra_headroom(void); ++ ++/**************************************************************************//** ++ at Function fm_port_set_rate_limit ++ ++ at Description Configure Shaper parameter on FM-port device (Tx port). ++ ++ at Param[in] port - A handle of the FM port device. ++ at Param[in] max_burst_size - Value of maximum burst size allowed. ++ at Param[in] rate_limit - The required rate value. ++ ++ at Cautions Allowed only after the port is initialized. ++*//***************************************************************************/ ++int fm_port_set_rate_limit(struct fm_port *port, ++ uint16_t max_burst_size, ++ uint32_t rate_limit); ++/**************************************************************************//** ++ at Function fm_port_set_rate_limit ++ ++ at Description Delete Shaper configuration on FM-port device (Tx port). ++ ++ at Param[in] port - A handle of the FM port device. ++ ++ at Cautions Allowed only after the port is initialized. ++*//***************************************************************************/ ++int fm_port_del_rate_limit(struct fm_port *port); ++ ++struct auto_res_tables_sizes ++{ ++ uint16_t max_num_of_arp_entries; ++ uint16_t max_num_of_echo_ipv4_entries; ++ uint16_t max_num_of_ndp_entries; ++ uint16_t max_num_of_echo_ipv6_entries; ++ uint16_t max_num_of_snmp_ipv4_entries; ++ uint16_t max_num_of_snmp_ipv6_entries; ++ uint16_t max_num_of_snmp_oid_entries; ++ uint16_t max_num_of_snmp_char; /* total amount of character needed ++ for the snmp table */ ++ uint16_t max_num_of_ip_prot_filtering; ++ uint16_t max_num_of_tcp_port_filtering; ++ uint16_t max_num_of_udp_port_filtering; ++}; ++/* ARP */ ++struct auto_res_arp_entry ++{ ++ uint32_t ip_address; ++ uint8_t mac[6]; ++ bool is_vlan; ++ uint16_t vid; ++}; ++struct auto_res_arp_info ++{ ++ uint8_t table_size; ++ struct auto_res_arp_entry *auto_res_table; ++ bool enable_conflict_detection; /* when TRUE ++ Conflict Detection will be checked and wake the host if ++ needed */ ++}; ++ ++/* NDP */ ++struct auto_res_ndp_entry ++{ ++ uint32_t ip_address[4]; ++ uint8_t mac[6]; ++ bool is_vlan; ++ uint16_t vid; ++}; ++struct auto_res_ndp_info ++{ ++ uint32_t multicast_group; ++ uint8_t table_size_assigned; ++ struct auto_res_ndp_entry *auto_res_table_assigned; /* This list ++ refer to solicitation IP addresses. Note that all IP adresses ++ must be from the same multicast group. This will be checked and ++ if not operation will fail. */ ++ uint8_t table_size_tmp; ++ struct auto_res_ndp_entry *auto_res_table_tmp; /* This list ++ refer to temp IP addresses. Note that all temp IP adresses must ++ be from the same multicast group. This will be checked and if ++ not operation will fail. */ ++ ++ bool enable_conflict_detection; /* when TRUE ++ Conflict Detection will be checked and wake the host if ++ needed */ ++}; ++ ++/* ICMP ECHO */ ++struct auto_res_echo_ipv4_info ++{ ++ uint8_t table_size; ++ struct auto_res_arp_entry *auto_res_table; ++}; ++ ++struct auto_res_echo_ipv6_info ++{ ++ uint8_t table_size; ++ struct auto_res_ndp_entry *auto_res_table; ++}; ++ ++/* SNMP */ ++struct auto_res_snmp_entry ++{ ++ uint16_t oidSize; ++ uint8_t *oidVal; /* only the oid string */ ++ uint16_t resSize; ++ uint8_t *resVal; /* resVal will be the entire reply, ++ i.e. "Type|Length|Value" */ ++}; ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response SNMP IPv4 Addresses Table Entry ++ Refer to the FMan Controller spec for more details. ++*//***************************************************************************/ ++struct auto_res_snmp_ipv4addr_tbl_entry ++{ ++ uint32_t ipv4addr; /*!< 32 bit IPv4 Address. */ ++ bool is_vlan; ++ uint16_t vid; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */ ++ /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */ ++}; ++ ++/**************************************************************************//** ++ @Description Deep Sleep Auto Response SNMP IPv6 Addresses Table Entry ++ Refer to the FMan Controller spec for more details. ++*//***************************************************************************/ ++struct auto_res_snmp_ipv6addr_tbl_entry ++{ ++ uint32_t ipv6Addr[4]; /*!< 4 * 32 bit IPv6 Address. */ ++ bool isVlan; ++ uint16_t vid; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */ ++ /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */ ++}; ++ ++struct auto_res_snmp_info ++{ ++ uint16_t control; /**< Control bits [0-15]. */ ++ uint16_t max_snmp_msg_length; /**< Maximal allowed SNMP message length. */ ++ uint16_t num_ipv4_addresses; /**< Number of entries in IPv4 addresses table. */ ++ uint16_t num_ipv6_addresses; /**< Number of entries in IPv6 addresses table. */ ++ struct auto_res_snmp_ipv4addr_tbl_entry *ipv4addr_tbl; /**< Pointer to IPv4 addresses table. */ ++ struct auto_res_snmp_ipv6addr_tbl_entry *ipv6addr_tbl; /**< Pointer to IPv6 addresses table. */ ++ char *community_read_write_string; ++ char *community_read_only_string; ++ struct auto_res_snmp_entry *oid_table; ++ uint32_t oid_table_size; ++ uint32_t *statistics; ++}; ++ ++/* Filtering */ ++struct auto_res_port_filtering_entry ++{ ++ uint16_t src_port; ++ uint16_t dst_port; ++ uint16_t src_port_mask; ++ uint16_t dst_port_mask; ++}; ++struct auto_res_filtering_info ++{ ++ /* IP protocol filtering parameters */ ++ uint8_t ip_prot_table_size; ++ uint8_t *ip_prot_table_ptr; ++ bool ip_prot_pass_on_hit; /* when TRUE, miss in the table will ++ cause the packet to be droped, hit will pass the packet to ++ UDP/TCP filters if needed and if not to the classification ++ tree. If the classification tree will pass the packet to a ++ queue it will cause a wake interupt. When FALSE it the other ++ way around. */ ++ /* UDP port filtering parameters */ ++ uint8_t udp_ports_table_size; ++ struct auto_res_port_filtering_entry *udp_ports_table_ptr; ++ bool udp_port_pass_on_hit; /* when TRUE, miss in the table will ++ cause the packet to be droped, hit will pass the packet to ++ classification tree. If the classification tree will pass the ++ packet to a queue it will cause a wake interupt. When FALSE it ++ the other way around. */ ++ /* TCP port filtering parameters */ ++ uint16_t tcp_flags_mask; ++ uint8_t tcp_ports_table_size; ++ struct auto_res_port_filtering_entry *tcp_ports_table_ptr; ++ bool tcp_port_pass_on_hit; /* when TRUE, miss in the table will ++ cause the packet to be droped, hit will pass the packet to ++ classification tree. If the classification tree will pass the ++ packet to a queue it will cause a wake interupt. When FALSE it ++ the other way around. */ ++}; ++ ++struct auto_res_port_params ++{ ++ t_Handle h_FmPortTx; ++ struct auto_res_arp_info *p_auto_res_arp_info; ++ struct auto_res_echo_ipv4_info *p_auto_res_echo_ipv4_info; ++ struct auto_res_ndp_info *p_auto_res_ndp_info; ++ struct auto_res_echo_ipv6_info *p_auto_res_echo_ipv6_info; ++ struct auto_res_snmp_info *p_auto_res_snmp_info; ++ struct auto_res_filtering_info *p_auto_res_filtering_info; ++}; ++ ++struct auto_res_port_stats ++{ ++ uint32_t arp_ar_cnt; ++ uint32_t echo_icmpv4_ar_cnt; ++ uint32_t ndp_ar_cnt; ++ uint32_t echo_icmpv6_ar_cnt; ++}; ++ ++int fm_port_config_autores_for_deepsleep_support(struct fm_port *port, ++ struct auto_res_tables_sizes *params); ++ ++int fm_port_enter_autores_for_deepsleep(struct fm_port *port, ++ struct auto_res_port_params *params); ++ ++void fm_port_exit_auto_res_for_deep_sleep(struct fm_port *port_rx, ++ struct fm_port *port_tx); ++ ++bool fm_port_is_in_auto_res_mode(struct fm_port *port); ++ ++struct auto_res_tables_sizes *fm_port_get_autores_maxsize( ++ struct fm_port *port); ++ ++int fm_port_get_autores_stats(struct fm_port *port, struct auto_res_port_stats ++ *stats); ++ ++int fm_port_resume(struct fm_port *port); ++ ++int fm_port_suspend(struct fm_port *port); ++ ++#ifdef CONFIG_FMAN_PFC ++/**************************************************************************//** ++ at Function fm_port_set_pfc_priorities_mapping_to_qman_wq ++ ++ at Description Associate a QMan Work Queue with a PFC priority on this ++ FM-port device (Tx port). ++ ++ at Param[in] port - A handle of the FM port device. ++ ++ at Param[in] prio - The PFC priority. ++ ++ at Param[in] wq - The Work Queue associated with the PFC priority. ++ ++ at Cautions Allowed only after the port is initialized. ++*//***************************************************************************/ ++int fm_port_set_pfc_priorities_mapping_to_qman_wq(struct fm_port *port, ++ uint8_t prio, uint8_t wq); ++#endif ++ ++/**************************************************************************//** ++ at Function fm_mac_set_exception ++ ++ at Description Set MAC exception state. ++ ++ at Param[in] fm_mac_dev - A handle of the FM MAC device. ++ at Param[in] exception - FM MAC exception type. ++ at Param[in] enable - new state. ++ ++*//***************************************************************************/ ++int fm_mac_set_exception(struct fm_mac_dev *fm_mac_dev, ++ e_FmMacExceptions exception, bool enable); ++ ++int fm_mac_free(struct fm_mac_dev *fm_mac_dev); ++ ++struct fm_mac_dev *fm_mac_config(t_FmMacParams *params); ++ ++int fm_mac_config_max_frame_length(struct fm_mac_dev *fm_mac_dev, ++ int len); ++ ++int fm_mac_config_pad_and_crc(struct fm_mac_dev *fm_mac_dev, bool enable); ++ ++int fm_mac_config_half_duplex(struct fm_mac_dev *fm_mac_dev, bool enable); ++ ++int fm_mac_config_reset_on_init(struct fm_mac_dev *fm_mac_dev, bool enable); ++ ++int fm_mac_init(struct fm_mac_dev *fm_mac_dev); ++ ++int fm_mac_get_version(struct fm_mac_dev *fm_mac_dev, uint32_t *version); ++ ++int fm_mac_enable(struct fm_mac_dev *fm_mac_dev); ++ ++int fm_mac_disable(struct fm_mac_dev *fm_mac_dev); ++ ++int fm_mac_set_promiscuous(struct fm_mac_dev *fm_mac_dev, ++ bool enable); ++ ++int fm_mac_remove_hash_mac_addr(struct fm_mac_dev *fm_mac_dev, ++ t_EnetAddr *mac_addr); ++ ++int fm_mac_add_hash_mac_addr(struct fm_mac_dev *fm_mac_dev, ++ t_EnetAddr *mac_addr); ++ ++int fm_mac_modify_mac_addr(struct fm_mac_dev *fm_mac_dev, ++ uint8_t *addr); ++ ++int fm_mac_adjust_link(struct fm_mac_dev *fm_mac_dev, ++ bool link, int speed, bool duplex); ++ ++int fm_mac_enable_1588_time_stamp(struct fm_mac_dev *fm_mac_dev); ++ ++int fm_mac_disable_1588_time_stamp(struct fm_mac_dev *fm_mac_dev); ++ ++int fm_mac_set_rx_pause_frames( ++ struct fm_mac_dev *fm_mac_dev, bool en); ++ ++int fm_mac_set_tx_pause_frames(struct fm_mac_dev *fm_mac_dev, ++ bool en); ++ ++int fm_rtc_enable(struct fm *fm_dev); ++ ++int fm_rtc_disable(struct fm *fm_dev); ++ ++int fm_rtc_get_cnt(struct fm *fm_dev, uint64_t *ts); ++ ++int fm_rtc_set_cnt(struct fm *fm_dev, uint64_t ts); ++ ++int fm_rtc_get_drift(struct fm *fm_dev, uint32_t *drift); ++ ++int fm_rtc_set_drift(struct fm *fm_dev, uint32_t drift); ++ ++int fm_rtc_set_alarm(struct fm *fm_dev, uint32_t id, ++ uint64_t time); ++ ++int fm_rtc_set_fiper(struct fm *fm_dev, uint32_t id, ++ uint64_t fiper); ++ ++int fm_mac_set_wol(struct fm_port *port, struct fm_mac_dev *fm_mac_dev, ++ bool en); ++ ++/**************************************************************************//** ++ at Function fm_macsec_set_exception ++ ++ at Description Set MACSEC exception state. ++ ++ at Param[in] fm_macsec_dev - A handle of the FM MACSEC device. ++ at Param[in] exception - FM MACSEC exception type. ++ at Param[in] enable - new state. ++ ++*//***************************************************************************/ ++ ++int fm_macsec_set_exception(struct fm_macsec_dev *fm_macsec_dev, ++ fm_macsec_exception exception, bool enable); ++int fm_macsec_free(struct fm_macsec_dev *fm_macsec_dev); ++struct fm_macsec_dev *fm_macsec_config(struct fm_macsec_params *fm_params); ++int fm_macsec_init(struct fm_macsec_dev *fm_macsec_dev); ++int fm_macsec_config_unknown_sci_frame_treatment(struct fm_macsec_dev ++ *fm_macsec_dev, ++ fm_macsec_unknown_sci_frame_treatment treat_mode); ++int fm_macsec_config_invalid_tags_frame_treatment(struct fm_macsec_dev *fm_macsec_dev, ++ bool deliver_uncontrolled); ++int fm_macsec_config_kay_frame_treatment(struct fm_macsec_dev *fm_macsec_dev, ++ bool discard_uncontrolled); ++int fm_macsec_config_untag_frame_treatment(struct fm_macsec_dev *fm_macsec_dev, ++ fm_macsec_untag_frame_treatment treat_mode); ++int fm_macsec_config_pn_exhaustion_threshold(struct fm_macsec_dev *fm_macsec_dev, ++ uint32_t pnExhThr); ++int fm_macsec_config_keys_unreadable(struct fm_macsec_dev *fm_macsec_dev); ++int fm_macsec_config_sectag_without_sci(struct fm_macsec_dev *fm_macsec_dev); ++int fm_macsec_config_exception(struct fm_macsec_dev *fm_macsec_dev, ++ fm_macsec_exception exception, bool enable); ++int fm_macsec_get_revision(struct fm_macsec_dev *fm_macsec_dev, ++ int *macsec_revision); ++int fm_macsec_enable(struct fm_macsec_dev *fm_macsec_dev); ++int fm_macsec_disable(struct fm_macsec_dev *fm_macsec_dev); ++ ++ ++int fm_macsec_secy_config_exception(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ fm_macsec_secy_exception exception, ++ bool enable); ++int fm_macsec_secy_free(struct fm_macsec_secy_dev *fm_macsec_secy_dev); ++struct fm_macsec_secy_dev *fm_macsec_secy_config(struct fm_macsec_secy_params *secy_params); ++int fm_macsec_secy_init(struct fm_macsec_secy_dev *fm_macsec_secy_dev); ++int fm_macsec_secy_config_sci_insertion_mode(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ fm_macsec_sci_insertion_mode sci_insertion_mode); ++int fm_macsec_secy_config_protect_frames(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ bool protect_frames); ++int fm_macsec_secy_config_replay_window(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ bool replay_protect, uint32_t replay_window); ++int fm_macsec_secy_config_validation_mode(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ fm_macsec_valid_frame_behavior validate_frames); ++int fm_macsec_secy_config_confidentiality(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ bool confidentiality_enable, ++ uint32_t confidentiality_offset); ++int fm_macsec_secy_config_point_to_point(struct fm_macsec_secy_dev *fm_macsec_secy_dev); ++int fm_macsec_secy_config_event(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ fm_macsec_secy_event event, ++ bool enable); ++struct rx_sc_dev *fm_macsec_secy_create_rxsc(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct fm_macsec_secy_sc_params *params); ++int fm_macsec_secy_delete_rxsc(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc); ++int fm_macsec_secy_create_rx_sa(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc, macsec_an_t an, ++ uint32_t lowest_pn, macsec_sa_key_t key); ++int fm_macsec_secy_delete_rx_sa(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc, macsec_an_t an); ++int fm_macsec_secy_rxsa_enable_receive(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc, ++ macsec_an_t an); ++int fm_macsec_secy_rxsa_disable_receive(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc, ++ macsec_an_t an); ++int fm_macsec_secy_rxsa_update_next_pn(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc, ++ macsec_an_t an, uint32_t updt_next_pn); ++int fm_macsec_secy_rxsa_update_lowest_pn(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc, ++ macsec_an_t an, uint32_t updt_lowest_pn); ++int fm_macsec_secy_rxsa_modify_key(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc, ++ macsec_an_t an, macsec_sa_key_t key); ++int fm_macsec_secy_create_tx_sa(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ macsec_an_t an, macsec_sa_key_t key); ++int fm_macsec_secy_delete_tx_sa(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ macsec_an_t an); ++int fm_macsec_secy_txsa_modify_key(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ macsec_an_t next_active_an, ++ macsec_sa_key_t key); ++int fm_macsec_secy_txsa_set_active(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ macsec_an_t an); ++int fm_macsec_secy_txsa_get_active(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ macsec_an_t *p_an); ++int fm_macsec_secy_get_rxsc_phys_id(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc, uint32_t *sc_phys_id); ++int fm_macsec_secy_get_txsc_phys_id(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ uint32_t *sc_phys_id); ++ ++/** @} */ /* end of FM_LnxKern_ctrl_grp group */ ++/** @} */ /* end of FM_LnxKern_grp group */ ++ ++/* default values for initializing PTP 1588 timer clock */ ++#define DPA_PTP_NOMINAL_FREQ_PERIOD_SHIFT 2 /* power of 2 for better performance */ ++#define DPA_PTP_NOMINAL_FREQ_PERIOD_NS (1 << DPA_PTP_NOMINAL_FREQ_PERIOD_SHIFT) /* 4ns,250MHz */ ++ ++#endif /* __LNXWRP_FSL_FMAN_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/inc/xx/xx.h b/drivers/net/ethernet/freescale/sdk_fman/src/inc/xx/xx.h +new file mode 100644 +index 0000000..b183c86 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/inc/xx/xx.h +@@ -0,0 +1,50 @@ ++/* ++ * Copyright 2008-2012 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 __XX_H ++#define __XX_H ++ ++#include "xx_ext.h" ++ ++void * xx_Malloc(uint32_t n); ++void xx_Free(void *p); ++ ++void *xx_MallocSmart(uint32_t size, int memPartitionId, uint32_t align); ++void xx_FreeSmart(void *p); ++ ++/* never used: */ ++#define GetDeviceName(irq) ((char *)NULL) ++ ++int GetDeviceIrqNum(int irq); ++ ++ ++#endif /* __XX_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/system/Makefile b/drivers/net/ethernet/freescale/sdk_fman/src/system/Makefile +new file mode 100644 +index 0000000..667cd85 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/system/Makefile +@@ -0,0 +1,10 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++ccflags-y += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk ++# ++ ++obj-y += sys_io.o +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/system/sys_io.c b/drivers/net/ethernet/freescale/sdk_fman/src/system/sys_io.c +new file mode 100644 +index 0000000..c106a8b +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/system/sys_io.c +@@ -0,0 +1,171 @@ ++/* ++ * Copyright 2008-2012 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 ++ ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ++#include ++#else ++#include ++#endif /* LINUX_VERSION_CODE */ ++#endif /* MODVERSIONS */ ++ ++#include ++#include ++ ++#include ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "string_ext.h" ++#include "list_ext.h" ++#include "sys_io_ext.h" ++ ++ ++#define __ERR_MODULE__ MODULE_UNKNOWN ++ ++ ++typedef struct { ++ uint64_t virtAddr; ++ uint64_t physAddr; ++ uint32_t size; ++ t_List node; ++} t_IoMap; ++#define IOMAP_OBJECT(ptr) LIST_OBJECT(ptr, t_IoMap, node) ++ ++LIST(mapsList); ++ ++ ++static void EnqueueIoMap(t_IoMap *p_IoMap) ++{ ++ uint32_t intFlags; ++ ++ intFlags = XX_DisableAllIntr(); ++ LIST_AddToTail(&p_IoMap->node, &mapsList); ++ XX_RestoreAllIntr(intFlags); ++} ++ ++static t_IoMap * FindIoMapByVirtAddr(uint64_t addr) ++{ ++ t_IoMap *p_IoMap; ++ t_List *p_Pos; ++ ++ LIST_FOR_EACH(p_Pos, &mapsList) ++ { ++ p_IoMap = IOMAP_OBJECT(p_Pos); ++ if ((addr >= p_IoMap->virtAddr) && (addr < p_IoMap->virtAddr+p_IoMap->size)) ++ return p_IoMap; ++ } ++ ++ return NULL; ++} ++ ++static t_IoMap * FindIoMapByPhysAddr(uint64_t addr) ++{ ++ t_IoMap *p_IoMap; ++ t_List *p_Pos; ++ ++ LIST_FOR_EACH(p_Pos, &mapsList) ++ { ++ p_IoMap = IOMAP_OBJECT(p_Pos); ++ if ((addr >= p_IoMap->physAddr) && (addr < p_IoMap->physAddr+p_IoMap->size)) ++ return p_IoMap; ++ } ++ ++ return NULL; ++} ++ ++t_Error SYS_RegisterIoMap (uint64_t virtAddr, uint64_t physAddr, uint32_t size) ++{ ++ t_IoMap *p_IoMap; ++ ++ p_IoMap = (t_IoMap*)XX_Malloc(sizeof(t_IoMap)); ++ if (!p_IoMap) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("message handler object!!!")); ++ memset(p_IoMap, 0, sizeof(t_IoMap)); ++ ++ p_IoMap->virtAddr = virtAddr; ++ p_IoMap->physAddr = physAddr; ++ p_IoMap->size = size; ++ ++ INIT_LIST(&p_IoMap->node); ++ EnqueueIoMap(p_IoMap); ++ ++ return E_OK; ++} ++ ++t_Error SYS_UnregisterIoMap (uint64_t virtAddr) ++{ ++ t_IoMap *p_IoMap = FindIoMapByVirtAddr(virtAddr); ++ if (!p_IoMap) ++ RETURN_ERROR(MINOR, E_NO_DEVICE, ("message handler not found in list!!!")); ++ ++ LIST_Del(&p_IoMap->node); ++ XX_Free(p_IoMap); ++ ++ return E_OK; ++} ++ ++uint64_t SYS_PhysToVirt(uint64_t addr) ++{ ++ t_IoMap *p_IoMap = FindIoMapByPhysAddr(addr); ++ if (p_IoMap) ++ { ++ /* This is optimization - put the latest in the list-head - like a cache */ ++ if (mapsList.p_Next != &p_IoMap->node) ++ { ++ uint32_t intFlags = XX_DisableAllIntr(); ++ LIST_DelAndInit(&p_IoMap->node); ++ LIST_Add(&p_IoMap->node, &mapsList); ++ XX_RestoreAllIntr(intFlags); ++ } ++ return (uint64_t)(addr - p_IoMap->physAddr + p_IoMap->virtAddr); ++ } ++ return PTR_TO_UINT(phys_to_virt((unsigned long)addr)); ++} ++ ++uint64_t SYS_VirtToPhys(uint64_t addr) ++{ ++ t_IoMap *p_IoMap; ++ ++ if (addr == 0) ++ return 0; ++ ++ p_IoMap = FindIoMapByVirtAddr(addr); ++ if (p_IoMap) ++ return (uint64_t)(addr - p_IoMap->virtAddr + p_IoMap->physAddr); ++ return (uint64_t)virt_to_phys(UINT_TO_PTR(addr)); ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/Makefile b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/Makefile +new file mode 100644 +index 0000000..62713d6 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/Makefile +@@ -0,0 +1,19 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++ccflags-y += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk ++ ++NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/inc ++ ++ccflags-y += -I$(NCSW_FM_INC) ++ccflags-y += -I$(NET_DPA) ++ ++obj-y += fsl-ncsw-PFM.o ++obj-$(CONFIG_FSL_SDK_FMAN_TEST) += fman_test.o ++ ++fsl-ncsw-PFM-objs := lnxwrp_fm.o lnxwrp_fm_port.o lnxwrp_ioctls_fm.o \ ++ lnxwrp_sysfs.o lnxwrp_sysfs_fm.o lnxwrp_sysfs_fm_port.o ++obj-$(CONFIG_COMPAT) += lnxwrp_ioctls_fm_compat.o +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/fman_test.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/fman_test.c +new file mode 100644 +index 0000000..270d07b +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/fman_test.c +@@ -0,0 +1,1665 @@ ++/* Copyright (c) 2008-2011 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++/* ++ @File fman_test.c ++ @Authors Pistirica Sorin Andrei ++ @Description FM Linux test environment ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* private headers */ ++#include "fm_ext.h" ++#include "lnxwrp_fsl_fman.h" ++#include "fm_port_ext.h" ++#if (DPAA_VERSION == 11) ++#include "../../Peripherals/FM/MAC/memac.h" ++#endif ++#include "fm_test_ioctls.h" ++#include "fsl_fman_test.h" ++ ++#include "dpaa_eth.h" ++#include "dpaa_eth_common.h" ++ ++#define FMT_FRM_WATERMARK 0xdeadbeefdeadbeeaLL ++ ++struct fmt_frame_s { ++ ioc_fmt_buff_desc_t buff; ++ struct list_head list; ++}; ++ ++struct fmt_fqs_s { ++ struct qman_fq fq_base; ++ bool init; ++ struct fmt_port_s *fmt_port_priv; ++}; ++ ++struct fmt_port_pcd_s { ++ int num_queues; ++ struct fmt_fqs_s *fmt_pcd_fqs; ++ uint32_t fqid_base; ++}; ++ ++/* char dev structure: fm test port */ ++struct fmt_port_s { ++ bool valid; ++ uint8_t id; ++ ioc_fmt_port_type port_type; ++ ioc_diag_mode diag; ++ bool compat_test_type; ++ ++ /* fm ports */ ++ /* ! for oh ports p_tx_fm_port_dev == p_rx_fm_port_dev && ++ * p_tx_port == p_rx_port */ ++ /* t_LnxWrpFmPortDev */ ++ struct fm_port *p_tx_port; ++ /* t_LnxWrpFmPortDev->h_Dev: t_FmPort */ ++ void *p_tx_fm_port_dev; ++ /* t_LnxWrpFmPortDev */ ++ struct fm_port *p_rx_port; ++ /* t_LnxWrpFmPortDev->h_Dev: t_FmPort */ ++ void *p_rx_fm_port_dev; ++ ++ void *p_mac_dev; ++ uint64_t fm_phys_base_addr; ++ ++ /* read/write queue manipulation */ ++ spinlock_t rx_q_lock; ++ struct list_head rx_q; ++ ++ /* tx queuee for injecting traffic */ ++ int num_of_tx_fqs; ++ struct fmt_fqs_s p_tx_fqs[FMAN_TEST_MAX_TX_FQS]; ++ ++ /* pcd private queues manipulation */ ++ struct fmt_port_pcd_s fmt_port_pcd; ++ ++ /* debugging stuff */ ++ ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ atomic_t enqueue_to_qman_frm; ++ atomic_t enqueue_to_rxq; ++ atomic_t dequeue_from_rxq; ++ atomic_t not_enqueue_to_rxq_wrong_frm; ++#endif ++ ++}; ++ ++/* The devices. */ ++struct fmt_s { ++ int major; ++ struct fmt_port_s ports[IOC_FMT_MAX_NUM_OF_PORTS]; ++ struct class *fmt_class; ++}; ++ ++/* fm test structure */ ++static struct fmt_s fm_test; ++ ++#if (DPAA_VERSION == 11) ++struct mac_priv_s { ++ t_Handle mac; ++}; ++#endif ++ ++#define DTSEC_BASE_ADDR 0x000e0000 ++#define DTSEC_MEM_RANGE 0x00002000 ++#define MAC_1G_MACCFG1 0x00000100 ++#define MAC_1G_LOOP_MASK 0x00000100 ++static int set_1gmac_loopback( ++ struct fmt_port_s *fmt_port, ++ bool en) ++{ ++#if (DPAA_VERSION <= 10) ++ uint32_t dtsec_idx = fmt_port->id; /* dtsec for which port */ ++ uint32_t dtsec_idx_off = dtsec_idx * DTSEC_MEM_RANGE; ++ phys_addr_t maccfg1_hw; ++ void *maccfg1_map; ++ uint32_t maccfg1_val; ++ ++ /* compute the maccfg1 register address */ ++ maccfg1_hw = fmt_port->fm_phys_base_addr + ++ (phys_addr_t)(DTSEC_BASE_ADDR + ++ dtsec_idx_off + ++ MAC_1G_MACCFG1); ++ ++ /* map register */ ++ maccfg1_map = ioremap(maccfg1_hw, sizeof(u32)); ++ ++ /* set register */ ++ maccfg1_val = in_be32(maccfg1_map); ++ if (en) ++ maccfg1_val |= MAC_1G_LOOP_MASK; ++ else ++ maccfg1_val &= ~MAC_1G_LOOP_MASK; ++ out_be32(maccfg1_map, maccfg1_val); ++ ++ /* unmap register */ ++ iounmap(maccfg1_map); ++#else ++ struct mac_device *mac_dev; ++ struct mac_priv_s *priv; ++ t_Memac *p_memac; ++ ++ if (!fmt_port) ++ return -EINVAL; ++ ++ mac_dev = (struct mac_device *)fmt_port->p_mac_dev; ++ ++ if (!mac_dev) ++ return -EINVAL; ++ ++ priv = macdev_priv(mac_dev); ++ ++ if (!priv) ++ return -EINVAL; ++ ++ p_memac = priv->mac; ++ ++ if (!p_memac) ++ return -EINVAL; ++ ++ memac_set_loopback(p_memac->p_MemMap, en); ++#endif ++ return 0; ++} ++ ++/* TODO: re-write this function */ ++static int set_10gmac_int_loopback( ++ struct fmt_port_s *fmt_port, ++ bool en) ++{ ++#ifndef FM_10G_MAC_NO_CTRL_LOOPBACK ++#define FM_10GMAC0_OFFSET 0x000f0000 ++#define FM_10GMAC_CMD_CONF_CTRL_OFFSET 0x8 ++#define CMD_CFG_LOOPBACK_EN 0x00000400 ++ ++ uint64_t base_addr, reg_addr; ++ uint32_t tmp_val; ++ ++ base_addr = fmt_port->fm_phys_base_addr + (FM_10GMAC0_OFFSET + ++ ((fmt_port->id-FM_MAX_NUM_OF_1G_RX_PORTS)*0x2000)); ++ ++ base_addr = PTR_TO_UINT(ioremap(base_addr, 0x1000)); ++ ++ reg_addr = base_addr + FM_10GMAC_CMD_CONF_CTRL_OFFSET; ++ tmp_val = GET_UINT32(*((uint32_t *)UINT_TO_PTR(reg_addr))); ++ if (en) ++ tmp_val |= CMD_CFG_LOOPBACK_EN; ++ else ++ tmp_val &= ~CMD_CFG_LOOPBACK_EN; ++ WRITE_UINT32(*((uint32_t *)UINT_TO_PTR(reg_addr)), tmp_val); ++ ++ iounmap(UINT_TO_PTR(base_addr)); ++ ++ return 0; ++#else ++ _fmt_err("TGEC don't have internal-loopback.\n"); ++ return -EPERM; ++#endif ++} ++ ++static int set_mac_int_loopback(struct fmt_port_s *fmt_port, bool en) ++{ ++ int _err = 0; ++ ++ switch (fmt_port->port_type) { ++ ++ case e_IOC_FMT_PORT_T_RXTX: ++ /* 1G port */ ++ if (fmt_port->id < FM_MAX_NUM_OF_1G_RX_PORTS) ++ _err = set_1gmac_loopback(fmt_port, en); ++ /* 10g port */ ++ else if ((fmt_port->id >= FM_MAX_NUM_OF_1G_RX_PORTS) && ++ (fmt_port->id < FM_MAX_NUM_OF_1G_RX_PORTS + ++ FM_MAX_NUM_OF_10G_RX_PORTS)) { ++ ++ _err = set_10gmac_int_loopback(fmt_port, en); ++ } else ++ _err = -EINVAL; ++ break; ++ /* op port does not have MAC (loopback mode) */ ++ case e_IOC_FMT_PORT_T_OP: ++ ++ _err = 0; ++ break; ++ default: ++ ++ _err = -EPERM; ++ break; ++ } ++ ++ return _err; ++} ++ ++static void enqueue_fmt_frame( ++ struct fmt_port_s *fmt_port, ++ struct fmt_frame_s *p_fmt_frame) ++{ ++ spinlock_t *rx_q_lock = NULL; ++ ++ rx_q_lock = &fmt_port->rx_q_lock; ++ ++ spin_lock(rx_q_lock); ++ list_add_tail(&p_fmt_frame->list, &fmt_port->rx_q); ++ spin_unlock(rx_q_lock); ++ ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ atomic_inc(&fmt_port->enqueue_to_rxq); ++#endif ++} ++ ++static struct fmt_frame_s *dequeue_fmt_frame( ++ struct fmt_port_s *fmt_port) ++{ ++ struct fmt_frame_s *p_fmt_frame = NULL; ++ spinlock_t *rx_q_lock = NULL; ++ ++ rx_q_lock = &fmt_port->rx_q_lock; ++ ++ spin_lock(rx_q_lock); ++ ++#define list_last_entry(ptr, type, member) list_entry((ptr)->prev, type, member) ++ ++ if (!list_empty(&fmt_port->rx_q)) { ++ p_fmt_frame = list_last_entry(&fmt_port->rx_q, ++ struct fmt_frame_s, ++ list); ++ list_del(&p_fmt_frame->list); ++ ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ atomic_inc(&fmt_port->dequeue_from_rxq); ++#endif ++ } ++ ++ spin_unlock(rx_q_lock); ++ ++ return p_fmt_frame; ++} ++ ++/* eth-dev -to- fmt port association */ ++struct fmt_port_s *match_dpa_to_fmt_port( ++ struct dpa_priv_s *dpa_priv) { ++ struct mac_device *mac_dev = dpa_priv->mac_dev; ++ struct fm_port *fm_port = (struct fm_port *) mac_dev; ++ struct fmt_port_s *fmt_port = NULL; ++ int i; ++ ++ _fmt_dbgr("calling...\n"); ++ ++ /* find the FM-test-port object */ ++ for (i = 0; i < IOC_FMT_MAX_NUM_OF_PORTS; i++) ++ if ((fm_test.ports[i].p_mac_dev && ++ mac_dev == fm_test.ports[i].p_mac_dev) || ++ fm_port == fm_test.ports[i].p_tx_port) { ++ ++ fmt_port = &fm_test.ports[i]; ++ break; ++ } ++ ++ _fmt_dbgr("called\n"); ++ return fmt_port; ++} ++ ++void dump_frame( ++ uint8_t *buffer, ++ uint32_t size) ++{ ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ unsigned int i; ++ ++ for (i = 0; i < size; i++) { ++ if (i%16 == 0) ++ printk(KERN_DEBUG "\n"); ++ printk(KERN_DEBUG "%2x ", *(buffer+i)); ++ } ++#endif ++ return; ++} ++ ++bool test_and_steal_frame(struct fmt_port_s *fmt_port, ++ uint32_t fqid, ++ uint8_t *buffer, ++ uint32_t size) ++{ ++ struct fmt_frame_s *p_fmt_frame = NULL; ++ bool test_and_steal_frame_frame; ++ uint32_t data_offset; ++ uint32_t i; ++ ++ _fmt_dbgr("calling...\n"); ++ ++ if (!fmt_port || !fmt_port->p_rx_fm_port_dev) ++ return false; ++ ++ /* check watermark */ ++ test_and_steal_frame_frame = false; ++ for (i = 0; i < size; i++) { ++ uint64_t temp = *((uint64_t *)(buffer + i)); ++ ++ if (temp == (uint64_t) FMT_FRM_WATERMARK) { ++ _fmt_dbgr("watermark found!\n"); ++ test_and_steal_frame_frame = true; ++ break; ++ } ++ } ++ ++ if (!test_and_steal_frame_frame) { ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ atomic_inc(&fmt_port->not_enqueue_to_rxq_wrong_frm); ++#endif ++ _fmt_dbgr("NOT watermark found!\n"); ++ return false; ++ } ++ ++ /* do not enqueue the tx conf/err frames */ ++ if ((fqid == FMT_TX_CONF_Q) || (fqid == FMT_TX_ERR_Q)) ++ goto _test_and_steal_frame_return_true; ++ ++ _fmt_dbgr("on port %d got FMUC frame\n", fmt_port->id); ++ data_offset = FM_PORT_GetBufferDataOffset( ++ fmt_port->p_rx_fm_port_dev); ++ ++ p_fmt_frame = kmalloc(sizeof(struct fmt_frame_s), GFP_KERNEL); ++ ++ /* dump frame... no more space left on device */ ++ if (p_fmt_frame == NULL) { ++ _fmt_err("no space left on device!\n"); ++ goto _test_and_steal_frame_return_true; ++ } ++ ++ memset(p_fmt_frame, 0, sizeof(struct fmt_frame_s)); ++ p_fmt_frame->buff.p_data = kmalloc(size * sizeof(uint8_t), GFP_KERNEL); ++ ++ /* No more space left on device*/ ++ if (p_fmt_frame->buff.p_data == NULL) { ++ _fmt_err("no space left on device!\n"); ++ kfree(p_fmt_frame); ++ goto _test_and_steal_frame_return_true; ++ } ++ ++ p_fmt_frame->buff.size = size-data_offset; ++ p_fmt_frame->buff.qid = fqid; ++ ++ memcpy(p_fmt_frame->buff.p_data, ++ (uint8_t *)PTR_MOVE(buffer, data_offset), ++ p_fmt_frame->buff.size); ++ ++ memcpy(p_fmt_frame->buff.buff_context.fm_prs_res, ++ FM_PORT_GetBufferPrsResult(fmt_port->p_rx_fm_port_dev, ++ (char *)buffer), ++ 32); ++ ++ /* enqueue frame - this frame will go to us */ ++ enqueue_fmt_frame(fmt_port, p_fmt_frame); ++ ++_test_and_steal_frame_return_true: ++ return true; ++} ++ ++static int fmt_fq_release(const struct qm_fd *fd) ++{ ++ struct dpa_bp *_dpa_bp; ++ struct bm_buffer _bmb; ++ ++ if (fd->format == qm_fd_contig) { ++ _dpa_bp = dpa_bpid2pool(fd->bpid); ++ BUG_ON(IS_ERR(_dpa_bp)); ++ ++ _bmb.hi = fd->addr_hi; ++ _bmb.lo = fd->addr_lo; ++ ++ while (bman_release(_dpa_bp->pool, &_bmb, 1, 0)) ++ cpu_relax(); ++ ++ } else { ++ _fmt_err("frame not supported !\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++/* sync it w/ dpaa_eth.c: DPA_BP_HEAD */ ++#define DPA_BP_HEADROOM (DPA_TX_PRIV_DATA_SIZE + \ ++ fm_get_rx_extra_headroom() + \ ++ DPA_PARSE_RESULTS_SIZE + \ ++ DPA_HASH_RESULTS_SIZE) ++#define MAC_HEADER_LENGTH 14 ++#define L2_AND_HEADROOM_OFF ((DPA_BP_HEADROOM) + (MAC_HEADER_LENGTH)) ++ ++/* dpa ingress hooks definition */ ++enum dpaa_eth_hook_result fmt_rx_default_hook( ++ struct sk_buff *skb, ++ struct net_device *net_dev, ++ u32 fqid) ++{ ++ struct dpa_priv_s *dpa_priv = NULL; ++ struct fmt_port_s *fmt_port = NULL; ++ uint8_t *buffer; ++ uint32_t buffer_len; ++ ++ _fmt_dbgr("calling...\n"); ++ ++ dpa_priv = netdev_priv(net_dev); ++ fmt_port = match_dpa_to_fmt_port(dpa_priv); ++ ++ /* conversion from skb to fd: ++ * skb cames processed for L3, so we need to go back for ++ * layer 2 offset */ ++ buffer = (uint8_t *)(skb->data - ((int)L2_AND_HEADROOM_OFF)); ++ buffer_len = skb->len + ((int)L2_AND_HEADROOM_OFF); ++ ++ /* if is not out frame let dpa to handle it */ ++ if (test_and_steal_frame(fmt_port, ++ FMT_RX_DFLT_Q, ++ buffer, ++ buffer_len)) ++ goto _fmt_rx_default_hook_stolen; ++ ++ _fmt_dbgr("called:DPAA_ETH_CONTINUE.\n"); ++ return DPAA_ETH_CONTINUE; ++ ++_fmt_rx_default_hook_stolen: ++ dev_kfree_skb(skb); ++ ++ _fmt_dbgr("called:DPAA_ETH_STOLEN.\n"); ++ return DPAA_ETH_STOLEN; ++} ++ ++enum dpaa_eth_hook_result fmt_rx_error_hook( ++ struct net_device *net_dev, ++ const struct qm_fd *fd, ++ u32 fqid) ++{ ++ struct dpa_priv_s *dpa_priv = NULL; ++ struct dpa_bp *dpa_bp = NULL; ++ struct fmt_port_s *fmt_port = NULL; ++ void *fd_virt_addr = NULL; ++ dma_addr_t addr = qm_fd_addr(fd); ++ ++ _fmt_dbgr("calling...\n"); ++ ++ dpa_priv = netdev_priv(net_dev); ++ fmt_port = match_dpa_to_fmt_port(dpa_priv); ++ ++ /* dpaa doesn't do this... we have to do it here */ ++ dpa_bp = dpa_bpid2pool(fd->bpid); ++ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, DMA_BIDIRECTIONAL); ++ ++ fd_virt_addr = phys_to_virt(addr); ++ /* if is not out frame let dpa to handle it */ ++ if (test_and_steal_frame(fmt_port, ++ FMT_RX_ERR_Q, ++ fd_virt_addr, ++ fd->length20 + fd->offset)) { ++ goto _fmt_rx_error_hook_stolen; ++ } ++ ++ _fmt_dbgr("called:DPAA_ETH_CONTINUE.\n"); ++ return DPAA_ETH_CONTINUE; ++ ++_fmt_rx_error_hook_stolen: ++ /* the frame data doesn't matter, ++ * so, no mapping is needed */ ++ fmt_fq_release(fd); ++ ++ _fmt_dbgr("called:DPAA_ETH_STOLEN.\n"); ++ return DPAA_ETH_STOLEN; ++} ++ ++enum dpaa_eth_hook_result fmt_tx_confirm_hook( ++ struct net_device *net_dev, ++ const struct qm_fd *fd, ++ u32 fqid) ++{ ++ struct dpa_priv_s *dpa_priv = NULL; ++ struct fmt_port_s *fmt_port = NULL; ++ dma_addr_t addr = qm_fd_addr(fd); ++ void *fd_virt_addr = NULL; ++ uint32_t fd_len = 0; ++ ++ _fmt_dbgr("calling...\n"); ++ ++ dpa_priv = netdev_priv(net_dev); ++ fmt_port = match_dpa_to_fmt_port(dpa_priv); ++ ++ fd_virt_addr = phys_to_virt(addr); ++ fd_len = fd->length20 + fd->offset; ++ ++ if (fd_len > fm_get_max_frm()) { ++ _fmt_err("tx confirm bad frame size: %u!\n", fd_len); ++ goto _fmt_tx_confirm_hook_continue; ++ } ++ ++ if (test_and_steal_frame(fmt_port, ++ FMT_TX_CONF_Q, ++ fd_virt_addr, ++ fd_len)) ++ goto _fmt_tx_confirm_hook_stolen; ++ ++_fmt_tx_confirm_hook_continue: ++ _fmt_dbgr("called:DPAA_ETH_CONTINUE.\n"); ++ return DPAA_ETH_CONTINUE; ++ ++_fmt_tx_confirm_hook_stolen: ++ kfree(fd_virt_addr); ++ ++ _fmt_dbgr("called:DPAA_ETH_STOLEN.\n"); ++ return DPAA_ETH_STOLEN; ++} ++ ++enum dpaa_eth_hook_result fmt_tx_confirm_error_hook( ++ struct net_device *net_dev, ++ const struct qm_fd *fd, ++ u32 fqid) ++{ ++ struct dpa_priv_s *dpa_priv = NULL; ++ struct fmt_port_s *fmt_port = NULL; ++ dma_addr_t addr = qm_fd_addr(fd); ++ void *fd_virt_addr = NULL; ++ uint32_t fd_len = 0; ++ ++ _fmt_dbgr("calling...\n"); ++ ++ dpa_priv = netdev_priv(net_dev); ++ fmt_port = match_dpa_to_fmt_port(dpa_priv); ++ ++ fd_virt_addr = phys_to_virt(addr); ++ fd_len = fd->length20 + fd->offset; ++ ++ if (fd_len > fm_get_max_frm()) { ++ _fmt_err("tx confirm err bad frame size: %u !\n", fd_len); ++ goto _priv_ingress_tx_err_continue; ++ } ++ ++ if (test_and_steal_frame(fmt_port, FMT_TX_ERR_Q, fd_virt_addr, fd_len)) ++ goto _priv_ingress_tx_err_stolen; ++ ++_priv_ingress_tx_err_continue: ++ _fmt_dbgr("called:DPAA_ETH_CONTINUE.\n"); ++ return DPAA_ETH_CONTINUE; ++ ++_priv_ingress_tx_err_stolen: ++ kfree(fd_virt_addr); ++ ++ _fmt_dbgr("called:DPAA_ETH_STOLEN.\n"); ++ return DPAA_ETH_STOLEN; ++} ++ ++/* egress callbacks definition */ ++enum qman_cb_dqrr_result fmt_egress_dqrr( ++ struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dqrr) ++{ ++ /* this callback should never be called */ ++ BUG(); ++ return qman_cb_dqrr_consume; ++} ++ ++static void fmt_egress_error_dqrr( ++ struct qman_portal *p, ++ struct qman_fq *fq, ++ const struct qm_mr_entry *msg) ++{ ++ uint8_t *fd_virt_addr = NULL; ++ ++ /* tx failure, on the ern callback - release buffer */ ++ fd_virt_addr = (uint8_t *)phys_to_virt(qm_fd_addr(&msg->ern.fd)); ++ kfree(fd_virt_addr); ++ ++ return; ++} ++ ++static const struct qman_fq fmt_egress_fq = { ++ .cb = { .dqrr = fmt_egress_dqrr, ++ .ern = fmt_egress_error_dqrr, ++ .fqs = NULL} ++}; ++ ++int fmt_fq_alloc( ++ struct fmt_fqs_s *fmt_fqs, ++ const struct qman_fq *qman_fq, ++ uint32_t fqid, uint32_t flags, ++ uint16_t channel, uint8_t wq) ++{ ++ int _errno = 0; ++ ++ _fmt_dbg("calling...\n"); ++ ++ fmt_fqs->fq_base = *qman_fq; ++ ++ if (fqid == 0) { ++ flags |= QMAN_FQ_FLAG_DYNAMIC_FQID; ++ flags &= ~QMAN_FQ_FLAG_NO_MODIFY; ++ } else ++ flags &= ~QMAN_FQ_FLAG_DYNAMIC_FQID; ++ ++ fmt_fqs->init = !(flags & QMAN_FQ_FLAG_NO_MODIFY); ++ ++ _errno = qman_create_fq(fqid, flags, &fmt_fqs->fq_base); ++ if (_errno < 0) { ++ _fmt_err("frame queues create failed.\n"); ++ return -EINVAL; ++ } ++ ++ if (fmt_fqs->init) { ++ struct qm_mcc_initfq initfq; ++ ++ initfq.we_mask = QM_INITFQ_WE_DESTWQ; ++ initfq.fqd.dest.channel = channel; ++ initfq.fqd.dest.wq = wq; ++ ++ _errno = qman_init_fq(&fmt_fqs->fq_base, ++ QMAN_INITFQ_FLAG_SCHED, ++ &initfq); ++ if (_errno < 0) { ++ _fmt_err("frame queues init erorr.\n"); ++ qman_destroy_fq(&fmt_fqs->fq_base, 0); ++ return -EINVAL; ++ } ++ } ++ ++ _fmt_dbg("called.\n"); ++ return 0; ++} ++ ++static int fmt_fq_free(struct fmt_fqs_s *fmt_fq) ++{ ++ int _err = 0; ++ ++ _fmt_dbg("calling...\n"); ++ ++ if (fmt_fq->init) { ++ _err = qman_retire_fq(&fmt_fq->fq_base, NULL); ++ if (unlikely(_err < 0)) ++ _fmt_err("qman_retire_fq(%u) = %d\n", ++ qman_fq_fqid(&fmt_fq->fq_base), _err); ++ ++ _err = qman_oos_fq(&fmt_fq->fq_base); ++ if (unlikely(_err < 0)) ++ _fmt_err("qman_oos_fq(%u) = %d\n", ++ qman_fq_fqid(&fmt_fq->fq_base), _err); ++ } ++ ++ qman_destroy_fq(&fmt_fq->fq_base, 0); ++ ++ _fmt_dbg("called.\n"); ++ return _err; ++} ++ ++/* private pcd dqrr calbacks */ ++static enum qman_cb_dqrr_result fmt_pcd_dqrr( ++ struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct dpa_bp *dpa_bp = NULL; ++ dma_addr_t addr = qm_fd_addr(&dq->fd); ++ uint8_t *fd_virt_addr = NULL; ++ struct fmt_port_s *fmt_port; ++ struct fmt_port_pcd_s *fmt_port_pcd; ++ uint32_t relative_fqid = 0; ++ uint32_t fd_len = 0; ++ ++ _fmt_dbgr("calling...\n"); ++ ++ /* upcast - from pcd_alloc_fq */ ++ fmt_port = ((struct fmt_fqs_s *)fq)->fmt_port_priv; ++ if (!fmt_port) { ++ _fmt_err(" wrong fmt port -to- fq match.\n"); ++ goto _fmt_pcd_dqrr_return; ++ } ++ fmt_port_pcd = &fmt_port->fmt_port_pcd; ++ ++ relative_fqid = dq->fqid - fmt_port_pcd->fqid_base; ++ _fmt_dbgr("pcd dqrr got frame on relative fq:%u at base:%u\n", ++ relative_fqid, fmt_port_pcd->fqid_base); ++ ++ fd_len = dq->fd.length20 + dq->fd.offset; ++ ++ if (fd_len > fm_get_max_frm()) { ++ _fmt_err("pcd dqrr wrong frame size: %u (%u:%u)!\n", ++ fd_len, dq->fd.length20, dq->fd.offset); ++ goto _fmt_pcd_dqrr_return; ++ } ++ ++ dpa_bp = dpa_bpid2pool(dq->fd.bpid); ++ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, DMA_BIDIRECTIONAL); ++ ++ fd_virt_addr = phys_to_virt(addr); ++ if (!test_and_steal_frame(fmt_port, relative_fqid, fd_virt_addr, ++ fd_len)) { ++ ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ atomic_inc(&fmt_port->not_enqueue_to_rxq_wrong_frm); ++#endif ++ _fmt_wrn("pcd dqrr unrecognized frame at fqid: %u," ++ " frame len: %u (dropped).\n", ++ dq->fqid, dq->fd.length20); ++ dump_frame(fd_virt_addr, fd_len); ++ } ++ ++_fmt_pcd_dqrr_return: ++ /* no need to map again here */ ++ fmt_fq_release(&dq->fd); ++ ++ _fmt_dbgr("calle.\n"); ++ return qman_cb_dqrr_consume; ++} ++ ++static void fmt_pcd_err_dqrr( ++ struct qman_portal *qm, ++ struct qman_fq *fq, ++ const struct qm_mr_entry *msg) ++{ ++ _fmt_err("this callback should never be called.\n"); ++ BUG(); ++ return; ++} ++ ++static void fmt_pcd_fqs_dqrr( ++ struct qman_portal *qm, ++ struct qman_fq *fq, ++ const struct qm_mr_entry *msg) ++{ ++ _fmt_dbg(" fq state(0x%x)@fqid(%u.\n", msg->fq.fqs, msg->fq.fqid); ++ return; ++} ++ ++/* private pcd queue template */ ++static const struct qman_fq pcd_fq = { ++ .cb = { .dqrr = fmt_pcd_dqrr, ++ .ern = fmt_pcd_err_dqrr, ++ .fqs = fmt_pcd_fqs_dqrr} ++}; ++ ++/* defined as weak in dpaa driver. */ ++/* ! parameters come from IOCTL call - US */ ++int dpa_alloc_pcd_fqids( ++ struct device *dev, ++ uint32_t num, uint8_t alignment, ++ uint32_t *base_fqid) ++{ ++ int _err = 0, i; ++ struct net_device *net_dev = NULL; ++ struct dpa_priv_s *dpa_priv = NULL; ++ struct fmt_port_pcd_s *fmt_port_pcd = NULL; ++ struct fmt_fqs_s *fmt_fqs = NULL; ++ struct fmt_port_s *fmt_port = NULL; ++ int num_allocated = 0; ++ ++ _fmt_dbg("calling...\n"); ++ ++ net_dev = (typeof(net_dev))dev_get_drvdata(dev); ++ dpa_priv = (typeof(dpa_priv))netdev_priv(net_dev); ++ ++ if (!netif_msg_probe(dpa_priv)) { ++ _fmt_err("dpa not probe.\n"); ++ _err = -ENODEV; ++ goto _pcd_alloc_fqs_err; ++ } ++ ++ fmt_port = match_dpa_to_fmt_port(dpa_priv); ++ if (!fmt_port) { ++ _fmt_err("fmt port not found."); ++ _err = -EINVAL; ++ goto _pcd_alloc_fqs_err; ++ } ++ ++ fmt_port_pcd = &fmt_port->fmt_port_pcd; ++ ++ num_allocated = qman_alloc_fqid_range(base_fqid, num, alignment, 0); ++ ++ if ((num_allocated <= 0) || ++ (num_allocated < num) || ++ (alignment && (*base_fqid) % alignment)) { ++ *base_fqid = 0; ++ _fmt_err("Failed to alloc pcd fqs rang.\n"); ++ _err = -EINVAL; ++ goto _pcd_alloc_fqs_err; ++ } ++ ++ _fmt_dbg("wanted %d fqs(align %d), got %d fqids@%u.\n", ++ num, alignment, num_allocated, *base_fqid); ++ ++ /* alloc pcd queues */ ++ fmt_port_pcd->fmt_pcd_fqs = kmalloc(num_allocated * ++ sizeof(struct fmt_fqs_s), ++ GFP_KERNEL); ++ fmt_port_pcd->num_queues = num_allocated; ++ fmt_port_pcd->fqid_base = *base_fqid; ++ fmt_fqs = fmt_port_pcd->fmt_pcd_fqs; ++ ++ /* alloc the pcd queues */ ++ for (i = 0; i < num_allocated; i++, fmt_fqs++) { ++ _err = fmt_fq_alloc( ++ fmt_fqs, ++ &pcd_fq, ++ (*base_fqid) + i, QMAN_FQ_FLAG_NO_ENQUEUE, ++ dpa_priv->channel, 7); ++ ++ if (_err < 0) ++ goto _pcd_alloc_fqs_err; ++ ++ /* upcast to identify from where the frames came from */ ++ fmt_fqs->fmt_port_priv = fmt_port; ++ } ++ ++ _fmt_dbg("called.\n"); ++ return _err; ++_pcd_alloc_fqs_err: ++ if (num_allocated > 0) ++ qman_release_fqid_range(*base_fqid, num_allocated); ++ /*TODO: free fmt_pcd_fqs if are any */ ++ ++ _fmt_dbg("called(_err:%d).\n", _err); ++ return _err; ++} ++ ++/* defined as weak in dpaa driver. */ ++int dpa_free_pcd_fqids( ++ struct device *dev, ++ uint32_t base_fqid) ++{ ++ ++ int _err = 0, i; ++ struct net_device *net_dev = NULL; ++ struct dpa_priv_s *dpa_priv = NULL; ++ struct fmt_port_pcd_s *fmt_port_pcd = NULL; ++ struct fmt_fqs_s *fmt_fqs = NULL; ++ struct fmt_port_s *fmt_port = NULL; ++ int num_allocated = 0; ++ ++ _fmt_dbg("calling...\n"); ++ ++ net_dev = (typeof(net_dev))dev_get_drvdata(dev); ++ dpa_priv = (typeof(dpa_priv))netdev_priv(net_dev); ++ ++ if (!netif_msg_probe(dpa_priv)) { ++ _fmt_err("dpa not probe.\n"); ++ _err = -ENODEV; ++ goto _pcd_free_fqs_err; ++ } ++ ++ fmt_port = match_dpa_to_fmt_port(dpa_priv); ++ if (!fmt_port) { ++ _fmt_err("fmt port not found."); ++ _err = -EINVAL; ++ goto _pcd_free_fqs_err; ++ } ++ ++ fmt_port_pcd = &fmt_port->fmt_port_pcd; ++ num_allocated = fmt_port_pcd->num_queues; ++ fmt_fqs = fmt_port_pcd->fmt_pcd_fqs; ++ ++ for (i = 0; i < num_allocated; i++, fmt_fqs++) ++ fmt_fq_free(fmt_fqs); ++ ++ qman_release_fqid_range(base_fqid,num_allocated); ++ ++ kfree(fmt_port_pcd->fmt_pcd_fqs); ++ memset(fmt_port_pcd, 0, sizeof(*fmt_port_pcd)); ++ ++ /* debugging stuff */ ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ _fmt_dbg(" portid: %u.\n", fmt_port->id); ++ _fmt_dbg(" frames enqueue to qman: %u.\n", ++ atomic_read(&fmt_port->enqueue_to_qman_frm)); ++ _fmt_dbg(" frames enqueue to rxq: %u.\n", ++ atomic_read(&fmt_port->enqueue_to_rxq)); ++ _fmt_dbg(" frames dequeue from rxq: %u.\n", ++ atomic_read(&fmt_port->dequeue_from_rxq)); ++ _fmt_dbg(" frames not enqueue to rxq - wrong frm: %u.\n", ++ atomic_read(&fmt_port->not_enqueue_to_rxq_wrong_frm)); ++ atomic_set(&fmt_port->enqueue_to_qman_frm, 0); ++ atomic_set(&fmt_port->enqueue_to_rxq, 0); ++ atomic_set(&fmt_port->dequeue_from_rxq, 0); ++ atomic_set(&fmt_port->not_enqueue_to_rxq_wrong_frm, 0); ++#endif ++ return 0; ++ ++_pcd_free_fqs_err: ++ return _err; ++} ++ ++static int fmt_port_init( ++ struct fmt_port_s *fmt_port, ++ ioc_fmt_port_param_t *p_Params) ++{ ++ struct device_node *fm_node, *fm_port_node; ++ const uint32_t *uint32_prop; ++ int _errno = 0, lenp = 0, i; ++ static struct of_device_id fm_node_of_match[] = { ++ { .compatible = "fsl,fman", }, ++ { /* end of list */ }, ++ }; ++ ++ _fmt_dbg("calling...\n"); ++ ++ /* init send/receive tu US list */ ++ INIT_LIST_HEAD(&fmt_port->rx_q); ++ ++ /* check parameters */ ++ if (p_Params->num_tx_queues > FMAN_TEST_MAX_TX_FQS || ++ p_Params->fm_port_id > IOC_FMT_MAX_NUM_OF_PORTS) { ++ _fmt_dbg("wrong test parameters.\n"); ++ return -EINVAL; ++ } ++ ++ /* set port parameters */ ++ fmt_port->num_of_tx_fqs = p_Params->num_tx_queues; ++ fmt_port->id = p_Params->fm_port_id; ++ fmt_port->port_type = p_Params->fm_port_type; ++ fmt_port->diag = e_IOC_DIAG_MODE_NONE; ++ ++ /* init debugging stuff */ ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ atomic_set(&fmt_port->enqueue_to_qman_frm, 0); ++ atomic_set(&fmt_port->enqueue_to_rxq, 0); ++ atomic_set(&fmt_port->dequeue_from_rxq, 0); ++ atomic_set(&fmt_port->not_enqueue_to_rxq_wrong_frm, 0); ++#endif ++ ++ /* TODO: This should be done at probe time not at runtime ++ * very ugly function */ ++ /* fill fmt port properties from dts */ ++ for_each_matching_node(fm_node, fm_node_of_match) { ++ ++ uint32_prop = (uint32_t *)of_get_property(fm_node, ++ "cell-index", &lenp); ++ if (unlikely(uint32_prop == NULL)) { ++ _fmt_wrn("of_get_property(%s, cell-index) invalid", ++ fm_node->full_name); ++ return -EINVAL; ++ } ++ if (WARN_ON(lenp != sizeof(uint32_t))) { ++ _fmt_wrn("of_get_property(%s, cell-index) invalid", ++ fm_node->full_name); ++ return -EINVAL; ++ } ++ ++ if (*uint32_prop == p_Params->fm_id) { ++ struct resource res; ++ ++ /* Get the FM address */ ++ _errno = of_address_to_resource(fm_node, 0, &res); ++ if (unlikely(_errno < 0)) { ++ _fmt_wrn("of_address_to_resource() = %u.\n", _errno); ++ return -EINVAL; ++ } ++ ++ fmt_port->fm_phys_base_addr = res.start; ++ ++ for_each_child_of_node(fm_node, fm_port_node) { ++ struct platform_device *of_dev; ++ ++ if (!of_device_is_available(fm_port_node)) ++ continue; ++ ++ uint32_prop = (uint32_t *)of_get_property( ++ fm_port_node, ++ "cell-index", ++ &lenp); ++ if (uint32_prop == NULL) ++ continue; ++ ++ if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-port-oh") && ++ (fmt_port->port_type == e_IOC_FMT_PORT_T_OP)) { ++ ++ if (*uint32_prop == fmt_port->id) { ++ of_dev = of_find_device_by_node(fm_port_node); ++ if (unlikely(of_dev == NULL)) { ++ _fmt_wrn("fm id invalid\n"); ++ return -EINVAL; ++ } ++ ++ fmt_port->p_tx_port = ++ fm_port_bind(&of_dev->dev); ++ fmt_port->p_tx_fm_port_dev = ++ (void *)fm_port_get_handle( ++ fmt_port->p_tx_port); ++ fmt_port->p_rx_port = ++ fmt_port->p_tx_port; ++ fmt_port->p_rx_fm_port_dev = ++ fmt_port->p_tx_fm_port_dev; ++ fmt_port->p_mac_dev = NULL; ++ break; ++ } ++ } else if ((*uint32_prop == fmt_port->id) && ++ fmt_port->port_type == e_IOC_FMT_PORT_T_RXTX) { ++ ++ of_dev = of_find_device_by_node(fm_port_node); ++ if (unlikely(of_dev == NULL)) { ++ _fmt_wrn("dtb fm id invalid value"); ++ return -EINVAL; ++ } ++ ++ if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-port-1g-tx")) { ++ fmt_port->p_tx_port = ++ fm_port_bind(&of_dev->dev); ++ fmt_port->p_tx_fm_port_dev = (void *) ++ fm_port_get_handle( ++ fmt_port->p_tx_port); ++ } else if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-port-1g-rx")) { ++ fmt_port->p_rx_port = ++ fm_port_bind(&of_dev->dev); ++ fmt_port->p_rx_fm_port_dev = (void *) ++ fm_port_get_handle( ++ fmt_port->p_rx_port); ++ } else if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-1g-mac") || ++ of_device_is_compatible(fm_port_node, ++ "fsl,fman-memac")) ++ fmt_port->p_mac_dev = ++ (typeof(fmt_port->p_mac_dev)) ++ dev_get_drvdata(&of_dev->dev); ++ else ++ continue; ++ ++ if (fmt_port->p_tx_fm_port_dev && ++ fmt_port->p_rx_fm_port_dev && fmt_port->p_mac_dev) ++ break; ++ } else if (((*uint32_prop + FM_MAX_NUM_OF_1G_RX_PORTS) == ++ fmt_port->id) && ++ fmt_port->port_type == e_IOC_FMT_PORT_T_RXTX) { ++ ++ of_dev = of_find_device_by_node(fm_port_node); ++ if (unlikely(of_dev == NULL)) { ++ _fmt_wrn("dtb fm id invalid value\n"); ++ return -EINVAL; ++ } ++ ++ if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-port-10g-tx")) { ++ fmt_port->p_tx_port = ++ fm_port_bind(&of_dev->dev); ++ fmt_port->p_tx_fm_port_dev = (void *) ++ fm_port_get_handle( ++ fmt_port->p_tx_port); ++ } else if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-port-10g-rx")) { ++ fmt_port->p_rx_port = ++ fm_port_bind(&of_dev->dev); ++ fmt_port->p_rx_fm_port_dev = (void *) ++ fm_port_get_handle( ++ fmt_port->p_rx_port); ++ } else if (of_device_is_compatible(fm_port_node, ++ "fsl,fman-10g-mac") || ++ of_device_is_compatible(fm_port_node, ++ "fsl,fman-memac")) ++ fmt_port->p_mac_dev = ++ (typeof(fmt_port->p_mac_dev)) ++ dev_get_drvdata(&of_dev->dev); ++ else ++ continue; ++ ++ if (fmt_port->p_tx_fm_port_dev && ++ fmt_port->p_rx_fm_port_dev && fmt_port->p_mac_dev) ++ break; ++ } ++ } /* for_each_child */ ++ } ++ } /* for each matching node */ ++ ++ if (fmt_port->p_tx_fm_port_dev == 0 || ++ fmt_port->p_rx_fm_port_dev == 0) { ++ ++ _fmt_err("bad fm port pointers.\n"); ++ return -EINVAL; ++ } ++ ++ _fmt_dbg("alloc %u tx queues.\n", fmt_port->num_of_tx_fqs); ++ ++ /* init fman test egress dynamic frame queues */ ++ for (i = 0; i < fmt_port->num_of_tx_fqs; i++) { ++ int _errno; ++ _errno = fmt_fq_alloc( ++ &fmt_port->p_tx_fqs[i], ++ &fmt_egress_fq, ++ 0, ++ QMAN_FQ_FLAG_TO_DCPORTAL, ++ fm_get_tx_port_channel(fmt_port->p_tx_port), ++ i); ++ ++ if (_errno < 0) { ++ _fmt_err("tx queues allocation failed.\n"); ++ /* TODO: memory leak here if 1 queue is allocated and ++ * next queues are failing ... */ ++ return -EINVAL; ++ } ++ } ++ ++ /* port is valid and ready to use. */ ++ fmt_port->valid = TRUE; ++ ++ _fmt_dbg("called.\n"); ++ return 0; ++} ++ ++/* fm test chardev functions */ ++static int fmt_open(struct inode *inode, struct file *file) ++{ ++ unsigned int minor = iminor(inode); ++ ++ _fmt_dbg("calling...\n"); ++ ++ if (file->private_data != NULL) ++ return 0; ++ ++ /* The minor represent the port number. ++ * Set the port structure accordingly, thus all the operations ++ * will be done on this port. */ ++ if ((minor >= DEV_FM_TEST_PORTS_MINOR_BASE) && ++ (minor < DEV_FM_TEST_MAX_MINORS)) ++ file->private_data = &fm_test.ports[minor]; ++ else ++ return -ENXIO; ++ ++ _fmt_dbg("called.\n"); ++ return 0; ++} ++ ++static int fmt_close(struct inode *inode, struct file *file) ++{ ++ struct fmt_port_s *fmt_port = NULL; ++ struct fmt_frame_s *fmt_frame = NULL; ++ ++ int err = 0; ++ ++ _fmt_dbg("calling...\n"); ++ ++ fmt_port = file->private_data; ++ if (!fmt_port) ++ return -ENODEV; ++ ++ /* Close the current test port by invalidating it. */ ++ fmt_port->valid = FALSE; ++ ++ /* clean the fmt port queue */ ++ while ((fmt_frame = dequeue_fmt_frame(fmt_port)) != NULL) { ++ if (fmt_frame && fmt_frame->buff.p_data){ ++ kfree(fmt_frame->buff.p_data); ++ kfree(fmt_frame); ++ } ++ } ++ ++ /* !!! the qman queues are cleaning from fm_ioctl... ++ * - very ugly */ ++ ++ _fmt_dbg("called.\n"); ++ return err; ++} ++ ++static int fmt_ioctls(unsigned int minor, ++ struct file *file, ++ unsigned int cmd, ++ unsigned long arg, ++ bool compat) ++{ ++ struct fmt_port_s *fmt_port = NULL; ++ ++ _fmt_dbg("IOCTL minor:%u " ++ " arg:0x%08lx ioctl cmd (0x%08x):(0x%02x:0x%02x.\n", ++ minor, arg, cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); ++ ++ fmt_port = file->private_data; ++ if (!fmt_port) { ++ _fmt_err("invalid fmt port.\n"); ++ return -ENODEV; ++ } ++ ++ /* set test type properly */ ++ if (compat) ++ fmt_port->compat_test_type = true; ++ else ++ fmt_port->compat_test_type = false; ++ ++ switch (cmd) { ++ case FMT_PORT_IOC_INIT: ++ { ++ ioc_fmt_port_param_t param; ++ ++ if (fmt_port->valid) { ++ _fmt_wrn("port is already initialized.\n"); ++ return -EFAULT; ++ } ++#if defined(CONFIG_COMPAT) ++ if (compat) { ++ if (copy_from_user(¶m, ++ (ioc_fmt_port_param_t *)compat_ptr(arg), ++ sizeof(ioc_fmt_port_param_t))) ++ ++ return -EFAULT; ++ } else ++#endif ++ { ++ if (copy_from_user(¶m, ++ (ioc_fmt_port_param_t *) arg, ++ sizeof(ioc_fmt_port_param_t))) ++ ++ return -EFAULT; ++ } ++ ++ return fmt_port_init(fmt_port, ¶m); ++ } ++ ++ case FMT_PORT_IOC_SET_DIAG_MODE: ++ if (get_user(fmt_port->diag, (ioc_diag_mode *)arg)) ++ return -EFAULT; ++ ++ if (fmt_port->diag == e_IOC_DIAG_MODE_CTRL_LOOPBACK) ++ return set_mac_int_loopback(fmt_port, TRUE); ++ else ++ return set_mac_int_loopback(fmt_port, FALSE); ++ break; ++ ++ case FMT_PORT_IOC_SET_DPAECHO_MODE: ++ case FMT_PORT_IOC_SET_IP_HEADER_MANIP: ++ default: ++ _fmt_wrn("ioctl unimplemented minor:%u at ioctl" ++ " cmd:0x%08x(type:0x%02x, nr:0x%02x.\n", ++ minor, cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++#ifdef CONFIG_COMPAT ++static long fmt_compat_ioctl( ++ struct file *file, ++ unsigned int cmd, ++ unsigned long arg) ++{ ++ unsigned int minor = iminor(file->f_path.dentry->d_inode); ++ ++ _fmt_dbg("calling...\n"); ++ return fmt_ioctls(minor, file, cmd, arg, true); ++} ++#endif ++ ++static long fmt_ioctl( ++ struct file *file, ++ unsigned int cmd, ++ unsigned long arg) ++{ ++ unsigned int minor = iminor(file->f_path.dentry->d_inode); ++ unsigned int res; ++ ++ _fmt_dbg("calling...\n"); ++ ++ fm_mutex_lock(); ++ res = fmt_ioctls(minor, file, cmd, arg, false); ++ fm_mutex_unlock(); ++ ++ _fmt_dbg("called.\n"); ++ ++ return res; ++} ++ ++#ifdef CONFIG_COMPAT ++void copy_compat_test_frame_buffer( ++ ioc_fmt_buff_desc_t *buff, ++ ioc_fmt_compat_buff_desc_t *compat_buff) ++{ ++ compat_buff->qid = buff->qid; ++ compat_buff->p_data = ptr_to_compat(buff->p_data); ++ compat_buff->size = buff->size; ++ compat_buff->status = buff->status; ++ ++ compat_buff->buff_context.p_user_priv = ++ ptr_to_compat(buff->buff_context.p_user_priv); ++ memcpy(compat_buff->buff_context.fm_prs_res, ++ buff->buff_context.fm_prs_res, ++ FM_PRS_MAX * sizeof(uint8_t)); ++ memcpy(compat_buff->buff_context.fm_time_stamp, ++ buff->buff_context.fm_time_stamp, ++ FM_TIME_STAMP_MAX * sizeof(uint8_t)); ++} ++#endif ++ ++ssize_t fmt_read( ++ struct file *file, ++ char __user *buf, ++ size_t size, ++ loff_t *ppos) ++{ ++ struct fmt_port_s *fmt_port = NULL; ++ struct fmt_frame_s *p_fmt_frame = NULL; ++ ssize_t cnt = 0; ++ ++ fmt_port = file->private_data; ++ if (!fmt_port || !fmt_port->valid) { ++ _fmt_err("fmt port not valid!\n"); ++ return -ENODEV; ++ } ++ ++ p_fmt_frame = dequeue_fmt_frame(fmt_port); ++ if (p_fmt_frame == NULL) ++ return 0; ++ ++ _fmt_dbgr("calling...\n"); ++ ++#ifdef CONFIG_COMPAT ++ if (fmt_port->compat_test_type){ ++ cnt = sizeof(ioc_fmt_compat_buff_desc_t); ++ } ++ else ++#endif ++ { ++ cnt = sizeof(ioc_fmt_buff_desc_t); ++ } ++ ++ if (size < cnt) { ++ _fmt_err("illegal buffer-size!\n"); ++ cnt = 0; ++ goto _fmt_read_return; ++ } ++ ++ /* Copy structure */ ++#ifdef CONFIG_COMPAT ++ if (fmt_port->compat_test_type) { ++ { ++ ioc_fmt_compat_buff_desc_t compat_buff; ++ copy_compat_test_frame_buffer(&p_fmt_frame->buff, ++ &compat_buff); ++ ++ if (copy_to_user(buf, &compat_buff, cnt)) { ++ _fmt_err("copy_to_user failed!\n"); ++ goto _fmt_read_return; ++ } ++ } ++ ++ ((ioc_fmt_compat_buff_desc_t *)buf)->p_data = ++ ptr_to_compat(buf+sizeof(ioc_fmt_compat_buff_desc_t)); ++ cnt += MIN(p_fmt_frame->buff.size, size-cnt); ++ } else ++#endif ++ { ++ if (copy_to_user(buf, &p_fmt_frame->buff, cnt)) { ++ _fmt_err("copy_to_user failed!\n"); ++ goto _fmt_read_return; ++ } ++ ++ ((ioc_fmt_buff_desc_t *)buf)->p_data = ++ buf + sizeof(ioc_fmt_buff_desc_t); ++ cnt += MIN(p_fmt_frame->buff.size, size-cnt); ++ } ++ ++ if (size < cnt) { ++ _fmt_err("illegal buffer-size!\n"); ++ goto _fmt_read_return; ++ } ++ ++ /* copy frame */ ++#ifdef CONFIG_COMPAT ++ if (fmt_port->compat_test_type) { ++ if (copy_to_user(buf+sizeof(ioc_fmt_compat_buff_desc_t), ++ p_fmt_frame->buff.p_data, cnt)) { ++ _fmt_err("copy_to_user failed!\n"); ++ goto _fmt_read_return; ++ } ++ } else ++#endif ++ { ++ if (copy_to_user(buf+sizeof(ioc_fmt_buff_desc_t), ++ p_fmt_frame->buff.p_data, cnt)) { ++ _fmt_err("copy_to_user failed!\n"); ++ goto _fmt_read_return; ++ } ++ } ++ ++_fmt_read_return: ++ kfree(p_fmt_frame->buff.p_data); ++ kfree(p_fmt_frame); ++ ++ _fmt_dbgr("called.\n"); ++ return cnt; ++} ++ ++ssize_t fmt_write( ++ struct file *file, ++ const char __user *buf, ++ size_t size, ++ loff_t *ppos) ++{ ++ struct fmt_port_s *fmt_port = NULL; ++ ioc_fmt_buff_desc_t buff_desc; ++#ifdef CONFIG_COMPAT ++ ioc_fmt_compat_buff_desc_t buff_desc_compat; ++#endif ++ uint8_t *p_data = NULL; ++ uint32_t data_offset; ++ int _errno; ++ t_DpaaFD fd; ++ ++ _fmt_dbgr("calling...\n"); ++ ++ fmt_port = file->private_data; ++ if (!fmt_port || !fmt_port->valid) { ++ _fmt_err("fmt port not valid.\n"); ++ return -EINVAL; ++ } ++ ++ /* If Compat (32B UserSpace - 64B KernelSpace) */ ++#ifdef CONFIG_COMPAT ++ if (fmt_port->compat_test_type) { ++ if (size < sizeof(ioc_fmt_compat_buff_desc_t)) { ++ _fmt_err("invalid buff_desc size.\n"); ++ return -EFAULT; ++ } ++ ++ if (copy_from_user(&buff_desc_compat, buf, ++ sizeof(ioc_fmt_compat_buff_desc_t))) ++ return -EFAULT; ++ ++ buff_desc.qid = buff_desc_compat.qid; ++ buff_desc.p_data = compat_ptr(buff_desc_compat.p_data); ++ buff_desc.size = buff_desc_compat.size; ++ buff_desc.status = buff_desc_compat.status; ++ ++ buff_desc.buff_context.p_user_priv = ++ compat_ptr(buff_desc_compat.buff_context.p_user_priv); ++ memcpy(buff_desc.buff_context.fm_prs_res, ++ buff_desc_compat.buff_context.fm_prs_res, ++ FM_PRS_MAX * sizeof(uint8_t)); ++ memcpy(buff_desc.buff_context.fm_time_stamp, ++ buff_desc_compat.buff_context.fm_time_stamp, ++ FM_TIME_STAMP_MAX * sizeof(uint8_t)); ++ } else ++#endif ++ { ++ if (size < sizeof(ioc_fmt_buff_desc_t)) { ++ _fmt_err("invalid buff_desc size.\n"); ++ return -EFAULT; ++ } ++ ++ if (copy_from_user(&buff_desc, (ioc_fmt_buff_desc_t *)buf, ++ sizeof(ioc_fmt_buff_desc_t))) ++ return -EFAULT; ++ } ++ ++ data_offset = FM_PORT_GetBufferDataOffset(fmt_port->p_tx_fm_port_dev); ++ p_data = kmalloc(buff_desc.size+data_offset, GFP_KERNEL); ++ if (!p_data) ++ return -ENOMEM; ++ ++ /* If Compat (32UserSpace - 64KernelSpace) the buff_desc.p_data is ok */ ++ if (copy_from_user((uint8_t *)PTR_MOVE(p_data, data_offset), ++ buff_desc.p_data, ++ buff_desc.size)) { ++ kfree(p_data); ++ return -EFAULT; ++ } ++ ++ /* TODO: dma_map_single here (cannot access the bpool struct) */ ++ ++ /* prepare fd */ ++ memset(&fd, 0, sizeof(fd)); ++ DPAA_FD_SET_ADDR(&fd, p_data); ++ DPAA_FD_SET_OFFSET(&fd, data_offset); ++ DPAA_FD_SET_LENGTH(&fd, buff_desc.size); ++ ++ _errno = qman_enqueue(&fmt_port->p_tx_fqs[buff_desc.qid].fq_base, ++ (struct qm_fd *)&fd, 0); ++ if (_errno) { ++ buff_desc.status = (uint32_t)_errno; ++ if (copy_to_user((ioc_fmt_buff_desc_t *)buf, &buff_desc, ++ sizeof(ioc_fmt_buff_desc_t))) { ++ kfree(p_data); ++ return -EFAULT; ++ } ++ } ++ ++ /* for debugging */ ++#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME) ++ atomic_inc(&fmt_port->enqueue_to_qman_frm); ++#endif ++ _fmt_dbgr("called.\n"); ++ return buff_desc.size; ++} ++ ++/* fm test character device definition */ ++static const struct file_operations fmt_fops = ++{ ++ .owner = THIS_MODULE, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = fmt_compat_ioctl, ++#endif ++ .unlocked_ioctl = fmt_ioctl, ++ .open = fmt_open, ++ .release = fmt_close, ++ .read = fmt_read, ++ .write = fmt_write, ++}; ++ ++static int fmt_init(void) ++{ ++ int id; ++ ++ _fmt_dbg("calling...\n"); ++ ++ /* Register to the /dev for IOCTL API */ ++ /* Register dynamically a new major number for the character device: */ ++ fm_test.major = register_chrdev(0, DEV_FM_TEST_NAME, &fmt_fops); ++ if (fm_test.major <= 0) { ++ _fmt_wrn("Failed to allocate major number for device %s.\n", ++ DEV_FM_TEST_NAME); ++ return -ENODEV; ++ } ++ ++ /* Creating class for FMan_test */ ++ fm_test.fmt_class = class_create(THIS_MODULE, DEV_FM_TEST_NAME); ++ if (IS_ERR(fm_test.fmt_class)) { ++ unregister_chrdev(fm_test.major, DEV_FM_TEST_NAME); ++ _fmt_wrn("Error creating %s class.\n", DEV_FM_TEST_NAME); ++ return -ENODEV; ++ } ++ ++ for (id = 0; id < IOC_FMT_MAX_NUM_OF_PORTS; id++) ++ if (NULL == device_create(fm_test.fmt_class, NULL, ++ MKDEV(fm_test.major, ++ DEV_FM_TEST_PORTS_MINOR_BASE + id), NULL, ++ DEV_FM_TEST_NAME "%d", id)) { ++ ++ _fmt_err("Error creating %s device.\n", ++ DEV_FM_TEST_NAME); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static void fmt_free(void) ++{ ++ int id; ++ ++ for (id = 0; id < IOC_FMT_MAX_NUM_OF_PORTS; id++) ++ device_destroy(fm_test.fmt_class, MKDEV(fm_test.major, ++ DEV_FM_TEST_PORTS_MINOR_BASE + id)); ++ class_destroy(fm_test.fmt_class); ++} ++ ++static int __init __cold fmt_load(void) ++{ ++ struct dpaa_eth_hooks_s priv_dpaa_eth_hooks; ++ ++ /* set dpaa hooks for default queues */ ++ memset(&priv_dpaa_eth_hooks, 0, sizeof(priv_dpaa_eth_hooks)); ++ priv_dpaa_eth_hooks.rx_default = fmt_rx_default_hook; ++ priv_dpaa_eth_hooks.rx_error = fmt_rx_error_hook; ++ priv_dpaa_eth_hooks.tx_confirm = fmt_tx_confirm_hook; ++ priv_dpaa_eth_hooks.tx_error = fmt_tx_confirm_error_hook; ++ ++ fsl_dpaa_eth_set_hooks(&priv_dpaa_eth_hooks); ++ ++ /* initialize the fman test environment */ ++ if (fmt_init() < 0) { ++ _fmt_err("Failed to init FM-test modul.\n"); ++ fmt_free(); ++ return -ENODEV; ++ } ++ ++ _fmt_inf("FSL FM test module loaded.\n"); ++ ++ return 0; ++} ++ ++static void __exit __cold fmt_unload(void) ++{ ++ fmt_free(); ++ _fmt_inf("FSL FM test module unloaded.\n"); ++} ++ ++module_init(fmt_load); ++module_exit(fmt_unload); +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c +new file mode 100755 +index 0000000..135e5bb +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c +@@ -0,0 +1,2753 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/* ++ @File lnxwrp_fm.c ++ @Author Shlomi Gridish ++ @Description FM Linux wrapper functions. ++*/ ++ ++#include ++#include ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#include ++#endif /* MODVERSIONS */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* For struct qe_firmware */ ++#include ++#include ++#include /* For file access mask */ ++#include ++#include ++ ++/* NetCommSw Headers --------------- */ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "sprint_ext.h" ++#include "debug_ext.h" ++#include "sys_io_ext.h" ++ ++#include "fm_ioctls.h" ++ ++#include "lnxwrp_fm.h" ++#include "lnxwrp_resources.h" ++#include "lnxwrp_sysfs_fm.h" ++#include "lnxwrp_sysfs_fm_port.h" ++#include "lnxwrp_exp_sym.h" ++#include "fm_common.h" ++#include "../../sdk_fman/Peripherals/FM/fm.h" ++#define __ERR_MODULE__ MODULE_FM ++ ++extern struct device_node *GetFmPortAdvArgsDevTreeNode (struct device_node *fm_node, ++ e_FmPortType portType, ++ uint8_t portId); ++ ++#define PROC_PRINT(args...) offset += sprintf(buf+offset,args) ++ ++#define ADD_ADV_CONFIG_NO_RET(_func, _param) \ ++ do { \ ++ if (ip_Function = _func; \ ++ _param \ ++ i++; \ ++ } \ ++ else \ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE,\ ++ ("Number of advanced-configuration entries exceeded"));\ ++ } while (0) ++ ++/* Bootarg used to override the Kconfig FSL_FM_MAX_FRAME_SIZE value */ ++#define FSL_FM_MAX_FRM_BOOTARG "fsl_fm_max_frm" ++ ++/* Bootarg used to override FSL_FM_RX_EXTRA_HEADROOM Kconfig value */ ++#define FSL_FM_RX_EXTRA_HEADROOM_BOOTARG "fsl_fm_rx_extra_headroom" ++ ++/* Minimum and maximum value for the fsl_fm_rx_extra_headroom bootarg */ ++#define FSL_FM_RX_EXTRA_HEADROOM_MIN 16 ++#define FSL_FM_RX_EXTRA_HEADROOM_MAX 384 ++ ++#define FSL_FM_PAUSE_TIME_ENABLE 0xf000 ++#define FSL_FM_PAUSE_TIME_DISABLE 0 ++#define FSL_FM_PAUSE_THRESH_DEFAULT 0 ++ ++/* ++ * Max frame size, across all interfaces. ++ * Configurable from Kconfig or bootargs, to avoid allocating ++ * oversized (socket) buffers when not using jumbo frames. ++ * Must be large enough to accommodate the network MTU, but small enough ++ * to avoid wasting skb memory. ++ * ++ * Could be overridden once, at boot-time, via the ++ * fm_set_max_frm() callback. ++ */ ++int fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE; ++ ++/* ++ * Extra headroom for Rx buffers. ++ * FMan is instructed to allocate, on the Rx path, this amount of ++ * space at the beginning of a data buffer, beside the DPA private ++ * data area and the IC fields. ++ * Does not impact Tx buffer layout. ++ * ++ * Configurable from Kconfig or bootargs. Zero by default, it's needed ++ * on particular forwarding scenarios that add extra headers to the ++ * forwarded frame. ++ */ ++int fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM; ++ ++#ifdef CONFIG_FMAN_PFC ++static int fsl_fm_pfc_quanta[] = { ++ CONFIG_FMAN_PFC_QUANTA_0, ++ CONFIG_FMAN_PFC_QUANTA_1, ++ CONFIG_FMAN_PFC_QUANTA_2, ++ CONFIG_FMAN_PFC_QUANTA_3 ++}; ++#endif ++ ++static t_LnxWrpFm lnxWrpFm; ++ ++int fm_get_max_frm() ++{ ++ return fsl_fm_max_frm; ++} ++EXPORT_SYMBOL(fm_get_max_frm); ++ ++int fm_get_rx_extra_headroom() ++{ ++ return ALIGN(fsl_fm_rx_extra_headroom, 16); ++} ++EXPORT_SYMBOL(fm_get_rx_extra_headroom); ++ ++static int __init fm_set_max_frm(char *str) ++{ ++ int ret = 0; ++ ++ ret = get_option(&str, &fsl_fm_max_frm); ++ if (ret != 1) { ++ /* ++ * This will only work if CONFIG_EARLY_PRINTK is compiled in, ++ * and something like "earlyprintk=serial,uart0,115200" is ++ * specified in the bootargs ++ */ ++ printk(KERN_WARNING "No suitable %s= prop in bootargs; " ++ "will use the default FSL_FM_MAX_FRAME_SIZE (%d) " ++ "from Kconfig.\n", FSL_FM_MAX_FRM_BOOTARG, ++ CONFIG_FSL_FM_MAX_FRAME_SIZE); ++ ++ fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE; ++ return 1; ++ } ++ ++ /* Don't allow invalid bootargs; fallback to the Kconfig value */ ++ if (fsl_fm_max_frm < 64 || fsl_fm_max_frm > 9600) { ++ printk(KERN_WARNING "Invalid %s=%d in bootargs, valid range is " ++ "64-9600. Falling back to the FSL_FM_MAX_FRAME_SIZE (%d) " ++ "from Kconfig.\n", ++ FSL_FM_MAX_FRM_BOOTARG, fsl_fm_max_frm, ++ CONFIG_FSL_FM_MAX_FRAME_SIZE); ++ ++ fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE; ++ return 1; ++ } ++ ++ printk(KERN_INFO "Using fsl_fm_max_frm=%d from bootargs\n", ++ fsl_fm_max_frm); ++ return 0; ++} ++early_param(FSL_FM_MAX_FRM_BOOTARG, fm_set_max_frm); ++ ++static int __init fm_set_rx_extra_headroom(char *str) ++{ ++ int ret; ++ ++ ret = get_option(&str, &fsl_fm_rx_extra_headroom); ++ ++ if (ret != 1) { ++ printk(KERN_WARNING "No suitable %s= prop in bootargs; " ++ "will use the default FSL_FM_RX_EXTRA_HEADROOM (%d) " ++ "from Kconfig.\n", FSL_FM_RX_EXTRA_HEADROOM_BOOTARG, ++ CONFIG_FSL_FM_RX_EXTRA_HEADROOM); ++ fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM; ++ ++ return 1; ++ } ++ ++ if (fsl_fm_rx_extra_headroom < FSL_FM_RX_EXTRA_HEADROOM_MIN || ++ fsl_fm_rx_extra_headroom > FSL_FM_RX_EXTRA_HEADROOM_MAX) { ++ printk(KERN_WARNING "Invalid value for %s=%d prop in " ++ "bootargs; will use the default " ++ "FSL_FM_RX_EXTRA_HEADROOM (%d) from Kconfig.\n", ++ FSL_FM_RX_EXTRA_HEADROOM_BOOTARG, ++ fsl_fm_rx_extra_headroom, ++ CONFIG_FSL_FM_RX_EXTRA_HEADROOM); ++ fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM; ++ } ++ ++ printk(KERN_INFO "Using fsl_fm_rx_extra_headroom=%d from bootargs\n", ++ fsl_fm_rx_extra_headroom); ++ ++ return 0; ++} ++early_param(FSL_FM_RX_EXTRA_HEADROOM_BOOTARG, fm_set_rx_extra_headroom); ++ ++static irqreturn_t fm_irq(int irq, void *_dev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)_dev; ++#ifdef CONFIG_PM_SLEEP ++ t_Fm *p_Fm = (t_Fm*)p_LnxWrpFmDev->h_Dev; ++#endif ++ if (!p_LnxWrpFmDev || !p_LnxWrpFmDev->h_Dev) ++ return IRQ_NONE; ++ ++#ifdef CONFIG_PM_SLEEP ++ if (fman_get_normal_pending(p_Fm->p_FmFpmRegs) & INTR_EN_WAKEUP) ++ { ++ pm_wakeup_event(p_LnxWrpFmDev->dev, 200); ++ } ++#endif ++ FM_EventIsr(p_LnxWrpFmDev->h_Dev); ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t fm_err_irq(int irq, void *_dev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)_dev; ++ ++ if (!p_LnxWrpFmDev || !p_LnxWrpFmDev->h_Dev) ++ return IRQ_NONE; ++ ++ if (FM_ErrorIsr(p_LnxWrpFmDev->h_Dev) == E_OK) ++ return IRQ_HANDLED; ++ ++ return IRQ_NONE; ++} ++ ++/* used to protect FMD/LLD from concurrent calls in functions fm_mutex_lock / fm_mutex_unlock */ ++static struct mutex lnxwrp_mutex; ++ ++static t_LnxWrpFmDev * CreateFmDev(uint8_t id) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ int j; ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *)XX_Malloc(sizeof(t_LnxWrpFmDev)); ++ if (!p_LnxWrpFmDev) ++ { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ return NULL; ++ } ++ ++ memset(p_LnxWrpFmDev, 0, sizeof(t_LnxWrpFmDev)); ++ p_LnxWrpFmDev->fmDevSettings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)); ++ memset(p_LnxWrpFmDev->fmDevSettings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry))); ++ p_LnxWrpFmDev->fmPcdDevSettings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)); ++ memset(p_LnxWrpFmDev->fmPcdDevSettings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry))); ++ p_LnxWrpFmDev->hcPort.settings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)); ++ memset(p_LnxWrpFmDev->hcPort.settings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry))); ++ for (j=0; jrxPorts[j].settings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)); ++ memset(p_LnxWrpFmDev->rxPorts[j].settings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry))); ++ } ++ for (j=0; jtxPorts[j].settings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)); ++ memset(p_LnxWrpFmDev->txPorts[j].settings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry))); ++ } ++ for (j=0; jopPorts[j].settings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)); ++ memset(p_LnxWrpFmDev->opPorts[j].settings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry))); ++ } ++ ++ return p_LnxWrpFmDev; ++} ++ ++static void DestroyFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev) ++{ ++ int j; ++ ++ for (j=0; jopPorts[j].settings.advConfig) ++ XX_Free(p_LnxWrpFmDev->opPorts[j].settings.advConfig); ++ for (j=0; jtxPorts[j].settings.advConfig) ++ XX_Free(p_LnxWrpFmDev->txPorts[j].settings.advConfig); ++ for (j=0; jrxPorts[j].settings.advConfig) ++ XX_Free(p_LnxWrpFmDev->rxPorts[j].settings.advConfig); ++ if (p_LnxWrpFmDev->hcPort.settings.advConfig) ++ XX_Free(p_LnxWrpFmDev->hcPort.settings.advConfig); ++ if (p_LnxWrpFmDev->fmPcdDevSettings.advConfig) ++ XX_Free(p_LnxWrpFmDev->fmPcdDevSettings.advConfig); ++ if (p_LnxWrpFmDev->fmDevSettings.advConfig) ++ XX_Free(p_LnxWrpFmDev->fmDevSettings.advConfig); ++ ++ XX_Free(p_LnxWrpFmDev); ++} ++ ++static t_Error FillRestFmInfo(t_LnxWrpFmDev *p_LnxWrpFmDev) ++{ ++#define FM_BMI_PPIDS_OFFSET 0x00080304 ++#define FM_DMA_PLR_OFFSET 0x000c2060 ++#define FM_FPM_IP_REV_1_OFFSET 0x000c30c4 ++#define DMA_HIGH_LIODN_MASK 0x0FFF0000 ++#define DMA_LOW_LIODN_MASK 0x00000FFF ++#define DMA_LIODN_SHIFT 16 ++ ++typedef _Packed struct { ++ uint32_t plr[32]; ++} _PackedType t_Plr; ++ ++typedef _Packed struct { ++ volatile uint32_t fmbm_ppid[63]; ++} _PackedType t_Ppids; ++ ++ t_Plr *p_Plr; ++ t_Ppids *p_Ppids; ++ int i,j; ++ uint32_t fmRev; ++ ++ static const uint8_t phys1GRxPortId[] = {0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf}; ++ static const uint8_t phys10GRxPortId[] = {0x10,0x11}; ++#if (DPAA_VERSION >= 11) ++ static const uint8_t physOhPortId[] = {/* 0x1, */0x2,0x3,0x4,0x5,0x6,0x7}; ++#else ++ static const uint8_t physOhPortId[] = {0x1,0x2,0x3,0x4,0x5,0x6,0x7}; ++#endif ++ static const uint8_t phys1GTxPortId[] = {0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f}; ++ static const uint8_t phys10GTxPortId[] = {0x30,0x31}; ++ ++ fmRev = (uint32_t)(*((volatile uint32_t *)UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr+FM_FPM_IP_REV_1_OFFSET))); ++ fmRev &= 0xffff; ++ ++ p_Plr = (t_Plr *)UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr+FM_DMA_PLR_OFFSET); ++#ifdef MODULE ++ for (i=0;iplr[i] = 0; ++#endif /* MODULE */ ++ ++ for (i=0; iplr[i/2] & DMA_LOW_LIODN_MASK) : ++ ((p_Plr->plr[i/2] & DMA_HIGH_LIODN_MASK) >> DMA_LIODN_SHIFT)); ++#ifdef FM_PARTITION_ARRAY ++ /* TODO: this was .liodnPerPartition[i] = liodnBase; is the index meaning the same? */ ++ p_LnxWrpFmDev->fmDevSettings.param.liodnBasePerPort[i] = liodnBase; ++#endif /* FM_PARTITION_ARRAY */ ++ ++ if ((i >= phys1GRxPortId[0]) && ++ (i <= phys1GRxPortId[FM_MAX_NUM_OF_1G_RX_PORTS-1])) ++ { ++ for (j=0; jrxPorts[j].settings.param.liodnBase = liodnBase; ++ } ++ else if (FM_MAX_NUM_OF_10G_RX_PORTS && ++ (i >= phys10GRxPortId[0]) && ++ (i <= phys10GRxPortId[FM_MAX_NUM_OF_10G_RX_PORTS-1])) ++ { ++ for (j=0; jrxPorts[FM_MAX_NUM_OF_1G_RX_PORTS+j].settings.param.liodnBase = liodnBase; ++ } ++ else if ((i >= physOhPortId[0]) && ++ (i <= physOhPortId[FM_MAX_NUM_OF_OH_PORTS-1])) ++ { ++ for (j=0; jhcPort.settings.param.liodnBase = liodnBase; ++ else ++ p_LnxWrpFmDev->opPorts[j - 1].settings.param.liodnBase = liodnBase; ++ } ++ else if ((i >= phys1GTxPortId[0]) && ++ (i <= phys1GTxPortId[FM_MAX_NUM_OF_1G_TX_PORTS-1])) ++ { ++ for (j=0; jtxPorts[j].settings.param.liodnBase = liodnBase; ++ } ++ else if (FM_MAX_NUM_OF_10G_TX_PORTS && ++ (i >= phys10GTxPortId[0]) && ++ (i <= phys10GTxPortId[FM_MAX_NUM_OF_10G_TX_PORTS-1])) ++ { ++ for (j=0; jtxPorts[FM_MAX_NUM_OF_1G_TX_PORTS+j].settings.param.liodnBase = liodnBase; ++ } ++ } ++ ++ p_Ppids = (t_Ppids *)UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr+FM_BMI_PPIDS_OFFSET); ++ ++ for (i=0; irxPorts[i].settings.param.specificParams.rxParams.liodnOffset = ++ p_Ppids->fmbm_ppid[phys1GRxPortId[i]-1]; ++ ++ for (i=0; irxPorts[FM_MAX_NUM_OF_1G_RX_PORTS+i].settings.param.specificParams.rxParams.liodnOffset = ++ p_Ppids->fmbm_ppid[phys10GRxPortId[i]-1]; ++ ++ return E_OK; ++} ++ ++/** ++ * FindFmanMicrocode - find the Fman microcode ++ * ++ * This function returns a pointer to the QE Firmware blob that holds ++ * the Fman microcode. We use the QE Firmware structure because Fman microcode ++ * is similar to QE microcode, so there's no point in defining a new layout. ++ * ++ * Current versions of U-Boot embed the Fman firmware into the device tree, ++ * so we check for that first. Each Fman node in the device tree contains a ++ * node or a pointer to node that holds the firmware. Technically, we should ++ * be fetching the firmware node for the current Fman, but we don't have that ++ * information any more, so we assume that there is only one firmware node in ++ * the device tree, and that all Fmen use the same firmware. ++ */ ++static const struct qe_firmware *FindFmanMicrocode(void) ++{ ++ static const struct qe_firmware *P4080_UCPatch; ++ struct device_node *np; ++ ++ if (P4080_UCPatch) ++ return P4080_UCPatch; ++ ++ /* The firmware should be inside the device tree. */ ++ np = of_find_compatible_node(NULL, NULL, "fsl,fman-firmware"); ++ if (np) { ++ P4080_UCPatch = of_get_property(np, "fsl,firmware", NULL); ++ of_node_put(np); ++ if (P4080_UCPatch) ++ return P4080_UCPatch; ++ else ++ REPORT_ERROR(WARNING, E_NOT_FOUND, ("firmware node is incomplete")); ++ } ++ ++ /* Returning NULL here forces the reuse of the IRAM content */ ++ return NULL; ++} ++#define SVR_SECURITY_MASK 0x00080000 ++#define SVR_PERSONALITY_MASK 0x0000FF00 ++#define SVR_VER_IGNORE_MASK (SVR_SECURITY_MASK | SVR_PERSONALITY_MASK) ++#define SVR_B4860_REV1_VALUE 0x86800010 ++#define SVR_B4860_REV2_VALUE 0x86800020 ++#define SVR_T4240_VALUE 0x82400000 ++#define SVR_T4120_VALUE 0x82400100 ++#define SVR_T4160_VALUE 0x82410000 ++#define SVR_T4080_VALUE 0x82410200 ++#define SVR_T4_DEVICE_ID 0x82400000 ++#define SVR_DEVICE_ID_MASK 0xFFF00000 ++ ++static t_LnxWrpFmDev * ReadFmDevTreeNode (struct platform_device *of_dev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ struct device_node *fm_node, *dev_node; ++ struct of_device_id name; ++ struct resource res; ++ const uint32_t *uint32_prop; ++ int _errno=0, lenp; ++ ++ fm_node = of_node_get(of_dev->dev.of_node); ++ ++ uint32_prop = (uint32_t *)of_get_property(fm_node, "cell-index", &lenp); ++ if (unlikely(uint32_prop == NULL)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_get_property(%s, cell-index) failed", fm_node->full_name)); ++ return NULL; ++ } ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ return NULL; ++ if (*uint32_prop > INTG_MAX_NUM_OF_FM) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("fm id!")); ++ return NULL; ++ } ++ p_LnxWrpFmDev = CreateFmDev(*uint32_prop); ++ if (!p_LnxWrpFmDev) { ++ REPORT_ERROR(MAJOR, E_NULL_POINTER, NO_MSG); ++ return NULL; ++ } ++ p_LnxWrpFmDev->dev = &of_dev->dev; ++ p_LnxWrpFmDev->id = *uint32_prop; ++ ++ /* Get the FM interrupt */ ++ p_LnxWrpFmDev->irq = of_irq_to_resource(fm_node, 0, NULL); ++ if (unlikely(p_LnxWrpFmDev->irq == /*NO_IRQ*/0)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_irq_to_resource() = %d", NO_IRQ)); ++ return NULL; ++ } ++ ++ /* Get the FM error interrupt */ ++ p_LnxWrpFmDev->err_irq = of_irq_to_resource(fm_node, 1, NULL); ++ /* TODO - un-comment it once there will be err_irq in the DTS */ ++#if 0 ++ if (unlikely(p_LnxWrpFmDev->err_irq == /*NO_IRQ*/0)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_irq_to_resource() = %d", NO_IRQ)); ++ return NULL; ++ } ++#endif /* 0 */ ++ ++ /* Get the FM address */ ++ _errno = of_address_to_resource(fm_node, 0, &res); ++ if (unlikely(_errno < 0)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_address_to_resource() = %d", _errno)); ++ return NULL; ++ } ++ ++ ++ p_LnxWrpFmDev->fmBaseAddr = 0; ++ p_LnxWrpFmDev->fmPhysBaseAddr = res.start; ++ p_LnxWrpFmDev->fmMemSize = res.end + 1 - res.start; ++ ++ uint32_prop = (uint32_t *)of_get_property(fm_node, "clock-frequency", &lenp); ++ if (unlikely(uint32_prop == NULL)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_get_property(%s, clock-frequency) failed", fm_node->full_name)); ++ return NULL; ++ } ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ return NULL; ++ p_LnxWrpFmDev->fmDevSettings.param.fmClkFreq = (*uint32_prop + 500000)/1000000; /* In MHz, rounded */ ++ ++ /* Get the MURAM base address and size */ ++ memset(&name, 0, sizeof(struct of_device_id)); ++ if (WARN_ON(strlen("muram") >= sizeof(name.name))) ++ return NULL; ++ strcpy(name.name, "muram"); ++ if (WARN_ON(strlen("fsl,fman-muram") >= sizeof(name.compatible))) ++ return NULL; ++ strcpy(name.compatible, "fsl,fman-muram"); ++ for_each_child_of_node(fm_node, dev_node) { ++ if (likely(of_match_node(&name, dev_node) != NULL)) { ++ _errno = of_address_to_resource(dev_node, 0, &res); ++ if (unlikely(_errno < 0)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_address_to_resource() = %d", _errno)); ++ return NULL; ++ } ++ ++ p_LnxWrpFmDev->fmMuramBaseAddr = 0; ++ p_LnxWrpFmDev->fmMuramPhysBaseAddr = res.start; ++ p_LnxWrpFmDev->fmMuramMemSize = res.end + 1 - res.start; ++ { ++ uint32_t svr; ++ svr = mfspr(SPRN_SVR); ++ ++ if ((svr & ~SVR_VER_IGNORE_MASK) >= SVR_B4860_REV2_VALUE) ++ p_LnxWrpFmDev->fmMuramMemSize = 0x80000; ++ } ++ } ++ } ++ ++ /* Get the RTC base address and size */ ++ memset(&name, 0, sizeof(struct of_device_id)); ++ if (WARN_ON(strlen("rtc") >= sizeof(name.name))) ++ return NULL; ++ strcpy(name.name, "rtc"); ++ if (WARN_ON(strlen("fsl,fman-rtc") >= sizeof(name.compatible))) ++ return NULL; ++ strcpy(name.compatible, "fsl,fman-rtc"); ++ for_each_child_of_node(fm_node, dev_node) { ++ if (likely(of_match_node(&name, dev_node) != NULL)) { ++ _errno = of_address_to_resource(dev_node, 0, &res); ++ if (unlikely(_errno < 0)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_address_to_resource() = %d", _errno)); ++ return NULL; ++ } ++ ++ p_LnxWrpFmDev->fmRtcBaseAddr = 0; ++ p_LnxWrpFmDev->fmRtcPhysBaseAddr = res.start; ++ p_LnxWrpFmDev->fmRtcMemSize = res.end + 1 - res.start; ++ } ++ } ++ ++#if (DPAA_VERSION >= 11) ++ /* Get the VSP base address */ ++ for_each_child_of_node(fm_node, dev_node) { ++ if (of_device_is_compatible(dev_node, "fsl,fman-vsps")) { ++ _errno = of_address_to_resource(dev_node, 0, &res); ++ if (unlikely(_errno < 0)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_address_to_resource() = %d", _errno)); ++ return NULL; ++ } ++ p_LnxWrpFmDev->fmVspBaseAddr = 0; ++ p_LnxWrpFmDev->fmVspPhysBaseAddr = res.start; ++ p_LnxWrpFmDev->fmVspMemSize = res.end + 1 - res.start; ++ } ++ } ++#endif ++ ++ /* Get all PCD nodes */ ++ memset(&name, 0, sizeof(struct of_device_id)); ++ if (WARN_ON(strlen("parser") >= sizeof(name.name))) ++ return NULL; ++ strcpy(name.name, "parser"); ++ if (WARN_ON(strlen("fsl,fman-parser") >= sizeof(name.compatible))) ++ return NULL; ++ strcpy(name.compatible, "fsl,fman-parser"); ++ for_each_child_of_node(fm_node, dev_node) ++ if (likely(of_match_node(&name, dev_node) != NULL)) ++ p_LnxWrpFmDev->prsActive = TRUE; ++ ++ memset(&name, 0, sizeof(struct of_device_id)); ++ if (WARN_ON(strlen("keygen") >= sizeof(name.name))) ++ return NULL; ++ strcpy(name.name, "keygen"); ++ if (WARN_ON(strlen("fsl,fman-keygen") >= sizeof(name.compatible))) ++ return NULL; ++ strcpy(name.compatible, "fsl,fman-keygen"); ++ for_each_child_of_node(fm_node, dev_node) ++ if (likely(of_match_node(&name, dev_node) != NULL)) ++ p_LnxWrpFmDev->kgActive = TRUE; ++ ++ memset(&name, 0, sizeof(struct of_device_id)); ++ if (WARN_ON(strlen("cc") >= sizeof(name.name))) ++ return NULL; ++ strcpy(name.name, "cc"); ++ if (WARN_ON(strlen("fsl,fman-cc") >= sizeof(name.compatible))) ++ return NULL; ++ strcpy(name.compatible, "fsl,fman-cc"); ++ for_each_child_of_node(fm_node, dev_node) ++ if (likely(of_match_node(&name, dev_node) != NULL)) ++ p_LnxWrpFmDev->ccActive = TRUE; ++ ++ memset(&name, 0, sizeof(struct of_device_id)); ++ if (WARN_ON(strlen("policer") >= sizeof(name.name))) ++ return NULL; ++ strcpy(name.name, "policer"); ++ if (WARN_ON(strlen("fsl,fman-policer") >= sizeof(name.compatible))) ++ return NULL; ++ strcpy(name.compatible, "fsl,fman-policer"); ++ for_each_child_of_node(fm_node, dev_node) ++ if (likely(of_match_node(&name, dev_node) != NULL)) ++ p_LnxWrpFmDev->plcrActive = TRUE; ++ ++ if (p_LnxWrpFmDev->prsActive || p_LnxWrpFmDev->kgActive || ++ p_LnxWrpFmDev->ccActive || p_LnxWrpFmDev->plcrActive) ++ p_LnxWrpFmDev->pcdActive = TRUE; ++ ++ if (p_LnxWrpFmDev->pcdActive) ++ { ++ const char *str_prop = (char *)of_get_property(fm_node, "fsl,default-pcd", &lenp); ++ if (str_prop) { ++ if (strncmp(str_prop, "3-tuple", strlen("3-tuple")) == 0) ++ p_LnxWrpFmDev->defPcd = e_FM_PCD_3_TUPLE; ++ } ++ else ++ p_LnxWrpFmDev->defPcd = e_NO_PCD; ++ } ++ ++ of_node_put(fm_node); ++ ++ p_LnxWrpFmDev->hcCh = ++ qman_affine_channel(cpumask_first(qman_affine_cpus())); ++ ++ p_LnxWrpFmDev->active = TRUE; ++ ++ return p_LnxWrpFmDev; ++} ++ ++struct device_node *GetFmAdvArgsDevTreeNode (uint8_t fmIndx) ++{ ++ struct device_node *dev_node; ++ const uint32_t *uint32_prop; ++ int lenp; ++ ++ for_each_compatible_node(dev_node, NULL, "fsl,fman-extended-args") { ++ uint32_prop = (uint32_t *)of_get_property(dev_node, "cell-index", &lenp); ++ if (unlikely(uint32_prop == NULL)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("of_get_property(%s, cell-index) failed", ++ dev_node->full_name)); ++ return NULL; ++ } ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ return NULL; ++ if (*uint32_prop > INTG_MAX_NUM_OF_FM) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("fm id!")); ++ return NULL; ++ } ++ if (fmIndx == *uint32_prop) ++ return dev_node; ++ } ++ ++ return NULL; ++} ++ ++static t_Error CheckNConfigFmAdvArgs (t_LnxWrpFmDev *p_LnxWrpFmDev) ++{ ++ struct device_node *dev_node; ++ t_Error err = E_INVALID_VALUE; ++ const uint32_t *uint32_prop; ++ const char *str_prop; ++ int lenp; ++ ++ dev_node = GetFmAdvArgsDevTreeNode(p_LnxWrpFmDev->id); ++ if (!dev_node) /* no advance parameters for FMan */ ++ return E_OK; ++ ++ str_prop = (char *)of_get_property(dev_node, "dma-aid-mode", &lenp); ++ if (str_prop) { ++ if (strcmp(str_prop, "port") == 0) ++ err = FM_ConfigDmaAidMode(p_LnxWrpFmDev->h_Dev, e_FM_DMA_AID_OUT_PORT_ID); ++ else if (strcmp(str_prop, "tnum") == 0) ++ err = FM_ConfigDmaAidMode(p_LnxWrpFmDev->h_Dev, e_FM_DMA_AID_OUT_TNUM); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ uint32_prop = (uint32_t *)of_get_property(dev_node, ++ "total-fifo-size", &lenp); ++ if (uint32_prop) { ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); ++ ++ if (FM_ConfigTotalFifoSize(p_LnxWrpFmDev->h_Dev, ++ *uint32_prop) != E_OK) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); ++ } ++ ++ uint32_prop = (uint32_t *)of_get_property(dev_node, "tnum-aging-period", ++ &lenp); ++ if (uint32_prop) { ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); ++ ++ err = FM_ConfigTnumAgingPeriod(p_LnxWrpFmDev->h_Dev, ++ (uint16_t)uint32_prop[0]/*tnumAgingPeriod*/); ++ ++ if (err != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ of_node_put(dev_node); ++ ++ return E_OK; ++} ++ ++static void LnxwrpFmDevExceptionsCb(t_Handle h_App, e_FmExceptions exception) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)h_App; ++ ++ ASSERT_COND(p_LnxWrpFmDev); ++ ++ DBG(INFO, ("got fm exception %d", exception)); ++ ++ /* do nothing */ ++ UNUSED(exception); ++} ++ ++static void LnxwrpFmDevBusErrorCb(t_Handle h_App, ++ e_FmPortType portType, ++ uint8_t portId, ++ uint64_t addr, ++ uint8_t tnum, ++ uint16_t liodn) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)h_App; ++ ++ ASSERT_COND(p_LnxWrpFmDev); ++ ++ /* do nothing */ ++ UNUSED(portType);UNUSED(portId);UNUSED(addr);UNUSED(tnum);UNUSED(liodn); ++} ++ ++static t_Error ConfigureFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev) ++{ ++ struct resource *dev_res; ++ int _errno; ++ ++ if (!p_LnxWrpFmDev->active) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM not configured!!!")); ++ ++#ifndef MODULE ++ _errno = can_request_irq(p_LnxWrpFmDev->irq, 0); ++ if (unlikely(_errno < 0)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("can_request_irq() = %d", _errno)); ++#endif ++ _errno = devm_request_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->irq, fm_irq, IRQF_NO_SUSPEND, "fman", p_LnxWrpFmDev); ++ if (unlikely(_errno < 0)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("request_irq(%d) = %d", p_LnxWrpFmDev->irq, _errno)); ++ ++ if (p_LnxWrpFmDev->err_irq != 0) { ++#ifndef MODULE ++ _errno = can_request_irq(p_LnxWrpFmDev->err_irq, 0); ++ if (unlikely(_errno < 0)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("can_request_irq() = %d", _errno)); ++#endif ++ _errno = devm_request_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->err_irq, fm_err_irq, IRQF_SHARED | IRQF_NO_SUSPEND, "fman-err", p_LnxWrpFmDev); ++ if (unlikely(_errno < 0)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("request_irq(%d) = %d", p_LnxWrpFmDev->err_irq, _errno)); ++ } ++ ++ p_LnxWrpFmDev->res = devm_request_mem_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize, "fman"); ++ if (unlikely(p_LnxWrpFmDev->res == NULL)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("request_mem_region() failed")); ++ ++ p_LnxWrpFmDev->fmBaseAddr = PTR_TO_UINT(devm_ioremap(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize)); ++ if (unlikely(p_LnxWrpFmDev->fmBaseAddr == 0)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("devm_ioremap() failed")); ++ ++ if (SYS_RegisterIoMap((uint64_t)p_LnxWrpFmDev->fmBaseAddr, (uint64_t)p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM memory map")); ++ ++ dev_res = __devm_request_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmMuramPhysBaseAddr, p_LnxWrpFmDev->fmMuramMemSize, "fman-muram"); ++ if (unlikely(dev_res == NULL)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("__devm_request_region() failed")); ++ ++ p_LnxWrpFmDev->fmMuramBaseAddr = PTR_TO_UINT(devm_ioremap(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmMuramPhysBaseAddr, p_LnxWrpFmDev->fmMuramMemSize)); ++ if (unlikely(p_LnxWrpFmDev->fmMuramBaseAddr == 0)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("devm_ioremap() failed")); ++ ++ if (SYS_RegisterIoMap((uint64_t)p_LnxWrpFmDev->fmMuramBaseAddr, (uint64_t)p_LnxWrpFmDev->fmMuramPhysBaseAddr, p_LnxWrpFmDev->fmMuramMemSize) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM MURAM memory map")); ++ ++ if (p_LnxWrpFmDev->fmRtcPhysBaseAddr) ++ { ++ dev_res = __devm_request_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmRtcPhysBaseAddr, p_LnxWrpFmDev->fmRtcMemSize, "fman-rtc"); ++ if (unlikely(dev_res == NULL)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("__devm_request_region() failed")); ++ ++ p_LnxWrpFmDev->fmRtcBaseAddr = PTR_TO_UINT(devm_ioremap(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmRtcPhysBaseAddr, p_LnxWrpFmDev->fmRtcMemSize)); ++ if (unlikely(p_LnxWrpFmDev->fmRtcBaseAddr == 0)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("devm_ioremap() failed")); ++ ++ if (SYS_RegisterIoMap((uint64_t)p_LnxWrpFmDev->fmRtcBaseAddr, (uint64_t)p_LnxWrpFmDev->fmRtcPhysBaseAddr, p_LnxWrpFmDev->fmRtcMemSize) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM-RTC memory map")); ++ } ++ ++#if (DPAA_VERSION >= 11) ++ if (p_LnxWrpFmDev->fmVspPhysBaseAddr) { ++ dev_res = __devm_request_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmVspPhysBaseAddr, p_LnxWrpFmDev->fmVspMemSize, "fman-vsp"); ++ if (unlikely(dev_res == NULL)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("__devm_request_region() failed")); ++ ++ p_LnxWrpFmDev->fmVspBaseAddr = PTR_TO_UINT(devm_ioremap(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmVspPhysBaseAddr, p_LnxWrpFmDev->fmVspMemSize)); ++ if (unlikely(p_LnxWrpFmDev->fmVspBaseAddr == 0)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("devm_ioremap() failed")); ++ } ++#endif ++ ++ p_LnxWrpFmDev->fmDevSettings.param.baseAddr = p_LnxWrpFmDev->fmBaseAddr; ++ p_LnxWrpFmDev->fmDevSettings.param.fmId = p_LnxWrpFmDev->id; ++ p_LnxWrpFmDev->fmDevSettings.param.irq = NO_IRQ; ++ p_LnxWrpFmDev->fmDevSettings.param.errIrq = NO_IRQ; ++ p_LnxWrpFmDev->fmDevSettings.param.f_Exception = LnxwrpFmDevExceptionsCb; ++ p_LnxWrpFmDev->fmDevSettings.param.f_BusError = LnxwrpFmDevBusErrorCb; ++ p_LnxWrpFmDev->fmDevSettings.param.h_App = p_LnxWrpFmDev; ++ ++ return FillRestFmInfo(p_LnxWrpFmDev); ++} ++ ++/* ++ * Table for matching compatible strings, for device tree ++ * guts node, for QorIQ SOCs. ++ * "fsl,qoriq-device-config-2.0" corresponds to T4 & B4 ++ * SOCs. For the older SOCs "fsl,qoriq-device-config-1.0" ++ * string would be used. ++*/ ++static const struct of_device_id guts_device_ids[] = { ++ { .compatible = "fsl,qoriq-device-config-1.0", }, ++ { .compatible = "fsl,qoriq-device-config-2.0", }, ++ {} ++}; ++ ++static unsigned int get_rcwsr(int regnum) ++{ ++ struct ccsr_guts __iomem *guts_regs = NULL; ++ struct device_node *guts_node; ++ ++ guts_node = of_find_matching_node(NULL, guts_device_ids); ++ if (!guts_node) { ++ pr_err("could not find GUTS node\n"); ++ return 0; ++ } ++ guts_regs = of_iomap(guts_node, 0); ++ of_node_put(guts_node); ++ if (!guts_regs) { ++ pr_err("ioremap of GUTS node failed\n"); ++ return 0; ++ } ++ ++ return ioread32be(&guts_regs->rcwsr[regnum]); ++} ++ ++static t_Error InitFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev) ++{ ++ const struct qe_firmware *fw; ++ ++ if (!p_LnxWrpFmDev->active) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM not configured!!!")); ++ ++ if ((p_LnxWrpFmDev->h_MuramDev = FM_MURAM_ConfigAndInit(p_LnxWrpFmDev->fmMuramBaseAddr, p_LnxWrpFmDev->fmMuramMemSize)) == NULL) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM-MURAM!")); ++ ++ /* Loading the fman-controller code */ ++ fw = FindFmanMicrocode(); ++ ++ if (!fw) { ++ /* this forces the reuse of the current IRAM content */ ++ p_LnxWrpFmDev->fmDevSettings.param.firmware.size = 0; ++ p_LnxWrpFmDev->fmDevSettings.param.firmware.p_Code = NULL; ++ } else { ++ p_LnxWrpFmDev->fmDevSettings.param.firmware.p_Code = ++ (void *) fw + fw->microcode[0].code_offset; ++ p_LnxWrpFmDev->fmDevSettings.param.firmware.size = ++ sizeof(u32) * fw->microcode[0].count; ++ DBG(INFO, ("Loading fman-controller code version %d.%d.%d", ++ fw->microcode[0].major, ++ fw->microcode[0].minor, ++ fw->microcode[0].revision)); ++ } ++ ++ p_LnxWrpFmDev->fmDevSettings.param.h_FmMuram = p_LnxWrpFmDev->h_MuramDev; ++ ++#if (DPAA_VERSION >= 11) ++ if (p_LnxWrpFmDev->fmVspBaseAddr) { ++ p_LnxWrpFmDev->fmDevSettings.param.vspBaseAddr = p_LnxWrpFmDev->fmVspBaseAddr; ++ p_LnxWrpFmDev->fmDevSettings.param.partVSPBase = 0; ++ p_LnxWrpFmDev->fmDevSettings.param.partNumOfVSPs = FM_VSP_MAX_NUM_OF_ENTRIES; ++ } ++#endif ++ ++ if(p_LnxWrpFmDev->fmDevSettings.param.fmId == 0) ++ p_LnxWrpFmDev->fmDevSettings.param.fmMacClkRatio = ++ !!(get_rcwsr(4) & 0x2); /* RCW[FM_MAC_RAT0] */ ++ else ++ p_LnxWrpFmDev->fmDevSettings.param.fmMacClkRatio = ++ !!(get_rcwsr(4) & 0x1); /* RCW[FM_MAC_RAT1] */ ++ ++ { ++ /* T4 Devices ClkRatio is always 1 regardless of RCW[FM_MAC_RAT1] */ ++ uint32_t svr; ++ svr = mfspr(SPRN_SVR); ++ ++ if ((svr & SVR_DEVICE_ID_MASK) == SVR_T4_DEVICE_ID) ++ p_LnxWrpFmDev->fmDevSettings.param.fmMacClkRatio = 1; ++ } ++ ++ if ((p_LnxWrpFmDev->h_Dev = FM_Config(&p_LnxWrpFmDev->fmDevSettings.param)) == NULL) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM")); ++ ++ ++ if (FM_ConfigResetOnInit(p_LnxWrpFmDev->h_Dev, TRUE) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM")); ++ ++#ifdef CONFIG_FMAN_P1023 ++ if (FM_ConfigDmaAidOverride(p_LnxWrpFmDev->h_Dev, TRUE) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM")); ++#endif ++ ++ ++ CheckNConfigFmAdvArgs(p_LnxWrpFmDev); ++ ++ if (FM_Init(p_LnxWrpFmDev->h_Dev) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM")); ++ ++ /* TODO: Why we mask these interrupts? */ ++ if (p_LnxWrpFmDev->err_irq == 0) { ++ FM_SetException(p_LnxWrpFmDev->h_Dev, e_FM_EX_DMA_BUS_ERROR,FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_DMA_READ_ECC,FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_DMA_SYSTEM_WRITE_ECC,FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_DMA_FM_WRITE_ECC,FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_DMA_SINGLE_PORT_ECC, FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_FPM_STALL_ON_TASKS , FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_FPM_SINGLE_ECC, FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_FPM_DOUBLE_ECC,FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_QMI_SINGLE_ECC, FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_QMI_DOUBLE_ECC,FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID,FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_BMI_LIST_RAM_ECC,FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_BMI_STORAGE_PROFILE_ECC, FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_BMI_STATISTICS_RAM_ECC, FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_BMI_DISPATCH_RAM_ECC, FALSE); ++ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_IRAM_ECC,FALSE); ++ /* TODO: FmDisableRamsEcc assert for ramsEccOwners. ++ * FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_MURAM_ECC,FALSE);*/ ++ } ++ ++ if (p_LnxWrpFmDev->fmRtcBaseAddr) ++ { ++ t_FmRtcParams fmRtcParam; ++ ++ memset(&fmRtcParam, 0, sizeof(fmRtcParam)); ++ fmRtcParam.h_App = p_LnxWrpFmDev; ++ fmRtcParam.h_Fm = p_LnxWrpFmDev->h_Dev; ++ fmRtcParam.baseAddress = p_LnxWrpFmDev->fmRtcBaseAddr; ++ ++ if(!(p_LnxWrpFmDev->h_RtcDev = FM_RTC_Config(&fmRtcParam))) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM-RTC")); ++ ++ if (FM_RTC_ConfigPeriod(p_LnxWrpFmDev->h_RtcDev, DPA_PTP_NOMINAL_FREQ_PERIOD_NS) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM-RTC")); ++ ++ if (FM_RTC_Init(p_LnxWrpFmDev->h_RtcDev) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM-RTC")); ++ } ++ ++ return E_OK; ++} ++ ++/* TODO: to be moved back here */ ++extern void FreeFmPcdDev(t_LnxWrpFmDev *p_LnxWrpFmDev); ++ ++static void FreeFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev) ++{ ++ if (!p_LnxWrpFmDev->active) ++ return; ++ ++ FreeFmPcdDev(p_LnxWrpFmDev); ++ ++ if (p_LnxWrpFmDev->h_RtcDev) ++ FM_RTC_Free(p_LnxWrpFmDev->h_RtcDev); ++ ++ if (p_LnxWrpFmDev->h_Dev) ++ FM_Free(p_LnxWrpFmDev->h_Dev); ++ ++ if (p_LnxWrpFmDev->h_MuramDev) ++ FM_MURAM_Free(p_LnxWrpFmDev->h_MuramDev); ++ ++ if (p_LnxWrpFmDev->fmRtcBaseAddr) ++ { ++ SYS_UnregisterIoMap(p_LnxWrpFmDev->fmRtcBaseAddr); ++ devm_iounmap(p_LnxWrpFmDev->dev, UINT_TO_PTR(p_LnxWrpFmDev->fmRtcBaseAddr)); ++ __devm_release_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmRtcPhysBaseAddr, p_LnxWrpFmDev->fmRtcMemSize); ++ } ++ SYS_UnregisterIoMap(p_LnxWrpFmDev->fmMuramBaseAddr); ++ devm_iounmap(p_LnxWrpFmDev->dev, UINT_TO_PTR(p_LnxWrpFmDev->fmMuramBaseAddr)); ++ __devm_release_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmMuramPhysBaseAddr, p_LnxWrpFmDev->fmMuramMemSize); ++ SYS_UnregisterIoMap(p_LnxWrpFmDev->fmBaseAddr); ++ devm_iounmap(p_LnxWrpFmDev->dev, UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr)); ++ devm_release_mem_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize); ++ if (p_LnxWrpFmDev->err_irq != 0) { ++ devm_free_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->err_irq, p_LnxWrpFmDev); ++ } ++ ++ devm_free_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->irq, p_LnxWrpFmDev); ++} ++ ++/* FMan character device file operations */ ++extern struct file_operations fm_fops; ++ ++static int /*__devinit*/ fm_probe(struct platform_device *of_dev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ ++ if ((p_LnxWrpFmDev = ReadFmDevTreeNode(of_dev)) == NULL) ++ return -EIO; ++ if (ConfigureFmDev(p_LnxWrpFmDev) != E_OK) ++ return -EIO; ++ if (InitFmDev(p_LnxWrpFmDev) != E_OK) ++ return -EIO; ++ ++ /* IOCTL ABI checking */ ++ LnxWrpPCDIOCTLEnumChecking(); ++ LnxWrpPCDIOCTLTypeChecking(); ++ ++ Sprint (p_LnxWrpFmDev->name, "%s%d", DEV_FM_NAME, p_LnxWrpFmDev->id); ++ ++ /* Register to the /dev for IOCTL API */ ++ /* Register dynamically a new major number for the character device: */ ++ if ((p_LnxWrpFmDev->major = register_chrdev(0, p_LnxWrpFmDev->name, &fm_fops)) <= 0) { ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Failed to allocate a major number for device \"%s\"", p_LnxWrpFmDev->name)); ++ return -EIO; ++ } ++ ++ /* Creating classes for FM */ ++ DBG(TRACE ,("class_create fm_class")); ++ p_LnxWrpFmDev->fm_class = class_create(THIS_MODULE, p_LnxWrpFmDev->name); ++ if (IS_ERR(p_LnxWrpFmDev->fm_class)) { ++ unregister_chrdev(p_LnxWrpFmDev->major, p_LnxWrpFmDev->name); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("class_create error fm_class")); ++ return -EIO; ++ } ++ ++ device_create(p_LnxWrpFmDev->fm_class, NULL, MKDEV(p_LnxWrpFmDev->major, DEV_FM_MINOR_BASE), NULL, ++ "fm%d", p_LnxWrpFmDev->id); ++ device_create(p_LnxWrpFmDev->fm_class, NULL, MKDEV(p_LnxWrpFmDev->major, DEV_FM_PCD_MINOR_BASE), NULL, ++ "fm%d-pcd", p_LnxWrpFmDev->id); ++ dev_set_drvdata(p_LnxWrpFmDev->dev, p_LnxWrpFmDev); ++ ++ /* create sysfs entries for stats and regs */ ++ if ( fm_sysfs_create(p_LnxWrpFmDev->dev) !=0 ) ++ { ++ FreeFmDev(p_LnxWrpFmDev); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Unable to create sysfs entry - fm!!!")); ++ return -EIO; ++ } ++ ++#ifdef CONFIG_PM ++ device_set_wakeup_capable(p_LnxWrpFmDev->dev, true); ++#endif ++ ++ DBG(TRACE, ("FM%d probed", p_LnxWrpFmDev->id)); ++ ++ return 0; ++} ++ ++static int fm_remove(struct platform_device *of_dev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ struct device *dev; ++ ++ dev = &of_dev->dev; ++ p_LnxWrpFmDev = dev_get_drvdata(dev); ++ ++ fm_sysfs_destroy(dev); ++ ++ DBG(TRACE, ("destroy fm_class")); ++ device_destroy(p_LnxWrpFmDev->fm_class, MKDEV(p_LnxWrpFmDev->major, DEV_FM_MINOR_BASE)); ++ device_destroy(p_LnxWrpFmDev->fm_class, MKDEV(p_LnxWrpFmDev->major, DEV_FM_PCD_MINOR_BASE)); ++ class_destroy(p_LnxWrpFmDev->fm_class); ++ ++ /* Destroy chardev */ ++ unregister_chrdev(p_LnxWrpFmDev->major, p_LnxWrpFmDev->name); ++ ++ FreeFmDev(p_LnxWrpFmDev); ++ ++ DestroyFmDev(p_LnxWrpFmDev); ++ ++ dev_set_drvdata(dev, NULL); ++ ++ return 0; ++} ++ ++static const struct of_device_id fm_match[] = { ++ { ++ .compatible = "fsl,fman" ++ }, ++ {} ++}; ++#ifndef MODULE ++MODULE_DEVICE_TABLE(of, fm_match); ++#endif /* !MODULE */ ++ ++#ifdef CONFIG_PM ++ ++#define SCFG_FMCLKDPSLPCR_ADDR 0xFFE0FC00C ++#define SCFG_FMCLKDPSLPCR_DS_VAL 0x48402000 ++#define SCFG_FMCLKDPSLPCR_NORMAL_VAL 0x00402000 ++ ++struct device *g_fm_dev; ++ ++static int fm_soc_suspend(struct device *dev) ++{ ++ int err = 0; ++ uint32_t *fmclk; ++ t_LnxWrpFmDev *p_LnxWrpFmDev = dev_get_drvdata(get_device(dev)); ++ g_fm_dev = dev; ++ fmclk = ioremap(SCFG_FMCLKDPSLPCR_ADDR, 4); ++ WRITE_UINT32(*fmclk, SCFG_FMCLKDPSLPCR_DS_VAL); ++ if (p_LnxWrpFmDev->h_DsarRxPort) ++ { ++#ifdef CONFIG_FSL_QORIQ_PM ++ device_set_wakeup_enable(p_LnxWrpFmDev->dev, 1); ++// TODO: fsl_set_power_except(dev->of_node?); ++#endif ++ err = FM_PORT_EnterDsarFinal(p_LnxWrpFmDev->h_DsarRxPort, ++ p_LnxWrpFmDev->h_DsarTxPort); ++ } ++ return err; ++} ++ ++static int fm_soc_resume(struct device *dev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = dev_get_drvdata(get_device(dev)); ++ uint32_t *fmclk; ++ fmclk = ioremap(SCFG_FMCLKDPSLPCR_ADDR, 4); ++ WRITE_UINT32(*fmclk, SCFG_FMCLKDPSLPCR_NORMAL_VAL); ++ if (p_LnxWrpFmDev->h_DsarRxPort) ++ { ++#ifdef CONFIG_FSL_QORIQ_PM ++// TODO fsl_set_power_except(dev->of_node?); ++ device_set_wakeup_enable(p_LnxWrpFmDev->dev, 0); ++#endif ++ FM_PORT_ExitDsar(p_LnxWrpFmDev->h_DsarRxPort, ++ p_LnxWrpFmDev->h_DsarTxPort); ++ p_LnxWrpFmDev->h_DsarRxPort = 0; ++ p_LnxWrpFmDev->h_DsarTxPort = 0; ++ } ++ return 0; ++} ++ ++static const struct dev_pm_ops fm_pm_ops = { ++ .suspend = fm_soc_suspend, ++ .resume = fm_soc_resume, ++}; ++ ++#define FM_PM_OPS (&fm_pm_ops) ++ ++#else /* CONFIG_PM */ ++ ++#define FM_PM_OPS NULL ++ ++#endif /* CONFIG_PM */ ++ ++static struct platform_driver fm_driver = { ++ .driver = { ++ .name = "fsl-fman", ++ .of_match_table = fm_match, ++ .owner = THIS_MODULE, ++ .pm = FM_PM_OPS, ++ }, ++ .probe = fm_probe, ++ .remove = fm_remove ++}; ++ ++t_Handle LNXWRP_FM_Init(void) ++{ ++ memset(&lnxWrpFm, 0, sizeof(lnxWrpFm)); ++ mutex_init(&lnxwrp_mutex); ++ ++ /* Register to the DTB for basic FM API */ ++ platform_driver_register(&fm_driver); ++ ++ return &lnxWrpFm; ++} ++ ++t_Error LNXWRP_FM_Free(t_Handle h_LnxWrpFm) ++{ ++ platform_driver_unregister(&fm_driver); ++ mutex_destroy(&lnxwrp_mutex); ++ ++ return E_OK; ++} ++ ++ ++struct fm * fm_bind(struct device *fm_dev) ++{ ++ return (struct fm *)(dev_get_drvdata(get_device(fm_dev))); ++} ++EXPORT_SYMBOL(fm_bind); ++ ++void fm_unbind(struct fm *fm) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev*)fm; ++ ++ put_device(p_LnxWrpFmDev->dev); ++} ++EXPORT_SYMBOL(fm_unbind); ++ ++struct resource * fm_get_mem_region(struct fm *fm) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev*)fm; ++ ++ return p_LnxWrpFmDev->res; ++} ++EXPORT_SYMBOL(fm_get_mem_region); ++ ++void * fm_get_handle(struct fm *fm) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev*)fm; ++ ++ return (void *)p_LnxWrpFmDev->h_Dev; ++} ++EXPORT_SYMBOL(fm_get_handle); ++ ++void * fm_get_rtc_handle(struct fm *fm) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev*)fm; ++ ++ return (void *)p_LnxWrpFmDev->h_RtcDev; ++} ++EXPORT_SYMBOL(fm_get_rtc_handle); ++ ++struct fm_port * fm_port_bind (struct device *fm_port_dev) ++{ ++ return (struct fm_port *)(dev_get_drvdata(get_device(fm_port_dev))); ++} ++EXPORT_SYMBOL(fm_port_bind); ++ ++void fm_port_unbind(struct fm_port *port) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port; ++ ++ put_device(p_LnxWrpFmPortDev->dev); ++} ++EXPORT_SYMBOL(fm_port_unbind); ++ ++void *fm_port_get_handle(const struct fm_port *port) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port; ++ ++ return (void *)p_LnxWrpFmPortDev->h_Dev; ++} ++EXPORT_SYMBOL(fm_port_get_handle); ++ ++u64 *fm_port_get_buffer_time_stamp(const struct fm_port *port, ++ const void *data) ++{ ++ return FM_PORT_GetBufferTimeStamp(fm_port_get_handle(port), ++ (void *)data); ++} ++EXPORT_SYMBOL(fm_port_get_buffer_time_stamp); ++ ++void fm_port_get_base_addr(const struct fm_port *port, uint64_t *base_addr) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; ++ ++ *base_addr = p_LnxWrpFmPortDev->settings.param.baseAddr; ++} ++EXPORT_SYMBOL(fm_port_get_base_addr); ++ ++void fm_port_pcd_bind (struct fm_port *port, struct fm_port_pcd_param *params) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port; ++ ++ p_LnxWrpFmPortDev->pcd_owner_params.cba = params->cba; ++ p_LnxWrpFmPortDev->pcd_owner_params.cbf = params->cbf; ++ p_LnxWrpFmPortDev->pcd_owner_params.dev = params->dev; ++} ++EXPORT_SYMBOL(fm_port_pcd_bind); ++ ++void fm_port_get_buff_layout_ext_params(struct fm_port *port, struct fm_port_params *params) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; ++ struct device_node *fm_node, *port_node; ++ const uint32_t *uint32_prop; ++ int lenp; ++ ++ params->data_align = 0; ++ params->manip_extra_space = 0; ++ ++ fm_node = GetFmAdvArgsDevTreeNode(((t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev)->id); ++ if (!fm_node) /* no advance parameters for FMan */ ++ return; ++ ++ port_node = GetFmPortAdvArgsDevTreeNode(fm_node, ++ p_LnxWrpFmPortDev->settings.param.portType, ++ p_LnxWrpFmPortDev->settings.param.portId); ++ if (!port_node) /* no advance parameters for FMan-Port */ ++ return; ++ ++ uint32_prop = (uint32_t *)of_get_property(port_node, "buffer-layout", &lenp); ++ if (uint32_prop) { ++ if (WARN_ON(lenp != sizeof(uint32_t)*2)) ++ return; ++ ++ params->manip_extra_space = (uint8_t)uint32_prop[0]; ++ params->data_align = (uint16_t)uint32_prop[1]; ++ } ++ ++ of_node_put(port_node); ++ of_node_put(fm_node); ++} ++EXPORT_SYMBOL(fm_port_get_buff_layout_ext_params); ++ ++uint16_t fm_get_tx_port_channel(struct fm_port *port) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port; ++ ++ return p_LnxWrpFmPortDev->txCh; ++} ++EXPORT_SYMBOL(fm_get_tx_port_channel); ++ ++int fm_port_enable (struct fm_port *port) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port; ++ t_Error err = FM_PORT_Enable(p_LnxWrpFmPortDev->h_Dev); ++ ++ return GET_ERROR_TYPE(err); ++} ++EXPORT_SYMBOL(fm_port_enable); ++ ++int fm_port_disable(struct fm_port *port) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port; ++ t_Error err = FM_PORT_Disable(p_LnxWrpFmPortDev->h_Dev); ++ ++ return GET_ERROR_TYPE(err); ++} ++EXPORT_SYMBOL(fm_port_disable); ++ ++int fm_port_set_rate_limit(struct fm_port *port, ++ uint16_t max_burst_size, ++ uint32_t rate_limit) ++{ ++ t_FmPortRateLimit param; ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; ++ int err = 0; ++ ++ param.maxBurstSize = max_burst_size; ++ param.rateLimit = rate_limit; ++ param.rateLimitDivider = 0; ++ ++ err = FM_PORT_SetRateLimit(p_LnxWrpFmPortDev->h_Dev, ¶m); ++ return err; ++} ++EXPORT_SYMBOL(fm_port_set_rate_limit); ++ ++int fm_port_del_rate_limit(struct fm_port *port) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; ++ ++ FM_PORT_DeleteRateLimit(p_LnxWrpFmPortDev->h_Dev); ++ return 0; ++} ++EXPORT_SYMBOL(fm_port_del_rate_limit); ++ ++void FM_PORT_Dsar_DumpRegs(void); ++int ar_showmem(struct file *file, const char __user *buffer, ++ unsigned long count, void *data) ++{ ++ FM_PORT_Dsar_DumpRegs(); ++ return 2; ++} ++ ++struct auto_res_tables_sizes *fm_port_get_autores_maxsize( ++ struct fm_port *port) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; ++ return &p_LnxWrpFmPortDev->dsar_table_sizes; ++} ++EXPORT_SYMBOL(fm_port_get_autores_maxsize); ++ ++int fm_port_enter_autores_for_deepsleep(struct fm_port *port, ++ struct auto_res_port_params *params) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; ++ t_LnxWrpFmDev* p_LnxWrpFmDev = (t_LnxWrpFmDev*)p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ p_LnxWrpFmDev->h_DsarRxPort = p_LnxWrpFmPortDev->h_Dev; ++ p_LnxWrpFmDev->h_DsarTxPort = params->h_FmPortTx; ++ ++ /*Register other under /proc/autoresponse */ ++ if (WARN_ON(sizeof(t_FmPortDsarParams) != sizeof(struct auto_res_port_params))) ++ return -EFAULT; ++ ++ FM_PORT_EnterDsar(p_LnxWrpFmPortDev->h_Dev, (t_FmPortDsarParams*)params); ++ return 0; ++} ++EXPORT_SYMBOL(fm_port_enter_autores_for_deepsleep); ++ ++void fm_port_exit_auto_res_for_deep_sleep(struct fm_port *port_rx, ++ struct fm_port *port_tx) ++{ ++} ++EXPORT_SYMBOL(fm_port_exit_auto_res_for_deep_sleep); ++ ++int fm_port_get_autores_stats(struct fm_port *port, ++ struct auto_res_port_stats *stats) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; ++ if (WARN_ON(sizeof(t_FmPortDsarStats) != sizeof(struct auto_res_port_stats))) ++ return -EFAULT; ++ return FM_PORT_GetDsarStats(p_LnxWrpFmPortDev->h_Dev, (t_FmPortDsarStats*)stats); ++} ++EXPORT_SYMBOL(fm_port_get_autores_stats); ++ ++int fm_port_suspend(struct fm_port *port) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; ++ if (!FM_PORT_IsInDsar(p_LnxWrpFmPortDev->h_Dev)) ++ return FM_PORT_Disable(p_LnxWrpFmPortDev->h_Dev); ++ else ++ return 0; ++} ++EXPORT_SYMBOL(fm_port_suspend); ++ ++int fm_port_resume(struct fm_port *port) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; ++ if (!FM_PORT_IsInDsar(p_LnxWrpFmPortDev->h_Dev)) ++ return FM_PORT_Enable(p_LnxWrpFmPortDev->h_Dev); ++ else ++ return 0; ++} ++EXPORT_SYMBOL(fm_port_resume); ++ ++bool fm_port_is_in_auto_res_mode(struct fm_port *port) ++{ ++ return FM_PORT_IsInDsar(port); ++} ++EXPORT_SYMBOL(fm_port_is_in_auto_res_mode); ++ ++#ifdef CONFIG_FMAN_PFC ++int fm_port_set_pfc_priorities_mapping_to_qman_wq(struct fm_port *port, ++ uint8_t prio, uint8_t wq) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; ++ int err; ++ int _errno; ++ ++ err = FM_PORT_SetPfcPrioritiesMappingToQmanWQ(p_LnxWrpFmPortDev->h_Dev, ++ prio, wq); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_PORT_SetPfcPrioritiesMappingToQmanWQ() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_port_set_pfc_priorities_mapping_to_qman_wq); ++#endif ++ ++int fm_mac_set_exception(struct fm_mac_dev *fm_mac_dev, ++ e_FmMacExceptions exception, bool enable) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MAC_SetException(fm_mac_dev, exception, enable); ++ ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MAC_SetException() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_mac_set_exception); ++ ++int fm_mac_free(struct fm_mac_dev *fm_mac_dev) ++{ ++ int err; ++ int _error; ++ ++ err = FM_MAC_Free(fm_mac_dev); ++ _error = -GET_ERROR_TYPE(err); ++ ++ if (unlikely(_error < 0)) ++ pr_err("FM_MAC_Free() = 0x%08x\n", err); ++ ++ return _error; ++} ++EXPORT_SYMBOL(fm_mac_free); ++ ++struct fm_mac_dev *fm_mac_config(t_FmMacParams *params) ++{ ++ struct fm_mac_dev *fm_mac_dev; ++ ++ fm_mac_dev = FM_MAC_Config(params); ++ if (unlikely(fm_mac_dev == NULL)) ++ pr_err("FM_MAC_Config() failed\n"); ++ ++ return fm_mac_dev; ++} ++EXPORT_SYMBOL(fm_mac_config); ++ ++int fm_mac_config_max_frame_length(struct fm_mac_dev *fm_mac_dev, ++ int len) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MAC_ConfigMaxFrameLength(fm_mac_dev, len); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MAC_ConfigMaxFrameLength() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_mac_config_max_frame_length); ++ ++int fm_mac_config_pad_and_crc(struct fm_mac_dev *fm_mac_dev, bool enable) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MAC_ConfigPadAndCrc(fm_mac_dev, enable); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MAC_ConfigPadAndCrc() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_mac_config_pad_and_crc); ++ ++int fm_mac_config_half_duplex(struct fm_mac_dev *fm_mac_dev, bool enable) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MAC_ConfigHalfDuplex(fm_mac_dev, enable); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MAC_ConfigHalfDuplex() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_mac_config_half_duplex); ++ ++int fm_mac_config_reset_on_init(struct fm_mac_dev *fm_mac_dev, bool enable) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MAC_ConfigResetOnInit(fm_mac_dev, enable); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MAC_ConfigResetOnInit() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_mac_config_reset_on_init); ++ ++int fm_mac_init(struct fm_mac_dev *fm_mac_dev) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MAC_Init(fm_mac_dev); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MAC_Init() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_mac_init); ++ ++int fm_mac_get_version(struct fm_mac_dev *fm_mac_dev, uint32_t *version) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MAC_GetVesrion(fm_mac_dev, version); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MAC_GetVesrion() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_mac_get_version); ++ ++int fm_mac_enable(struct fm_mac_dev *fm_mac_dev) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_MAC_Enable(fm_mac_dev, e_COMM_MODE_RX_AND_TX); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MAC_Enable() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_mac_enable); ++ ++int fm_mac_disable(struct fm_mac_dev *fm_mac_dev) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_MAC_Disable(fm_mac_dev, e_COMM_MODE_RX_AND_TX); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MAC_Disable() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_mac_disable); ++ ++int fm_mac_set_promiscuous(struct fm_mac_dev *fm_mac_dev, ++ bool enable) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_MAC_SetPromiscuous(fm_mac_dev, enable); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MAC_SetPromiscuous() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_mac_set_promiscuous); ++ ++int fm_mac_remove_hash_mac_addr(struct fm_mac_dev *fm_mac_dev, ++ t_EnetAddr *mac_addr) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_MAC_RemoveHashMacAddr(fm_mac_dev, mac_addr); ++ _errno = -GET_ERROR_TYPE(err); ++ if (_errno < 0) { ++ pr_err("FM_MAC_RemoveHashMacAddr() = 0x%08x\n", err); ++ return _errno; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(fm_mac_remove_hash_mac_addr); ++ ++int fm_mac_add_hash_mac_addr(struct fm_mac_dev *fm_mac_dev, ++ t_EnetAddr *mac_addr) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_MAC_AddHashMacAddr(fm_mac_dev, mac_addr); ++ _errno = -GET_ERROR_TYPE(err); ++ if (_errno < 0) { ++ pr_err("FM_MAC_AddHashMacAddr() = 0x%08x\n", err); ++ return _errno; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(fm_mac_add_hash_mac_addr); ++ ++int fm_mac_modify_mac_addr(struct fm_mac_dev *fm_mac_dev, ++ uint8_t *addr) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_MAC_ModifyMacAddr(fm_mac_dev, (t_EnetAddr *)addr); ++ _errno = -GET_ERROR_TYPE(err); ++ if (_errno < 0) ++ pr_err("FM_MAC_ModifyMacAddr() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_mac_modify_mac_addr); ++ ++int fm_mac_adjust_link(struct fm_mac_dev *fm_mac_dev, ++ bool link, int speed, bool duplex) ++{ ++ int _errno; ++ t_Error err; ++ ++ if (!link) { ++#if (DPAA_VERSION < 11) ++ FM_MAC_RestartAutoneg(fm_mac_dev); ++#endif ++ return 0; ++ } ++ ++ err = FM_MAC_AdjustLink(fm_mac_dev, speed, duplex); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MAC_AdjustLink() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_mac_adjust_link); ++ ++int fm_mac_enable_1588_time_stamp(struct fm_mac_dev *fm_mac_dev) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_MAC_Enable1588TimeStamp(fm_mac_dev); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MAC_Enable1588TimeStamp() = 0x%08x\n", err); ++ return _errno; ++} ++EXPORT_SYMBOL(fm_mac_enable_1588_time_stamp); ++ ++int fm_mac_disable_1588_time_stamp(struct fm_mac_dev *fm_mac_dev) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_MAC_Disable1588TimeStamp(fm_mac_dev); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MAC_Disable1588TimeStamp() = 0x%08x\n", err); ++ return _errno; ++} ++EXPORT_SYMBOL(fm_mac_disable_1588_time_stamp); ++ ++int fm_mac_set_rx_pause_frames( ++ struct fm_mac_dev *fm_mac_dev, bool en) ++{ ++ int _errno; ++ t_Error err; ++ ++ /* if rx pause is enabled, do NOT ignore pause frames */ ++ err = FM_MAC_SetRxIgnorePauseFrames(fm_mac_dev, !en); ++ ++ _errno = -GET_ERROR_TYPE(err); ++ if (_errno < 0) ++ pr_err("FM_MAC_SetRxIgnorePauseFrames() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_mac_set_rx_pause_frames); ++ ++#ifdef CONFIG_FMAN_PFC ++int fm_mac_set_tx_pause_frames(struct fm_mac_dev *fm_mac_dev, ++ bool en) ++{ ++ int _errno, i; ++ t_Error err; ++ ++ if (en) ++ for (i = 0; i < CONFIG_FMAN_PFC_COS_COUNT; i++) { ++ err = FM_MAC_SetTxPauseFrames(fm_mac_dev, ++ i, fsl_fm_pfc_quanta[i], ++ FSL_FM_PAUSE_THRESH_DEFAULT); ++ _errno = -GET_ERROR_TYPE(err); ++ if (_errno < 0) { ++ pr_err("FM_MAC_SetTxPauseFrames() = 0x%08x\n", err); ++ return _errno; ++ } ++ } ++ else ++ for (i = 0; i < CONFIG_FMAN_PFC_COS_COUNT; i++) { ++ err = FM_MAC_SetTxPauseFrames(fm_mac_dev, ++ i, FSL_FM_PAUSE_TIME_DISABLE, ++ FSL_FM_PAUSE_THRESH_DEFAULT); ++ _errno = -GET_ERROR_TYPE(err); ++ if (_errno < 0) { ++ pr_err("FM_MAC_SetTxPauseFrames() = 0x%08x\n", err); ++ return _errno; ++ } ++ } ++ ++ return _errno; ++} ++#else ++int fm_mac_set_tx_pause_frames(struct fm_mac_dev *fm_mac_dev, ++ bool en) ++{ ++ int _errno; ++ t_Error err; ++ ++ if (en) ++ err = FM_MAC_SetTxAutoPauseFrames(fm_mac_dev, ++ FSL_FM_PAUSE_TIME_ENABLE); ++ else ++ err = FM_MAC_SetTxAutoPauseFrames(fm_mac_dev, ++ FSL_FM_PAUSE_TIME_DISABLE); ++ ++ _errno = -GET_ERROR_TYPE(err); ++ if (_errno < 0) ++ pr_err("FM_MAC_SetTxAutoPauseFrames() = 0x%08x\n", err); ++ ++ return _errno; ++} ++#endif ++EXPORT_SYMBOL(fm_mac_set_tx_pause_frames); ++ ++int fm_rtc_enable(struct fm *fm_dev) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_RTC_Enable(fm_get_rtc_handle(fm_dev), 0); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_RTC_Enable = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_rtc_enable); ++ ++int fm_rtc_disable(struct fm *fm_dev) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_RTC_Disable(fm_get_rtc_handle(fm_dev)); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_RTC_Disable = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_rtc_disable); ++ ++int fm_rtc_get_cnt(struct fm *fm_dev, uint64_t *ts) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_RTC_GetCurrentTime(fm_get_rtc_handle(fm_dev), ts); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_RTC_GetCurrentTime = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_rtc_get_cnt); ++ ++int fm_rtc_set_cnt(struct fm *fm_dev, uint64_t ts) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_RTC_SetCurrentTime(fm_get_rtc_handle(fm_dev), ts); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_RTC_SetCurrentTime = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_rtc_set_cnt); ++ ++int fm_rtc_get_drift(struct fm *fm_dev, uint32_t *drift) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_RTC_GetFreqCompensation(fm_get_rtc_handle(fm_dev), ++ drift); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_RTC_GetFreqCompensation = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_rtc_get_drift); ++ ++int fm_rtc_set_drift(struct fm *fm_dev, uint32_t drift) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_RTC_SetFreqCompensation(fm_get_rtc_handle(fm_dev), ++ drift); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_RTC_SetFreqCompensation = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_rtc_set_drift); ++ ++int fm_rtc_set_alarm(struct fm *fm_dev, uint32_t id, ++ uint64_t time) ++{ ++ t_FmRtcAlarmParams alarm; ++ int _errno; ++ t_Error err; ++ ++ alarm.alarmId = id; ++ alarm.alarmTime = time; ++ alarm.f_AlarmCallback = NULL; ++ err = FM_RTC_SetAlarm(fm_get_rtc_handle(fm_dev), ++ &alarm); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_RTC_SetAlarm = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_rtc_set_alarm); ++ ++int fm_rtc_set_fiper(struct fm *fm_dev, uint32_t id, ++ uint64_t fiper) ++{ ++ t_FmRtcPeriodicPulseParams pp; ++ int _errno; ++ t_Error err; ++ ++ pp.periodicPulseId = id; ++ pp.periodicPulsePeriod = fiper; ++ pp.f_PeriodicPulseCallback = NULL; ++ err = FM_RTC_SetPeriodicPulse(fm_get_rtc_handle(fm_dev), &pp); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_RTC_SetPeriodicPulse = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_rtc_set_fiper); ++ ++#ifdef CONFIG_PTP_1588_CLOCK_DPAA ++int fm_rtc_enable_interrupt(struct fm *fm_dev, uint32_t events) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_RTC_EnableInterrupt(fm_get_rtc_handle(fm_dev), ++ events); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_RTC_EnableInterrupt = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_rtc_enable_interrupt); ++ ++int fm_rtc_disable_interrupt(struct fm *fm_dev, uint32_t events) ++{ ++ int _errno; ++ t_Error err; ++ ++ err = FM_RTC_DisableInterrupt(fm_get_rtc_handle(fm_dev), ++ events); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_RTC_DisableInterrupt = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_rtc_disable_interrupt); ++#endif ++ ++int fm_mac_set_wol(struct fm_port *port, struct fm_mac_dev *fm_mac_dev, bool en) ++{ ++ int _errno; ++ t_Error err; ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; ++ ++ /* Do not set WoL on AR ports */ ++ if (FM_PORT_IsInDsar(p_LnxWrpFmPortDev->h_Dev)) { ++ printk(KERN_WARNING "Port is AutoResponse enabled! WoL will not be set on this port!\n"); ++ return 0; ++ } ++ ++ err = FM_MAC_SetWakeOnLan(fm_mac_dev, en); ++ ++ _errno = -GET_ERROR_TYPE(err); ++ if (_errno < 0) ++ pr_err("FM_MAC_SetWakeOnLan() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_mac_set_wol); ++ ++void fm_mutex_lock(void) ++{ ++ mutex_lock(&lnxwrp_mutex); ++} ++EXPORT_SYMBOL(fm_mutex_lock); ++ ++void fm_mutex_unlock(void) ++{ ++ mutex_unlock(&lnxwrp_mutex); ++} ++EXPORT_SYMBOL(fm_mutex_unlock); ++ ++/*Macsec wrapper functions*/ ++struct fm_macsec_dev *fm_macsec_config(struct fm_macsec_params *fm_params) ++{ ++ struct fm_macsec_dev *fm_macsec_dev; ++ ++ fm_macsec_dev = FM_MACSEC_Config((t_FmMacsecParams *)fm_params); ++ if (unlikely(fm_macsec_dev == NULL)) ++ pr_err("FM_MACSEC_Config() failed\n"); ++ ++ return fm_macsec_dev; ++} ++EXPORT_SYMBOL(fm_macsec_config); ++ ++int fm_macsec_init(struct fm_macsec_dev *fm_macsec_dev) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_Init(fm_macsec_dev); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_Init() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_init); ++ ++int fm_macsec_free(struct fm_macsec_dev *fm_macsec_dev) ++{ ++ int err; ++ int _error; ++ ++ err = FM_MACSEC_Free(fm_macsec_dev); ++ _error = -GET_ERROR_TYPE(err); ++ ++ if (unlikely(_error < 0)) ++ pr_err("FM_MACSEC_Free() = 0x%08x\n", err); ++ ++ return _error; ++} ++EXPORT_SYMBOL(fm_macsec_free); ++ ++int fm_macsec_config_unknown_sci_frame_treatment(struct fm_macsec_dev ++ *fm_macsec_dev, ++ fm_macsec_unknown_sci_frame_treatment treat_mode) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_ConfigUnknownSciFrameTreatment(fm_macsec_dev, ++ treat_mode); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_ConfigUnknownSciFrameTreatmen() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_config_unknown_sci_frame_treatment); ++ ++int fm_macsec_config_invalid_tags_frame_treatment(struct fm_macsec_dev *fm_macsec_dev, ++ bool deliver_uncontrolled) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_ConfigInvalidTagsFrameTreatment(fm_macsec_dev, ++ deliver_uncontrolled); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MAC_ConfigMaxFrameLength() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_config_invalid_tags_frame_treatment); ++ ++int fm_macsec_config_kay_frame_treatment(struct fm_macsec_dev *fm_macsec_dev, ++ bool discard_uncontrolled) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_ConfigEncryptWithNoChangedTextFrameTreatment(fm_macsec_dev, ++ discard_uncontrolled); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_ConfigEncryptWithNoChangedTextFrameTreatmen() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_config_kay_frame_treatment); ++ ++int fm_macsec_config_untag_frame_treatment(struct fm_macsec_dev *fm_macsec_dev, ++ fm_macsec_untag_frame_treatment treat_mode) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_ConfigUntagFrameTreatment(fm_macsec_dev, treat_mode); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_ConfigUntagFrameTreatment() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_config_untag_frame_treatment); ++ ++int fm_macsec_config_pn_exhaustion_threshold(struct fm_macsec_dev *fm_macsec_dev, ++ uint32_t pn_exh_thr) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_ConfigPnExhaustionThreshold(fm_macsec_dev, pn_exh_thr); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_ConfigPnExhaustionThreshold() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_config_pn_exhaustion_threshold); ++ ++int fm_macsec_config_keys_unreadable(struct fm_macsec_dev *fm_macsec_dev) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_ConfigKeysUnreadable(fm_macsec_dev); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_ConfigKeysUnreadable() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_config_keys_unreadable); ++ ++int fm_macsec_config_sectag_without_sci(struct fm_macsec_dev *fm_macsec_dev) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_ConfigSectagWithoutSCI(fm_macsec_dev); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_ConfigSectagWithoutSCI() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_config_sectag_without_sci); ++ ++int fm_macsec_config_exception(struct fm_macsec_dev *fm_macsec_dev, ++ fm_macsec_exception exception, bool enable) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_ConfigException(fm_macsec_dev, exception, enable); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_ConfigException() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_config_exception); ++ ++int fm_macsec_get_revision(struct fm_macsec_dev *fm_macsec_dev, ++ int *macsec_revision) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_GetRevision(fm_macsec_dev, macsec_revision); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_GetRevision() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_get_revision); ++ ++int fm_macsec_enable(struct fm_macsec_dev *fm_macsec_dev) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_Enable(fm_macsec_dev); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_Enable() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_enable); ++ ++int fm_macsec_disable(struct fm_macsec_dev *fm_macsec_dev) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_Disable(fm_macsec_dev); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_Disable() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_disable); ++ ++int fm_macsec_set_exception(struct fm_macsec_dev *fm_macsec_dev, ++ fm_macsec_exception exception, bool enable) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SetException(fm_macsec_dev, exception, enable); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SetException() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_set_exception); ++ ++/* Macsec SECY wrapper API */ ++struct fm_macsec_secy_dev *fm_macsec_secy_config(struct fm_macsec_secy_params *secy_params) ++{ ++ struct fm_macsec_secy_dev *fm_macsec_secy; ++ ++ fm_macsec_secy = FM_MACSEC_SECY_Config((t_FmMacsecSecYParams *)secy_params); ++ if (unlikely(fm_macsec_secy < 0)) ++ pr_err("FM_MACSEC_SECY_Config() failed\n"); ++ ++ return fm_macsec_secy; ++} ++EXPORT_SYMBOL(fm_macsec_secy_config); ++ ++int fm_macsec_secy_init(struct fm_macsec_secy_dev *fm_macsec_secy_dev) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_Init(fm_macsec_secy_dev); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_Init() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_init); ++ ++int fm_macsec_secy_free(struct fm_macsec_secy_dev *fm_macsec_secy_dev) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_Free(fm_macsec_secy_dev); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_Free() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_free); ++ ++int fm_macsec_secy_config_sci_insertion_mode(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ fm_macsec_sci_insertion_mode sci_insertion_mode) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_ConfigSciInsertionMode(fm_macsec_secy_dev, ++ sci_insertion_mode); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_ConfigSciInsertionMode() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_config_sci_insertion_mode); ++ ++int fm_macsec_secy_config_protect_frames(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ bool protect_frames) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_ConfigProtectFrames(fm_macsec_secy_dev, ++ protect_frames); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_ConfigProtectFrames() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_config_protect_frames); ++ ++int fm_macsec_secy_config_replay_window(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ bool replay_protect, uint32_t replay_window) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_ConfigReplayWindow(fm_macsec_secy_dev, ++ replay_protect, replay_window); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_ConfigReplayWindow() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_config_replay_window); ++ ++int fm_macsec_secy_config_validation_mode(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ fm_macsec_valid_frame_behavior validate_frames) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_ConfigValidationMode(fm_macsec_secy_dev, ++ validate_frames); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_ConfigValidationMode() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_config_validation_mode); ++ ++int fm_macsec_secy_config_confidentiality(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ bool confidentiality_enable, ++ uint32_t confidentiality_offset) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_ConfigConfidentiality(fm_macsec_secy_dev, ++ confidentiality_enable, ++ confidentiality_offset); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_ConfigConfidentiality() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_config_confidentiality); ++ ++int fm_macsec_secy_config_point_to_point(struct fm_macsec_secy_dev *fm_macsec_secy_dev) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_ConfigPointToPoint(fm_macsec_secy_dev); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_ConfigPointToPoint() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_config_point_to_point); ++ ++int fm_macsec_secy_config_exception(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ fm_macsec_secy_exception exception, ++ bool enable) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_ConfigException(fm_macsec_secy_dev, exception, ++ enable); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_ConfigException() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_config_exception); ++ ++int fm_macsec_secy_config_event(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ fm_macsec_secy_event event, ++ bool enable) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_ConfigEvent(fm_macsec_secy_dev, event, enable); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_ConfigEvent() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_config_event); ++ ++struct rx_sc_dev *fm_macsec_secy_create_rxsc(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct fm_macsec_secy_sc_params *params) ++{ ++ struct rx_sc_dev *rx_sc_dev; ++ ++ rx_sc_dev = FM_MACSEC_SECY_CreateRxSc(fm_macsec_secy_dev, (t_FmMacsecSecYSCParams *)params); ++ if (unlikely(rx_sc_dev == NULL)) ++ pr_err("FM_MACSEC_SECY_CreateRxSc() failed\n"); ++ ++ return rx_sc_dev; ++} ++EXPORT_SYMBOL(fm_macsec_secy_create_rxsc); ++ ++int fm_macsec_secy_delete_rxsc(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_DeleteRxSc(fm_macsec_secy_dev, sc); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_DeleteRxSc() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_delete_rxsc); ++ ++int fm_macsec_secy_create_rx_sa(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc, macsec_an_t an, ++ uint32_t lowest_pn, macsec_sa_key_t key) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_CreateRxSa(fm_macsec_secy_dev, sc, an, ++ lowest_pn, key); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_CreateRxSa() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_create_rx_sa); ++ ++int fm_macsec_secy_delete_rx_sa(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc, macsec_an_t an) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_DeleteRxSa(fm_macsec_secy_dev, sc, an); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_DeleteRxSa() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_delete_rx_sa); ++ ++int fm_macsec_secy_rxsa_enable_receive(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc, ++ macsec_an_t an) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_RxSaEnableReceive(fm_macsec_secy_dev, sc, an); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_RxSaEnableReceive() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_rxsa_enable_receive); ++ ++int fm_macsec_secy_rxsa_disable_receive(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc, ++ macsec_an_t an) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_RxSaDisableReceive(fm_macsec_secy_dev, sc, an); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_RxSaDisableReceive() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_rxsa_disable_receive); ++ ++int fm_macsec_secy_rxsa_update_next_pn(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc, ++ macsec_an_t an, uint32_t updt_next_pn) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_RxSaUpdateNextPn(fm_macsec_secy_dev, sc, an, ++ updt_next_pn); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_RxSaUpdateNextPn() = 0x%08x\n", err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_rxsa_update_next_pn); ++ ++int fm_macsec_secy_rxsa_update_lowest_pn(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc, ++ macsec_an_t an, uint32_t updt_lowest_pn) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_RxSaUpdateLowestPn(fm_macsec_secy_dev, sc, an, ++ updt_lowest_pn); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_RxSaUpdateLowestPn() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_rxsa_update_lowest_pn); ++ ++int fm_macsec_secy_rxsa_modify_key(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc, ++ macsec_an_t an, macsec_sa_key_t key) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_RxSaModifyKey(fm_macsec_secy_dev, sc, an, key); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_RxSaModifyKey() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_rxsa_modify_key); ++ ++int fm_macsec_secy_create_tx_sa(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ macsec_an_t an, macsec_sa_key_t key) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_CreateTxSa(fm_macsec_secy_dev, an, key); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_CreateTxSa() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_create_tx_sa); ++ ++int fm_macsec_secy_delete_tx_sa(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ macsec_an_t an) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_DeleteTxSa(fm_macsec_secy_dev, an); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_DeleteTxSa() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_delete_tx_sa); ++ ++int fm_macsec_secy_txsa_modify_key(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ macsec_an_t next_active_an, ++ macsec_sa_key_t key) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_TxSaModifyKey(fm_macsec_secy_dev, next_active_an, ++ key); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_TxSaModifyKey() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_txsa_modify_key); ++ ++int fm_macsec_secy_txsa_set_active(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ macsec_an_t an) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_TxSaSetActive(fm_macsec_secy_dev, an); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_TxSaSetActive() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_txsa_set_active); ++ ++int fm_macsec_secy_txsa_get_active(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ macsec_an_t *p_an) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_TxSaGetActive(fm_macsec_secy_dev, p_an); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_TxSaGetActive() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_txsa_get_active); ++ ++int fm_macsec_secy_get_rxsc_phys_id(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ struct rx_sc_dev *sc, uint32_t *sc_phys_id) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_GetRxScPhysId(fm_macsec_secy_dev, sc, sc_phys_id); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_GetRxScPhysId() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_get_rxsc_phys_id); ++ ++int fm_macsec_secy_get_txsc_phys_id(struct fm_macsec_secy_dev *fm_macsec_secy_dev, ++ uint32_t *sc_phys_id) ++{ ++ int err; ++ int _errno; ++ ++ err = FM_MACSEC_SECY_GetTxScPhysId(fm_macsec_secy_dev, sc_phys_id); ++ _errno = -GET_ERROR_TYPE(err); ++ if (unlikely(_errno < 0)) ++ pr_err("FM_MACSEC_SECY_GetTxScPhysId() = 0x%08x\n", ++ err); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(fm_macsec_secy_get_txsc_phys_id); ++ ++static t_Handle h_FmLnxWrp; ++ ++static int __init __cold fm_load (void) ++{ ++ if ((h_FmLnxWrp = LNXWRP_FM_Init()) == NULL) ++ { ++ printk("Failed to init FM wrapper!\n"); ++ return -ENODEV; ++ } ++ ++ printk(KERN_CRIT "Freescale FM module," \ ++ " FMD API version %d.%d.%d\n", ++ FMD_API_VERSION_MAJOR, ++ FMD_API_VERSION_MINOR, ++ FMD_API_VERSION_RESPIN); ++ return 0; ++} ++ ++static void __exit __cold fm_unload (void) ++{ ++ if (h_FmLnxWrp) ++ LNXWRP_FM_Free(h_FmLnxWrp); ++} ++ ++module_init (fm_load); ++module_exit (fm_unload); +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.h b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.h +new file mode 100644 +index 0000000..95e382c +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.h +@@ -0,0 +1,294 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/* ++ @File lnxwrp_fm.h ++ ++ @Author Shlomi Gridish ++ ++ @Description FM Linux wrapper functions. ++ ++*/ ++ ++#ifndef __LNXWRP_FM_H__ ++#define __LNXWRP_FM_H__ ++ ++#include /* struct qman_fq */ ++ ++#include "std_ext.h" ++#include "error_ext.h" ++#include "list_ext.h" ++ ++#include "lnxwrp_fm_ext.h" ++ ++#define FM_MAX_NUM_OF_ADV_SETTINGS 10 ++ ++#define LNXWRP_FM_NUM_OF_SHARED_PROFILES 16 ++ ++#if defined(CONFIG_FMAN_DISABLE_OH_TO_REUSE_RESOURCES) ++#define FM_10G_OPENDMA_MIN_TRESHOLD 8 /* 10g minimum treshold if only HC is enabled and no OH port enabled */ ++#define FM_OPENDMA_RX_TX_RAPORT 2 /* RX = 2*TX */ ++#else ++#define FM_10G_OPENDMA_MIN_TRESHOLD 7 /* 10g minimum treshold if 7 OH ports are enabled */ ++#define FM_OPENDMA_RX_TX_RAPORT 1 /* RX = TX */ ++#endif ++#define FM_DEFAULT_TX10G_OPENDMA 8 /* default TX 10g open dmas */ ++#define FM_DEFAULT_RX10G_OPENDMA 8 /* default RX 10g open dmas */ ++ ++#define FRAG_MANIP_SPACE 128 ++#define FRAG_DATA_ALIGN 64 ++ ++#ifndef CONFIG_FSL_FM_MAX_FRAME_SIZE ++#define CONFIG_FSL_FM_MAX_FRAME_SIZE 0 ++#endif ++ ++#ifndef CONFIG_FSL_FM_RX_EXTRA_HEADROOM ++#define CONFIG_FSL_FM_RX_EXTRA_HEADROOM 16 ++#endif ++ ++typedef enum { ++ e_NO_PCD = 0, ++ e_FM_PCD_3_TUPLE ++} e_LnxWrpFmPortPcdDefUseCase; ++ ++ ++typedef struct t_FmTestFq { ++ struct qman_fq fq_base; ++ t_Handle h_Arg; ++} t_FmTestFq; ++ ++typedef struct { ++ uint8_t id; /* sw port id, see SW_PORT_ID_TO_HW_PORT_ID() in fm_common.h */ ++ int minor; ++ char name[20]; ++ bool active; ++ uint64_t phys_baseAddr; ++ uint64_t baseAddr; /* Port's *virtual* address */ ++ uint32_t memSize; ++ t_WrpFmPortDevSettings settings; ++ t_FmExtPools opExtPools; ++ uint8_t totalNumOfSchemes; ++ uint8_t schemesBase; ++ uint8_t numOfSchemesUsed; ++ uint32_t pcdBaseQ; ++ uint16_t pcdNumOfQs; ++ struct fm_port_pcd_param pcd_owner_params; ++ e_LnxWrpFmPortPcdDefUseCase defPcd; ++ t_Handle h_DefNetEnv; ++ t_Handle h_Schemes[FM_PCD_KG_NUM_OF_SCHEMES]; ++ t_FmBufferPrefixContent buffPrefixContent; ++ t_Handle h_Dev; ++ t_Handle h_DfltVsp; ++ t_Handle h_LnxWrpFmDev; ++ uint16_t txCh; ++ struct device *dev; ++ struct device_attribute *dev_attr_stats; ++ struct device_attribute *dev_attr_regs; ++ struct device_attribute *dev_attr_bmi_regs; ++ struct device_attribute *dev_attr_qmi_regs; ++#if (DPAA_VERSION >= 11) ++ struct device_attribute *dev_attr_ipv4_opt; ++#endif ++ struct device_attribute *dev_attr_dsar_regs; ++ struct device_attribute *dev_attr_dsar_mem; ++ struct auto_res_tables_sizes dsar_table_sizes; ++} t_LnxWrpFmPortDev; ++ ++typedef struct { ++ uint8_t id; ++ bool active; ++ uint64_t baseAddr; ++ uint32_t memSize; ++ t_WrpFmMacDevSettings settings; ++ t_Handle h_Dev; ++ t_Handle h_LnxWrpFmDev; ++} t_LnxWrpFmMacDev; ++ ++/* information about all active ports for an FMan. ++ * !Some ports may be disabled by u-boot, thus will not be available */ ++struct fm_active_ports { ++ uint32_t num_oh_ports; ++ uint32_t num_tx_ports; ++ uint32_t num_rx_ports; ++ uint32_t num_tx25_ports; ++ uint32_t num_rx25_ports; ++ uint32_t num_tx10_ports; ++ uint32_t num_rx10_ports; ++}; ++ ++/* FMan resources precalculated at fm probe based ++ * on available FMan port. */ ++struct fm_resource_settings { ++ /* buffers - fifo sizes */ ++ uint32_t tx1g_num_buffers; ++ uint32_t rx1g_num_buffers; ++ uint32_t tx2g5_num_buffers; /* Not supported yet by LLD */ ++ uint32_t rx2g5_num_buffers; /* Not supported yet by LLD */ ++ uint32_t tx10g_num_buffers; ++ uint32_t rx10g_num_buffers; ++ uint32_t oh_num_buffers; ++ uint32_t shared_ext_buffers; ++ ++ /* open DMAs */ ++ uint32_t tx_1g_dmas; ++ uint32_t rx_1g_dmas; ++ uint32_t tx_2g5_dmas; /* Not supported yet by LLD */ ++ uint32_t rx_2g5_dmas; /* Not supported yet by LLD */ ++ uint32_t tx_10g_dmas; ++ uint32_t rx_10g_dmas; ++ uint32_t oh_dmas; ++ uint32_t shared_ext_open_dma; ++ ++ /* Tnums */ ++ uint32_t tx_1g_tnums; ++ uint32_t rx_1g_tnums; ++ uint32_t tx_2g5_tnums; /* Not supported yet by LLD */ ++ uint32_t rx_2g5_tnums; /* Not supported yet by LLD */ ++ uint32_t tx_10g_tnums; ++ uint32_t rx_10g_tnums; ++ uint32_t oh_tnums; ++ uint32_t shared_ext_tnums; ++}; ++ ++typedef struct { ++ uint8_t id; ++ char name[10]; ++ bool active; ++ bool pcdActive; ++ bool prsActive; ++ bool kgActive; ++ bool ccActive; ++ bool plcrActive; ++ e_LnxWrpFmPortPcdDefUseCase defPcd; ++ uint32_t usedSchemes; ++ uint8_t totalNumOfSharedSchemes; ++ uint8_t sharedSchemesBase; ++ uint8_t numOfSchemesUsed; ++ uint8_t defNetEnvId; ++ uint64_t fmPhysBaseAddr; ++ uint64_t fmBaseAddr; ++ uint32_t fmMemSize; ++ uint64_t fmMuramPhysBaseAddr; ++ uint64_t fmMuramBaseAddr; ++ uint32_t fmMuramMemSize; ++ uint64_t fmRtcPhysBaseAddr; ++ uint64_t fmRtcBaseAddr; ++ uint32_t fmRtcMemSize; ++ uint64_t fmVspPhysBaseAddr; ++ uint64_t fmVspBaseAddr; ++ uint32_t fmVspMemSize; ++ int irq; ++ int err_irq; ++ t_WrpFmDevSettings fmDevSettings; ++ t_WrpFmPcdDevSettings fmPcdDevSettings; ++ t_Handle h_Dev; ++ uint16_t hcCh; ++ ++ t_Handle h_MuramDev; ++ t_Handle h_PcdDev; ++ t_Handle h_RtcDev; ++ ++ t_Handle h_DsarRxPort; ++ t_Handle h_DsarTxPort; ++ ++ t_LnxWrpFmPortDev hcPort; ++ t_LnxWrpFmPortDev opPorts[FM_MAX_NUM_OF_OH_PORTS-1]; ++ t_LnxWrpFmPortDev rxPorts[FM_MAX_NUM_OF_RX_PORTS]; ++ t_LnxWrpFmPortDev txPorts[FM_MAX_NUM_OF_TX_PORTS]; ++ t_LnxWrpFmMacDev macs[FM_MAX_NUM_OF_MACS]; ++ struct fm_active_ports fm_active_ports_info; ++ struct fm_resource_settings fm_resource_settings_info; ++ ++ struct device *dev; ++ struct resource *res; ++ int major; ++ struct class *fm_class; ++ struct device_attribute *dev_attr_stats; ++ struct device_attribute *dev_attr_regs; ++ struct device_attribute *dev_attr_risc_load; ++ ++ struct device_attribute *dev_pcd_attr_stats; ++ struct device_attribute *dev_plcr_attr_regs; ++ struct device_attribute *dev_prs_attr_regs; ++ struct device_attribute *dev_fm_fpm_attr_regs; ++ struct device_attribute *dev_fm_kg_attr_regs; ++ struct device_attribute *dev_fm_kg_pe_attr_regs; ++ struct device_attribute *dev_attr_muram_free_size; ++ struct device_attribute *dev_attr_fm_ctrl_code_ver; ++ ++ ++ struct qman_fq *hc_tx_conf_fq, *hc_tx_err_fq, *hc_tx_fq; ++} t_LnxWrpFmDev; ++ ++typedef struct { ++ t_LnxWrpFmDev *p_FmDevs[INTG_MAX_NUM_OF_FM]; ++} t_LnxWrpFm; ++#define LNXWRP_FM_OBJECT(ptr) LIST_OBJECT(ptr, t_LnxWrpFm, fms[((t_LnxWrpFmDev *)ptr)->id]) ++ ++ ++t_Error LnxwrpFmIOCTL(t_LnxWrpFmDev *p_LnxWrpFmDev, unsigned int cmd, unsigned long arg, bool compat); ++t_Error LnxwrpFmPortIOCTL(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev, unsigned int cmd, unsigned long arg, bool compat); ++ ++ ++#if 0 ++static __inline__ t_Error AllocSchemesForPort(t_LnxWrpFmDev *p_LnxWrpFmDev, uint8_t numSchemes, uint8_t *p_BaseSchemeNum) ++{ ++ uint32_t schemeMask; ++ uint8_t i; ++ ++ if (!numSchemes) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); ++ ++ schemeMask = 0x80000000; ++ *p_BaseSchemeNum = 0xff; ++ ++ for (i=0; schemeMask && numSchemes; schemeMask>>=1, i++) ++ if ((p_LnxWrpFmDev->usedSchemes & schemeMask) == 0) ++ { ++ p_LnxWrpFmDev->usedSchemes |= schemeMask; ++ numSchemes--; ++ if (*p_BaseSchemeNum==0xff) ++ *p_BaseSchemeNum = i; ++ } ++ else if (*p_BaseSchemeNum!=0xff) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Fragmentation on schemes array!!!")); ++ ++ if (numSchemes) ++ RETURN_ERROR(MINOR, E_FULL, ("schemes!!!")); ++ return E_OK; ++} ++#endif ++ ++void LnxWrpPCDIOCTLTypeChecking(void); ++void LnxWrpPCDIOCTLEnumChecking(void); ++ ++#endif /* __LNXWRP_FM_H__ */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm_port.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm_port.c +new file mode 100644 +index 0000000..fa73867 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm_port.c +@@ -0,0 +1,1424 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/* ++ @File lnxwrp_fm_port.c ++ ++ @Description FMD wrapper - FMan port functions. ++ ++*/ ++ ++#include ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#include ++#endif /* MODVERSIONS */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "sprint_ext.h" ++#include "fm_common.h" ++#include "lnxwrp_fsl_fman.h" ++#include "fm_port_ext.h" ++#if (DPAA_VERSION >= 11) ++#include "fm_vsp_ext.h" ++#endif /* DPAA_VERSION >= 11 */ ++#include "fm_ioctls.h" ++#include "lnxwrp_resources.h" ++#include "lnxwrp_sysfs_fm_port.h" ++ ++#define __ERR_MODULE__ MODULE_FM ++ ++extern struct device_node *GetFmAdvArgsDevTreeNode (uint8_t fmIndx); ++ ++/* TODO: duplicated, see lnxwrp_fm.c */ ++#define ADD_ADV_CONFIG_NO_RET(_func, _param)\ ++do {\ ++ if (i < max) {\ ++ p_Entry = &p_Entrys[i];\ ++ p_Entry->p_Function = _func;\ ++ _param\ ++ i++;\ ++ } else {\ ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE,\ ++ ("Number of advanced-configuration entries exceeded"));\ ++ } \ ++} while (0) ++ ++#define IS_T1023_T1024 (SVR_SOC_VER(mfspr(SPRN_SVR)) == SVR_T1024 || \ ++ SVR_SOC_VER(mfspr(SPRN_SVR)) == SVR_T1023) ++ ++static volatile int hcFrmRcv/* = 0 */; ++static spinlock_t lock; ++ ++static enum qman_cb_dqrr_result qm_tx_conf_dqrr_cb(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry ++ *dq) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = ((t_FmTestFq *) fq)->h_Arg; ++ unsigned long flags; ++ ++ FM_PCD_HcTxConf(p_LnxWrpFmDev->h_PcdDev, (t_DpaaFD *)&dq->fd); ++ spin_lock_irqsave(&lock, flags); ++ hcFrmRcv--; ++ spin_unlock_irqrestore(&lock, flags); ++ ++ return qman_cb_dqrr_consume; ++} ++ ++static enum qman_cb_dqrr_result qm_tx_dqrr_cb(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__, ++ __func__); ++ return qman_cb_dqrr_consume; ++} ++ ++static void qm_err_cb(struct qman_portal *portal, ++ struct qman_fq *fq, const struct qm_mr_entry *msg) ++{ ++ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__, ++ __func__); ++} ++ ++static struct qman_fq *FqAlloc(t_LnxWrpFmDev * p_LnxWrpFmDev, ++ uint32_t fqid, ++ uint32_t flags, uint16_t channel, uint8_t wq) ++{ ++ int _errno; ++ struct qman_fq *fq = NULL; ++ t_FmTestFq *p_FmtFq; ++ struct qm_mcc_initfq initfq; ++ ++ p_FmtFq = (t_FmTestFq *) XX_Malloc(sizeof(t_FmTestFq)); ++ if (!p_FmtFq) { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FQ obj!!!")); ++ return NULL; ++ } ++ ++ p_FmtFq->fq_base.cb.dqrr = ((flags & QMAN_FQ_FLAG_NO_ENQUEUE) ++ ? qm_tx_conf_dqrr_cb ++ : qm_tx_dqrr_cb); ++ p_FmtFq->fq_base.cb.ern = qm_err_cb; ++ /* p_FmtFq->fq_base.cb.fqs = qm_err_cb; */ ++ /* qm_err_cb wrongly called when the FQ is parked */ ++ p_FmtFq->fq_base.cb.fqs = NULL; ++ p_FmtFq->h_Arg = (t_Handle) p_LnxWrpFmDev; ++ if (fqid == 0) { ++ flags |= QMAN_FQ_FLAG_DYNAMIC_FQID; ++ flags &= ~QMAN_FQ_FLAG_NO_MODIFY; ++ } else { ++ flags &= ~QMAN_FQ_FLAG_DYNAMIC_FQID; ++ } ++ ++ if (qman_create_fq(fqid, flags, &p_FmtFq->fq_base)) { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FQ obj - qman_new_fq!!!")); ++ XX_Free(p_FmtFq); ++ return NULL; ++ } ++ fq = &p_FmtFq->fq_base; ++ ++ if (!(flags & QMAN_FQ_FLAG_NO_MODIFY)) { ++ initfq.we_mask = QM_INITFQ_WE_DESTWQ; ++ initfq.fqd.dest.channel = channel; ++ initfq.fqd.dest.wq = wq; ++ ++ _errno = qman_init_fq(fq, QMAN_INITFQ_FLAG_SCHED, &initfq); ++ if (unlikely(_errno < 0)) { ++ REPORT_ERROR(MAJOR, E_NO_MEMORY, ++ ("FQ obj - qman_init_fq!!!")); ++ qman_destroy_fq(fq, 0); ++ XX_Free(p_FmtFq); ++ return NULL; ++ } ++ } ++ ++ DBG(TRACE, ++ ("fqid %d, flags 0x%08x, channel %d, wq %d", qman_fq_fqid(fq), ++ flags, channel, wq)); ++ ++ return fq; ++} ++ ++static void FqFree(struct qman_fq *fq) ++{ ++ int _errno; ++ ++ _errno = qman_retire_fq(fq, NULL); ++ if (unlikely(_errno < 0)) ++ printk(KERN_WARNING "qman_retire_fq(%u) = %d\n", qman_fq_fqid(fq), _errno); ++ ++ _errno = qman_oos_fq(fq); ++ if (unlikely(_errno < 0)) ++ printk(KERN_WARNING "qman_oos_fq(%u) = %d\n", qman_fq_fqid(fq), _errno); ++ ++ qman_destroy_fq(fq, 0); ++ XX_Free((t_FmTestFq *) fq); ++} ++ ++static t_Error QmEnqueueCB(t_Handle h_Arg, void *p_Fd) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *) h_Arg; ++ int _errno, timeout = 1000000; ++ unsigned long flags; ++ ++ ASSERT_COND(p_LnxWrpFmDev); ++ ++ spin_lock_irqsave(&lock, flags); ++ hcFrmRcv++; ++ spin_unlock_irqrestore(&lock, flags); ++ ++ _errno = qman_enqueue(p_LnxWrpFmDev->hc_tx_fq, (struct qm_fd *) p_Fd, ++ 0); ++ if (_errno) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ++ ("qman_enqueue() failed")); ++ ++ while (hcFrmRcv && --timeout) { ++ udelay(1); ++ cpu_relax(); ++ } ++ if (timeout == 0) { ++ dump_stack(); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, ++ ("timeout waiting for Tx confirmation")); ++ return E_WRITE_FAILED; ++ } ++ ++ return E_OK; ++} ++ ++static t_LnxWrpFmPortDev *ReadFmPortDevTreeNode(struct platform_device ++ *of_dev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev; ++ struct device_node *fm_node, *port_node; ++ struct resource res; ++ const uint32_t *uint32_prop; ++ int _errno = 0, lenp; ++#ifdef CONFIG_FMAN_P1023 ++ static unsigned char have_oh_port/* = 0 */; ++#endif ++ ++ port_node = of_node_get(of_dev->dev.of_node); ++ ++ /* Get the FM node */ ++ fm_node = of_get_parent(port_node); ++ if (unlikely(fm_node == NULL)) { ++ REPORT_ERROR(MAJOR, E_NO_DEVICE, ++ ("of_get_parent() = %d", _errno)); ++ return NULL; ++ } ++ ++ p_LnxWrpFmDev = ++ dev_get_drvdata(&of_find_device_by_node(fm_node)->dev); ++ of_node_put(fm_node); ++ ++ /* if fm_probe() failed, no point in going further with port probing */ ++ if (p_LnxWrpFmDev == NULL) ++ return NULL; ++ ++ uint32_prop = ++ (uint32_t *) of_get_property(port_node, "cell-index", &lenp); ++ if (unlikely(uint32_prop == NULL)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("of_get_property(%s, cell-index) failed", ++ port_node->full_name)); ++ return NULL; ++ } ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ return NULL; ++ if (of_device_is_compatible(port_node, "fsl,fman-port-oh")) { ++ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_OH_PORTS)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("of_get_property(%s, cell-index) failed", ++ port_node->full_name)); ++ return NULL; ++ } ++ ++#ifdef CONFIG_FMAN_P1023 ++ /* Beware, this can be done when there is only ++ one FMan to be initialized */ ++ if (!have_oh_port) { ++ have_oh_port = 1; /* first OP/HC port ++ is used for host command */ ++#else ++ /* Here it is hardcoded the use of the OH port 1 ++ (with cell-index 0) */ ++ if (*uint32_prop == 0) { ++#endif ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->hcPort; ++ p_LnxWrpFmPortDev->id = 0; ++ /* ++ p_LnxWrpFmPortDev->id = *uint32_prop-1; ++ p_LnxWrpFmPortDev->id = *uint32_prop; ++ */ ++ p_LnxWrpFmPortDev->settings.param.portType = ++ e_FM_PORT_TYPE_OH_HOST_COMMAND; ++ } else { ++ p_LnxWrpFmPortDev = ++ &p_LnxWrpFmDev->opPorts[*uint32_prop - 1]; ++ p_LnxWrpFmPortDev->id = *uint32_prop - 1; ++ p_LnxWrpFmPortDev->settings.param.portType = ++ e_FM_PORT_TYPE_OH_OFFLINE_PARSING; ++ } ++ p_LnxWrpFmPortDev->settings.param.portId = *uint32_prop; ++ ++ uint32_prop = ++ (uint32_t *) of_get_property(port_node, ++ "fsl,qman-channel-id", ++ &lenp); ++ if (uint32_prop == NULL) { ++ /* ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("missing fsl,qman-channel-id")); ++ */ ++ XX_Print("FM warning: missing fsl,qman-channel-id" ++ " for OH port.\n"); ++ return NULL; ++ } ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ return NULL; ++ p_LnxWrpFmPortDev->txCh = *uint32_prop; ++ ++ p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams. ++ qmChannel = p_LnxWrpFmPortDev->txCh; ++ } else if (of_device_is_compatible(port_node, "fsl,fman-port-1g-tx")) { ++ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_1G_TX_PORTS)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("of_get_property(%s, cell-index) failed", ++ port_node->full_name)); ++ return NULL; ++ } ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[*uint32_prop]; ++ ++ p_LnxWrpFmPortDev->id = *uint32_prop; ++ p_LnxWrpFmPortDev->settings.param.portId = ++ p_LnxWrpFmPortDev->id; ++ p_LnxWrpFmPortDev->settings.param.portType = e_FM_PORT_TYPE_TX; ++ ++ uint32_prop = (uint32_t *) of_get_property(port_node, ++ "fsl,qman-channel-id", &lenp); ++ if (uint32_prop == NULL) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("missing fsl,qman-channel-id")); ++ return NULL; ++ } ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ return NULL; ++ p_LnxWrpFmPortDev->txCh = *uint32_prop; ++ p_LnxWrpFmPortDev-> ++ settings.param.specificParams.nonRxParams.qmChannel = ++ p_LnxWrpFmPortDev->txCh; ++ } else if (of_device_is_compatible(port_node, "fsl,fman-port-10g-tx")) { ++ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_10G_TX_PORTS)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("of_get_property(%s, cell-index) failed", ++ port_node->full_name)); ++ return NULL; ++ } ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[*uint32_prop + ++ FM_MAX_NUM_OF_1G_TX_PORTS]; ++ if (IS_T1023_T1024) ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[*uint32_prop]; ++ ++ p_LnxWrpFmPortDev->id = *uint32_prop; ++ p_LnxWrpFmPortDev->settings.param.portId = ++ p_LnxWrpFmPortDev->id; ++ p_LnxWrpFmPortDev->settings.param.portType = ++ e_FM_PORT_TYPE_TX_10G; ++ uint32_prop = (uint32_t *) of_get_property(port_node, ++ "fsl,qman-channel-id", &lenp); ++ if (uint32_prop == NULL) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("missing fsl,qman-channel-id")); ++ return NULL; ++ } ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ return NULL; ++ p_LnxWrpFmPortDev->txCh = *uint32_prop; ++ p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams. ++ qmChannel = p_LnxWrpFmPortDev->txCh; ++ } else if (of_device_is_compatible(port_node, "fsl,fman-port-1g-rx")) { ++ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_1G_RX_PORTS)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("of_get_property(%s, cell-index) failed", ++ port_node->full_name)); ++ return NULL; ++ } ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[*uint32_prop]; ++ ++ p_LnxWrpFmPortDev->id = *uint32_prop; ++ p_LnxWrpFmPortDev->settings.param.portId = ++ p_LnxWrpFmPortDev->id; ++ p_LnxWrpFmPortDev->settings.param.portType = e_FM_PORT_TYPE_RX; ++ if (p_LnxWrpFmDev->pcdActive) ++ p_LnxWrpFmPortDev->defPcd = p_LnxWrpFmDev->defPcd; ++ } else if (of_device_is_compatible(port_node, "fsl,fman-port-10g-rx")) { ++ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_10G_RX_PORTS)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("of_get_property(%s, cell-index) failed", ++ port_node->full_name)); ++ return NULL; ++ } ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[*uint32_prop + ++ FM_MAX_NUM_OF_1G_RX_PORTS]; ++ ++ if (IS_T1023_T1024) ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[*uint32_prop]; ++ ++ p_LnxWrpFmPortDev->id = *uint32_prop; ++ p_LnxWrpFmPortDev->settings.param.portId = ++ p_LnxWrpFmPortDev->id; ++ p_LnxWrpFmPortDev->settings.param.portType = ++ e_FM_PORT_TYPE_RX_10G; ++ if (p_LnxWrpFmDev->pcdActive) ++ p_LnxWrpFmPortDev->defPcd = p_LnxWrpFmDev->defPcd; ++ } else { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal port type")); ++ return NULL; ++ } ++ ++ _errno = of_address_to_resource(port_node, 0, &res); ++ if (unlikely(_errno < 0)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("of_address_to_resource() = %d", _errno)); ++ return NULL; ++ } ++ ++ p_LnxWrpFmPortDev->dev = &of_dev->dev; ++ p_LnxWrpFmPortDev->baseAddr = 0; ++ p_LnxWrpFmPortDev->phys_baseAddr = res.start; ++ p_LnxWrpFmPortDev->memSize = res.end + 1 - res.start; ++ p_LnxWrpFmPortDev->settings.param.h_Fm = p_LnxWrpFmDev->h_Dev; ++ p_LnxWrpFmPortDev->h_LnxWrpFmDev = (t_Handle) p_LnxWrpFmDev; ++ ++ of_node_put(port_node); ++ ++ p_LnxWrpFmPortDev->active = TRUE; ++ ++#if defined(CONFIG_FMAN_DISABLE_OH_TO_REUSE_RESOURCES) ++ /* for performance mode no OH port available. */ ++ if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ p_LnxWrpFmPortDev->active = FALSE; ++#endif ++ ++ return p_LnxWrpFmPortDev; ++} ++ ++struct device_node * GetFmPortAdvArgsDevTreeNode (struct device_node *fm_node, ++ e_FmPortType portType, ++ uint8_t portId) ++{ ++ struct device_node *port_node; ++ const uint32_t *uint32_prop; ++ int lenp; ++ char *portTypeString; ++ ++ switch(portType) { ++ case e_FM_PORT_TYPE_OH_OFFLINE_PARSING: ++ portTypeString = "fsl,fman-port-op-extended-args"; ++ break; ++ case e_FM_PORT_TYPE_TX: ++ portTypeString = "fsl,fman-port-1g-tx-extended-args"; ++ break; ++ case e_FM_PORT_TYPE_TX_10G: ++ portTypeString = "fsl,fman-port-10g-tx-extended-args"; ++ break; ++ case e_FM_PORT_TYPE_RX: ++ portTypeString = "fsl,fman-port-1g-rx-extended-args"; ++ break; ++ case e_FM_PORT_TYPE_RX_10G: ++ portTypeString = "fsl,fman-port-10g-rx-extended-args"; ++ break; ++ default: ++ return NULL; ++ } ++ ++ for_each_child_of_node(fm_node, port_node) { ++ uint32_prop = (uint32_t *)of_get_property(port_node, "cell-index", &lenp); ++ if (unlikely(uint32_prop == NULL)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ++ ("of_get_property(%s, cell-index) failed", ++ port_node->full_name)); ++ return NULL; ++ } ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ return NULL; ++ if ((portId == *uint32_prop) && ++ (of_device_is_compatible(port_node, portTypeString))) { ++ return port_node; ++ } ++ } ++ ++ return NULL; ++} ++ ++static t_Error CheckNConfigFmPortAdvArgs (t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) ++{ ++ struct device_node *fm_node, *port_node; ++ t_Error err; ++ t_FmPortRsrc portRsrc; ++ const uint32_t *uint32_prop; ++ /*const char *str_prop;*/ ++ int lenp; ++#ifdef CONFIG_FMAN_PFC ++ uint8_t i, id, num_pools; ++ t_FmBufPoolDepletion poolDepletion; ++ ++ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX || ++ p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX_10G) { ++ memset(&poolDepletion, 0, sizeof(t_FmBufPoolDepletion)); ++ poolDepletion.singlePoolModeEnable = true; ++ num_pools = p_LnxWrpFmPortDev->settings.param.specificParams.rxParams. ++ extBufPools.numOfPoolsUsed; ++ for (i = 0; i < num_pools; i++) { ++ id = p_LnxWrpFmPortDev->settings.param.specificParams.rxParams. ++ extBufPools.extBufPool[i].id; ++ poolDepletion.poolsToConsiderForSingleMode[id] = true; ++ } ++ ++ for (i = 0; i < CONFIG_FMAN_PFC_COS_COUNT; i++) ++ poolDepletion.pfcPrioritiesEn[i] = true; ++ ++ err = FM_PORT_ConfigPoolDepletion(p_LnxWrpFmPortDev->h_Dev, ++ &poolDepletion); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, ("FM_PORT_ConfigPoolDepletion() failed")); ++ } ++#endif ++ ++ fm_node = GetFmAdvArgsDevTreeNode(((t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev)->id); ++ if (!fm_node) /* no advance parameters for FMan */ ++ return E_OK; ++ ++ port_node = GetFmPortAdvArgsDevTreeNode(fm_node, ++ p_LnxWrpFmPortDev->settings.param.portType, ++ p_LnxWrpFmPortDev->settings.param.portId); ++ if (!port_node) /* no advance parameters for FMan-Port */ ++ return E_OK; ++ ++ uint32_prop = (uint32_t *)of_get_property(port_node, "num-tnums", &lenp); ++ if (uint32_prop) { ++ if (WARN_ON(lenp != sizeof(uint32_t)*2)) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); ++ ++ portRsrc.num = uint32_prop[0]; ++ portRsrc.extra = uint32_prop[1]; ++ ++ if ((err = FM_PORT_ConfigNumOfTasks(p_LnxWrpFmPortDev->h_Dev, ++ &portRsrc)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ uint32_prop = (uint32_t *)of_get_property(port_node, "num-dmas", &lenp); ++ if (uint32_prop) { ++ if (WARN_ON(lenp != sizeof(uint32_t)*2)) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); ++ ++ portRsrc.num = uint32_prop[0]; ++ portRsrc.extra = uint32_prop[1]; ++ ++ if ((err = FM_PORT_ConfigNumOfOpenDmas(p_LnxWrpFmPortDev->h_Dev, ++ &portRsrc)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ uint32_prop = (uint32_t *)of_get_property(port_node, "fifo-size", &lenp); ++ if (uint32_prop) { ++ if (WARN_ON(lenp != sizeof(uint32_t)*2)) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); ++ ++ portRsrc.num = uint32_prop[0]; ++ portRsrc.extra = uint32_prop[1]; ++ ++ if ((err = FM_PORT_ConfigSizeOfFifo(p_LnxWrpFmPortDev->h_Dev, ++ &portRsrc)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ uint32_prop = (uint32_t *)of_get_property(port_node, "errors-to-discard", &lenp); ++ if (uint32_prop) { ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); ++ if ((err = FM_PORT_ConfigErrorsToDiscard(p_LnxWrpFmPortDev->h_Dev, ++ uint32_prop[0])) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ uint32_prop = (uint32_t *)of_get_property(port_node, "ar-tables-sizes", ++ &lenp); ++ if (uint32_prop) { ++ ++ if (WARN_ON(lenp != sizeof(uint32_t)*8)) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); ++ if (WARN_ON(p_LnxWrpFmPortDev->settings.param.portType != ++ e_FM_PORT_TYPE_RX) && ++ (p_LnxWrpFmPortDev->settings.param.portType != ++ e_FM_PORT_TYPE_RX_10G)) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, ++ ("Auto Response is an Rx port atribute.")); ++ ++ memset(&p_LnxWrpFmPortDev->dsar_table_sizes, 0, sizeof(struct auto_res_tables_sizes)); ++ ++ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_arp_entries = ++ (uint16_t)uint32_prop[0]; ++ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_echo_ipv4_entries = ++ (uint16_t)uint32_prop[1]; ++ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_ndp_entries = ++ (uint16_t)uint32_prop[2]; ++ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_echo_ipv6_entries = ++ (uint16_t)uint32_prop[3]; ++ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_snmp_ipv4_entries = ++ (uint16_t)uint32_prop[4]; ++ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_snmp_ipv6_entries = ++ (uint16_t)uint32_prop[5]; ++ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_snmp_oid_entries = ++ (uint16_t)uint32_prop[6]; ++ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_snmp_char = ++ (uint16_t)uint32_prop[7]; ++ uint32_prop = (uint32_t *)of_get_property(port_node, ++ "ar-filters-sizes", &lenp); ++ if (uint32_prop) { ++ if (WARN_ON(lenp != sizeof(uint32_t)*3)) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); ++ ++ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_ip_prot_filtering = ++ (uint16_t)uint32_prop[0]; ++ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_tcp_port_filtering = ++ (uint16_t)uint32_prop[1]; ++ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_udp_port_filtering = ++ (uint16_t)uint32_prop[2]; ++ } ++ ++ if ((err = FM_PORT_ConfigDsarSupport(p_LnxWrpFmPortDev->h_Dev, ++ (t_FmPortDsarTablesSizes*)&p_LnxWrpFmPortDev->dsar_table_sizes)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++ ++ of_node_put(port_node); ++ of_node_put(fm_node); ++ ++ return E_OK; ++} ++ ++static t_Error CheckNSetFmPortAdvArgs (t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) ++{ ++ struct device_node *fm_node, *port_node; ++ t_Error err; ++ const uint32_t *uint32_prop; ++ /*const char *str_prop;*/ ++ int lenp; ++ ++ fm_node = GetFmAdvArgsDevTreeNode(((t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev)->id); ++ if (!fm_node) /* no advance parameters for FMan */ ++ return E_OK; ++ ++ port_node = GetFmPortAdvArgsDevTreeNode(fm_node, ++ p_LnxWrpFmPortDev->settings.param.portType, ++ p_LnxWrpFmPortDev->settings.param.portId); ++ if (!port_node) /* no advance parameters for FMan-Port */ ++ return E_OK; ++ ++#if (DPAA_VERSION >= 11) ++ uint32_prop = (uint32_t *)of_get_property(port_node, "vsp-window", &lenp); ++ if (uint32_prop) { ++ t_FmPortVSPAllocParams portVSPAllocParams; ++ t_FmVspParams fmVspParams; ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ uint8_t portId; ++ ++ p_LnxWrpFmDev = ((t_LnxWrpFmDev *)p_LnxWrpFmPortDev->h_LnxWrpFmDev); ++ ++ if (WARN_ON(lenp != sizeof(uint32_t)*2)) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); ++ ++ if ((p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_TX) || ++ (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_TX_10G) || ++ ((p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) && ++ p_LnxWrpFmPortDev->settings.frag_enabled)) ++ return E_OK; ++ ++ memset(&portVSPAllocParams, 0, sizeof(portVSPAllocParams)); ++ memset(&fmVspParams, 0, sizeof(fmVspParams)); ++ ++ portVSPAllocParams.numOfProfiles = (uint8_t)uint32_prop[0]; ++ portVSPAllocParams.dfltRelativeId = (uint8_t)uint32_prop[1]; ++ fmVspParams.h_Fm = p_LnxWrpFmDev->h_Dev; ++ ++ fmVspParams.portParams.portType = p_LnxWrpFmPortDev->settings.param.portType; ++ fmVspParams.portParams.portId = p_LnxWrpFmPortDev->settings.param.portId; ++ fmVspParams.relativeProfileId = portVSPAllocParams.dfltRelativeId; ++ ++ if (p_LnxWrpFmPortDev->settings.param.portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ++ { ++ portId = fmVspParams.portParams.portId; ++ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX_10G){ ++ if (!(IS_T1023_T1024)) ++ portId += FM_MAX_NUM_OF_1G_RX_PORTS; ++ } ++ portVSPAllocParams.h_FmTxPort = ++ p_LnxWrpFmDev->txPorts[portId].h_Dev; ++ fmVspParams.liodnOffset = ++ p_LnxWrpFmDev->rxPorts[portId].settings.param.specificParams.rxParams.liodnOffset; ++ memcpy(&fmVspParams.extBufPools, ++ &p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.extBufPools, ++ sizeof(t_FmExtPools)); ++ } ++ else ++ { ++ memcpy(&fmVspParams.extBufPools, ++ &p_LnxWrpFmPortDev->opExtPools, ++ sizeof(t_FmExtPools)); ++ } ++ ++ if ((err = FM_PORT_VSPAlloc(p_LnxWrpFmPortDev->h_Dev, ++ &portVSPAllocParams)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ /* We're initializing only the default VSP that are being used by the Linux-Ethernet-driver */ ++ if ((p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) && ++ !p_LnxWrpFmPortDev->opExtPools.numOfPoolsUsed) ++ return E_OK; ++ ++ p_LnxWrpFmPortDev->h_DfltVsp = FM_VSP_Config(&fmVspParams); ++ if (!p_LnxWrpFmPortDev->h_DfltVsp) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("default-VSP for port!")); ++ ++ if ((err = FM_VSP_ConfigBufferPrefixContent(p_LnxWrpFmPortDev->h_DfltVsp, ++ &p_LnxWrpFmPortDev->buffPrefixContent)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ ++ if ((err = FM_VSP_Init(p_LnxWrpFmPortDev->h_DfltVsp)) != E_OK) ++ RETURN_ERROR(MINOR, err, NO_MSG); ++ } ++#else ++UNUSED(err); UNUSED(uint32_prop); UNUSED(lenp); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ of_node_put(port_node); ++ of_node_put(fm_node); ++ ++ return E_OK; ++} ++ ++static t_Error ConfigureFmPortDev(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = ++ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ struct resource *dev_res; ++ ++ if (!p_LnxWrpFmPortDev->active) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("FM port not configured!!!")); ++ ++ dev_res = ++ __devm_request_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, ++ p_LnxWrpFmPortDev->phys_baseAddr, ++ p_LnxWrpFmPortDev->memSize, ++ "fman-port-hc"); ++ if (unlikely(dev_res == NULL)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, ++ ("__devm_request_region() failed")); ++ p_LnxWrpFmPortDev->baseAddr = ++ PTR_TO_UINT(devm_ioremap ++ (p_LnxWrpFmDev->dev, ++ p_LnxWrpFmPortDev->phys_baseAddr, ++ p_LnxWrpFmPortDev->memSize)); ++ if (unlikely(p_LnxWrpFmPortDev->baseAddr == 0)) ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ++ ("devm_ioremap() failed")); ++ ++ p_LnxWrpFmPortDev->settings.param.baseAddr = ++ p_LnxWrpFmPortDev->baseAddr; ++ ++ return E_OK; ++} ++ ++static t_Error InitFmPortDev(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) ++{ ++#define MY_ADV_CONFIG_CHECK_END \ ++ RETURN_ERROR(MAJOR, E_INVALID_SELECTION,\ ++ ("Advanced configuration routine"));\ ++ if (errCode != E_OK)\ ++ RETURN_ERROR(MAJOR, errCode, NO_MSG);\ ++ } ++ ++ int i = 0; ++ ++ if (!p_LnxWrpFmPortDev->active || p_LnxWrpFmPortDev->h_Dev) ++ return E_INVALID_STATE; ++ ++ p_LnxWrpFmPortDev->h_Dev = ++ FM_PORT_Config(&p_LnxWrpFmPortDev->settings.param); ++ if (p_LnxWrpFmPortDev->h_Dev == NULL) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM-port")); ++ ++#ifndef FM_QMI_NO_DEQ_OPTIONS_SUPPORT ++ if ((p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_TX_10G) ++ || (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_TX)) { ++ t_Error errCode = E_OK; ++ errCode = ++ FM_PORT_ConfigDeqHighPriority(p_LnxWrpFmPortDev->h_Dev, ++ TRUE); ++ if (errCode != E_OK) ++ RETURN_ERROR(MAJOR, errCode, NO_MSG); ++ errCode = ++ FM_PORT_ConfigDeqPrefetchOption(p_LnxWrpFmPortDev->h_Dev, ++ e_FM_PORT_DEQ_FULL_PREFETCH); ++ if (errCode ++ != E_OK) ++ RETURN_ERROR(MAJOR, errCode, NO_MSG); ++ } ++#endif /* !FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ ++ ++#ifdef FM_BCB_ERRATA_BMI_SW001 ++/* Configure BCB workaround on Rx ports, only for B4860 rev1 */ ++#define SVR_SECURITY_MASK 0x00080000 ++#define SVR_PERSONALITY_MASK 0x0000FF00 ++#define SVR_VER_IGNORE_MASK (SVR_SECURITY_MASK | SVR_PERSONALITY_MASK) ++#define SVR_B4860_REV1_VALUE 0x86800010 ++ ++ if ((p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_RX_10G) || ++ (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_RX)) { ++ unsigned int svr; ++ ++ svr = mfspr(SPRN_SVR); ++ ++ if ((svr & ~SVR_VER_IGNORE_MASK) == SVR_B4860_REV1_VALUE) ++ FM_PORT_ConfigBCBWorkaround(p_LnxWrpFmPortDev->h_Dev); ++ } ++#endif /* FM_BCB_ERRATA_BMI_SW001 */ ++ ++/* Call the driver's advanced configuration routines, if requested: ++ Compare the function pointer of each entry to the available routines, ++ and invoke the matching routine with proper casting of arguments. */ ++ while (p_LnxWrpFmPortDev->settings.advConfig[i].p_Function ++ && (i < FM_MAX_NUM_OF_ADV_SETTINGS)) { ++ ++/* TODO: Change this MACRO */ ++ ADV_CONFIG_CHECK_START( ++ &(p_LnxWrpFmPortDev->settings.advConfig[i])) ++ ++ ADV_CONFIG_CHECK(p_LnxWrpFmPortDev->h_Dev, ++ FM_PORT_ConfigBufferPrefixContent, ++ NCSW_PARAMS(1, ++ (t_FmBufferPrefixContent *))) ++ ++ if ((p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_OH_OFFLINE_PARSING) && ++ (p_LnxWrpFmPortDev->settings.frag_enabled == TRUE)) { ++ ++ ADV_CONFIG_CHECK(p_LnxWrpFmPortDev->h_Dev, ++ FM_PORT_ConfigExtBufPools, ++ NCSW_PARAMS(1, (t_FmExtPools *))) ++ ++ /* this define contains an else */ ++ MY_ADV_CONFIG_CHECK_END ++ } ++ ++ /* Advance to next advanced configuration entry */ ++ i++; ++ } ++ ++ ++ if ((p_LnxWrpFmPortDev->settings.param.portType != e_FM_PORT_TYPE_TX) && ++ (p_LnxWrpFmPortDev->settings.param.portType != e_FM_PORT_TYPE_TX_10G)) { ++ if (FM_PORT_ConfigErrorsToDiscard(p_LnxWrpFmPortDev->h_Dev, (FM_PORT_FRM_ERR_IPRE | ++ FM_PORT_FRM_ERR_IPR_NCSP | ++ FM_PORT_FRM_ERR_CLS_DISCARD)) !=E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ } ++ ++ if (CheckNConfigFmPortAdvArgs(p_LnxWrpFmPortDev) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ if (FM_PORT_Init(p_LnxWrpFmPortDev->h_Dev) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++ if (CheckNSetFmPortAdvArgs(p_LnxWrpFmPortDev) != E_OK) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++ ++/* FMan Fifo sizes behind the scene": ++ * Using the following formulae (*), under a set of simplifying assumptions (.): ++ * . all ports are configured in Normal Mode (rather than Independent Mode) ++ * . the DPAA Eth driver allocates buffers of size: ++ * . MAXFRM + NET_IP_ALIGN + DPA_PRIV_DATA_SIZE + DPA_PARSE_RESULTS_SIZE ++ * + DPA_HASH_RESULTS_SIZE, i.e.: ++ * MAXFRM + 2 + 16 + sizeof(t_FmPrsResult) + 16, i.e.: ++ * MAXFRM + 66 ++ * . excessive buffer pools not accounted for ++ * ++ * * for Rx ports on P4080: ++ * . IFSZ = ceil(max(FMBM_EBMPI[PBS]) / 256) * 256 + 7 * 256 ++ * . no internal frame offset (FMBM_RIM[FOF] == 0) - otherwise, ++ * add up to 256 to the above ++ * ++ * * for Rx ports on P1023: ++ * . IFSZ = ceil(second_largest(FMBM_EBMPI[PBS] / 256)) * 256 + 7 * 256, ++ * if at least 2 bpools are configured ++ * . IFSZ = 8 * 256, if only a single bpool is configured ++ * ++ * * for Tx ports: ++ * . IFSZ = ceil(frame_size / 256) * 256 + 3 * 256 ++ * + FMBM_TFP[DPDE] * 256, i.e.: ++ * IFSZ = ceil(MAXFRM / 256) * 256 + 3 x 256 + FMBM_TFP[DPDE] * 256 ++ * ++ * * for OH ports on P4080: ++ * . IFSZ = ceil(frame_size / 256) * 256 + 1 * 256 + FMBM_PP[MXT] * 256 ++ * * for OH ports on P1023: ++ * . IFSZ = ceil(frame_size / 256) * 256 + 3 * 256 + FMBM_TFP[DPDE] * 256 ++ * * for both P4080 and P1023: ++ * . (conservative decisions, assuming that BMI must bring the entire ++ * frame, not only the frame header) ++ * . no internal frame offset (FMBM_OIM[FOF] == 0) - otherwise, ++ * add up to 256 to the above ++ * ++ * . for P4080/P5020/P3041/P2040, DPDE is: ++ * > 0 or 1, for 1Gb ports, HW default: 0 ++ * > 2..7 (recommended: 3..7) for 10Gb ports, HW default: 3 ++ * . for P1023, DPDE should be 1 ++ * ++ * . for P1023, MXT is in range (0..31) ++ * . for P4080, MXT is in range (0..63) ++ * ++ */ ++#if 0 ++ if ((p_LnxWrpFmPortDev->defPcd != e_NO_PCD) && ++ (InitFmPort3TupleDefPcd(p_LnxWrpFmPortDev) != E_OK)) ++ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); ++#endif ++ return E_OK; ++} ++ ++void fm_set_rx_port_params(struct fm_port *port, ++ struct fm_port_params *params) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) port; ++ int i; ++ ++ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.errFqid = ++ params->errq; ++ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.dfltFqid = ++ params->defq; ++ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.extBufPools. ++ numOfPoolsUsed = params->num_pools; ++ for (i = 0; i < params->num_pools; i++) { ++ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams. ++ extBufPools.extBufPool[i].id = ++ params->pool_param[i].id; ++ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams. ++ extBufPools.extBufPool[i].size = ++ params->pool_param[i].size; ++ } ++ ++ p_LnxWrpFmPortDev->buffPrefixContent.privDataSize = ++ params->priv_data_size; ++ p_LnxWrpFmPortDev->buffPrefixContent.passPrsResult = ++ params->parse_results; ++ p_LnxWrpFmPortDev->buffPrefixContent.passHashResult = ++ params->hash_results; ++ p_LnxWrpFmPortDev->buffPrefixContent.passTimeStamp = ++ params->time_stamp; ++ p_LnxWrpFmPortDev->buffPrefixContent.dataAlign = ++ params->data_align; ++ p_LnxWrpFmPortDev->buffPrefixContent.manipExtraSpace = ++ params->manip_extra_space; ++ ++ ADD_ADV_CONFIG_START(p_LnxWrpFmPortDev->settings.advConfig, ++ FM_MAX_NUM_OF_ADV_SETTINGS) ++ ++ ADD_ADV_CONFIG_NO_RET(FM_PORT_ConfigBufferPrefixContent, ++ ARGS(1, ++ (&p_LnxWrpFmPortDev-> ++ buffPrefixContent))); ++ ++ ADD_ADV_CONFIG_END InitFmPortDev(p_LnxWrpFmPortDev); ++} ++EXPORT_SYMBOL(fm_set_rx_port_params); ++ ++/* this function is called from oh_probe as well, thus it contains oh port ++ * specific parameters (make sure everything is checked) */ ++void fm_set_tx_port_params(struct fm_port *port, ++ struct fm_port_params *params) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) port; ++ ++ p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams.errFqid = ++ params->errq; ++ p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams. ++ dfltFqid = params->defq; ++ ++ p_LnxWrpFmPortDev->buffPrefixContent.privDataSize = ++ params->priv_data_size; ++ p_LnxWrpFmPortDev->buffPrefixContent.passPrsResult = ++ params->parse_results; ++ p_LnxWrpFmPortDev->buffPrefixContent.passHashResult = ++ params->hash_results; ++ p_LnxWrpFmPortDev->buffPrefixContent.passTimeStamp = ++ params->time_stamp; ++ p_LnxWrpFmPortDev->settings.frag_enabled = ++ params->frag_enable; ++ p_LnxWrpFmPortDev->buffPrefixContent.dataAlign = ++ params->data_align; ++ p_LnxWrpFmPortDev->buffPrefixContent.manipExtraSpace = ++ params->manip_extra_space; ++ ++ ADD_ADV_CONFIG_START(p_LnxWrpFmPortDev->settings.advConfig, ++ FM_MAX_NUM_OF_ADV_SETTINGS) ++ ++ ADD_ADV_CONFIG_NO_RET(FM_PORT_ConfigBufferPrefixContent, ++ ARGS(1, ++ (&p_LnxWrpFmPortDev-> ++ buffPrefixContent))); ++ ++ /* oh port specific parameter (for fragmentation only) */ ++ if ((p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_OH_OFFLINE_PARSING) && ++ params->num_pools) { ++ int i; ++ ++ p_LnxWrpFmPortDev->opExtPools.numOfPoolsUsed = params->num_pools; ++ for (i = 0; i < params->num_pools; i++) { ++ p_LnxWrpFmPortDev->opExtPools.extBufPool[i].id = params->pool_param[i].id; ++ p_LnxWrpFmPortDev->opExtPools.extBufPool[i].size = params->pool_param[i].size; ++ } ++ ++ if (p_LnxWrpFmPortDev->settings.frag_enabled) ++ ADD_ADV_CONFIG_NO_RET(FM_PORT_ConfigExtBufPools, ++ ARGS(1, (&p_LnxWrpFmPortDev->opExtPools))); ++ } ++ ++ ADD_ADV_CONFIG_END InitFmPortDev(p_LnxWrpFmPortDev); ++} ++EXPORT_SYMBOL(fm_set_tx_port_params); ++ ++void fm_mac_set_handle(t_Handle h_lnx_wrp_fm_dev, ++ t_Handle h_fm_mac, ++ int mac_id) ++{ ++ t_LnxWrpFmDev *p_lnx_wrp_fm_dev = (t_LnxWrpFmDev *)h_lnx_wrp_fm_dev; ++ ++ p_lnx_wrp_fm_dev->macs[mac_id].h_Dev = h_fm_mac; ++ p_lnx_wrp_fm_dev->macs[mac_id].h_LnxWrpFmDev = h_lnx_wrp_fm_dev; ++} ++EXPORT_SYMBOL(fm_mac_set_handle); ++ ++static void LnxwrpFmPcdDevExceptionsCb(t_Handle h_App, ++ e_FmPcdExceptions exception) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *) h_App; ++ ++ ASSERT_COND(p_LnxWrpFmDev); ++ ++ DBG(INFO, ("got fm-pcd exception %d", exception)); ++ ++ /* do nothing */ ++ UNUSED(exception); ++} ++ ++static void LnxwrpFmPcdDevIndexedExceptionsCb(t_Handle h_App, ++ e_FmPcdExceptions exception, ++ uint16_t index) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *) h_App; ++ ++ ASSERT_COND(p_LnxWrpFmDev); ++ ++ DBG(INFO, ++ ("got fm-pcd-indexed exception %d, indx %d", exception, index)); ++ ++ /* do nothing */ ++ UNUSED(exception); ++ UNUSED(index); ++} ++ ++static t_Error InitFmPcdDev(t_LnxWrpFmDev *p_LnxWrpFmDev) ++{ ++ spin_lock_init(&lock); ++ ++ if (p_LnxWrpFmDev->pcdActive) { ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = &p_LnxWrpFmDev->hcPort; ++ t_FmPcdParams fmPcdParams; ++ t_Error err; ++ ++ memset(&fmPcdParams, 0, sizeof(fmPcdParams)); ++ fmPcdParams.h_Fm = p_LnxWrpFmDev->h_Dev; ++ fmPcdParams.prsSupport = p_LnxWrpFmDev->prsActive; ++ fmPcdParams.kgSupport = p_LnxWrpFmDev->kgActive; ++ fmPcdParams.plcrSupport = p_LnxWrpFmDev->plcrActive; ++ fmPcdParams.ccSupport = p_LnxWrpFmDev->ccActive; ++ fmPcdParams.numOfSchemes = FM_PCD_KG_NUM_OF_SCHEMES; ++ ++#ifndef CONFIG_GUEST_PARTITION ++ fmPcdParams.f_Exception = LnxwrpFmPcdDevExceptionsCb; ++ if (fmPcdParams.kgSupport) ++ fmPcdParams.f_ExceptionId = ++ LnxwrpFmPcdDevIndexedExceptionsCb; ++ fmPcdParams.h_App = p_LnxWrpFmDev; ++#endif /* !CONFIG_GUEST_PARTITION */ ++ ++#ifdef CONFIG_MULTI_PARTITION_SUPPORT ++ fmPcdParams.numOfSchemes = 0; ++ fmPcdParams.numOfClsPlanEntries = 0; ++ fmPcdParams.partitionId = 0; ++#endif /* CONFIG_MULTI_PARTITION_SUPPORT */ ++ fmPcdParams.useHostCommand = TRUE; ++ ++ p_LnxWrpFmDev->hc_tx_fq = ++ FqAlloc(p_LnxWrpFmDev, ++ 0, ++ QMAN_FQ_FLAG_TO_DCPORTAL, ++ p_LnxWrpFmPortDev->txCh, 0); ++ if (!p_LnxWrpFmDev->hc_tx_fq) ++ RETURN_ERROR(MAJOR, E_NULL_POINTER, ++ ("Frame queue allocation failed...")); ++ ++ p_LnxWrpFmDev->hc_tx_conf_fq = ++ FqAlloc(p_LnxWrpFmDev, ++ 0, ++ QMAN_FQ_FLAG_NO_ENQUEUE, ++ p_LnxWrpFmDev->hcCh, 7); ++ if (!p_LnxWrpFmDev->hc_tx_conf_fq) ++ RETURN_ERROR(MAJOR, E_NULL_POINTER, ++ ("Frame queue allocation failed...")); ++ ++ p_LnxWrpFmDev->hc_tx_err_fq = ++ FqAlloc(p_LnxWrpFmDev, ++ 0, ++ QMAN_FQ_FLAG_NO_ENQUEUE, ++ p_LnxWrpFmDev->hcCh, 7); ++ if (!p_LnxWrpFmDev->hc_tx_err_fq) ++ RETURN_ERROR(MAJOR, E_NULL_POINTER, ++ ("Frame queue allocation failed...")); ++ ++ fmPcdParams.hc.portBaseAddr = p_LnxWrpFmPortDev->baseAddr; ++ fmPcdParams.hc.portId = ++ p_LnxWrpFmPortDev->settings.param.portId; ++ fmPcdParams.hc.liodnBase = ++ p_LnxWrpFmPortDev->settings.param.liodnBase; ++ fmPcdParams.hc.errFqid = ++ qman_fq_fqid(p_LnxWrpFmDev->hc_tx_err_fq); ++ fmPcdParams.hc.confFqid = ++ qman_fq_fqid(p_LnxWrpFmDev->hc_tx_conf_fq); ++ fmPcdParams.hc.qmChannel = p_LnxWrpFmPortDev->txCh; ++ fmPcdParams.hc.f_QmEnqueue = QmEnqueueCB; ++ fmPcdParams.hc.h_QmArg = (t_Handle) p_LnxWrpFmDev; ++ ++ p_LnxWrpFmDev->h_PcdDev = FM_PCD_Config(&fmPcdParams); ++ if (!p_LnxWrpFmDev->h_PcdDev) ++ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM PCD!")); ++ ++ err = ++ FM_PCD_ConfigPlcrNumOfSharedProfiles(p_LnxWrpFmDev->h_PcdDev, ++ LNXWRP_FM_NUM_OF_SHARED_PROFILES); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ err = FM_PCD_Init(p_LnxWrpFmDev->h_PcdDev); ++ if (err != E_OK) ++ RETURN_ERROR(MAJOR, err, NO_MSG); ++ ++ if (p_LnxWrpFmDev->err_irq == 0) { ++ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, ++ e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC, ++ FALSE); ++ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, ++ e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW, ++ FALSE); ++ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, ++ e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR, ++ FALSE); ++ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, ++ e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC, ++ FALSE); ++ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, ++ e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC, ++ FALSE); ++ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, ++ e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE, ++ FALSE); ++ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, ++ e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE, ++ FALSE); ++ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, ++ e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC, ++ FALSE); ++ } ++ } ++ ++ return E_OK; ++} ++ ++void FreeFmPcdDev(t_LnxWrpFmDev *p_LnxWrpFmDev) ++{ ++ ++ if (p_LnxWrpFmDev->h_PcdDev) ++ FM_PCD_Free(p_LnxWrpFmDev->h_PcdDev); ++ ++ if (p_LnxWrpFmDev->hc_tx_err_fq) ++ FqFree(p_LnxWrpFmDev->hc_tx_err_fq); ++ ++ if (p_LnxWrpFmDev->hc_tx_conf_fq) ++ FqFree(p_LnxWrpFmDev->hc_tx_conf_fq); ++ ++ if (p_LnxWrpFmDev->hc_tx_fq) ++ FqFree(p_LnxWrpFmDev->hc_tx_fq); ++} ++ ++static void FreeFmPortDev(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = ++ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ ++ if (!p_LnxWrpFmPortDev->active) ++ return; ++ ++ if (p_LnxWrpFmPortDev->h_Dev) ++ FM_PORT_Free(p_LnxWrpFmPortDev->h_Dev); ++ ++ devm_iounmap(p_LnxWrpFmDev->dev, ++ UINT_TO_PTR(p_LnxWrpFmPortDev->baseAddr)); ++ __devm_release_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, ++ p_LnxWrpFmPortDev->phys_baseAddr, ++ p_LnxWrpFmPortDev->memSize); ++} ++ ++static int /*__devinit*/ fm_port_probe(struct platform_device *of_dev) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev; ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ struct device *dev; ++ ++ dev = &of_dev->dev; ++ ++ p_LnxWrpFmPortDev = ReadFmPortDevTreeNode(of_dev); ++ if (p_LnxWrpFmPortDev == NULL) ++ return -EIO; ++ /* Port can be inactive, thus will not be probed: ++ - in performance mode, OH ports are disabled ++ ... ++ */ ++ if (!p_LnxWrpFmPortDev->active) ++ return 0; ++ ++ if (ConfigureFmPortDev(p_LnxWrpFmPortDev) != E_OK) ++ return -EIO; ++ ++ dev_set_drvdata(dev, p_LnxWrpFmPortDev); ++ ++ if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_OH_HOST_COMMAND) ++ InitFmPcdDev((t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev); ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ ++ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX) { ++ Sprint(p_LnxWrpFmPortDev->name, "%s-port-rx%d", ++ p_LnxWrpFmDev->name, p_LnxWrpFmPortDev->id); ++ p_LnxWrpFmPortDev->minor = ++ p_LnxWrpFmPortDev->id + DEV_FM_RX_PORTS_MINOR_BASE; ++ } else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_RX_10G) { ++ Sprint(p_LnxWrpFmPortDev->name, "%s-port-rx%d", ++ p_LnxWrpFmDev->name, ++ p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_RX_PORTS); ++ p_LnxWrpFmPortDev->minor = ++ p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_RX_PORTS + ++ DEV_FM_RX_PORTS_MINOR_BASE; ++ if (IS_T1023_T1024) { ++ Sprint(p_LnxWrpFmPortDev->name, "%s-port-rx%d", ++ p_LnxWrpFmDev->name, ++ p_LnxWrpFmPortDev->id); ++ p_LnxWrpFmPortDev->minor = ++ p_LnxWrpFmPortDev->id + ++ DEV_FM_RX_PORTS_MINOR_BASE; ++ } ++ } else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_TX) { ++ Sprint(p_LnxWrpFmPortDev->name, "%s-port-tx%d", ++ p_LnxWrpFmDev->name, p_LnxWrpFmPortDev->id); ++ p_LnxWrpFmPortDev->minor = ++ p_LnxWrpFmPortDev->id + DEV_FM_TX_PORTS_MINOR_BASE; ++ } else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_TX_10G) { ++ Sprint(p_LnxWrpFmPortDev->name, "%s-port-tx%d", ++ p_LnxWrpFmDev->name, ++ p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_TX_PORTS); ++ p_LnxWrpFmPortDev->minor = ++ p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_TX_PORTS + ++ DEV_FM_TX_PORTS_MINOR_BASE; ++ if (IS_T1023_T1024) { ++ Sprint(p_LnxWrpFmPortDev->name, "%s-port-tx%d", ++ p_LnxWrpFmDev->name, ++ p_LnxWrpFmPortDev->id); ++ p_LnxWrpFmPortDev->minor = ++ p_LnxWrpFmPortDev->id + ++ DEV_FM_TX_PORTS_MINOR_BASE; ++ } ++ } else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_OH_HOST_COMMAND) { ++ Sprint(p_LnxWrpFmPortDev->name, "%s-port-oh%d", ++ p_LnxWrpFmDev->name, p_LnxWrpFmPortDev->id); ++ p_LnxWrpFmPortDev->minor = ++ p_LnxWrpFmPortDev->id + DEV_FM_OH_PORTS_MINOR_BASE; ++ } else if (p_LnxWrpFmPortDev->settings.param.portType == ++ e_FM_PORT_TYPE_OH_OFFLINE_PARSING) { ++ Sprint(p_LnxWrpFmPortDev->name, "%s-port-oh%d", ++ p_LnxWrpFmDev->name, p_LnxWrpFmPortDev->id + 1); ++ p_LnxWrpFmPortDev->minor = ++ p_LnxWrpFmPortDev->id + 1 + ++ DEV_FM_OH_PORTS_MINOR_BASE; ++ } ++ ++ device_create(p_LnxWrpFmDev->fm_class, NULL, ++ MKDEV(p_LnxWrpFmDev->major, p_LnxWrpFmPortDev->minor), ++ NULL, p_LnxWrpFmPortDev->name); ++ ++ /* create sysfs entries for stats and regs */ ++ ++ if (fm_port_sysfs_create(dev) != 0) { ++ FreeFmPortDev(p_LnxWrpFmPortDev); ++ REPORT_ERROR(MAJOR, E_INVALID_STATE, ++ ("Unable to create sys entry - fm port!!!")); ++ return -EIO; ++ } ++ ++#ifdef FM_TX_INVALID_ECC_ERRATA_10GMAC_A009 ++ FM_DisableRamsEcc(p_LnxWrpFmDev->h_Dev); ++#endif /* FM_TX_INVALID_ECC_ERRATA_10GMAC_A009 */ ++ ++ DBG(TRACE, ("%s probed", p_LnxWrpFmPortDev->name)); ++ ++ return 0; ++} ++ ++static int fm_port_remove(struct platform_device *of_dev) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev; ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ struct device *dev; ++ ++ dev = &of_dev->dev; ++ p_LnxWrpFmPortDev = dev_get_drvdata(dev); ++ ++ fm_port_sysfs_destroy(dev); ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ device_destroy(p_LnxWrpFmDev->fm_class, ++ MKDEV(p_LnxWrpFmDev->major, p_LnxWrpFmPortDev->minor)); ++ ++ FreeFmPortDev(p_LnxWrpFmPortDev); ++ ++ dev_set_drvdata(dev, NULL); ++ ++ return 0; ++} ++ ++static const struct of_device_id fm_port_match[] = { ++ { ++ .compatible = "fsl,fman-port-oh"}, ++ { ++ .compatible = "fsl,fman-port-1g-rx"}, ++ { ++ .compatible = "fsl,fman-port-10g-rx"}, ++ { ++ .compatible = "fsl,fman-port-1g-tx"}, ++ { ++ .compatible = "fsl,fman-port-10g-tx"}, ++ {} ++}; ++ ++#ifndef MODULE ++MODULE_DEVICE_TABLE(of, fm_port_match); ++#endif /* !MODULE */ ++ ++static struct platform_driver fm_port_driver = { ++ ++ .driver = { ++ .name = "fsl-fman-port", ++ .of_match_table = fm_port_match, ++ .owner = THIS_MODULE, ++ }, ++ .probe = fm_port_probe, ++ .remove = fm_port_remove ++}; ++ ++ ++t_Error LNXWRP_FM_Port_Init(void) ++{ ++ /* Register to the DTB for basic FM port API */ ++ if (platform_driver_register(&fm_port_driver)) ++ return E_NO_DEVICE; ++ ++ return E_OK; ++} ++ ++void LNXWRP_FM_Port_Free(void) ++{ ++ platform_driver_unregister(&fm_port_driver); ++} ++ ++static int __init __cold fm_port_load(void) ++{ ++ if (LNXWRP_FM_Port_Init() != E_OK) { ++ printk(KERN_CRIT "Failed to init FM Ports wrapper!\n"); ++ return -ENODEV; ++ } ++ ++ printk(KERN_CRIT "Freescale FM Ports module\n"); ++ ++ return 0; ++} ++ ++static void __exit __cold fm_port_unload(void) ++{ ++ LNXWRP_FM_Port_Free(); ++} ++ ++module_init(fm_port_load); ++module_exit(fm_port_unload); +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c +new file mode 100644 +index 0000000..fcc0198 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c +@@ -0,0 +1,4799 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/* ++ @File lnxwrp_ioctls_fm.c ++ @Author Shlomi Gridish ++ @Description FM Linux wrapper functions. ++*/ ++ ++/* Linux Headers ------------------- */ ++#include ++ ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#include ++#endif /* MODVERSIONS */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(CONFIG_COMPAT) ++#include ++#endif ++ ++#include "part_ext.h" ++#include "fm_ioctls.h" ++#include "fm_pcd_ioctls.h" ++#include "fm_port_ioctls.h" ++#include "fm_vsp_ext.h" ++ ++#define IS_T1023_T1024 (SVR_SOC_VER(mfspr(SPRN_SVR)) == SVR_T1024 || \ ++ SVR_SOC_VER(mfspr(SPRN_SVR)) == SVR_T1023) ++ ++#define __ERR_MODULE__ MODULE_FM ++ ++#if defined(CONFIG_COMPAT) ++#include "lnxwrp_ioctls_fm_compat.h" ++#endif ++ ++#include "lnxwrp_fm.h" ++ ++#define CMP_IOC_DEFINE(def) (IOC_##def != def) ++ ++/* fm_pcd_ioctls.h === fm_pcd_ext.h assertions */ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_PRIVATE_HDRS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_PRS_NUM_OF_HDRS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_KG_NUM_OF_GENERIC_REGS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_KG_NUM_OF_EXTRACT_MASKS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_KG_NUM_OF_DEFAULT_GROUPS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_PRS_NUM_OF_LABELS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_SW_PRS_SIZE) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_MANIP_INSRT_TEMPLATE_SIZE) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if DPAA_VERSION >= 11 ++#if CMP_IOC_DEFINE(FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES) ++#error Error: please synchronize IOC_ defines! ++#endif ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_CC_TREES) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_CC_GROUPS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_CC_UNITS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_KEYS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_SIZE_OF_KEY) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(FM_PCD_LAST_KEY_INDEX) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++/* net_ioctls.h === net_ext.h assertions */ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPP_PID) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPP_COMPRESSED) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPPoE_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPPMUX_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPPMUX_SUBFRAME_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_ETH_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPv4_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPv6_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_ICMP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IGMP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_TCP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_SCTP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_DCCP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_UDP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_UDP_ENCAP_ESP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPHC_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_SCTP_CHUNK_DATA_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_L2TPv2_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_L2TPv3_CTRL_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_L2TPv3_SESS_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_VLAN_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_LLC_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_NLPID_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_SNAP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_LLC_SNAP_ALL_FIELDS) ++#warning Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_ARP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_RFC2684_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_USER_DEFINED_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PAYLOAD_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_GRE_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_MINENCAP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPSEC_AH_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPSEC_ESP_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_MPLS_LABEL_STACK_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++#if CMP_IOC_DEFINE(NET_HEADER_FIELD_MACSEC_ALL_FIELDS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++/* fm_ioctls.h === fm_ext.h assertions */ ++#if CMP_IOC_DEFINE(FM_MAX_NUM_OF_VALID_PORTS) ++#error Error: please synchronize IOC_ defines! ++#endif ++ ++void LnxWrpPCDIOCTLTypeChecking(void) ++{ ++ /* fm_ext.h == fm_ioctls.h */ ++ ASSERT_COND(sizeof(ioc_fm_port_bandwidth_params) == sizeof(t_FmPortsBandwidthParams)); ++ ASSERT_COND(sizeof(ioc_fm_revision_info_t) == sizeof(t_FmRevisionInfo)); ++ ++ /* fm_pcd_ext.h == fm_pcd_ioctls.h */ ++ /*ioc_fm_pcd_counters_params_t : NOT USED */ ++ /*ioc_fm_pcd_exception_params_t : private */ ++#if (DPAA_VERSION >= 11) ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_capwap_params_t) == sizeof(t_FmPcdManipFragCapwapParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_capwap_params_t) == sizeof(t_FmPcdManipReassemCapwapParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_insrt_by_hdr_params_t) == sizeof(t_FmPcdManipHdrInsrtByHdrParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_insrt_ip_params_t) == sizeof(t_FmPcdManipHdrInsrtIpParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_insrt_t) == sizeof(t_FmPcdManipHdrInsrt)); ++ ASSERT_COND(sizeof(ioc_fm_manip_hdr_info_t) == sizeof(t_FmManipHdrInfo)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_rmv_by_hdr_params_t) == sizeof(t_FmPcdManipHdrRmvByHdrParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_special_offload_capwap_params_t) == sizeof(t_FmPcdManipSpecialOffloadCapwapParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_capwap_stats_t) == sizeof(t_FmPcdManipFragCapwapStats)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_capwap_stats_t) == sizeof(t_FmPcdManipReassemCapwapStats)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_params_t) == sizeof(t_FmPcdManipFragParams)); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ ASSERT_COND(sizeof(ioc_fm_pcd_prs_label_params_t) == sizeof(t_FmPcdPrsLabelParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_prs_sw_params_t) == sizeof(t_FmPcdPrsSwParams)); ++ /*ioc_fm_pcd_kg_dflt_value_params_t : private */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_hdr_protocol_opt_u) == sizeof(u_FmPcdHdrProtocolOpt)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_fields_u) == sizeof(t_FmPcdFields)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_from_hdr_t) == sizeof(t_FmPcdFromHdr)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_from_field_t) == sizeof(t_FmPcdFromField)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_distinction_unit_t) == sizeof(t_FmPcdDistinctionUnit)); ++#if !defined(CONFIG_COMPAT) ++ /* different alignment */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_net_env_params_t) == sizeof(t_FmPcdNetEnvParams) + sizeof(void *)); ++#endif ++ ASSERT_COND(sizeof(ioc_fm_pcd_extract_entry_t) == sizeof(t_FmPcdExtractEntry)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_extract_mask_t) == sizeof(t_FmPcdKgExtractMask)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_extract_dflt_t) == sizeof(t_FmPcdKgExtractDflt)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_key_extract_and_hash_params_t) == sizeof(t_FmPcdKgKeyExtractAndHashParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_extracted_or_params_t) == sizeof(t_FmPcdKgExtractedOrParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_scheme_counter_t) == sizeof(t_FmPcdKgSchemeCounter)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_plcr_profile_t) == sizeof(t_FmPcdKgPlcrProfile)); ++#if (DPAA_VERSION >= 11) ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_storage_profile_t) == sizeof(t_FmPcdKgStorageProfile)); ++#endif ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_cc_t) == sizeof(t_FmPcdKgCc)); ++#if !defined(CONFIG_COMPAT) ++ /* different alignment */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_scheme_params_t) == sizeof(t_FmPcdKgSchemeParams) + sizeof(void *)); ++#endif ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_cc_params_t) == sizeof(t_FmPcdCcNextCcParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_plcr_params_t) == sizeof(t_FmPcdCcNextPlcrParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_enqueue_params_t) == sizeof(t_FmPcdCcNextEnqueueParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_kg_params_t) == sizeof(t_FmPcdCcNextKgParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_engine_params_t) == sizeof(t_FmPcdCcNextEngineParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_key_params_t) == sizeof(t_FmPcdCcKeyParams)); ++ ASSERT_COND(sizeof(ioc_keys_params_t) == sizeof(t_KeysParams)); ++#if !defined(CONFIG_COMPAT) ++ /* different alignment */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_node_params_t) == sizeof(t_FmPcdCcNodeParams) + sizeof(void *)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_hash_table_params_t) == sizeof(t_FmPcdHashTableParams) + sizeof(void *)); ++#endif ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_grp_params_t) == sizeof(t_FmPcdCcGrpParams)); ++#if !defined(CONFIG_COMPAT) ++ /* different alignment */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_cc_tree_params_t) == sizeof(t_FmPcdCcTreeParams) + sizeof(void *)); ++#endif ++ ASSERT_COND(sizeof(ioc_fm_pcd_plcr_byte_rate_mode_param_t) == sizeof(t_FmPcdPlcrByteRateModeParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_plcr_non_passthrough_alg_param_t) == sizeof(t_FmPcdPlcrNonPassthroughAlgParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_plcr_next_engine_params_u) == sizeof(u_FmPcdPlcrNextEngineParams)); ++ /*ioc_fm_pcd_port_params_t : private */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_plcr_profile_params_t) == sizeof(t_FmPcdPlcrProfileParams) + sizeof(void *)); ++ /*ioc_fm_pcd_cc_tree_modify_next_engine_params_t : private */ ++ ++#ifdef FM_CAPWAP_SUPPORT ++#error TODO: unsupported feature ++/* ++ ASSERT_COND(sizeof(TODO) == sizeof(t_FmPcdManipHdrInsrtByTemplateParams)); ++ ASSERT_COND(sizeof(TODO) == sizeof(t_CapwapFragmentationParams)); ++ ASSERT_COND(sizeof(TODO) == sizeof(t_CapwapReassemblyParams)); ++*/ ++#endif ++ ++ /*ioc_fm_pcd_cc_node_modify_next_engine_params_t : private */ ++ /*ioc_fm_pcd_cc_node_remove_key_params_t : private */ ++ /*ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t : private */ ++ /*ioc_fm_pcd_cc_node_modify_key_params_t : private */ ++ /*ioc_fm_manip_hdr_info_t : private */ ++ /*ioc_fm_pcd_hash_table_set_t : private */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_ip_params_t) == sizeof(t_FmPcdManipFragIpParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_ip_params_t) == sizeof(t_FmPcdManipReassemIpParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_special_offload_ipsec_params_t) == sizeof(t_FmPcdManipSpecialOffloadIPSecParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_special_offload_params_t) == sizeof(t_FmPcdManipSpecialOffloadParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_rmv_generic_params_t) == sizeof(t_FmPcdManipHdrRmvGenericParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_insrt_generic_params_t) == sizeof(t_FmPcdManipHdrInsrtGenericParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_insrt_params_t) == sizeof(t_FmPcdManipHdrInsrtParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_rmv_params_t) == sizeof(t_FmPcdManipHdrRmvParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_params_t) == sizeof(t_FmPcdManipHdrParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_params_t) == sizeof(t_FmPcdManipFragParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_params_t) == sizeof(t_FmPcdManipReassemParams)); ++#if !defined(CONFIG_COMPAT) ++ /* different alignment */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_params_t) == sizeof(t_FmPcdManipParams) + sizeof(void *)); ++#endif ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_ip_stats_t) == sizeof(t_FmPcdManipReassemIpStats)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_ip_stats_t) == sizeof(t_FmPcdManipFragIpStats)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_stats_t) == sizeof(t_FmPcdManipReassemStats)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_stats_t) == sizeof(t_FmPcdManipFragStats)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_manip_stats_t) == sizeof(t_FmPcdManipStats)); ++#if DPAA_VERSION >= 11 ++ ASSERT_COND(sizeof(ioc_fm_pcd_frm_replic_group_params_t) == sizeof(t_FmPcdFrmReplicGroupParams) + sizeof(void *)); ++#endif ++ ++ /* fm_port_ext.h == fm_port_ioctls.h */ ++ ASSERT_COND(sizeof(ioc_fm_port_rate_limit_t) == sizeof(t_FmPortRateLimit)); ++ ASSERT_COND(sizeof(ioc_fm_port_pcd_params_t) == sizeof(t_FmPortPcdParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_kg_scheme_select_t) == sizeof(t_FmPcdKgSchemeSelect)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_port_schemes_params_t) == sizeof(t_FmPcdPortSchemesParams)); ++ ASSERT_COND(sizeof(ioc_fm_pcd_prs_start_t) == sizeof(t_FmPcdPrsStart)); ++ ++ return; ++} ++ ++#define ASSERT_IOC_NET_ENUM(def) ASSERT_COND((unsigned long)e_IOC_NET_##def == (unsigned long)def) ++ ++void LnxWrpPCDIOCTLEnumChecking(void) ++{ ++ /* net_ext.h == net_ioctls.h : sampling checks */ ++ ASSERT_IOC_NET_ENUM(HEADER_TYPE_MACSEC); ++ ASSERT_IOC_NET_ENUM(HEADER_TYPE_PPP); ++ ASSERT_IOC_NET_ENUM(MAX_HEADER_TYPE_COUNT); ++ ++ /* fm_ext.h == fm_ioctls.h */ ++ ASSERT_COND((unsigned long)e_IOC_FM_PORT_TYPE_DUMMY == (unsigned long)e_FM_PORT_TYPE_DUMMY); ++ ASSERT_COND((unsigned long)e_IOC_EX_MURAM_ECC == (unsigned long)e_FM_EX_MURAM_ECC); ++ ASSERT_COND((unsigned long)e_IOC_FM_COUNTERS_DEQ_CONFIRM == (unsigned long)e_FM_COUNTERS_DEQ_CONFIRM); ++ ++ /* fm_pcd_ext.h == fm_pcd_ioctls.h */ ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES == (unsigned long)e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PRS_EXCEPTION_SINGLE_ECC == (unsigned long)e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PRS == (unsigned long)e_FM_PCD_PRS); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_EXTRACT_FULL_FIELD == (unsigned long)e_FM_PCD_EXTRACT_FULL_FIELD); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_EXTRACT_FROM_FLOW_ID == (unsigned long)e_FM_PCD_EXTRACT_FROM_FLOW_ID); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO == (unsigned long)e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_KG_DFLT_ILLEGAL == (unsigned long)e_FM_PCD_KG_DFLT_ILLEGAL); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_KG_GENERIC_NOT_FROM_DATA == (unsigned long)e_FM_PCD_KG_GENERIC_NOT_FROM_DATA); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_HDR_INDEX_LAST == (unsigned long)e_FM_PCD_HDR_INDEX_LAST); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_SHARED == (unsigned long)e_FM_PCD_PLCR_SHARED); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_RFC_4115 == (unsigned long)e_FM_PCD_PLCR_RFC_4115); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_COLOR_AWARE == (unsigned long)e_FM_PCD_PLCR_COLOR_AWARE); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_OVERRIDE == (unsigned long)e_FM_PCD_PLCR_OVERRIDE); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_FULL_FRM_LEN == (unsigned long)e_FM_PCD_PLCR_FULL_FRM_LEN); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN == (unsigned long)e_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_PACKET_MODE == (unsigned long)e_FM_PCD_PLCR_PACKET_MODE); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_DROP_FRAME == (unsigned long)e_FM_PCD_DROP_FRAME); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER == (unsigned long)e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_ACTION_INDEXED_LOOKUP == (unsigned long)e_FM_PCD_ACTION_INDEXED_LOOKUP); ++ ASSERT_COND((unsigned long)e_IOC_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR == (unsigned long)e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR); ++#if !defined(FM_CAPWAP_SUPPORT) ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_INSRT_GENERIC == (unsigned long)e_FM_PCD_MANIP_INSRT_GENERIC); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_RMV_GENERIC == (unsigned long)e_FM_PCD_MANIP_RMV_GENERIC); ++#else ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_INSRT_BY_TEMPLATE == (unsigned long)e_FM_PCD_MANIP_INSRT_BY_TEMPLATE); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_RMV_BY_HDR == (unsigned long)e_FM_PCD_MANIP_RMV_BY_HDR); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_RMV_BY_HDR_FROM_START == (unsigned long)e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START); ++#endif ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAG == (unsigned long)e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAG); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_EIGHT_WAYS_HASH == (unsigned long)e_FM_PCD_MANIP_EIGHT_WAYS_HASH); ++ ++#ifdef FM_CAPWAP_SUPPORT ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_STATS_PER_FLOWID == (unsigned long)e_FM_PCD_STATS_PER_FLOWID); ++#endif ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_SPECIAL_OFFLOAD == (unsigned long)e_FM_PCD_MANIP_SPECIAL_OFFLOAD); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_CC_STATS_MODE_FRAME == (unsigned long)e_FM_PCD_CC_STATS_MODE_FRAME); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_CONTINUE_WITHOUT_FRAG == (unsigned long)e_FM_PCD_MANIP_CONTINUE_WITHOUT_FRAG); ++ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC == (unsigned long)e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC); ++ ++ /* fm_port_ext.h == fm_port_ioctls.h */ ++#if !defined(FM_CAPWAP_SUPPORT) ++ ASSERT_COND((unsigned long)e_IOC_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR == (unsigned long)e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR); ++#else ++ ASSERT_COND((unsigned long)e_IOC_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR == (unsigned long)e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR); ++#endif ++ ASSERT_COND((unsigned long)e_IOC_FM_PORT_COUNTERS_DEQ_CONFIRM == (unsigned long)e_FM_PORT_COUNTERS_DEQ_CONFIRM); ++ ASSERT_COND((unsigned long)e_IOC_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_8 == (unsigned long)e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_8); ++ ++ return; ++} ++ ++static t_Error LnxwrpFmPcdIOCTL(t_LnxWrpFmDev *p_LnxWrpFmDev, unsigned int cmd, unsigned long arg, bool compat) ++{ ++ t_Error err = E_OK; ++ ++/* ++Status: PCD API to fmlib (file: drivers/net/dpa/NetCommSw/inc/Peripherals/fm_pcd_ext.h): ++ ++ FM_PCD_PrsLoadSw ++ FM_PCD_SetAdvancedOffloadSupport ++ FM_PCD_Enable ++ FM_PCD_Disable ++ FM_PCD_ForceIntr ++ FM_PCD_SetException ++ FM_PCD_KgSetAdditionalDataAfterParsing ++ FM_PCD_KgSetDfltValue ++ FM_PCD_NetEnvCharacteristicsSet ++ FM_PCD_NetEnvCharacteristicsDelete ++ FM_PCD_KgSchemeSet ++ FM_PCD_KgSchemeDelete ++ FM_PCD_MatchTableSet ++ FM_PCD_MatchTableDelete ++ FM_PCD_CcRootBuild ++ FM_PCD_CcRootDelete ++ FM_PCD_PlcrProfileSet ++ FM_PCD_PlcrProfileDelete ++ FM_PCD_CcRootModifyNextEngine ++ FM_PCD_MatchTableModifyNextEngine ++ FM_PCD_MatchTableModifyMissNextEngine ++ FM_PCD_MatchTableRemoveKey ++ FM_PCD_MatchTableAddKey ++ FM_PCD_MatchTableModifyKeyAndNextEngine ++ FM_PCD_HashTableSet ++ FM_PCD_HashTableDelete ++ FM_PCD_HashTableAddKey ++ FM_PCD_HashTableRemoveKey ++ FM_PCD_MatchTableModifyKey ++ FM_PCD_ManipNodeReplace ++ FM_PCD_ManipNodeSet ++ FM_PCD_ManipNodeDelete ++ ++Status: not exported, should be thru sysfs ++ FM_PCD_KgSchemeGetCounter ++ FM_PCD_KgSchemeSetCounter ++ FM_PCD_PlcrProfileGetCounter ++ FM_PCD_PlcrProfileSetCounter ++ ++Status: not exported ++ FM_PCD_MatchTableFindNRemoveKey ++ FM_PCD_MatchTableFindNModifyNextEngine ++ FM_PCD_MatchTableFindNModifyKeyAndNextEngine ++ FM_PCD_MatchTableFindNModifyKey ++ FM_PCD_MatchTableGetIndexedHashBucket ++ FM_PCD_MatchTableGetNextEngine ++ FM_PCD_MatchTableGetKeyCounter ++ ++Status: not exported, would be nice to have ++ FM_PCD_HashTableModifyNextEngine ++ FM_PCD_HashTableModifyMissNextEngine ++ FM_PCD_HashTableGetMissNextEngine ++ FM_PCD_ManipGetStatistics ++ ++Status: not exported ++#if DPAA_VERSION >= 11 ++ ++ FM_VSP_GetStatistics -- it's not available yet ++#endif ++ ++Status: feature not supported ++#ifdef FM_CAPWAP_SUPPORT ++#error unsupported feature ++ FM_PCD_StatisticsSetNode ++#endif ++ ++ */ ++ _fm_ioctl_dbg("cmd:0x%08x(type:0x%02x, nr:%u).\n", ++ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd) - 20); ++ ++ switch (cmd) ++ { ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_PRS_LOAD_SW_COMPAT: ++#endif ++ case FM_PCD_IOC_PRS_LOAD_SW: ++ { ++ ioc_fm_pcd_prs_sw_params_t *param; ++ uint8_t *p_code; ++ ++ param = (ioc_fm_pcd_prs_sw_params_t *) XX_Malloc(sizeof(ioc_fm_pcd_prs_sw_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_prs_sw_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_prs_sw_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_prs_sw_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_prs_sw_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_prs_sw_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_prs_sw_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_prs_sw_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_fm_pcd_prs_sw(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_prs_sw_params_t *)arg, ++ sizeof(ioc_fm_pcd_prs_sw_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (!param->p_code || !param->size) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ p_code = (uint8_t *) XX_Malloc(param->size); ++ if (!p_code) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(p_code, 0, param->size); ++ if (copy_from_user(p_code, param->p_code, param->size)) ++ { ++ XX_Free(p_code); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->p_code = p_code; ++ ++ err = FM_PCD_PrsLoadSw(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdPrsSwParams*)param); ++ ++ XX_Free(p_code); ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_PCD_IOC_SET_ADVANCED_OFFLOAD_SUPPORT: ++ err = FM_PCD_SetAdvancedOffloadSupport(p_LnxWrpFmDev->h_PcdDev); ++ break; ++ ++ case FM_PCD_IOC_ENABLE: ++ err = FM_PCD_Enable(p_LnxWrpFmDev->h_PcdDev); ++ break; ++ ++ case FM_PCD_IOC_DISABLE: ++ err = FM_PCD_Disable(p_LnxWrpFmDev->h_PcdDev); ++ break; ++ ++ case FM_PCD_IOC_FORCE_INTR: ++ { ++ int exception; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (get_user(exception, (int *) compat_ptr(arg))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ else ++#endif ++ { ++ if (get_user(exception, (int *)arg)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_ForceIntr(p_LnxWrpFmDev->h_PcdDev, (e_FmPcdExceptions)exception); ++ break; ++ } ++ ++ case FM_PCD_IOC_SET_EXCEPTION: ++ { ++ ioc_fm_pcd_exception_params_t *param; ++ ++ param = (ioc_fm_pcd_exception_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_exception_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_exception_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_exception_params_t *)compat_ptr(arg), ++ sizeof(ioc_fm_pcd_exception_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_exception_params_t *)arg, ++ sizeof(ioc_fm_pcd_exception_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, param->exception, param->enable); ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_PCD_IOC_KG_SET_ADDITIONAL_DATA_AFTER_PARSING: ++ { ++ uint8_t payloadOffset; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (get_user(payloadOffset, (uint8_t*) compat_ptr(arg))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ else ++#endif ++ { ++ if (get_user(payloadOffset, (uint8_t*) arg)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_KgSetAdditionalDataAfterParsing(p_LnxWrpFmDev->h_PcdDev, payloadOffset); ++ break; ++ } ++ ++ case FM_PCD_IOC_KG_SET_DFLT_VALUE: ++ { ++ ioc_fm_pcd_kg_dflt_value_params_t *param; ++ ++ param = (ioc_fm_pcd_kg_dflt_value_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_kg_dflt_value_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_kg_dflt_value_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_kg_dflt_value_params_t *)compat_ptr(arg), ++ sizeof(ioc_fm_pcd_kg_dflt_value_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_kg_dflt_value_params_t *)arg, ++ sizeof(ioc_fm_pcd_kg_dflt_value_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PCD_KgSetDfltValue(p_LnxWrpFmDev->h_PcdDev, param->valueId, param->value); ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_NET_ENV_CHARACTERISTICS_SET_COMPAT: ++#endif ++ case FM_PCD_IOC_NET_ENV_CHARACTERISTICS_SET: ++ { ++ ioc_fm_pcd_net_env_params_t *param; ++ ++ param = (ioc_fm_pcd_net_env_params_t *) XX_Malloc(sizeof(ioc_fm_pcd_net_env_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_net_env_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_net_env_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_net_env_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_net_env_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_net_env_params_t)); ++ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_net_env_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_net_env_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_net_env(compat_param, param, COMPAT_US_TO_K); ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_net_env_params_t *) arg, ++ sizeof(ioc_fm_pcd_net_env_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ param->id = FM_PCD_NetEnvCharacteristicsSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdNetEnvParams*)param); ++ ++ if (!param->id) ++ { ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ /* Since the LLD has no errno-style error reporting, ++ we're left here with no other option than to report ++ a generic E_INVALID_VALUE */ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_net_env_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_net_env_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_net_env_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_net_env_params_t)); ++ compat_copy_fm_pcd_net_env(compat_param, param, COMPAT_K_TO_US); ++ ++ if (copy_to_user((ioc_compat_fm_pcd_net_env_params_t *) compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_net_env_params_t))) ++ err = E_READ_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_net_env_params_t *)arg, ++ param, ++ sizeof(ioc_fm_pcd_net_env_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_NET_ENV_CHARACTERISTICS_DELETE_COMPAT: ++#endif ++ case FM_PCD_IOC_NET_ENV_CHARACTERISTICS_DELETE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0 , sizeof(ioc_fm_obj_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_obj_delete(&compat_id, &id); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_NetEnvCharacteristicsDelete(id.obj); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_KG_SCHEME_SET_COMPAT: ++#endif ++ case FM_PCD_IOC_KG_SCHEME_SET: ++ { ++ ioc_fm_pcd_kg_scheme_params_t *param; ++ ++ param = (ioc_fm_pcd_kg_scheme_params_t *) XX_Malloc(sizeof(ioc_fm_pcd_kg_scheme_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_kg_scheme_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_kg_scheme_params_t *compat_param = NULL; ++ ++ compat_param = (ioc_compat_fm_pcd_kg_scheme_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_kg_scheme_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_kg_scheme_params_t)); ++ ++ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_kg_scheme_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_kg_scheme_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_kg_scheme(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_kg_scheme_params_t *)arg, ++ sizeof(ioc_fm_pcd_kg_scheme_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ param->id = FM_PCD_KgSchemeSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdKgSchemeParams*)param); ++ ++ if (!param->id) ++ { ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ /* Since the LLD has no errno-style error reporting, ++ we're left here with no other option than to report ++ a generic E_INVALID_VALUE */ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_kg_scheme_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_kg_scheme_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_kg_scheme_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_kg_scheme_params_t)); ++ compat_copy_fm_pcd_kg_scheme(compat_param, param, COMPAT_K_TO_US); ++ if (copy_to_user((ioc_compat_fm_pcd_kg_scheme_params_t *)compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_kg_scheme_params_t))) ++ err = E_READ_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_kg_scheme_params_t *)arg, ++ param, ++ sizeof(ioc_fm_pcd_kg_scheme_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_KG_SCHEME_GET_CNTR_COMPAT: ++#endif ++ case FM_PCD_IOC_KG_SCHEME_GET_CNTR: ++ { ++ ioc_fm_pcd_kg_scheme_spc_t *param; ++ ++ param = (ioc_fm_pcd_kg_scheme_spc_t *) XX_Malloc(sizeof(ioc_fm_pcd_kg_scheme_spc_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_kg_scheme_spc_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_kg_scheme_spc_t *compat_param = NULL; ++ ++ compat_param = (ioc_compat_fm_pcd_kg_scheme_spc_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_kg_scheme_spc_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_kg_scheme_spc_t)); ++ ++ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_kg_scheme_spc_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_kg_scheme_spc_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_kg_scheme_spc(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_kg_scheme_spc_t *)arg, ++ sizeof(ioc_fm_pcd_kg_scheme_spc_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ param->val = FM_PCD_KgSchemeGetCounter((t_Handle)param->id); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_kg_scheme_spc_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_kg_scheme_spc_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_kg_scheme_spc_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_kg_scheme_spc_t)); ++ compat_copy_fm_pcd_kg_scheme_spc(compat_param, param, COMPAT_K_TO_US); ++ if (copy_to_user((ioc_compat_fm_pcd_kg_scheme_spc_t *)compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_kg_scheme_spc_t))) ++ err = E_READ_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_kg_scheme_spc_t *)arg, ++ param, ++ sizeof(ioc_fm_pcd_kg_scheme_spc_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_KG_SCHEME_DELETE_COMPAT: ++#endif ++ case FM_PCD_IOC_KG_SCHEME_DELETE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0 , sizeof(ioc_fm_obj_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_obj_delete(&compat_id, &id); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_KgSchemeDelete(id.obj); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_SET_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_SET: ++ { ++ ioc_fm_pcd_cc_node_params_t *param; ++ uint8_t *keys; ++ uint8_t *masks; ++ int i,k; ++ ++ param = (ioc_fm_pcd_cc_node_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_cc_node_params_t) + ++ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_params_t) + ++ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY); ++ ++ keys = (uint8_t *) (param + 1); ++ masks = keys + IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_node_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_node_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_node_params_t) + ++ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_params_t) + ++ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY); ++ ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_cc_node_params_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_node_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_node(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_node_params_t *)arg, sizeof(ioc_fm_pcd_cc_node_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ ASSERT_COND(param->keys_params.num_of_keys <= IOC_FM_PCD_MAX_NUM_OF_KEYS); ++ ASSERT_COND(param->keys_params.key_size <= IOC_FM_PCD_MAX_SIZE_OF_KEY); ++ ++ /* support for indexed lookup */ ++ if( !(param->extract_cc_params.type == e_IOC_FM_PCD_EXTRACT_NON_HDR && ++ param->extract_cc_params.extract_params.extract_non_hdr.src == e_IOC_FM_PCD_EXTRACT_FROM_HASH && ++ param->extract_cc_params.extract_params.extract_non_hdr.action == e_IOC_FM_PCD_ACTION_INDEXED_LOOKUP)) ++ { ++ for (i=0, k=0; ++ i < param->keys_params.num_of_keys; ++ i++, k += IOC_FM_PCD_MAX_SIZE_OF_KEY) ++ { ++ if (param->keys_params.key_params[i].p_key && ++ param->keys_params.key_size) ++ { ++ if (copy_from_user(&keys[k], ++ param->keys_params.key_params[i].p_key, ++ param->keys_params.key_size)) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->keys_params.key_params[i].p_key = &keys[k]; ++ } ++ ++ if (param->keys_params.key_params[i].p_mask) ++ { ++ if (copy_from_user(&masks[k], ++ param->keys_params.key_params[i].p_mask, ++ param->keys_params.key_size)) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->keys_params.key_params[i].p_mask = &masks[k]; ++ } ++ } ++ } ++ ++ param->id = FM_PCD_MatchTableSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdCcNodeParams*)param); ++ ++ if (!param->id) { ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ /* Since the LLD has no errno-style error reporting, ++ we're left here with no other option than to report ++ a generic E_INVALID_VALUE */ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_node_params_t *compat_param; ++ compat_param = (ioc_compat_fm_pcd_cc_node_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_node_params_t) + ++ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_params_t) + ++ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY); ++ compat_copy_fm_pcd_cc_node(compat_param, param, COMPAT_K_TO_US); ++ ++ if (copy_to_user((ioc_compat_fm_pcd_cc_node_params_t *)compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_cc_node_params_t))) ++ err = E_READ_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_cc_node_params_t *)arg, ++ param, ++ sizeof(ioc_fm_pcd_cc_node_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_DELETE_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_DELETE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0 , sizeof(ioc_fm_obj_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_obj_delete(&compat_id, &id); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_MatchTableDelete(id.obj); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_CC_ROOT_BUILD_COMPAT: ++#endif ++ case FM_PCD_IOC_CC_ROOT_BUILD: ++ { ++ ioc_fm_pcd_cc_tree_params_t *param; ++ ++ param = (ioc_fm_pcd_cc_tree_params_t *) XX_Malloc(sizeof(ioc_fm_pcd_cc_tree_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_tree_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_tree_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_tree_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_tree_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tree_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_cc_tree_params_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_tree_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_tree(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_tree_params_t *)arg, ++ sizeof(ioc_fm_pcd_cc_tree_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ param->id = FM_PCD_CcRootBuild(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdCcTreeParams*)param); ++ ++ if (!param->id) { ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ /* Since the LLD has no errno-style error reporting, ++ we're left here with no other option than to report ++ a generic E_INVALID_VALUE */ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_tree_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_tree_params_t *) XX_Malloc(sizeof(ioc_compat_fm_pcd_cc_tree_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tree_params_t)); ++ ++ compat_copy_fm_pcd_cc_tree(compat_param, param, COMPAT_K_TO_US); ++ ++ if (copy_to_user((ioc_compat_fm_pcd_cc_tree_params_t *)compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_cc_tree_params_t))) ++ err = E_READ_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_cc_tree_params_t *)arg, ++ param, ++ sizeof(ioc_fm_pcd_cc_tree_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_CC_ROOT_DELETE_COMPAT: ++#endif ++ case FM_PCD_IOC_CC_ROOT_DELETE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0 , sizeof(ioc_fm_obj_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_obj_delete(&compat_id, &id); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_CcRootDelete(id.obj); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_PLCR_PROFILE_SET_COMPAT: ++#endif ++ case FM_PCD_IOC_PLCR_PROFILE_SET: ++ { ++ ioc_fm_pcd_plcr_profile_params_t *param; ++ ++ param = (ioc_fm_pcd_plcr_profile_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_plcr_profile_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_plcr_profile_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_plcr_profile_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_plcr_profile_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_plcr_profile_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_plcr_profile_params_t)); ++ if (copy_from_user(compat_param, ( ++ ioc_compat_fm_pcd_plcr_profile_params_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_plcr_profile_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_plcr_profile(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_plcr_profile_params_t *)arg, ++ sizeof(ioc_fm_pcd_plcr_profile_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (!param->modify && ++ (((t_FmPcdPlcrProfileParams*)param)->id.newParams.profileType != e_FM_PCD_PLCR_SHARED)) ++ { ++ t_Handle h_Port; ++ ioc_fm_pcd_port_params_t *port_params; ++ ++ port_params = (ioc_fm_pcd_port_params_t*) XX_Malloc(sizeof(ioc_fm_pcd_port_params_t)); ++ if (!port_params) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(port_params, 0, sizeof(ioc_fm_pcd_port_params_t)); ++ if (copy_from_user(port_params, (ioc_fm_pcd_port_params_t*)((t_FmPcdPlcrProfileParams*)param)->id.newParams.h_FmPort, ++ sizeof(ioc_fm_pcd_port_params_t))) ++ { ++ XX_Free(port_params); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ switch(port_params->port_type) ++ { ++ case (e_IOC_FM_PORT_TYPE_RX): ++ if (port_params->port_id < FM_MAX_NUM_OF_1G_RX_PORTS) { ++ h_Port = p_LnxWrpFmDev->rxPorts[port_params->port_id].h_Dev; ++ break; ++ } ++ goto invalid_port_id; ++ ++ case (e_IOC_FM_PORT_TYPE_RX_10G): ++ if (port_params->port_id < FM_MAX_NUM_OF_10G_RX_PORTS) { ++ if (IS_T1023_T1024) { ++ h_Port = p_LnxWrpFmDev->rxPorts[port_params->port_id].h_Dev; ++ } else { ++ h_Port = p_LnxWrpFmDev->rxPorts[port_params->port_id + FM_MAX_NUM_OF_1G_RX_PORTS].h_Dev; ++ } ++ break; ++ } ++ goto invalid_port_id; ++ ++ case (e_IOC_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ if (port_params->port_id && port_params->port_id < FM_MAX_NUM_OF_OH_PORTS) { ++ h_Port = p_LnxWrpFmDev->opPorts[port_params->port_id - 1].h_Dev; ++ break; ++ } ++ goto invalid_port_id; ++ ++ default: ++invalid_port_id: ++ XX_Free(port_params); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, NO_MSG); ++ } ++ ++ ((t_FmPcdPlcrProfileParams*)param)->id.newParams.h_FmPort = h_Port; ++ XX_Free(port_params); ++ } ++ ++ param->id = FM_PCD_PlcrProfileSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdPlcrProfileParams*)param); ++ ++ if (!param->id) { ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ /* Since the LLD has no errno-style error reporting, ++ we're left here with no other option than to report ++ a generic E_INVALID_VALUE */ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_plcr_profile_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_plcr_profile_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_plcr_profile_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_plcr_profile_params_t)); ++ compat_copy_fm_pcd_plcr_profile(compat_param, param, COMPAT_K_TO_US); ++ if (copy_to_user((ioc_compat_fm_pcd_plcr_profile_params_t *) compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_plcr_profile_params_t))) ++ err = E_READ_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_plcr_profile_params_t *)arg, ++ param, ++ sizeof(ioc_fm_pcd_plcr_profile_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_PLCR_PROFILE_DELETE_COMPAT: ++#endif ++ case FM_PCD_IOC_PLCR_PROFILE_DELETE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0 , sizeof(ioc_fm_obj_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_obj_delete(&compat_id, &id); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_PlcrProfileDelete(id.obj); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_CC_ROOT_MODIFY_NEXT_ENGINE_COMPAT: ++#endif ++ case FM_PCD_IOC_CC_ROOT_MODIFY_NEXT_ENGINE: ++ { ++ ioc_fm_pcd_cc_tree_modify_next_engine_params_t *param; ++ ++ param = (ioc_fm_pcd_cc_tree_modify_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_cc_tree_modify_next_engine_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_tree_modify_next_engine_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t)); ++ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_fm_pcd_cc_tree_modify_next_engine(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_tree_modify_next_engine_params_t *)arg, ++ sizeof(ioc_fm_pcd_cc_tree_modify_next_engine_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PCD_CcRootModifyNextEngine(param->id, ++ param->grp_indx, ++ param->indx, ++ (t_FmPcdCcNextEngineParams*)(¶m->cc_next_engine_params)); ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_MODIFY_NEXT_ENGINE_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_MODIFY_NEXT_ENGINE: ++ { ++ ioc_fm_pcd_cc_node_modify_next_engine_params_t *param; ++ ++ param = (ioc_fm_pcd_cc_node_modify_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t)); ++ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_node_modify_next_engine(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_next_engine_params_t *)arg, ++ sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PCD_MatchTableModifyNextEngine(param->id, ++ param->key_indx, ++ (t_FmPcdCcNextEngineParams*)(¶m->cc_next_engine_params)); ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_MODIFY_MISS_NEXT_ENGINE_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_MODIFY_MISS_NEXT_ENGINE: ++ { ++ ioc_fm_pcd_cc_node_modify_next_engine_params_t *param; ++ ++ param = (ioc_fm_pcd_cc_node_modify_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t)); ++ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_node_modify_next_engine(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_next_engine_params_t *) arg, ++ sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PCD_MatchTableModifyMissNextEngine(param->id, ++ (t_FmPcdCcNextEngineParams*)(¶m->cc_next_engine_params)); ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_REMOVE_KEY_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_REMOVE_KEY: ++ { ++ ioc_fm_pcd_cc_node_remove_key_params_t *param; ++ ++ param = (ioc_fm_pcd_cc_node_remove_key_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_cc_node_remove_key_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_remove_key_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_node_remove_key_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_node_remove_key_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_node_remove_key_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_remove_key_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_cc_node_remove_key_params_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_node_remove_key_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->id = compat_ptr(compat_param->id); ++ param->key_indx = compat_param->key_indx; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_node_remove_key_params_t *) arg, ++ sizeof(ioc_fm_pcd_cc_node_remove_key_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PCD_MatchTableRemoveKey(param->id, param->key_indx); ++ ++ XX_Free(param); ++ break; ++ } ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_ADD_KEY_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_ADD_KEY: ++ { ++ ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *param; ++ ++ param = (ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_node_modify_key_and_next_engine(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *)arg, ++ sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (param->key_size) ++ { ++ int size = 0; ++ ++ if (param->key_params.p_key) size += param->key_size; ++ if (param->key_params.p_mask) size += param->key_size; ++ ++ if (size) ++ { ++ uint8_t *p_tmp; ++ ++ p_tmp = (uint8_t*) XX_Malloc(size); ++ if (!p_tmp) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD key/mask")); ++ } ++ ++ if (param->key_params.p_key) ++ { ++ if (copy_from_user(p_tmp, param->key_params.p_key, param->key_size)) ++ { ++ XX_Free(p_tmp); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->key_params.p_key = p_tmp; ++ } ++ ++ if (param->key_params.p_mask) ++ { ++ p_tmp += param->key_size; ++ if (copy_from_user(p_tmp, param->key_params.p_mask, param->key_size)) ++ { ++ XX_Free(p_tmp - param->key_size); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->key_params.p_mask = p_tmp; ++ } ++ } ++ } ++ ++ err = FM_PCD_MatchTableAddKey( ++ param->id, ++ param->key_indx, ++ param->key_size, ++ (t_FmPcdCcKeyParams*)¶m->key_params); ++ ++ if (param->key_params.p_key) ++ XX_Free(param->key_params.p_key); ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_AND_NEXT_ENGINE_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_AND_NEXT_ENGINE: ++ { ++ ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *param; ++ ++ param = (ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_node_modify_key_and_next_engine(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *)arg, ++ sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PCD_MatchTableModifyKeyAndNextEngine(param->id, ++ param->key_indx, ++ param->key_size, ++ (t_FmPcdCcKeyParams*)(¶m->key_params)); ++ ++ XX_Free(param); ++ break; ++ } ++ ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_GET_KEY_STAT_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_GET_KEY_STAT: ++ { ++ ioc_fm_pcd_cc_tbl_get_stats_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_tbl_get_stats_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_tbl_get_stats_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t)); ++ if (!compat_param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_cc_tbl_get_stats_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t))) ++ { ++ XX_Free(compat_param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_tbl_get_stats(compat_param, ¶m, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(¶m, (ioc_fm_pcd_cc_tbl_get_stats_t *)arg, ++ sizeof(ioc_fm_pcd_cc_tbl_get_stats_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ ++ err = FM_PCD_MatchTableGetKeyStatistics((t_Handle) param.id, ++ param.key_index, ++ (t_FmPcdCcKeyStatistics *) ¶m.statistics); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_tbl_get_stats_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_tbl_get_stats_t*) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t)); ++ if (!compat_param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t)); ++ compat_copy_fm_pcd_cc_tbl_get_stats(compat_param, ¶m, COMPAT_K_TO_US); ++ if (copy_to_user((ioc_compat_fm_pcd_cc_tbl_get_stats_t*) compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t))){ ++ XX_Free(compat_param); ++ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); ++ } ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_cc_tbl_get_stats_t *)arg, ++ ¶m, ++ sizeof(ioc_fm_pcd_cc_tbl_get_stats_t))) ++ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); ++ } ++ ++ break; ++ } ++ ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_GET_MISS_STAT_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_GET_MISS_STAT: ++ { ++ ioc_fm_pcd_cc_tbl_get_stats_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_tbl_get_stats_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_tbl_get_stats_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t)); ++ if (!compat_param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_cc_tbl_get_stats_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t))) ++ { ++ XX_Free(compat_param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_tbl_get_stats(compat_param, ¶m, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(¶m, (ioc_fm_pcd_cc_tbl_get_stats_t *)arg, ++ sizeof(ioc_fm_pcd_cc_tbl_get_stats_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ ++ err = FM_PCD_MatchTableGetMissStatistics((t_Handle) param.id, ++ (t_FmPcdCcKeyStatistics *) ¶m.statistics); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_tbl_get_stats_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_tbl_get_stats_t*) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t)); ++ if (!compat_param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t)); ++ compat_copy_fm_pcd_cc_tbl_get_stats(compat_param, ¶m, COMPAT_K_TO_US); ++ if (copy_to_user((ioc_compat_fm_pcd_cc_tbl_get_stats_t*) compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t))){ ++ XX_Free(compat_param); ++ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); ++ } ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_cc_tbl_get_stats_t *)arg, ++ ¶m, ++ sizeof(ioc_fm_pcd_cc_tbl_get_stats_t))) ++ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); ++ } ++ ++ break; ++ } ++ ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_HASH_TABLE_GET_MISS_STAT_COMPAT: ++#endif ++ case FM_PCD_IOC_HASH_TABLE_GET_MISS_STAT: ++ { ++ ioc_fm_pcd_cc_tbl_get_stats_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_tbl_get_stats_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_tbl_get_stats_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t)); ++ if (!compat_param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_cc_tbl_get_stats_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t))) ++ { ++ XX_Free(compat_param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_tbl_get_stats(compat_param, ¶m, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(¶m, (ioc_fm_pcd_cc_tbl_get_stats_t *)arg, ++ sizeof(ioc_fm_pcd_cc_tbl_get_stats_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ ++ err = FM_PCD_HashTableGetMissStatistics((t_Handle) param.id, ++ (t_FmPcdCcKeyStatistics *) ¶m.statistics); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_tbl_get_stats_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_tbl_get_stats_t*) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t)); ++ if (!compat_param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t)); ++ compat_copy_fm_pcd_cc_tbl_get_stats(compat_param, ¶m, COMPAT_K_TO_US); ++ if (copy_to_user((ioc_compat_fm_pcd_cc_tbl_get_stats_t*) compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_cc_tbl_get_stats_t))){ ++ XX_Free(compat_param); ++ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); ++ } ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_cc_tbl_get_stats_t *)arg, ++ ¶m, ++ sizeof(ioc_fm_pcd_cc_tbl_get_stats_t))) ++ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); ++ } ++ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_HASH_TABLE_SET_COMPAT: ++#endif ++ case FM_PCD_IOC_HASH_TABLE_SET: ++ { ++ ioc_fm_pcd_hash_table_params_t *param; ++ ++ param = (ioc_fm_pcd_hash_table_params_t*) XX_Malloc( ++ sizeof(ioc_fm_pcd_hash_table_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_hash_table_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_hash_table_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_hash_table_params_t*) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_hash_table_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_hash_table_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_hash_table_params_t*)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_hash_table_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_hash_table(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_hash_table_params_t *)arg, ++ sizeof(ioc_fm_pcd_hash_table_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ param->id = FM_PCD_HashTableSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdHashTableParams *) param); ++ ++ if (!param->id) ++ { ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ /* Since the LLD has no errno-style error reporting, ++ we're left here with no other option than to report ++ a generic E_INVALID_VALUE */ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_hash_table_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_hash_table_params_t*) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_hash_table_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_hash_table_params_t)); ++ compat_copy_fm_pcd_hash_table(compat_param, param, COMPAT_K_TO_US); ++ if (copy_to_user((ioc_compat_fm_pcd_hash_table_params_t*) compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_hash_table_params_t))) ++ err = E_READ_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_hash_table_params_t *)arg, ++ param, ++ sizeof(ioc_fm_pcd_hash_table_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_HASH_TABLE_DELETE_COMPAT: ++#endif ++ case FM_PCD_IOC_HASH_TABLE_DELETE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0, sizeof(ioc_fm_obj_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ id.obj = compat_pcd_id2ptr(compat_id.obj); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_HashTableDelete(id.obj); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_HASH_TABLE_ADD_KEY_COMPAT: ++#endif ++ case FM_PCD_IOC_HASH_TABLE_ADD_KEY: ++ { ++ ioc_fm_pcd_hash_table_add_key_params_t *param = NULL; ++ ++ param = (ioc_fm_pcd_hash_table_add_key_params_t*) XX_Malloc( ++ sizeof(ioc_fm_pcd_hash_table_add_key_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_hash_table_add_key_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_hash_table_add_key_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_hash_table_add_key_params_t*) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_hash_table_add_key_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_hash_table_add_key_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_hash_table_add_key_params_t*) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_hash_table_add_key_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ if (compat_param->key_size) ++ { ++ param->p_hash_tbl = compat_pcd_id2ptr(compat_param->p_hash_tbl); ++ param->key_size = compat_param->key_size; ++ ++ compat_copy_fm_pcd_cc_key(&compat_param->key_params, ¶m->key_params, COMPAT_US_TO_K); ++ } ++ else ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ break; ++ } ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_hash_table_add_key_params_t*) arg, ++ sizeof(ioc_fm_pcd_hash_table_add_key_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (param->key_size) ++ { ++ int size = 0; ++ ++ if (param->key_params.p_key) size += param->key_size; ++ if (param->key_params.p_mask) size += param->key_size; ++ ++ if (size) ++ { ++ uint8_t *p_tmp; ++ ++ p_tmp = (uint8_t*) XX_Malloc(size); ++ if (!p_tmp) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD key/mask")); ++ } ++ ++ if (param->key_params.p_key) ++ { ++ if (copy_from_user(p_tmp, param->key_params.p_key, param->key_size)) ++ { ++ XX_Free(p_tmp); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->key_params.p_key = p_tmp; ++ } ++ ++ if (param->key_params.p_mask) ++ { ++ p_tmp += param->key_size; ++ if (copy_from_user(p_tmp, param->key_params.p_mask, param->key_size)) ++ { ++ XX_Free(p_tmp - param->key_size); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->key_params.p_mask = p_tmp; ++ } ++ } ++ } ++ ++ err = FM_PCD_HashTableAddKey( ++ param->p_hash_tbl, ++ param->key_size, ++ (t_FmPcdCcKeyParams*)¶m->key_params); ++ ++ if (param->key_params.p_key) ++ XX_Free(param->key_params.p_key); ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_HASH_TABLE_REMOVE_KEY_COMPAT: ++#endif ++ case FM_PCD_IOC_HASH_TABLE_REMOVE_KEY: ++ { ++ ioc_fm_pcd_hash_table_remove_key_params_t *param = NULL; ++ ++ param = (ioc_fm_pcd_hash_table_remove_key_params_t*) XX_Malloc( ++ sizeof(ioc_fm_pcd_hash_table_remove_key_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_hash_table_remove_key_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_hash_table_remove_key_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_hash_table_remove_key_params_t*) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_hash_table_remove_key_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_hash_table_remove_key_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_hash_table_remove_key_params_t*) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_hash_table_remove_key_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->p_hash_tbl = compat_pcd_id2ptr(compat_param->p_hash_tbl); ++ param->key_size = compat_param->key_size; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_hash_table_remove_key_params_t*)arg, ++ sizeof(ioc_fm_pcd_hash_table_remove_key_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (param->key_size) ++ { ++ uint8_t *p_key; ++ ++ p_key = (uint8_t*) XX_Malloc(param->key_size); ++ if (!p_key) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ if (param->p_key && copy_from_user(p_key, param->p_key, param->key_size)) ++ { ++ XX_Free(p_key); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ param->p_key = p_key; ++ } ++ ++ err = FM_PCD_HashTableRemoveKey( ++ param->p_hash_tbl, ++ param->key_size, ++ param->p_key); ++ ++ if (param->p_key) ++ XX_Free(param->p_key); ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_COMPAT: ++#endif ++ case FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY: ++ { ++ ioc_fm_pcd_cc_node_modify_key_params_t *param; ++ ++ param = (ioc_fm_pcd_cc_node_modify_key_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_cc_node_modify_key_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_key_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_cc_node_modify_key_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_cc_node_modify_key_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_key_params_t)); ++ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_cc_node_modify_key_params_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_cc_node_modify_key(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_key_params_t *)arg, ++ sizeof(ioc_fm_pcd_cc_node_modify_key_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (param->key_size) ++ { ++ int size = 0; ++ ++ if (param->p_key) size += param->key_size; ++ if (param->p_mask) size += param->key_size; ++ ++ if (size) ++ { ++ uint8_t *p_tmp; ++ ++ p_tmp = (uint8_t*) XX_Malloc(size); ++ if (!p_tmp) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD key/mask")); ++ } ++ ++ if (param->p_key) ++ { ++ if (copy_from_user(p_tmp, param->p_key, param->key_size)) ++ { ++ XX_Free(p_tmp); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->p_key = p_tmp; ++ } ++ ++ if (param->p_mask) ++ { ++ p_tmp += param->key_size; ++ if (copy_from_user(p_tmp, param->p_mask, param->key_size)) ++ { ++ XX_Free(p_tmp - param->key_size); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->p_mask = p_tmp; ++ } ++ } ++ } ++ ++ err = FM_PCD_MatchTableModifyKey(param->id, ++ param->key_indx, ++ param->key_size, ++ param->p_key, ++ param->p_mask); ++ ++ if (param->p_key) ++ XX_Free(param->p_key); ++ else if (param->p_mask) ++ XX_Free(param->p_mask); ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MANIP_NODE_SET_COMPAT: ++#endif ++ case FM_PCD_IOC_MANIP_NODE_SET: ++ { ++ ioc_fm_pcd_manip_params_t *param; ++ uint8_t *p_data = NULL; ++ uint8_t size; ++ ++ param = (ioc_fm_pcd_manip_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_manip_params_t)); ++ ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_manip_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_manip_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_manip_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_manip_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_manip_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_manip_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_manip_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_fm_pcd_manip_set_node(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_manip_params_t *)arg, ++ sizeof(ioc_fm_pcd_manip_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (param->type == e_IOC_FM_PCD_MANIP_HDR) ++ { ++ size = param->u.hdr.insrt_params.u.generic.size; ++ p_data = (uint8_t *) XX_Malloc(size); ++ if (!p_data ) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, NO_MSG); ++ } ++ ++ if (param->u.hdr.insrt_params.u.generic.p_data && ++ copy_from_user(p_data, ++ param->u.hdr.insrt_params.u.generic.p_data, size)) ++ { ++ XX_Free(p_data); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ param->u.hdr.insrt_params.u.generic.p_data = p_data; ++ } ++ ++ if (param->id) ++ { ++ /* Security Hole: the user can pass any piece of garbage ++ in 'param->id', and that will go straight through to the LLD, ++ no checks being done by the wrapper! */ ++ err = FM_PCD_ManipNodeReplace( ++ (t_Handle) param->id, ++ (t_FmPcdManipParams*) param); ++ if (err) ++ { ++ if (p_data) ++ XX_Free(p_data); ++ XX_Free(param); ++ break; ++ } ++ } ++ else ++ { ++ param->id = FM_PCD_ManipNodeSet( ++ p_LnxWrpFmDev->h_PcdDev, ++ (t_FmPcdManipParams*) param); ++ if (!param->id) ++ { ++ if (p_data) ++ XX_Free(p_data); ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ /* Since the LLD has no errno-style error reporting, ++ we're left here with no other option than to report ++ a generic E_INVALID_VALUE */ ++ break; ++ } ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_manip_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_manip_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_manip_params_t)); ++ if (!compat_param) ++ { ++ if (p_data) ++ XX_Free(p_data); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_manip_params_t)); ++ ++ compat_fm_pcd_manip_set_node(compat_param, param, COMPAT_K_TO_US); ++ ++ if (copy_to_user((ioc_compat_fm_pcd_manip_params_t *) compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_manip_params_t))) ++ err = E_READ_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_pcd_manip_params_t *)arg, ++ param, sizeof(ioc_fm_pcd_manip_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ if (p_data) ++ XX_Free(p_data); ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MANIP_NODE_DELETE_COMPAT: ++#endif ++ case FM_PCD_IOC_MANIP_NODE_DELETE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0, sizeof(ioc_fm_obj_t)); ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_obj_delete(&compat_id, &id); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_ManipNodeDelete(id.obj); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_MANIP_GET_STATS_COMPAT: ++#endif ++ case FM_PCD_IOC_MANIP_GET_STATS: ++ { ++ ioc_fm_pcd_manip_get_stats_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_manip_get_stats_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_manip_get_stats_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_manip_get_stats_t)); ++ if (!compat_param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_manip_get_stats_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_manip_get_stats_t *)compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_manip_get_stats_t))) ++ { ++ XX_Free(compat_param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_manip_get_stats(compat_param, ¶m, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(¶m, (ioc_fm_pcd_manip_get_stats_t *)arg, ++ sizeof(ioc_fm_pcd_manip_get_stats_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PCD_ManipGetStatistics((t_Handle) param.id, ++ (t_FmPcdManipStats*) ¶m.stats); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_manip_get_stats_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_manip_get_stats_t*) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_manip_get_stats_t)); ++ if (!compat_param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_manip_get_stats_t)); ++ compat_copy_fm_pcd_manip_get_stats(compat_param, ¶m, COMPAT_K_TO_US); ++ if (copy_to_user((ioc_compat_fm_pcd_manip_get_stats_t*) compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_manip_get_stats_t))){ ++ XX_Free(compat_param); ++ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); ++ } ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ if (copy_to_user((ioc_fm_pcd_manip_get_stats_t *)arg, ++ ¶m, ++ sizeof(ioc_fm_pcd_manip_get_stats_t))) ++ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); ++ ++ break; ++ } ++ ++#if (DPAA_VERSION >= 11) ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_FRM_REPLIC_GROUP_SET_COMPAT: ++#endif ++ case FM_PCD_IOC_FRM_REPLIC_GROUP_SET: ++ { ++ ioc_fm_pcd_frm_replic_group_params_t *param; ++ ++ param = (ioc_fm_pcd_frm_replic_group_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_frm_replic_group_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_frm_replic_group_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_frm_replic_group_params_t ++ *compat_param; ++ ++ compat_param = ++ (ioc_compat_fm_pcd_frm_replic_group_params_t *) ++ XX_Malloc(sizeof(ioc_compat_fm_pcd_frm_replic_group_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ++ ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_frm_replic_group_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_frm_replic_group_params_t *) ++ compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_frm_replic_group_params_t))) { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_frm_replic_group_params(compat_param, ++ param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, ++ (ioc_fm_pcd_frm_replic_group_params_t *)arg, ++ sizeof(ioc_fm_pcd_frm_replic_group_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); ++ } ++ } ++ ++ param->id = FM_PCD_FrmReplicSetGroup(p_LnxWrpFmDev->h_PcdDev, ++ (t_FmPcdFrmReplicGroupParams*)param); ++ ++ if (!param->id) { ++ XX_Free(param); ++ err = E_INVALID_VALUE; ++ /* ++ * Since the LLD has no errno-style error reporting, ++ * we're left here with no other option than to report ++ * a generic E_INVALID_VALUE ++ */ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_frm_replic_group_params_t ++ *compat_param; ++ ++ compat_param = ++ (ioc_compat_fm_pcd_frm_replic_group_params_t *) ++ XX_Malloc(sizeof(ioc_compat_fm_pcd_frm_replic_group_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ++ ("IOCTL FM PCD")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_frm_replic_group_params_t)); ++ compat_copy_fm_pcd_frm_replic_group_params(compat_param, ++ param, COMPAT_K_TO_US); ++ if (copy_to_user( ++ (ioc_compat_fm_pcd_frm_replic_group_params_t *) ++ compat_ptr(arg), ++ compat_param, ++ sizeof(ioc_compat_fm_pcd_frm_replic_group_params_t))) ++ err = E_WRITE_FAILED; ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_to_user( ++ (ioc_fm_pcd_frm_replic_group_params_t *)arg, ++ param, ++ sizeof(ioc_fm_pcd_frm_replic_group_params_t))) ++ err = E_WRITE_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ break; ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_FRM_REPLIC_GROUP_DELETE_COMPAT: ++#endif ++ case FM_PCD_IOC_FRM_REPLIC_GROUP_DELETE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0, sizeof(ioc_fm_obj_t)); ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, ++ (ioc_compat_fm_obj_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_obj_t))) ++ break; ++ compat_obj_delete(&compat_id, &id); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, ++ sizeof(ioc_fm_obj_t))) ++ break; ++ } ++ ++ return FM_PCD_FrmReplicDeleteGroup(id.obj); ++ } ++ break; ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_FRM_REPLIC_MEMBER_ADD_COMPAT: ++#endif ++ case FM_PCD_IOC_FRM_REPLIC_MEMBER_ADD: ++ { ++ ioc_fm_pcd_frm_replic_member_params_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_frm_replic_member_params_t compat_param; ++ ++ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_copy_fm_pcd_frm_replic_member_params(&compat_param, ¶m, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ if (copy_from_user(¶m, (void *)arg, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ return FM_PCD_FrmReplicAddMember(param.member.h_replic_group, ++ param.member.member_index, ++ (t_FmPcdCcNextEngineParams*)¶m.next_engine_params); ++ } ++ break; ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_FRM_REPLIC_MEMBER_REMOVE_COMPAT: ++#endif ++ case FM_PCD_IOC_FRM_REPLIC_MEMBER_REMOVE: ++ { ++ ioc_fm_pcd_frm_replic_member_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_frm_replic_member_t compat_param; ++ ++ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_copy_fm_pcd_frm_replic_member(&compat_param, ¶m, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ if (copy_from_user(¶m, (void *)arg, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ return FM_PCD_FrmReplicRemoveMember(param.h_replic_group, param.member_index); ++ } ++ break; ++ ++#if defined(CONFIG_COMPAT) ++ case FM_IOC_VSP_CONFIG_COMPAT: ++#endif ++ case FM_IOC_VSP_CONFIG: ++ { ++ ioc_fm_vsp_params_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_vsp_params_t compat_param; ++ ++ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_copy_fm_vsp_params(&compat_param, ¶m, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ if (copy_from_user(¶m, (void *)arg, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ { ++ uint8_t portId = param.port_params.port_id; ++ param.p_fm = p_LnxWrpFmDev->h_Dev; ++ param.liodn_offset = ++ p_LnxWrpFmDev->rxPorts[portId].settings.param.specificParams.rxParams.liodnOffset; ++ } ++ param.id = FM_VSP_Config((t_FmVspParams *)¶m); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_vsp_params_t compat_param; ++ ++ memset(&compat_param, 0, sizeof(compat_param)); ++ compat_copy_fm_vsp_params(&compat_param, ¶m, COMPAT_K_TO_US); ++ ++ if (copy_to_user(compat_ptr(arg), &compat_param, sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ else ++#endif ++ if (copy_to_user((void *)arg, ¶m, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_IOC_VSP_INIT_COMPAT: ++#endif ++ case FM_IOC_VSP_INIT: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0, sizeof(ioc_fm_obj_t)); ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, ++ (ioc_compat_fm_obj_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_obj_t))) ++ break; ++ id.obj = compat_pcd_id2ptr(compat_id.obj); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, ++ sizeof(ioc_fm_obj_t))) ++ break; ++ } ++ ++ return FM_VSP_Init(id.obj); ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_IOC_VSP_FREE_COMPAT: ++#endif ++ case FM_IOC_VSP_FREE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0, sizeof(ioc_fm_obj_t)); ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, ++ (ioc_compat_fm_obj_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_obj_t))) ++ break; ++ compat_obj_delete(&compat_id, &id); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, ++ sizeof(ioc_fm_obj_t))) ++ break; ++ } ++ ++ return FM_VSP_Free(id.obj); ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_IOC_VSP_CONFIG_POOL_DEPLETION_COMPAT: ++#endif ++ case FM_IOC_VSP_CONFIG_POOL_DEPLETION: ++ { ++ ioc_fm_buf_pool_depletion_params_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_buf_pool_depletion_params_t compat_param; ++ ++ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_copy_fm_buf_pool_depletion_params(&compat_param, ¶m, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ if (copy_from_user(¶m, (void *)arg, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ if (FM_VSP_ConfigPoolDepletion(param.p_fm_vsp, ++ (t_FmBufPoolDepletion *)¶m.fm_buf_pool_depletion)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ break; ++ } ++ ++ ++#if defined(CONFIG_COMPAT) ++ case FM_IOC_VSP_CONFIG_BUFFER_PREFIX_CONTENT_COMPAT: ++#endif ++ case FM_IOC_VSP_CONFIG_BUFFER_PREFIX_CONTENT: ++ { ++ ioc_fm_buffer_prefix_content_params_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_buffer_prefix_content_params_t compat_param; ++ ++ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_copy_fm_buffer_prefix_content_params(&compat_param, ¶m, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ if (copy_from_user(¶m, (void *)arg, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ if (FM_VSP_ConfigBufferPrefixContent(param.p_fm_vsp, ++ (t_FmBufferPrefixContent *)¶m.fm_buffer_prefix_content)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_IOC_VSP_CONFIG_NO_SG_COMPAT: ++#endif ++ case FM_IOC_VSP_CONFIG_NO_SG: ++ { ++ ioc_fm_vsp_config_no_sg_params_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_vsp_config_no_sg_params_t compat_param; ++ ++ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_copy_fm_vsp_config_no_sg_params(&compat_param, ¶m, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ if (copy_from_user(¶m, (void *)arg, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ if (FM_VSP_ConfigNoScatherGather(param.p_fm_vsp, param.no_sg)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_IOC_VSP_GET_BUFFER_PRS_RESULT_COMPAT: ++#endif ++ case FM_IOC_VSP_GET_BUFFER_PRS_RESULT: ++ { ++ ioc_fm_vsp_prs_result_params_t param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_vsp_prs_result_params_t compat_param; ++ ++ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_copy_fm_vsp_prs_result_params(&compat_param, ¶m, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ if (copy_from_user(¶m, (void *)arg, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ /* this call just adds the parse results offset to p_data */ ++ param.p_data = FM_VSP_GetBufferPrsResult(param.p_fm_vsp, param.p_data); ++ ++ if (!param.p_data) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_vsp_prs_result_params_t compat_param; ++ ++ memset(&compat_param, 0, sizeof(compat_param)); ++ compat_copy_fm_vsp_prs_result_params(&compat_param, ¶m, COMPAT_K_TO_US); ++ ++ if (copy_to_user(compat_ptr(arg), &compat_param, sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ else ++#endif ++ if (copy_to_user((void *)arg, ¶m, sizeof(param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ break; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++#ifdef FM_CAPWAP_SUPPORT ++#warning "feature not supported!" ++#if defined(CONFIG_COMPAT) ++ case FM_PCD_IOC_STATISTICS_SET_NODE_COMPAT: ++#endif ++ case FM_PCD_IOC_STATISTICS_SET_NODE: ++ { ++/* ioc_fm_pcd_stats_params_t param; ++ ... ++ param->id = FM_PCD_StatisticsSetNode(p_LnxWrpFmDev->h_PcdDev, ++ (t_FmPcdStatsParams *)¶m); ++*/ ++ err = E_NOT_SUPPORTED; ++ break; ++ } ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ++ ("invalid ioctl: cmd:0x%08x(type:0x%02x, nr: %d.\n", ++ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd))); ++ } ++ ++ if (err) ++ RETURN_ERROR(MINOR, err, ("IOCTL FM PCD")); ++ ++ return E_OK; ++} ++ ++void FM_Get_Api_Version(ioc_fm_api_version_t *p_version) ++{ ++ p_version->version.major = FMD_API_VERSION_MAJOR; ++ p_version->version.minor = FMD_API_VERSION_MINOR; ++ p_version->version.respin = FMD_API_VERSION_RESPIN; ++ p_version->version.reserved = 0; ++} ++ ++t_Error LnxwrpFmIOCTL(t_LnxWrpFmDev *p_LnxWrpFmDev, unsigned int cmd, unsigned long arg, bool compat) ++{ ++ t_Error err = E_OK; ++ ++ switch (cmd) ++ { ++ case FM_IOC_SET_PORTS_BANDWIDTH: ++ { ++ ioc_fm_port_bandwidth_params *param; ++ ++ param = (ioc_fm_port_bandwidth_params*) XX_Malloc(sizeof(ioc_fm_port_bandwidth_params)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_port_bandwidth_params)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_port_bandwidth_params*)compat_ptr(arg), sizeof(ioc_fm_port_bandwidth_params))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_port_bandwidth_params*)arg, sizeof(ioc_fm_port_bandwidth_params))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_SetPortsBandwidth(p_LnxWrpFmDev->h_Dev, (t_FmPortsBandwidthParams*) param); ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_IOC_GET_REVISION: ++ { ++ ioc_fm_revision_info_t *param; ++ ++ param = (ioc_fm_revision_info_t *) XX_Malloc(sizeof(ioc_fm_revision_info_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ FM_GetRevision(p_LnxWrpFmDev->h_Dev, (t_FmRevisionInfo*)param); ++ /* This one never returns anything other than E_OK */ ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_to_user((ioc_fm_revision_info_t *)compat_ptr(arg), ++ param, ++ sizeof(ioc_fm_revision_info_t))){ ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_revision_info_t *)arg, ++ param, ++ sizeof(ioc_fm_revision_info_t))){ ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG); ++ } ++ } ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_IOC_SET_COUNTER: ++ { ++ ioc_fm_counters_params_t *param; ++ ++ param = (ioc_fm_counters_params_t *) XX_Malloc(sizeof(ioc_fm_counters_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_counters_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_counters_params_t *)compat_ptr(arg), sizeof(ioc_fm_counters_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_counters_params_t *)arg, sizeof(ioc_fm_counters_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_ModifyCounter(p_LnxWrpFmDev->h_Dev, param->cnt, param->val); ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_IOC_GET_COUNTER: ++ { ++ ioc_fm_counters_params_t *param; ++ ++ param = (ioc_fm_counters_params_t *) XX_Malloc(sizeof(ioc_fm_counters_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD")); ++ ++ memset(param, 0, sizeof(ioc_fm_counters_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_counters_params_t *)compat_ptr(arg), sizeof(ioc_fm_counters_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_counters_params_t *)arg, sizeof(ioc_fm_counters_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ param->val = FM_GetCounter(p_LnxWrpFmDev->h_Dev, param->cnt); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_to_user((ioc_fm_counters_params_t *)compat_ptr(arg), param, sizeof(ioc_fm_counters_params_t))) ++ err = E_READ_FAILED; ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_counters_params_t *)arg, param, sizeof(ioc_fm_counters_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_IOC_FORCE_INTR: ++ { ++ ioc_fm_exceptions param; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (get_user(param, (ioc_fm_exceptions*) compat_ptr(arg))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ else ++#endif ++ { ++ if (get_user(param, (ioc_fm_exceptions*)arg)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_ForceIntr(p_LnxWrpFmDev->h_Dev, (e_FmExceptions)param); ++ break; ++ } ++ ++ case FM_IOC_GET_API_VERSION: ++ { ++ ioc_fm_api_version_t version; ++ ++ FM_Get_Api_Version(&version); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_to_user( ++ (ioc_fm_api_version_t *)compat_ptr(arg), ++ &version, sizeof(version))) ++ err = E_READ_FAILED; ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_api_version_t *)arg, ++ &version, sizeof(version))) ++ err = E_READ_FAILED; ++ } ++ } ++ break; ++ ++ case FM_IOC_CTRL_MON_START: ++ { ++ FM_CtrlMonStart(p_LnxWrpFmDev->h_Dev); ++ } ++ break; ++ ++ case FM_IOC_CTRL_MON_STOP: ++ { ++ FM_CtrlMonStop(p_LnxWrpFmDev->h_Dev); ++ } ++ break; ++ ++#if defined(CONFIG_COMPAT) ++ case FM_IOC_CTRL_MON_GET_COUNTERS_COMPAT: ++#endif ++ case FM_IOC_CTRL_MON_GET_COUNTERS: ++ { ++ ioc_fm_ctrl_mon_counters_params_t param; ++ t_FmCtrlMon mon; ++ ++#if defined(CONFIG_COMPAT) ++ ioc_compat_fm_ctrl_mon_counters_params_t compat_param; ++ ++ if (compat) ++ { ++ if (copy_from_user(&compat_param, (void *)compat_ptr(arg), ++ sizeof(compat_param))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ param.fm_ctrl_index = compat_param.fm_ctrl_index; ++ param.p_mon = (fm_ctrl_mon_t *)compat_ptr(compat_param.p_mon); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(¶m, (void *)arg, sizeof(ioc_fm_ctrl_mon_counters_params_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ if (FM_CtrlMonGetCounters(p_LnxWrpFmDev->h_Dev, param.fm_ctrl_index, &mon)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ if (copy_to_user(param.p_mon, &mon, sizeof(t_FmCtrlMon))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ break; ++ ++ default: ++ return LnxwrpFmPcdIOCTL(p_LnxWrpFmDev, cmd, arg, compat); ++ } ++ ++ if (err) ++ RETURN_ERROR(MINOR, E_INVALID_OPERATION, ("IOCTL FM")); ++ ++ return E_OK; ++} ++ ++t_Error LnxwrpFmPortIOCTL(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev, unsigned int cmd, unsigned long arg, bool compat) ++{ ++ t_Error err = E_OK; ++ ++ _fm_ioctl_dbg("cmd:0x%08x(type:0x%02x, nr:%u).\n", ++ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd) - 70); ++ ++ switch (cmd) ++ { ++ case FM_PORT_IOC_DISABLE: ++ FM_PORT_Disable(p_LnxWrpFmPortDev->h_Dev); ++ /* deliberately ignoring error codes here */ ++ return E_OK; ++ ++ case FM_PORT_IOC_ENABLE: ++ FM_PORT_Enable(p_LnxWrpFmPortDev->h_Dev); ++ /* deliberately ignoring error codes here */ ++ return E_OK; ++ ++ case FM_PORT_IOC_SET_ERRORS_ROUTE: ++ { ++ ioc_fm_port_frame_err_select_t errs; ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (get_user(errs, (ioc_fm_port_frame_err_select_t*)compat_ptr(arg))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ else ++#endif ++ { ++ if (get_user(errs, (ioc_fm_port_frame_err_select_t*)arg)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PORT_SetErrorsRoute(p_LnxWrpFmPortDev->h_Dev, (fmPortFrameErrSelect_t)errs); ++ break; ++ } ++ ++ case FM_PORT_IOC_SET_RATE_LIMIT: ++ { ++ ioc_fm_port_rate_limit_t *param; ++ ++ param = (ioc_fm_port_rate_limit_t *) XX_Malloc(sizeof(ioc_fm_port_rate_limit_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0, sizeof(ioc_fm_port_rate_limit_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_port_rate_limit_t *)compat_ptr(arg), sizeof(ioc_fm_port_rate_limit_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_port_rate_limit_t *)arg, sizeof(ioc_fm_port_rate_limit_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PORT_SetRateLimit(p_LnxWrpFmPortDev->h_Dev, (t_FmPortRateLimit *)param); ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_PORT_IOC_REMOVE_RATE_LIMIT: ++ FM_PORT_DeleteRateLimit(p_LnxWrpFmPortDev->h_Dev); ++ /* deliberately ignoring error codes here */ ++ return E_OK; ++ ++ case FM_PORT_IOC_ALLOC_PCD_FQIDS: ++ { ++ ioc_fm_port_pcd_fqids_params_t *param; ++ ++ if (!p_LnxWrpFmPortDev->pcd_owner_params.cba) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("No one to listen on this PCD!!!")); ++ ++ param = (ioc_fm_port_pcd_fqids_params_t *) XX_Malloc(sizeof(ioc_fm_port_pcd_fqids_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0, sizeof(ioc_fm_port_pcd_fqids_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_port_pcd_fqids_params_t *)compat_ptr(arg), ++ sizeof(ioc_fm_port_pcd_fqids_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_port_pcd_fqids_params_t *)arg, ++ sizeof(ioc_fm_port_pcd_fqids_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (p_LnxWrpFmPortDev->pcd_owner_params.cba(p_LnxWrpFmPortDev->pcd_owner_params.dev, ++ param->num_fqids, ++ param->alignment, ++ ¶m->base_fqid)) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("can't allocate fqids for PCD!!!")); ++ } ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_to_user((ioc_fm_port_pcd_fqids_params_t *)compat_ptr(arg), ++ param, sizeof(ioc_fm_port_pcd_fqids_params_t))) ++ err = E_READ_FAILED; ++ } ++ else ++#endif ++ { ++ if (copy_to_user((ioc_fm_port_pcd_fqids_params_t *)arg, ++ param, sizeof(ioc_fm_port_pcd_fqids_params_t))) ++ err = E_READ_FAILED; ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_PORT_IOC_FREE_PCD_FQIDS: ++ { ++ uint32_t base_fqid; ++ ++ if (!p_LnxWrpFmPortDev->pcd_owner_params.cbf) ++ RETURN_ERROR(MINOR, E_INVALID_STATE, ("No one to listen on this PCD!!!")); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (get_user(base_fqid, (uint32_t*) compat_ptr(arg))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ else ++#endif ++ { ++ if (get_user(base_fqid, (uint32_t*)arg)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ if (p_LnxWrpFmPortDev->pcd_owner_params.cbf(p_LnxWrpFmPortDev->pcd_owner_params.dev, base_fqid)) ++ err = E_WRITE_FAILED; ++ ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PORT_IOC_SET_PCD_COMPAT: ++#endif ++ case FM_PORT_IOC_SET_PCD: ++ { ++ ioc_fm_port_pcd_params_t *port_pcd_params; ++ ioc_fm_port_pcd_prs_params_t *port_pcd_prs_params; ++ ioc_fm_port_pcd_cc_params_t *port_pcd_cc_params; ++ ioc_fm_port_pcd_kg_params_t *port_pcd_kg_params; ++ ioc_fm_port_pcd_plcr_params_t *port_pcd_plcr_params; ++ ++ port_pcd_params = (ioc_fm_port_pcd_params_t *) XX_Malloc( ++ sizeof(ioc_fm_port_pcd_params_t) + ++ sizeof(ioc_fm_port_pcd_prs_params_t) + ++ sizeof(ioc_fm_port_pcd_cc_params_t) + ++ sizeof(ioc_fm_port_pcd_kg_params_t) + ++ sizeof(ioc_fm_port_pcd_plcr_params_t)); ++ if (!port_pcd_params) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(port_pcd_params, 0, ++ sizeof(ioc_fm_port_pcd_params_t) + ++ sizeof(ioc_fm_port_pcd_prs_params_t) + ++ sizeof(ioc_fm_port_pcd_cc_params_t) + ++ sizeof(ioc_fm_port_pcd_kg_params_t) + ++ sizeof(ioc_fm_port_pcd_plcr_params_t)); ++ ++ port_pcd_prs_params = (ioc_fm_port_pcd_prs_params_t *) (port_pcd_params + 1); ++ port_pcd_cc_params = (ioc_fm_port_pcd_cc_params_t *) (port_pcd_prs_params + 1); ++ port_pcd_kg_params = (ioc_fm_port_pcd_kg_params_t *) (port_pcd_cc_params + 1); ++ port_pcd_plcr_params = (ioc_fm_port_pcd_plcr_params_t *) (port_pcd_kg_params + 1); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_port_pcd_params_t *compat_port_pcd_params; ++ ioc_fm_port_pcd_prs_params_t *same_port_pcd_prs_params; ++ ioc_compat_fm_port_pcd_cc_params_t *compat_port_pcd_cc_params; ++ ioc_compat_fm_port_pcd_kg_params_t *compat_port_pcd_kg_params; ++ ioc_compat_fm_port_pcd_plcr_params_t *compat_port_pcd_plcr_params; ++ ++ compat_port_pcd_params = (ioc_compat_fm_port_pcd_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_port_pcd_params_t) + ++ sizeof(ioc_fm_port_pcd_prs_params_t) + ++ sizeof(ioc_compat_fm_port_pcd_cc_params_t) + ++ sizeof(ioc_compat_fm_port_pcd_kg_params_t) + ++ sizeof(ioc_compat_fm_port_pcd_plcr_params_t)); ++ if (!compat_port_pcd_params) ++ { ++ XX_Free(port_pcd_params); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ } ++ ++ memset(compat_port_pcd_params, 0, ++ sizeof(ioc_compat_fm_port_pcd_params_t) + ++ sizeof(ioc_fm_port_pcd_prs_params_t) + ++ sizeof(ioc_compat_fm_port_pcd_cc_params_t) + ++ sizeof(ioc_compat_fm_port_pcd_kg_params_t) + ++ sizeof(ioc_compat_fm_port_pcd_plcr_params_t)); ++ same_port_pcd_prs_params = (ioc_fm_port_pcd_prs_params_t *) (compat_port_pcd_params + 1); ++ compat_port_pcd_cc_params = (ioc_compat_fm_port_pcd_cc_params_t *) (same_port_pcd_prs_params + 1); ++ compat_port_pcd_kg_params = (ioc_compat_fm_port_pcd_kg_params_t *) (compat_port_pcd_cc_params + 1); ++ compat_port_pcd_plcr_params = (ioc_compat_fm_port_pcd_plcr_params_t *) (compat_port_pcd_kg_params + 1); ++ ++ if (copy_from_user(compat_port_pcd_params, ++ (ioc_compat_fm_port_pcd_params_t*) compat_ptr(arg), ++ sizeof(ioc_compat_fm_port_pcd_params_t))) ++ err = E_WRITE_FAILED; ++ ++ while (!err) /* pseudo-while */ ++ { ++ /* set pointers from where to copy from: */ ++ port_pcd_params->p_prs_params = compat_ptr(compat_port_pcd_params->p_prs_params); /* same structure */ ++ port_pcd_params->p_cc_params = compat_ptr(compat_port_pcd_params->p_cc_params); ++ port_pcd_params->p_kg_params = compat_ptr(compat_port_pcd_params->p_kg_params); ++ port_pcd_params->p_plcr_params = compat_ptr(compat_port_pcd_params->p_plcr_params); ++ port_pcd_params->p_ip_reassembly_manip = compat_ptr(compat_port_pcd_params->p_ip_reassembly_manip); ++#if (DPAA_VERSION >= 11) ++ port_pcd_params->p_capwap_reassembly_manip = compat_ptr(compat_port_pcd_params->p_capwap_reassembly_manip); ++#endif ++ /* the prs member is the same, no compat structure...memcpy only */ ++ if (port_pcd_params->p_prs_params) ++ { ++ if (copy_from_user(same_port_pcd_prs_params, ++ port_pcd_params->p_prs_params, ++ sizeof(ioc_fm_port_pcd_prs_params_t))) ++ { ++ err = E_WRITE_FAILED; ++ break; /* from pseudo-while */ ++ } ++ ++ memcpy(port_pcd_prs_params, same_port_pcd_prs_params, sizeof(ioc_fm_port_pcd_prs_params_t)); ++ port_pcd_params->p_prs_params = port_pcd_prs_params; ++ } ++ ++ if (port_pcd_params->p_cc_params) ++ { ++ if (copy_from_user(compat_port_pcd_cc_params, ++ port_pcd_params->p_cc_params, ++ sizeof(ioc_compat_fm_port_pcd_cc_params_t))) ++ { ++ err = E_WRITE_FAILED; ++ break; /* from pseudo-while */ ++ } ++ ++ port_pcd_params->p_cc_params = port_pcd_cc_params; ++ } ++ ++ if (port_pcd_params->p_kg_params) ++ { ++ if (copy_from_user(compat_port_pcd_kg_params, ++ port_pcd_params->p_kg_params, ++ sizeof(ioc_compat_fm_port_pcd_kg_params_t))) ++ { ++ err = E_WRITE_FAILED; ++ break; /* from pseudo-while */ ++ } ++ ++ port_pcd_params->p_kg_params = port_pcd_kg_params; ++ } ++ ++ if (port_pcd_params->p_plcr_params) ++ { ++ if (copy_from_user(compat_port_pcd_plcr_params, ++ port_pcd_params->p_plcr_params, ++ sizeof(ioc_compat_fm_port_pcd_plcr_params_t))) ++ { ++ err = E_WRITE_FAILED; ++ break; /* from pseudo-while */ ++ } ++ ++ port_pcd_params->p_plcr_params = port_pcd_plcr_params; ++ } ++ ++ break; /* pseudo-while: always run once! */ ++ } ++ ++ if (!err) ++ compat_copy_fm_port_pcd(compat_port_pcd_params, port_pcd_params, COMPAT_US_TO_K); ++ ++ XX_Free(compat_port_pcd_params); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(port_pcd_params, ++ (ioc_fm_port_pcd_params_t*) arg, ++ sizeof(ioc_fm_port_pcd_params_t))) ++ err = E_WRITE_FAILED; ++ ++ while (!err) /* pseudo-while */ ++ { ++ if (port_pcd_params->p_prs_params) ++ { ++ if (copy_from_user(port_pcd_prs_params, ++ port_pcd_params->p_prs_params, ++ sizeof(ioc_fm_port_pcd_prs_params_t))) ++ { ++ err = E_WRITE_FAILED; ++ break; /* from pseudo-while */ ++ } ++ ++ port_pcd_params->p_prs_params = port_pcd_prs_params; ++ } ++ ++ if (port_pcd_params->p_cc_params) ++ { ++ if (copy_from_user(port_pcd_cc_params, ++ port_pcd_params->p_cc_params, ++ sizeof(ioc_fm_port_pcd_cc_params_t))) ++ { ++ err = E_WRITE_FAILED; ++ break; /* from pseudo-while */ ++ } ++ ++ port_pcd_params->p_cc_params = port_pcd_cc_params; ++ } ++ ++ if (port_pcd_params->p_kg_params) ++ { ++ if (copy_from_user(port_pcd_kg_params, ++ port_pcd_params->p_kg_params, ++ sizeof(ioc_fm_port_pcd_kg_params_t))) ++ { ++ err = E_WRITE_FAILED; ++ break; /* from pseudo-while */ ++ } ++ ++ port_pcd_params->p_kg_params = port_pcd_kg_params; ++ } ++ ++ if (port_pcd_params->p_plcr_params) ++ { ++ if (copy_from_user(port_pcd_plcr_params, ++ port_pcd_params->p_plcr_params, ++ sizeof(ioc_fm_port_pcd_plcr_params_t))) ++ { ++ err = E_WRITE_FAILED; ++ break; /* from pseudo-while */ ++ } ++ ++ port_pcd_params->p_plcr_params = port_pcd_plcr_params; ++ } ++ ++ break; /* pseudo-while: always run once! */ ++ } ++ } ++ ++ if (!err) ++ err = FM_PORT_SetPCD(p_LnxWrpFmPortDev->h_Dev, (t_FmPortPcdParams*) port_pcd_params); ++ ++ XX_Free(port_pcd_params); ++ break; ++ } ++ ++ case FM_PORT_IOC_DELETE_PCD: ++ err = FM_PORT_DeletePCD(p_LnxWrpFmPortDev->h_Dev); ++ break; ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PORT_IOC_PCD_KG_MODIFY_INITIAL_SCHEME_COMPAT: ++#endif ++ case FM_PORT_IOC_PCD_KG_MODIFY_INITIAL_SCHEME: ++ { ++ ioc_fm_pcd_kg_scheme_select_t *param; ++ ++ param = (ioc_fm_pcd_kg_scheme_select_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_kg_scheme_select_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0, sizeof(ioc_fm_pcd_kg_scheme_select_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_kg_scheme_select_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_pcd_kg_scheme_select_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_pcd_kg_scheme_select_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_kg_scheme_select_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_pcd_kg_scheme_select_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_kg_scheme_select_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_kg_scheme_select(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_kg_scheme_select_t *)arg, ++ sizeof(ioc_fm_pcd_kg_scheme_select_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PORT_PcdKgModifyInitialScheme(p_LnxWrpFmPortDev->h_Dev, (t_FmPcdKgSchemeSelect *)param); ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PORT_IOC_PCD_PLCR_MODIFY_INITIAL_PROFILE_COMPAT: ++#endif ++ case FM_PORT_IOC_PCD_PLCR_MODIFY_INITIAL_PROFILE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0 , sizeof(ioc_fm_obj_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ id.obj = compat_ptr(compat_id.obj); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PORT_PcdPlcrModifyInitialProfile(p_LnxWrpFmPortDev->h_Dev, id.obj); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PORT_IOC_PCD_KG_BIND_SCHEMES_COMPAT: ++#endif ++ case FM_PORT_IOC_PCD_KG_BIND_SCHEMES: ++ { ++ ioc_fm_pcd_port_schemes_params_t *param; ++ ++ param = (ioc_fm_pcd_port_schemes_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_port_schemes_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0 , sizeof(ioc_fm_pcd_port_schemes_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_port_schemes_params_t compat_param; ++ ++ if (copy_from_user(&compat_param, ++ (ioc_compat_fm_pcd_port_schemes_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_port_schemes_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_kg_schemes_params(&compat_param, param, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_port_schemes_params_t *) arg, ++ sizeof(ioc_fm_pcd_port_schemes_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PORT_PcdKgBindSchemes(p_LnxWrpFmPortDev->h_Dev, (t_FmPcdPortSchemesParams *)param); ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PORT_IOC_PCD_KG_UNBIND_SCHEMES_COMPAT: ++#endif ++ case FM_PORT_IOC_PCD_KG_UNBIND_SCHEMES: ++ { ++ ioc_fm_pcd_port_schemes_params_t *param; ++ ++ param = (ioc_fm_pcd_port_schemes_params_t *) XX_Malloc( ++ sizeof(ioc_fm_pcd_port_schemes_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0 , sizeof(ioc_fm_pcd_port_schemes_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_pcd_port_schemes_params_t compat_param; ++ ++ if (copy_from_user(&compat_param, ++ (ioc_compat_fm_pcd_port_schemes_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_pcd_port_schemes_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_pcd_kg_schemes_params(&compat_param, param, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_pcd_port_schemes_params_t *) arg, ++ sizeof(ioc_fm_pcd_port_schemes_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = FM_PORT_PcdKgUnbindSchemes(p_LnxWrpFmPortDev->h_Dev, (t_FmPcdPortSchemesParams *)param); ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_PORT_IOC_PCD_PLCR_ALLOC_PROFILES: ++ { ++ uint16_t num; ++ if (get_user(num, (uint16_t*) arg)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ err = FM_PORT_PcdPlcrAllocProfiles(p_LnxWrpFmPortDev->h_Dev, num); ++ break; ++ } ++ ++ case FM_PORT_IOC_PCD_PLCR_FREE_PROFILES: ++ err = FM_PORT_PcdPlcrFreeProfiles(p_LnxWrpFmPortDev->h_Dev); ++ break; ++ ++ case FM_PORT_IOC_DETACH_PCD: ++ err = FM_PORT_DetachPCD(p_LnxWrpFmPortDev->h_Dev); ++ break; ++ ++ case FM_PORT_IOC_ATTACH_PCD: ++ err = FM_PORT_AttachPCD(p_LnxWrpFmPortDev->h_Dev); ++ break; ++ ++#if defined(CONFIG_COMPAT) ++ case FM_PORT_IOC_PCD_CC_MODIFY_TREE_COMPAT: ++#endif ++ case FM_PORT_IOC_PCD_CC_MODIFY_TREE: ++ { ++ ioc_fm_obj_t id; ++ ++ memset(&id, 0 , sizeof(ioc_fm_obj_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_obj_t compat_id; ++ ++ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ compat_copy_fm_port_pcd_modify_tree(&compat_id, &id, COMPAT_US_TO_K); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ err = FM_PORT_PcdCcModifyTree(p_LnxWrpFmPortDev->h_Dev, id.obj); ++ break; ++ } ++ ++ case FM_PORT_IOC_ADD_CONGESTION_GRPS: ++ case FM_PORT_IOC_REMOVE_CONGESTION_GRPS: ++ { ++ ioc_fm_port_congestion_groups_t *param; ++ ++ param = (ioc_fm_port_congestion_groups_t*) XX_Malloc(sizeof(ioc_fm_port_congestion_groups_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0, sizeof(ioc_fm_port_congestion_groups_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (t_FmPortCongestionGrps*) compat_ptr(arg), ++ sizeof(t_FmPortCongestionGrps))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif /* CONFIG_COMPAT */ ++ { ++ if (copy_from_user(param, (t_FmPortCongestionGrps*) arg, ++ sizeof(t_FmPortCongestionGrps))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ err = (cmd == FM_PORT_IOC_ADD_CONGESTION_GRPS) ++ ? FM_PORT_AddCongestionGrps(p_LnxWrpFmPortDev->h_Dev, (t_FmPortCongestionGrps*) param) ++ : FM_PORT_RemoveCongestionGrps(p_LnxWrpFmPortDev->h_Dev, (t_FmPortCongestionGrps*) param) ++ ; ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_PORT_IOC_ADD_RX_HASH_MAC_ADDR: ++ case FM_PORT_IOC_REMOVE_RX_HASH_MAC_ADDR: ++ { ++ ioc_fm_port_mac_addr_params_t *param; ++ ++ param = (ioc_fm_port_mac_addr_params_t*) XX_Malloc( ++ sizeof(ioc_fm_port_mac_addr_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0, sizeof(ioc_fm_port_mac_addr_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ if (copy_from_user(param, (ioc_fm_port_mac_addr_params_t*) compat_ptr(arg), ++ sizeof(ioc_fm_port_mac_addr_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ else ++#endif /* CONFIG_COMPAT */ ++ { ++ if (copy_from_user(param, (ioc_fm_port_mac_addr_params_t*) arg, ++ sizeof(ioc_fm_port_mac_addr_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ if (p_LnxWrpFmPortDev->pcd_owner_params.dev) ++ { ++ int id = -1; ++ ++ switch(p_LnxWrpFmPortDev->settings.param.portType) ++ { ++ case e_FM_PORT_TYPE_RX: ++ case e_FM_PORT_TYPE_TX: ++ id = p_LnxWrpFmPortDev->id; ++ break; ++ case e_FM_PORT_TYPE_RX_10G: ++ case e_FM_PORT_TYPE_TX_10G: ++ id = p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_MACS; ++ break; ++ default: ++ err = E_NOT_AVAILABLE; ++ REPORT_ERROR(MINOR, err, ("Attempt to add/remove hash MAC addr. to/from MAC-less port!")); ++ } ++ if (id >= 0) ++ { ++ t_LnxWrpFmDev *fm = (t_LnxWrpFmDev *)p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ t_Handle mac_handle = fm->macs[id].h_Dev; ++ ++ err = (cmd == FM_PORT_IOC_ADD_RX_HASH_MAC_ADDR) ++ ? FM_MAC_AddHashMacAddr(mac_handle, (t_EnetAddr*) param) ++ : FM_MAC_RemoveHashMacAddr(mac_handle, (t_EnetAddr*) param); ++ } ++ } ++ else ++ { ++ err = E_NOT_AVAILABLE; ++ REPORT_ERROR(MINOR, err, ("Port not initialized or other error!?!?")); ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++ case FM_PORT_IOC_SET_TX_PAUSE_FRAMES: ++ { ++ t_LnxWrpFmDev *p_LnxWrpFmDev = ++ (t_LnxWrpFmDev *)p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ ioc_fm_port_tx_pause_frames_params_t param; ++ int mac_id = p_LnxWrpFmPortDev->id; ++ ++ if(&p_LnxWrpFmDev->txPorts[mac_id] != p_LnxWrpFmPortDev) ++ mac_id += FM_MAX_NUM_OF_1G_MACS; /* 10G port */ ++ ++ if (copy_from_user(¶m, (ioc_fm_port_tx_pause_frames_params_t *)arg, ++ sizeof(ioc_fm_port_tx_pause_frames_params_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ if (p_LnxWrpFmDev && p_LnxWrpFmDev->macs[mac_id].h_Dev) ++ { ++ FM_MAC_SetTxPauseFrames(p_LnxWrpFmDev->macs[mac_id].h_Dev, ++ param.priority, ++ param.pause_time, ++ param.thresh_time); ++ } ++ else ++ { ++ err = E_NOT_AVAILABLE; ++ REPORT_ERROR(MINOR, err, ("Port not initialized or other error!")); ++ } ++ ++ break; ++ } ++ ++ case FM_PORT_IOC_CONFIG_BUFFER_PREFIX_CONTENT: ++ { ++ ioc_fm_buffer_prefix_content_t *param; ++ ++ param = (ioc_fm_buffer_prefix_content_t*) XX_Malloc(sizeof(ioc_fm_buffer_prefix_content_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0, sizeof(ioc_fm_buffer_prefix_content_t)); ++ ++ if (copy_from_user(param, (ioc_fm_buffer_prefix_content_t*) arg, ++ sizeof(ioc_fm_buffer_prefix_content_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ if (FM_PORT_ConfigBufferPrefixContent(p_LnxWrpFmPortDev->h_Dev, ++ (t_FmBufferPrefixContent *)param)) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ XX_Free(param); ++ break; ++ } ++ ++#if (DPAA_VERSION >= 11) ++#if defined(CONFIG_COMPAT) ++ case FM_PORT_IOC_VSP_ALLOC_COMPAT: ++#endif ++ case FM_PORT_IOC_VSP_ALLOC: ++ { ++ ioc_fm_port_vsp_alloc_params_t *param; ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ t_LnxWrpFmPortDev *p_LnxWrpFmTxPortDev; ++ ++ param = (ioc_fm_port_vsp_alloc_params_t *) XX_Malloc( ++ sizeof(ioc_fm_port_vsp_alloc_params_t)); ++ if (!param) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ ++ memset(param, 0, sizeof(ioc_fm_port_vsp_alloc_params_t)); ++ ++#if defined(CONFIG_COMPAT) ++ if (compat) ++ { ++ ioc_compat_fm_port_vsp_alloc_params_t *compat_param; ++ ++ compat_param = (ioc_compat_fm_port_vsp_alloc_params_t *) XX_Malloc( ++ sizeof(ioc_compat_fm_port_vsp_alloc_params_t)); ++ if (!compat_param) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT")); ++ } ++ ++ memset(compat_param, 0, sizeof(ioc_compat_fm_port_vsp_alloc_params_t)); ++ if (copy_from_user(compat_param, ++ (ioc_compat_fm_port_vsp_alloc_params_t *) compat_ptr(arg), ++ sizeof(ioc_compat_fm_port_vsp_alloc_params_t))) ++ { ++ XX_Free(compat_param); ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ compat_copy_fm_port_vsp_alloc_params(compat_param, param, COMPAT_US_TO_K); ++ ++ XX_Free(compat_param); ++ } ++ else ++#endif ++ { ++ if (copy_from_user(param, (ioc_fm_port_vsp_alloc_params_t *)arg, ++ sizeof(ioc_fm_port_vsp_alloc_params_t))) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ } ++ ++ /* Userspace may not have the Tx port t_handle when issuing the IOCTL */ ++ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX || ++ p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX_10G) ++ { ++ /* Determine the Tx port t_Handle from the Rx port id */ ++ p_LnxWrpFmDev = p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ p_LnxWrpFmTxPortDev = &p_LnxWrpFmDev->txPorts[p_LnxWrpFmPortDev->id]; ++ param->p_fm_tx_port = p_LnxWrpFmTxPortDev->h_Dev; ++ } ++ ++ if (FM_PORT_VSPAlloc(p_LnxWrpFmPortDev->h_Dev, (t_FmPortVSPAllocParams *)param)) ++ { ++ XX_Free(param); ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ } ++ ++ XX_Free(param); ++ break; ++ } ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ case FM_PORT_IOC_GET_MAC_STATISTICS: ++ { ++ t_LnxWrpFmDev *p_LnxWrpFmDev = ++ (t_LnxWrpFmDev *)p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ ioc_fm_port_mac_statistics_t param; ++ int mac_id = p_LnxWrpFmPortDev->id; ++ ++ if (!p_LnxWrpFmDev) ++ RETURN_ERROR(MINOR, E_NOT_AVAILABLE, ("Port not initialized or other error!")); ++ ++ if (&p_LnxWrpFmDev->txPorts[mac_id] != p_LnxWrpFmPortDev && ++ &p_LnxWrpFmDev->rxPorts[mac_id] != p_LnxWrpFmPortDev) ++ mac_id += FM_MAX_NUM_OF_1G_MACS; /* 10G port */ ++ ++ if (!p_LnxWrpFmDev->macs[mac_id].h_Dev) ++ RETURN_ERROR(MINOR, E_NOT_AVAILABLE, ("Port not initialized or other error!")); ++ ++ if (FM_MAC_GetStatistics(p_LnxWrpFmDev->macs[mac_id].h_Dev, ++ (t_FmMacStatistics *)¶m)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ if (copy_to_user((ioc_fm_port_mac_statistics_t *)arg, ¶m, ++ sizeof(ioc_fm_port_mac_statistics_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ break; ++ } ++ ++ case FM_PORT_IOC_GET_BMI_COUNTERS: ++ { ++ t_LnxWrpFmDev *p_LnxWrpFmDev = ++ (t_LnxWrpFmDev *)p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ ioc_fm_port_bmi_stats_t param; ++ int port_id = p_LnxWrpFmPortDev->id; ++ ++ if (!p_LnxWrpFmDev) ++ RETURN_ERROR(MINOR, E_NOT_AVAILABLE, ("Port not initialized or other error!")); ++ ++ if (FM_PORT_GetBmiCounters(p_LnxWrpFmPortDev->h_Dev, ++ (t_FmPortBmiStats *)¶m)) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ if (copy_to_user((ioc_fm_port_bmi_stats_t *)arg, ¶m, ++ sizeof(ioc_fm_port_bmi_stats_t))) ++ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG); ++ ++ break; ++ } ++ ++ default: ++ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ++ ("invalid ioctl: cmd:0x%08x(type:0x%02x, nr:0x%02x.\n", ++ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd))); ++ } ++ ++ if (err) ++ RETURN_ERROR(MINOR, E_INVALID_OPERATION, ("IOCTL FM PORT")); ++ ++ return E_OK; ++} ++ ++/*****************************************************************************/ ++/* API routines for the FM Linux Device */ ++/*****************************************************************************/ ++ ++static int fm_open(struct inode *inode, struct file *file) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL; ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = NULL; ++ unsigned int major = imajor(inode); ++ unsigned int minor = iminor(inode); ++ struct device_node *fm_node; ++ static struct of_device_id fm_node_of_match[] = { ++ { .compatible = "fsl,fman", }, ++ { /* end of list */ }, ++ }; ++ ++ DBG(TRACE, ("Opening minor - %d - ", minor)); ++ ++ if (file->private_data != NULL) ++ return 0; ++ ++ /* Get all the FM nodes */ ++ for_each_matching_node(fm_node, fm_node_of_match) { ++ struct platform_device *of_dev; ++ ++ of_dev = of_find_device_by_node(fm_node); ++ if (unlikely(of_dev == NULL)) { ++ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("fm id!")); ++ return -ENXIO; ++ } ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *)fm_bind(&of_dev->dev); ++ if (p_LnxWrpFmDev->major == major) ++ break; ++ fm_unbind((struct fm *)p_LnxWrpFmDev); ++ p_LnxWrpFmDev = NULL; ++ } ++ ++ if (!p_LnxWrpFmDev) ++ return -ENODEV; ++ ++ if (minor == DEV_FM_MINOR_BASE) ++ file->private_data = p_LnxWrpFmDev; ++ else if (minor == DEV_FM_PCD_MINOR_BASE) ++ file->private_data = p_LnxWrpFmDev; ++ else { ++ if (minor == DEV_FM_OH_PORTS_MINOR_BASE) ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->hcPort; ++ else if ((minor > DEV_FM_OH_PORTS_MINOR_BASE) && (minor < DEV_FM_RX_PORTS_MINOR_BASE)) ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->opPorts[minor-DEV_FM_OH_PORTS_MINOR_BASE-1]; ++ else if ((minor >= DEV_FM_RX_PORTS_MINOR_BASE) && (minor < DEV_FM_TX_PORTS_MINOR_BASE)) ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[minor-DEV_FM_RX_PORTS_MINOR_BASE]; ++ else if ((minor >= DEV_FM_TX_PORTS_MINOR_BASE) && (minor < DEV_FM_MAX_MINORS)) ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[minor-DEV_FM_TX_PORTS_MINOR_BASE]; ++ else ++ return -EINVAL; ++ ++ /* if trying to open port, check if it initialized */ ++ if (!p_LnxWrpFmPortDev->h_Dev) ++ return -ENODEV; ++ ++ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)fm_port_bind(p_LnxWrpFmPortDev->dev); ++ file->private_data = p_LnxWrpFmPortDev; ++ fm_unbind((struct fm *)p_LnxWrpFmDev); ++ } ++ ++ if (file->private_data == NULL) ++ return -ENXIO; ++ ++ return 0; ++} ++ ++static int fm_close(struct inode *inode, struct file *file) ++{ ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev; ++ unsigned int minor = iminor(inode); ++ int err = 0; ++ ++ DBG(TRACE, ("Closing minor - %d - ", minor)); ++ ++ if ((minor == DEV_FM_MINOR_BASE) || ++ (minor == DEV_FM_PCD_MINOR_BASE)) ++ { ++ p_LnxWrpFmDev = (t_LnxWrpFmDev*)file->private_data; ++ if (!p_LnxWrpFmDev) ++ return -ENODEV; ++ fm_unbind((struct fm *)p_LnxWrpFmDev); ++ } ++ else if (((minor >= DEV_FM_OH_PORTS_MINOR_BASE) && (minor < DEV_FM_RX_PORTS_MINOR_BASE)) || ++ ((minor >= DEV_FM_RX_PORTS_MINOR_BASE) && (minor < DEV_FM_TX_PORTS_MINOR_BASE)) || ++ ((minor >= DEV_FM_TX_PORTS_MINOR_BASE) && (minor < DEV_FM_MAX_MINORS))) ++ { ++ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)file->private_data; ++ if (!p_LnxWrpFmPortDev) ++ return -ENODEV; ++ fm_port_unbind((struct fm_port *)p_LnxWrpFmPortDev); ++ } ++ ++ return err; ++} ++ ++static int fm_ioctls(unsigned int minor, struct file *file, unsigned int cmd, unsigned long arg, bool compat) ++{ ++ DBG(TRACE, ("IOCTL minor - %u, cmd - 0x%08x, arg - 0x%08lx \n", minor, cmd, arg)); ++ ++ if ((minor == DEV_FM_MINOR_BASE) || ++ (minor == DEV_FM_PCD_MINOR_BASE)) ++ { ++ t_LnxWrpFmDev *p_LnxWrpFmDev = ((t_LnxWrpFmDev*)file->private_data); ++ if (!p_LnxWrpFmDev) ++ return -ENODEV; ++ if (LnxwrpFmIOCTL(p_LnxWrpFmDev, cmd, arg, compat)) ++ return -EFAULT; ++ } ++ else if (((minor >= DEV_FM_OH_PORTS_MINOR_BASE) && (minor < DEV_FM_RX_PORTS_MINOR_BASE)) || ++ ((minor >= DEV_FM_RX_PORTS_MINOR_BASE) && (minor < DEV_FM_TX_PORTS_MINOR_BASE)) || ++ ((minor >= DEV_FM_TX_PORTS_MINOR_BASE) && (minor < DEV_FM_MAX_MINORS))) ++ { ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = ((t_LnxWrpFmPortDev*)file->private_data); ++ if (!p_LnxWrpFmPortDev) ++ return -ENODEV; ++ if (LnxwrpFmPortIOCTL(p_LnxWrpFmPortDev, cmd, arg, compat)) ++ return -EFAULT; ++ } ++ else ++ { ++ REPORT_ERROR(MINOR, E_INVALID_VALUE, ("minor")); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++#ifdef CONFIG_COMPAT ++static long fm_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ unsigned int minor = iminor(file->f_path.dentry->d_inode); ++ long res; ++ ++ fm_mutex_lock(); ++ res = fm_ioctls(minor, file, cmd, arg, true); ++ fm_mutex_unlock(); ++ ++ return res; ++} ++#endif ++ ++static long fm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ unsigned int minor = iminor(file->f_path.dentry->d_inode); ++ long res; ++ ++ fm_mutex_lock(); ++ res = fm_ioctls(minor, file, cmd, arg, false); ++ fm_mutex_unlock(); ++ ++ return res; ++} ++ ++/* Globals for FM character device */ ++struct file_operations fm_fops = ++{ ++ .owner = THIS_MODULE, ++ .unlocked_ioctl = fm_ioctl, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = fm_compat_ioctl, ++#endif ++ .open = fm_open, ++ .release = fm_close, ++}; +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.c +new file mode 100644 +index 0000000..1de4886 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.c +@@ -0,0 +1,1296 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/* ++ @File lnxwrp_fm_compat_ioctls.c ++ ++ @Description FM PCD compat functions ++ ++*/ ++ ++#if !defined(CONFIG_COMPAT) ++#error "missing COMPAT layer..." ++#endif ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "part_ext.h" ++#include "fm_ioctls.h" ++#include "fm_pcd_ioctls.h" ++#include "fm_port_ioctls.h" ++#include "lnxwrp_ioctls_fm_compat.h" ++ ++#if defined(FM_COMPAT_DBG) ++static void hex_dump(void * p_addr, unsigned int size) ++{ ++ int i; ++ ++ for(i=0; i\n", p); ++ ++ if(!p) ++ return 0; ++ ++ for(k=1; k < COMPAT_PTR2ID_ARRAY_MAX; k++) ++ if(compat_ptr2id_array[k].ptr == NULL) ++ { ++ compat_ptr2id_array[k].ptr = p; ++ compat_ptr2id_array[k].node_type = node_type; ++ _fm_cpt_dbg(COMPAT_GENERIC, "0x%08x \n", k | COMPAT_PTR2ID_WATERMARK); ++ return k | COMPAT_PTR2ID_WATERMARK; ++ } ++ ++ printk(KERN_WARNING "FMan map list full! No more PCD space on kernel!\n"); ++ return 0; ++} ++EXPORT_SYMBOL(compat_add_ptr2id); ++ ++compat_uptr_t compat_get_ptr2id(void *p, enum fm_map_node_type node_type) ++{ ++ compat_uptr_t k; ++ ++ _fm_cpt_dbg(COMPAT_GENERIC, " (%p) get -> \n", p); ++ ++ for(k=1; k < COMPAT_PTR2ID_ARRAY_MAX; k++) ++ if(compat_ptr2id_array[k].ptr == p && ++ compat_ptr2id_array[k].node_type == node_type) { ++ ++ _fm_cpt_dbg(COMPAT_GENERIC, "0x%08x\n", k | COMPAT_PTR2ID_WATERMARK); ++ return k | COMPAT_PTR2ID_WATERMARK; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(compat_get_ptr2id); ++ ++void *compat_get_id2ptr(compat_uptr_t comp, enum fm_map_node_type node_type) ++{ ++ ++ _fm_cpt_dbg(COMPAT_GENERIC, " (0x%08x) get -> \n", comp); ++ ++ if((COMPAT_PTR2ID_WM_MASK & comp) != COMPAT_PTR2ID_WATERMARK) { ++ _fm_cpt_dbg(COMPAT_GENERIC, "Error, invalid watermark (0x%08x)!\n\n", comp); ++ dump_stack(); ++ return compat_ptr(comp); ++ } ++ ++ comp &= ~COMPAT_PTR2ID_WM_MASK; ++ ++ if(((0 < comp) && (comp < COMPAT_PTR2ID_ARRAY_MAX) && (compat_ptr2id_array[comp].ptr != NULL) ++ && compat_ptr2id_array[comp].node_type == node_type)) { ++ _fm_cpt_dbg(COMPAT_GENERIC, "%p\n", compat_ptr2id_array[comp].ptr); ++ return compat_ptr2id_array[comp].ptr; ++ } ++ return NULL; ++} ++EXPORT_SYMBOL(compat_get_id2ptr); ++/* } maping kernel pointers w/ UserSpace id's */ ++ ++void compat_obj_delete( ++ ioc_compat_fm_obj_t *compat_id, ++ ioc_fm_obj_t *id) ++{ ++ id->obj = compat_pcd_id2ptr(compat_id->obj); ++ compat_del_ptr2id(id->obj, FM_MAP_TYPE_PCD_NODE); ++} ++ ++static inline void compat_copy_fm_pcd_plcr_next_engine( ++ ioc_compat_fm_pcd_plcr_next_engine_params_u *compat_param, ++ ioc_fm_pcd_plcr_next_engine_params_u *param, ++ ioc_fm_pcd_engine next_engine, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ switch (next_engine) ++ { ++ case e_IOC_FM_PCD_PLCR: ++ if (compat == COMPAT_US_TO_K) ++ param->p_profile = compat_pcd_id2ptr(compat_param->p_profile); ++ else ++ compat_param->p_profile = compat_pcd_ptr2id(param->p_profile); ++ break; ++ case e_IOC_FM_PCD_KG: ++ if (compat == COMPAT_US_TO_K) ++ param->p_direct_scheme = compat_pcd_id2ptr(compat_param->p_direct_scheme); ++ else ++ compat_param->p_direct_scheme = compat_pcd_ptr2id(param->p_direct_scheme); ++ break; ++ default: ++ if (compat == COMPAT_US_TO_K) ++ param->action = compat_param->action; ++ else ++ compat_param->action = param->action; ++ break; ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_pcd_plcr_profile( ++ ioc_compat_fm_pcd_plcr_profile_params_t *compat_param, ++ ioc_fm_pcd_plcr_profile_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->modify = compat_param->modify; ++ ++ /* profile_select */ ++ if (!compat_param->modify) ++ { ++ param->profile_select.new_params.profile_type = ++ compat_param->profile_select.new_params.profile_type; ++ param->profile_select.new_params.p_fm_port = ++ compat_ptr(compat_param->profile_select.new_params.p_fm_port); ++ param->profile_select.new_params.relative_profile_id = ++ compat_param->profile_select.new_params.relative_profile_id; ++ } ++ else ++ param->profile_select.p_profile = ++ compat_pcd_id2ptr(compat_param->profile_select.p_profile); ++ ++ param->alg_selection = compat_param->alg_selection; ++ param->color_mode = compat_param->color_mode; ++ ++ /* both parameters in the union has the same size, so memcpy works */ ++ memcpy(¶m->color, &compat_param->color, sizeof(param->color)); ++ ++ memcpy(¶m->non_passthrough_alg_param, ++ &compat_param->non_passthrough_alg_param, ++ sizeof(ioc_fm_pcd_plcr_non_passthrough_alg_param_t)); ++ ++ param->next_engine_on_green = compat_param->next_engine_on_green; ++ param->next_engine_on_yellow = compat_param->next_engine_on_yellow; ++ param->next_engine_on_red = compat_param->next_engine_on_red; ++ ++ param->trap_profile_on_flow_A = compat_param->trap_profile_on_flow_A; ++ param->trap_profile_on_flow_B = compat_param->trap_profile_on_flow_B; ++ param->trap_profile_on_flow_C = compat_param->trap_profile_on_flow_C; ++ } ++ else ++ { ++ compat_param->modify = param->modify; ++ ++ /* profile_select */ ++ if (!param->modify) ++ { ++ compat_param->profile_select.new_params.profile_type = ++ param->profile_select.new_params.profile_type; ++ compat_param->profile_select.new_params.p_fm_port = ++ ptr_to_compat(param->profile_select.new_params.p_fm_port); ++ compat_param->profile_select.new_params.relative_profile_id = ++ param->profile_select.new_params.relative_profile_id; ++ } ++ else ++ compat_param->profile_select.p_profile = ++ compat_pcd_ptr2id(param->profile_select.p_profile); ++ ++ compat_param->alg_selection = param->alg_selection; ++ compat_param->color_mode = param->color_mode; ++ ++ /* both parameters in the union has the same size, so memcpy works */ ++ memcpy(&compat_param->color, ¶m->color, sizeof(compat_param->color)); ++ ++ memcpy(&compat_param->non_passthrough_alg_param, ++ ¶m->non_passthrough_alg_param, ++ sizeof(ioc_fm_pcd_plcr_non_passthrough_alg_param_t)); ++ ++ compat_param->next_engine_on_green = param->next_engine_on_green; ++ compat_param->next_engine_on_yellow = param->next_engine_on_yellow; ++ compat_param->next_engine_on_red = param->next_engine_on_red; ++ ++ compat_param->trap_profile_on_flow_A = param->trap_profile_on_flow_A; ++ compat_param->trap_profile_on_flow_B = param->trap_profile_on_flow_B; ++ compat_param->trap_profile_on_flow_C = param->trap_profile_on_flow_C; ++ ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ } ++ ++ compat_copy_fm_pcd_plcr_next_engine(&compat_param->params_on_green, ++ ¶m->params_on_green, param->next_engine_on_green, compat); ++ ++ compat_copy_fm_pcd_plcr_next_engine(&compat_param->params_on_yellow, ++ ¶m->params_on_yellow, param->next_engine_on_yellow, compat); ++ ++ compat_copy_fm_pcd_plcr_next_engine(&compat_param->params_on_red, ++ ¶m->params_on_red, param->next_engine_on_red, compat); ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++static inline void compat_copy_fm_pcd_cc_next_kg( ++ ioc_compat_fm_pcd_cc_next_kg_params_t *compat_param, ++ ioc_fm_pcd_cc_next_kg_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->new_fqid = compat_param->new_fqid; ++ param->override_fqid = compat_param->override_fqid; ++#if DPAA_VERSION >= 11 ++ param->new_relative_storage_profile_id = compat_param->new_relative_storage_profile_id; ++#endif ++ param->p_direct_scheme = compat_pcd_id2ptr(compat_param->p_direct_scheme); ++ } ++ else ++ { ++ compat_param->new_fqid = param->new_fqid; ++ compat_param->override_fqid = param->override_fqid; ++#if DPAA_VERSION >= 11 ++ compat_param->new_relative_storage_profile_id = param->new_relative_storage_profile_id; ++#endif ++ compat_param->p_direct_scheme = compat_pcd_ptr2id(param->p_direct_scheme); ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++static inline void compat_copy_fm_pcd_cc_next_cc( ++ ioc_compat_fm_pcd_cc_next_cc_params_t *compat_param, ++ ioc_fm_pcd_cc_next_cc_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ param->cc_node_id = compat_pcd_id2ptr(compat_param->cc_node_id); ++ else ++ compat_param->cc_node_id = compat_pcd_ptr2id(param->cc_node_id); ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++static inline void compat_copy_fm_pcd_cc_next_engine( ++ ioc_compat_fm_pcd_cc_next_engine_params_t *compat_param, ++ ioc_fm_pcd_cc_next_engine_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->next_engine = compat_param->next_engine; ++ if (param->next_engine != e_IOC_FM_PCD_INVALID ) ++ _fm_cpt_dbg(compat, " param->next_engine = %i \n", param->next_engine); ++ ++ switch (param->next_engine) ++ { ++#if DPAA_VERSION >= 11 ++ case e_IOC_FM_PCD_FR: ++ param->params.fr_params.frm_replic_id = compat_pcd_id2ptr(compat_param->params.fr_params.frm_replic_id); ++ break; ++#endif /* DPAA_VERSION >= 11 */ ++ case e_IOC_FM_PCD_CC: ++ compat_copy_fm_pcd_cc_next_cc(&compat_param->params.cc_params, ¶m->params.cc_params, compat); ++ break; ++ case e_IOC_FM_PCD_KG: ++ param->manip_id = compat_pcd_id2ptr(compat_param->manip_id); ++ compat_copy_fm_pcd_cc_next_kg(&compat_param->params.kg_params, ¶m->params.kg_params, compat); ++ break; ++ case e_IOC_FM_PCD_DONE: ++ case e_IOC_FM_PCD_PLCR: ++ param->manip_id = compat_pcd_id2ptr(compat_param->manip_id); ++ default: ++ memcpy(¶m->params, &compat_param->params, sizeof(param->params)); ++ } ++ param->statistics_en = compat_param->statistics_en; ++ } ++ else ++ { ++ compat_param->next_engine = param->next_engine; ++ ++ switch (compat_param->next_engine) ++ { ++#if DPAA_VERSION >= 11 ++ case e_IOC_FM_PCD_FR: ++ compat_param->params.fr_params.frm_replic_id = compat_pcd_ptr2id(param->params.fr_params.frm_replic_id); ++ break; ++#endif /* DPAA_VERSION >= 11 */ ++ case e_IOC_FM_PCD_CC: ++ compat_copy_fm_pcd_cc_next_cc(&compat_param->params.cc_params, ¶m->params.cc_params, compat); ++ break; ++ case e_IOC_FM_PCD_KG: ++ compat_param->manip_id = compat_pcd_ptr2id(param->manip_id); ++ compat_copy_fm_pcd_cc_next_kg(&compat_param->params.kg_params, ¶m->params.kg_params, compat); ++ break; ++ case e_IOC_FM_PCD_DONE: ++ case e_IOC_FM_PCD_PLCR: ++ compat_param->manip_id = compat_pcd_ptr2id(param->manip_id); ++ default: ++ memcpy(&compat_param->params, ¶m->params, sizeof(compat_param->params)); ++ } ++ compat_param->statistics_en = param->statistics_en; ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_pcd_cc_key( ++ ioc_compat_fm_pcd_cc_key_params_t *compat_param, ++ ioc_fm_pcd_cc_key_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->p_key = compat_ptr(compat_param->p_key); ++ param->p_mask = compat_ptr(compat_param->p_mask); ++ } ++ else ++ { ++ compat_param->p_key = ptr_to_compat(param->p_key); ++ compat_param->p_mask = ptr_to_compat(param->p_mask); ++ } ++ ++ compat_copy_fm_pcd_cc_next_engine( ++ &compat_param->cc_next_engine_params, ++ ¶m->cc_next_engine_params, ++ compat); ++} ++ ++void compat_copy_fm_pcd_cc_node_modify_key_and_next_engine( ++ ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *compat_param, ++ ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ param->key_indx = compat_param->key_indx; ++ param->key_size = compat_param->key_size; ++ compat_copy_fm_pcd_cc_key( ++ &compat_param->key_params, ++ ¶m->key_params, ++ compat); ++ } ++ else ++ { ++ compat_param->id = compat_pcd_ptr2id(param->id); ++ compat_param->key_indx = param->key_indx; ++ compat_param->key_size = param->key_size; ++ compat_copy_fm_pcd_cc_key( ++ &compat_param->key_params, ++ ¶m->key_params, ++ compat); ++ } ++} ++ ++void compat_copy_fm_pcd_cc_node_modify_next_engine( ++ ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *compat_param, ++ ioc_fm_pcd_cc_node_modify_next_engine_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ param->key_indx = compat_param->key_indx; ++ param->key_size = compat_param->key_size; ++ } ++ else ++ { ++ compat_param->id = compat_pcd_ptr2id(param->id); ++ compat_param->key_indx = param->key_indx; ++ compat_param->key_size = param->key_size; ++ } ++ ++ compat_copy_fm_pcd_cc_next_engine( ++ &compat_param->cc_next_engine_params, ++ ¶m->cc_next_engine_params, ++ compat); ++} ++ ++void compat_fm_pcd_cc_tree_modify_next_engine( ++ ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *compat_param, ++ ioc_fm_pcd_cc_tree_modify_next_engine_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ param->grp_indx = compat_param->grp_indx; ++ param->indx = compat_param->indx; ++ } ++ else ++ { ++ compat_param->id = compat_pcd_ptr2id(param->id); ++ compat_param->grp_indx = param->grp_indx; ++ compat_param->indx = param->indx; ++ } ++ ++ compat_copy_fm_pcd_cc_next_engine( ++ &compat_param->cc_next_engine_params, ++ ¶m->cc_next_engine_params, ++ compat); ++} ++ ++void compat_copy_fm_pcd_hash_table( ++ ioc_compat_fm_pcd_hash_table_params_t *compat_param, ++ ioc_fm_pcd_hash_table_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->max_num_of_keys = compat_param->max_num_of_keys; ++ param->statistics_mode = compat_param->statistics_mode; ++ param->kg_hash_shift = compat_param->kg_hash_shift; ++ param->hash_res_mask = compat_param->hash_res_mask; ++ param->hash_shift = compat_param->hash_shift; ++ param->match_key_size = compat_param->match_key_size; ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ } ++ else ++ { ++ compat_param->max_num_of_keys = param->max_num_of_keys; ++ compat_param->statistics_mode = param->statistics_mode; ++ compat_param->kg_hash_shift = param->kg_hash_shift; ++ compat_param->hash_res_mask = param->hash_res_mask; ++ compat_param->hash_shift = param->hash_shift; ++ compat_param->match_key_size = param->match_key_size; ++ ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ } ++ ++ compat_copy_fm_pcd_cc_next_engine( ++ &compat_param->cc_next_engine_params_for_miss, ++ ¶m->cc_next_engine_params_for_miss, ++ compat); ++} ++ ++void compat_copy_fm_pcd_cc_grp( ++ ioc_compat_fm_pcd_cc_grp_params_t *compat_param, ++ ioc_fm_pcd_cc_grp_params_t *param, ++ uint8_t compat) ++{ ++ int k; ++ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->num_of_distinction_units = compat_param->num_of_distinction_units; ++ memcpy(param->unit_ids, compat_param->unit_ids, IOC_FM_PCD_MAX_NUM_OF_CC_UNITS); ++ } ++ else ++ { ++ compat_param->num_of_distinction_units = param->num_of_distinction_units; ++ memcpy(compat_param->unit_ids, param->unit_ids, IOC_FM_PCD_MAX_NUM_OF_CC_UNITS); ++ } ++ ++ for (k=0; k < IOC_FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP; k++) ++ compat_copy_fm_pcd_cc_next_engine( ++ &compat_param->next_engine_per_entries_in_grp[k], ++ ¶m->next_engine_per_entries_in_grp[k], ++ compat); ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_pcd_cc_tree( ++ ioc_compat_fm_pcd_cc_tree_params_t *compat_param, ++ ioc_fm_pcd_cc_tree_params_t *param, ++ uint8_t compat) ++{ ++ int k; ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->net_env_id = compat_pcd_id2ptr(compat_param->net_env_id); ++ param->num_of_groups = compat_param->num_of_groups; ++ } ++ else ++ { ++ compat_param->net_env_id = compat_pcd_ptr2id(param->net_env_id); ++ compat_param->num_of_groups = param->num_of_groups; ++ ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ } ++ ++ for (k=0; k < IOC_FM_PCD_MAX_NUM_OF_CC_GROUPS; k++) ++ compat_copy_fm_pcd_cc_grp( ++ &compat_param->fm_pcd_cc_group_params[k], ++ ¶m->fm_pcd_cc_group_params[k], ++ compat); ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_fm_pcd_prs_sw( ++ ioc_compat_fm_pcd_prs_sw_params_t *compat_param, ++ ioc_fm_pcd_prs_sw_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->override = compat_param->override; ++ param->size = compat_param->size; ++ param->base = compat_param->base; ++ param->p_code = compat_ptr(compat_param->p_code); ++ memcpy(param->sw_prs_data_params,compat_param->sw_prs_data_params,IOC_FM_PCD_PRS_NUM_OF_HDRS*sizeof(uint32_t)); ++ param->num_of_labels = compat_param->num_of_labels; ++ memcpy(param->labels_table,compat_param->labels_table,IOC_FM_PCD_PRS_NUM_OF_LABELS*sizeof(ioc_fm_pcd_prs_label_params_t)); ++ } ++} ++ ++void compat_copy_fm_pcd_kg_scheme( ++ ioc_compat_fm_pcd_kg_scheme_params_t *compat_param, ++ ioc_fm_pcd_kg_scheme_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg(compat," {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->modify = compat_param->modify; ++ ++ /* scm_id */ ++ if (compat_param->modify) ++ { ++ param->scm_id.scheme_id = compat_pcd_id2ptr(compat_param->scm_id.scheme_id); ++ _fm_cpt_dbg(compat," param->scm_id.scheme_id = %p \n", param->scm_id.scheme_id); ++ } ++ else ++ param->scm_id.relative_scheme_id = compat_param->scm_id.relative_scheme_id; ++ ++ param->always_direct = compat_param->always_direct; ++ /* net_env_params */ ++ param->net_env_params.net_env_id = compat_pcd_id2ptr(compat_param->net_env_params.net_env_id); ++ param->net_env_params.num_of_distinction_units = compat_param->net_env_params.num_of_distinction_units; ++ memcpy(param->net_env_params.unit_ids, ++ compat_param->net_env_params.unit_ids, ++ IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ ++ param->use_hash = compat_param->use_hash; ++ memcpy(¶m->key_extract_and_hash_params, ++ &compat_param->key_extract_and_hash_params, ++ sizeof(ioc_fm_pcd_kg_key_extract_and_hash_params_t)); ++ param->bypass_fqid_generation = compat_param->bypass_fqid_generation; ++ param->base_fqid = compat_param->base_fqid; ++#if DPAA_VERSION >= 11 ++ param->override_storage_profile = ++ compat_param->override_storage_profile; ++ param->storage_profile = compat_param->storage_profile; ++#endif ++ param->num_of_used_extracted_ors = compat_param->num_of_used_extracted_ors; ++ memcpy(param->extracted_ors, ++ compat_param->extracted_ors, ++ IOC_FM_PCD_KG_NUM_OF_GENERIC_REGS * sizeof(ioc_fm_pcd_kg_extracted_or_params_t)); ++ param->next_engine = compat_param->next_engine; ++ ++ /* kg_next_engine_params */ ++ if (param->next_engine == e_IOC_FM_PCD_CC) ++ { ++ param->kg_next_engine_params.cc.tree_id = compat_pcd_id2ptr(compat_param->kg_next_engine_params.cc.tree_id); ++ param->kg_next_engine_params.cc.grp_id = compat_param->kg_next_engine_params.cc.grp_id; ++ param->kg_next_engine_params.cc.plcr_next = compat_param->kg_next_engine_params.cc.plcr_next; ++ param->kg_next_engine_params.cc.bypass_plcr_profile_generation ++ = compat_param->kg_next_engine_params.cc.bypass_plcr_profile_generation; ++ memcpy(¶m->kg_next_engine_params.cc.plcr_profile, ++ &compat_param->kg_next_engine_params.cc.plcr_profile, ++ sizeof(ioc_fm_pcd_kg_plcr_profile_t)); ++ } ++ else ++ memcpy(¶m->kg_next_engine_params, ++ &compat_param->kg_next_engine_params, ++ sizeof(param->kg_next_engine_params)); ++ ++ memcpy(¶m->scheme_counter, ++ &compat_param->scheme_counter, ++ sizeof(ioc_fm_pcd_kg_scheme_counter_t)); ++ } ++ else ++ { ++ compat_param->modify = param->modify; ++ ++ /* scm_id */ ++ if (param->modify) ++ compat_param->scm_id.scheme_id = compat_pcd_ptr2id(param->scm_id.scheme_id); ++ else ++ compat_param->scm_id.relative_scheme_id = param->scm_id.relative_scheme_id; ++ ++ compat_param->always_direct = param->always_direct; ++ ++ /* net_env_params */ ++ compat_param->net_env_params.net_env_id = compat_pcd_ptr2id(param->net_env_params.net_env_id); ++ compat_param->net_env_params.num_of_distinction_units = param->net_env_params.num_of_distinction_units; ++ memcpy(compat_param->net_env_params.unit_ids, param->net_env_params.unit_ids, IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ ++ compat_param->use_hash = param->use_hash; ++ memcpy(&compat_param->key_extract_and_hash_params, ¶m->key_extract_and_hash_params, sizeof(ioc_fm_pcd_kg_key_extract_and_hash_params_t)); ++ compat_param->bypass_fqid_generation = param->bypass_fqid_generation; ++ compat_param->base_fqid = param->base_fqid; ++#if DPAA_VERSION >= 11 ++ compat_param->override_storage_profile = ++ param->override_storage_profile; ++ compat_param->storage_profile = param->storage_profile; ++#endif ++ compat_param->num_of_used_extracted_ors = param->num_of_used_extracted_ors; ++ memcpy(compat_param->extracted_ors, param->extracted_ors, IOC_FM_PCD_KG_NUM_OF_GENERIC_REGS * sizeof(ioc_fm_pcd_kg_extracted_or_params_t)); ++ compat_param->next_engine = param->next_engine; ++ ++ /* kg_next_engine_params */ ++ if (compat_param->next_engine == e_IOC_FM_PCD_CC) ++ { ++ compat_param->kg_next_engine_params.cc.tree_id = compat_pcd_ptr2id(param->kg_next_engine_params.cc.tree_id); ++ compat_param->kg_next_engine_params.cc.grp_id = param->kg_next_engine_params.cc.grp_id; ++ compat_param->kg_next_engine_params.cc.plcr_next = param->kg_next_engine_params.cc.plcr_next; ++ compat_param->kg_next_engine_params.cc.bypass_plcr_profile_generation ++ = param->kg_next_engine_params.cc.bypass_plcr_profile_generation; ++ memcpy(&compat_param->kg_next_engine_params.cc.plcr_profile, ++ ¶m->kg_next_engine_params.cc.plcr_profile, ++ sizeof(ioc_fm_pcd_kg_plcr_profile_t)); ++ } ++ else ++ memcpy(¶m->kg_next_engine_params, &compat_param->kg_next_engine_params, sizeof(compat_param->kg_next_engine_params)); ++ ++ memcpy(&compat_param->scheme_counter, ¶m->scheme_counter, sizeof(ioc_fm_pcd_kg_scheme_counter_t)); ++ ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ } ++ ++ _fm_cpt_dbg(compat," ...->}\n"); ++} ++ ++void compat_copy_fm_pcd_kg_scheme_spc( ++ ioc_compat_fm_pcd_kg_scheme_spc_t *compat_param, ++ ioc_fm_pcd_kg_scheme_spc_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ param->val = compat_param->val; ++ } else { ++ compat_param->id = compat_pcd_ptr2id(param->id); ++ compat_param->val = param->val; ++ } ++} ++ ++ ++void compat_copy_fm_pcd_kg_scheme_select( ++ ioc_compat_fm_pcd_kg_scheme_select_t *compat_param, ++ ioc_fm_pcd_kg_scheme_select_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->direct = compat_param->direct; ++ if (param->direct) ++ param->scheme_id = compat_pcd_id2ptr(compat_param->scheme_id); ++ } ++} ++ ++void compat_copy_fm_pcd_kg_schemes_params( ++ ioc_compat_fm_pcd_port_schemes_params_t *compat_param, ++ ioc_fm_pcd_port_schemes_params_t *param, ++ uint8_t compat) ++{ ++ int k; ++ ++ if (compat == COMPAT_US_TO_K) { ++ param->num_of_schemes = compat_param->num_of_schemes; ++ for(k=0; k < compat_param->num_of_schemes; k++) ++ param->scheme_ids[k] = compat_pcd_id2ptr(compat_param->scheme_ids[k]); ++ } ++} ++ ++void compat_copy_fm_port_pcd_cc( ++ ioc_compat_fm_port_pcd_cc_params_t *compat_cc_params , ++ ioc_fm_port_pcd_cc_params_t *p_cc_params, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K){ ++ p_cc_params->cc_tree_id = compat_pcd_id2ptr(compat_cc_params->cc_tree_id); ++ } ++} ++ ++void compat_copy_fm_port_pcd_kg( ++ ioc_compat_fm_port_pcd_kg_params_t *compat_param, ++ ioc_fm_port_pcd_kg_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K){ ++ uint8_t k; ++ ++ param->num_of_schemes = compat_param->num_of_schemes; ++ for(k=0; knum_of_schemes; k++) ++ param->scheme_ids[k] = compat_pcd_id2ptr(compat_param->scheme_ids[k]); ++ ++ param->direct_scheme = compat_param->direct_scheme; ++ if (param->direct_scheme) ++ param->direct_scheme_id = compat_pcd_id2ptr(compat_param->direct_scheme_id); ++ } ++} ++ ++void compat_copy_fm_port_pcd( ++ ioc_compat_fm_port_pcd_params_t *compat_param, ++ ioc_fm_port_pcd_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ ioc_fm_port_pcd_prs_params_t *same_port_pcd_prs_params; ++ ioc_compat_fm_port_pcd_cc_params_t *compat_port_pcd_cc_params; ++ ioc_compat_fm_port_pcd_kg_params_t *compat_port_pcd_kg_params; ++ ioc_compat_fm_port_pcd_plcr_params_t *compat_port_pcd_plcr_params; ++ ++ same_port_pcd_prs_params = (ioc_fm_port_pcd_prs_params_t *) (compat_param + 1); ++ compat_port_pcd_cc_params = (ioc_compat_fm_port_pcd_cc_params_t *) (same_port_pcd_prs_params + 1); ++ compat_port_pcd_kg_params = (ioc_compat_fm_port_pcd_kg_params_t *) (compat_port_pcd_cc_params + 1); ++ compat_port_pcd_plcr_params = (ioc_compat_fm_port_pcd_plcr_params_t *) (compat_port_pcd_kg_params + 1); ++ ++ _fm_cpt_dbg(compat,"\n param->p_prs_params=%p \n", param->p_prs_params); ++ _fm_cpt_dbg(compat," param->p_cc_params=%p \n", param->p_cc_params); ++ _fm_cpt_dbg(compat," param->p_kg_params=%p \n", param->p_kg_params); ++ _fm_cpt_dbg(compat," param->p_plcr_params=%p \n", param->p_plcr_params); ++ _fm_cpt_dbg(compat," param->p_ip_reassembly_manip=%p \n", param->p_ip_reassembly_manip); ++#if (DPAA_VERSION >= 11) ++ _fm_cpt_dbg(compat," param->p_capwap_reassembly_manip=%p \n", param->p_capwap_reassembly_manip); ++#endif ++ param->pcd_support = compat_param->pcd_support; ++ param->net_env_id = compat_pcd_id2ptr(compat_param->net_env_id); ++ ++ if (param->p_cc_params) ++ compat_copy_fm_port_pcd_cc(compat_port_pcd_cc_params, param->p_cc_params, COMPAT_US_TO_K); ++ if (param->p_kg_params) ++ compat_copy_fm_port_pcd_kg(compat_port_pcd_kg_params, param->p_kg_params, COMPAT_US_TO_K); ++ if (param->p_plcr_params) ++ param->p_plcr_params->plcr_profile_id = compat_pcd_id2ptr(compat_port_pcd_plcr_params->plcr_profile_id); ++ param->p_ip_reassembly_manip = compat_pcd_id2ptr(compat_param->p_ip_reassembly_manip); ++#if (DPAA_VERSION >= 11) ++ param->p_capwap_reassembly_manip = compat_pcd_id2ptr(compat_param->p_capwap_reassembly_manip); ++#endif ++ } ++} ++ ++void compat_copy_fm_port_pcd_modify_tree( ++ ioc_compat_fm_obj_t *compat_id, ++ ioc_fm_obj_t *id, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ id->obj = compat_pcd_id2ptr(compat_id->obj); ++} ++ ++#if (DPAA_VERSION >= 11) ++void compat_copy_fm_port_vsp_alloc_params( ++ ioc_compat_fm_port_vsp_alloc_params_t *compat_param, ++ ioc_fm_port_vsp_alloc_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ _fm_cpt_dbg(compat," param->p_fm_tx_port=%p \n", param->p_fm_tx_port); ++ ++ param->dflt_relative_id = compat_param->dflt_relative_id; ++ param->num_of_profiles = compat_param->num_of_profiles; ++ param->p_fm_tx_port = compat_pcd_id2ptr(compat_param->p_fm_tx_port); ++ } ++} ++#endif /* (DPAA_VERSION >= 11) */ ++ ++void compat_copy_fm_pcd_cc_tbl_get_stats( ++ ioc_compat_fm_pcd_cc_tbl_get_stats_t *compat_param, ++ ioc_fm_pcd_cc_tbl_get_stats_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ param->key_index = compat_param->key_index; ++ memcpy(¶m->statistics, &compat_param->statistics, sizeof(ioc_fm_pcd_cc_key_statistics_t)); ++ } else { ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ compat_param->key_index = param->key_index; ++ memcpy(&compat_param->statistics, ¶m->statistics, sizeof(ioc_fm_pcd_cc_key_statistics_t)); ++ } ++} ++ ++ ++void compat_copy_fm_pcd_net_env( ++ ioc_compat_fm_pcd_net_env_params_t *compat_param, ++ ioc_fm_pcd_net_env_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->num_of_distinction_units = compat_param->num_of_distinction_units; ++ memcpy(param->units, compat_param->units, sizeof(ioc_fm_pcd_distinction_unit_t)*IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ param->id = NULL; /* to avoid passing garbage to the kernel */ ++ } ++ else ++ { ++ compat_param->num_of_distinction_units = param->num_of_distinction_units; ++ memcpy(compat_param->units, param->units, sizeof(ioc_fm_pcd_distinction_unit_t)*IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS); ++ ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ } ++} ++ ++void compat_copy_fm_pcd_cc_node_modify_key( ++ ioc_compat_fm_pcd_cc_node_modify_key_params_t *compat_param, ++ ioc_fm_pcd_cc_node_modify_key_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->key_indx = compat_param->key_indx; ++ param->key_size = compat_param->key_size; ++ param->p_key = (uint8_t *)compat_ptr(compat_param->p_key); ++ _fm_cpt_dbg(compat," param->p_key = %p \n", param->p_key); ++ param->p_mask = (uint8_t *)compat_ptr(compat_param->p_mask); ++ _fm_cpt_dbg(compat," param->p_mask = %p\n", param->p_mask); ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ _fm_cpt_dbg(compat," param->id = %p \n", param->id); ++ } ++ else ++ { ++ compat_param->key_indx = param->key_indx; ++ compat_param->key_size = param->key_size; ++ compat_param->p_key = ptr_to_compat((void *)param->p_key); ++ compat_param->p_mask = ptr_to_compat((void *)param->p_mask); ++ ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ } ++} ++ ++void compat_copy_keys( ++ ioc_compat_keys_params_t *compat_param, ++ ioc_keys_params_t *param, ++ uint8_t compat) ++{ ++ int k = 0; ++ ++ _fm_cpt_dbg(compat," {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) { ++ param->max_num_of_keys = compat_param->max_num_of_keys; ++ param->mask_support = compat_param->mask_support; ++ param->statistics_mode = compat_param->statistics_mode; ++ param->num_of_keys = compat_param->num_of_keys; ++ param->key_size = compat_param->key_size; ++#if (DPAA_VERSION >= 11) ++ memcpy(¶m->frame_length_ranges, ++ &compat_param->frame_length_ranges, ++ sizeof(param->frame_length_ranges[0]) * ++ IOC_FM_PCD_CC_STATS_MAX_NUM_OF_FLR); ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ else { ++ compat_param->max_num_of_keys = param->max_num_of_keys; ++ compat_param->mask_support = param->mask_support; ++ compat_param->statistics_mode = param->statistics_mode; ++ compat_param->num_of_keys = param->num_of_keys; ++ compat_param->key_size = param->key_size; ++#if (DPAA_VERSION >= 11) ++ memcpy(&compat_param->frame_length_ranges, ++ ¶m->frame_length_ranges, ++ sizeof(compat_param->frame_length_ranges[0]) * ++ IOC_FM_PCD_CC_STATS_MAX_NUM_OF_FLR); ++#endif /* (DPAA_VERSION >= 11) */ ++ } ++ ++ for (k=0; k < IOC_FM_PCD_MAX_NUM_OF_KEYS; k++) ++ compat_copy_fm_pcd_cc_key( ++ &compat_param->key_params[k], ++ ¶m->key_params[k], ++ compat); ++ ++ compat_copy_fm_pcd_cc_next_engine( ++ &compat_param->cc_next_engine_params_for_miss, ++ ¶m->cc_next_engine_params_for_miss, ++ compat); ++ ++ _fm_cpt_dbg(compat," ...->}\n"); ++} ++ ++void compat_copy_fm_pcd_cc_node( ++ ioc_compat_fm_pcd_cc_node_params_t *compat_param, ++ ioc_fm_pcd_cc_node_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg(compat," {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ memcpy(¶m->extract_cc_params, &compat_param->extract_cc_params, sizeof(ioc_fm_pcd_extract_entry_t)); ++ ++ else ++ { ++ compat_copy_keys(&compat_param->keys_params, ¶m->keys_params, compat); ++ ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ _fm_cpt_dbg(compat," param->id = %p \n", param->id); ++ } ++ ++ compat_copy_keys(&compat_param->keys_params, ¶m->keys_params, compat); ++ ++ _fm_cpt_dbg(compat," ...->}\n"); ++} ++ ++void compat_fm_pcd_manip_set_node( ++ ioc_compat_fm_pcd_manip_params_t *compat_param, ++ ioc_fm_pcd_manip_params_t *param, ++ uint8_t compat) ++{ ++ if (compat == COMPAT_US_TO_K) { ++ param->type = compat_param->type; ++ switch (param->type) { ++ case e_IOC_FM_PCD_MANIP_HDR: ++ param->u.hdr.rmv = compat_param->u.hdr.rmv; ++ memcpy(¶m->u.hdr.rmv_params, ++ &compat_param->u.hdr.rmv_params, ++ sizeof(param->u.hdr.rmv_params)); ++ ++ param->u.hdr.insrt = compat_param->u.hdr.insrt; ++ param->u.hdr.insrt_params.type = ++ compat_param->u.hdr.insrt_params.type; ++ switch (compat_param->u.hdr.insrt_params.type) ++ { ++ case e_IOC_FM_PCD_MANIP_INSRT_GENERIC: ++ param->u.hdr.insrt_params.u.generic.offset = ++ compat_param->u.hdr.insrt_params.u.generic.offset; ++ param->u.hdr.insrt_params.u.generic.size = ++ compat_param->u.hdr.insrt_params.u.generic.size; ++ param->u.hdr.insrt_params.u.generic.replace = ++ compat_param->u.hdr.insrt_params.u.generic.replace; ++ param->u.hdr.insrt_params.u.generic.p_data = ++ compat_ptr(compat_param->u.hdr.insrt_params.u.generic.p_data); ++ break; ++ case e_IOC_FM_PCD_MANIP_INSRT_BY_HDR: ++ param->u.hdr.insrt_params.u.by_hdr.type = ++ compat_param->u.hdr.insrt_params.u.by_hdr.type; ++ param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.specific_l2 = ++ compat_param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.specific_l2; ++ param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.update = ++ compat_param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.update; ++ param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.size = ++ compat_param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.size; ++ param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.p_data = ++ compat_ptr(compat_param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.p_data); ++ break; ++ default: ++ _fm_cpt_err("Unsupported type: %d", compat_param->u.hdr.insrt_params.type); ++ } ++ ++ param->u.hdr.field_update = compat_param->u.hdr.field_update; ++ memcpy(¶m->u.hdr.field_update_params, ++ &compat_param->u.hdr.field_update_params, ++ sizeof(param->u.hdr.field_update_params)); ++ ++ param->u.hdr.custom = compat_param->u.hdr.custom; ++ memcpy(¶m->u.hdr.custom_params, ++ &compat_param->u.hdr.custom_params, ++ sizeof(param->u.hdr.custom_params)); ++ ++ param->u.hdr.dont_parse_after_manip = ++ compat_param->u.hdr.dont_parse_after_manip; ++ break; ++ case e_IOC_FM_PCD_MANIP_REASSEM: ++ memcpy(¶m->u.reassem, &compat_param->u.reassem, sizeof(param->u.reassem)); ++ break; ++ case e_IOC_FM_PCD_MANIP_FRAG: ++ memcpy(¶m->u.frag, &compat_param->u.frag, sizeof(param->u.frag)); ++ break; ++ case e_IOC_FM_PCD_MANIP_SPECIAL_OFFLOAD: ++ memcpy(¶m->u.special_offload, ++ &compat_param->u.special_offload, ++ sizeof(param->u.special_offload)); ++ break; ++ } ++ ++ param->p_next_manip = compat_pcd_id2ptr(compat_param->p_next_manip); ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ } ++ else { ++ compat_param->type = param->type; ++ memcpy(&compat_param->u, ¶m->u, sizeof(compat_param->u)); ++ ++ if (param->type == e_IOC_FM_PCD_MANIP_HDR && ++ param->u.hdr.insrt_params.type == e_IOC_FM_PCD_MANIP_INSRT_GENERIC) ++ compat_param->u.hdr.insrt_params.u.generic.p_data = ++ ptr_to_compat(param->u.hdr.insrt_params.u.generic.p_data); ++ ++ compat_param->p_next_manip = compat_pcd_ptr2id(param->id); ++ /* ... should be one that was added previously by the very call to ++ compat_add_ptr2id() below: */ ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ } ++} ++ ++void compat_copy_fm_pcd_manip_get_stats( ++ ioc_compat_fm_pcd_manip_get_stats_t *compat_param, ++ ioc_fm_pcd_manip_get_stats_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ memcpy(¶m->stats, &compat_param->stats, ++ sizeof(ioc_fm_pcd_manip_stats_t)); ++ } ++ else ++ { ++ compat_param->id = compat_add_ptr2id(param->id, ++ FM_MAP_TYPE_PCD_NODE); ++ memcpy(&compat_param->stats, ¶m->stats, ++ sizeof(ioc_fm_pcd_manip_stats_t)); ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++#if (DPAA_VERSION >= 11) ++void compat_copy_fm_pcd_frm_replic_group_params( ++ ioc_compat_fm_pcd_frm_replic_group_params_t *compat_param, ++ ioc_fm_pcd_frm_replic_group_params_t *param, ++ uint8_t compat) ++{ ++ int k; ++ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->max_num_of_entries = compat_param->max_num_of_entries; ++ param->num_of_entries = compat_param->num_of_entries; ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ } ++ else ++ { ++ compat_param->max_num_of_entries = param->max_num_of_entries; ++ compat_param->num_of_entries = param->num_of_entries; ++ compat_param->id = compat_add_ptr2id(param->id, ++ FM_MAP_TYPE_PCD_NODE); ++ } ++ ++ for (k=0; k < IOC_FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES; k++) ++ compat_copy_fm_pcd_cc_next_engine( ++ &compat_param->next_engine_params[k], ++ ¶m->next_engine_params[k], ++ compat); ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_pcd_frm_replic_member( ++ ioc_compat_fm_pcd_frm_replic_member_t *compat_param, ++ ioc_fm_pcd_frm_replic_member_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->h_replic_group = compat_pcd_id2ptr(compat_param->h_replic_group); ++ param->member_index = compat_param->member_index; ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_pcd_frm_replic_member_params( ++ ioc_compat_fm_pcd_frm_replic_member_params_t *compat_param, ++ ioc_fm_pcd_frm_replic_member_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ compat_copy_fm_pcd_frm_replic_member(&compat_param->member, ++ ¶m->member, compat); ++ ++ compat_copy_fm_pcd_cc_next_engine(&compat_param->next_engine_params, ++ ¶m->next_engine_params, compat); ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_vsp_params( ++ ioc_compat_fm_vsp_params_t *compat_param, ++ ioc_fm_vsp_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->p_fm = compat_pcd_id2ptr(compat_param->p_fm); ++ memcpy(¶m->ext_buf_pools, &compat_param->ext_buf_pools, sizeof(ioc_fm_ext_pools)); ++ param->liodn_offset = compat_param->liodn_offset; ++ param->port_params.port_id = compat_param->port_params.port_id; ++ param->port_params.port_type = compat_param->port_params.port_type; ++ param->relative_profile_id = compat_param->relative_profile_id; ++ param->id = compat_pcd_id2ptr(compat_param->id); ++ } ++ else ++ { ++ compat_param->p_fm = compat_pcd_ptr2id(param->p_fm); ++ memcpy(&compat_param->ext_buf_pools, ¶m->ext_buf_pools, sizeof(ioc_fm_ext_pools)); ++ compat_param->liodn_offset = param->liodn_offset; ++ compat_param->port_params.port_id = param->port_params.port_id; ++ compat_param->port_params.port_type = param->port_params.port_type; ++ compat_param->relative_profile_id = param->relative_profile_id; ++ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE); ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_buf_pool_depletion_params( ++ ioc_compat_fm_buf_pool_depletion_params_t *compat_param, ++ ioc_fm_buf_pool_depletion_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->p_fm_vsp = compat_pcd_id2ptr(compat_param->p_fm_vsp); ++ memcpy(¶m->fm_buf_pool_depletion, ++ &compat_param->fm_buf_pool_depletion, ++ sizeof(ioc_fm_buf_pool_depletion_t)); ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_buffer_prefix_content_params( ++ ioc_compat_fm_buffer_prefix_content_params_t *compat_param, ++ ioc_fm_buffer_prefix_content_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->p_fm_vsp = compat_pcd_id2ptr(compat_param->p_fm_vsp); ++ memcpy(¶m->fm_buffer_prefix_content, ++ &compat_param->fm_buffer_prefix_content, ++ sizeof(ioc_fm_buffer_prefix_content_t)); ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_vsp_config_no_sg_params( ++ ioc_compat_fm_vsp_config_no_sg_params_t *compat_param, ++ ioc_fm_vsp_config_no_sg_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->p_fm_vsp = compat_pcd_id2ptr(compat_param->p_fm_vsp); ++ param->no_sg = compat_param->no_sg; ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++ ++void compat_copy_fm_vsp_prs_result_params( ++ ioc_compat_fm_vsp_prs_result_params_t *compat_param, ++ ioc_fm_vsp_prs_result_params_t *param, ++ uint8_t compat) ++{ ++ _fm_cpt_dbg (compat, " {->...\n"); ++ ++ if (compat == COMPAT_US_TO_K) ++ { ++ param->p_fm_vsp = compat_pcd_id2ptr(compat_param->p_fm_vsp); ++ /* p_data is an user-space pointer that needs to remain unmodified */ ++ param->p_data = (void *)(unsigned long long)compat_param->p_data; ++ } ++ else ++ { ++ compat_param->p_fm_vsp = compat_pcd_ptr2id(param->p_fm_vsp); ++ /* p_data is an user-space pointer that needs to remain unmodified */ ++ compat_param->p_data = (compat_uptr_t)((unsigned long long)param->p_data & 0xFFFFFFFF); ++ } ++ ++ _fm_cpt_dbg (compat, " ...->}\n"); ++} ++#endif /* (DPAA_VERSION >= 11) */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.h b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.h +new file mode 100644 +index 0000000..187011f +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.h +@@ -0,0 +1,755 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/* ++ @File lnxwrp_ioctls_fm_compat.h ++ ++ @Description FM PCD compat structures definition. ++ ++*/ ++ ++#ifndef __FM_COMPAT_IOCTLS_H ++#define __FM_COMPAT_IOCTLS_H ++ ++#include ++ ++#define COMPAT_K_TO_US 0 /* copy from Kernel to User */ ++#define COMPAT_US_TO_K 1 /* copy from User to Kernel */ ++#define COMPAT_GENERIC 2 ++ ++#define COMPAT_COPY_K2US(dest, src, type) compat_copy_##type(src, dest, 0) ++#define COMPAT_COPY_US2K(dest, src, type) compat_copy_##type(dest, src, 1) ++ ++/* mapping kernel pointers w/ UserSpace id's { */ ++/* Because compat_ptr(ptr_to_compat(X)) != X, this way we cannot exchange pointers ++ back and forth (US - KS). compat_ptr is a cast and pointers are broken. */ ++#define COMPAT_PTR2ID_ARRAY_MAX (512+1) /* first location is not used */ ++#define COMPAT_PTR2ID_WATERMARK 0xface0000 ++#define COMPAT_PTR2ID_WM_MASK 0xffff0000 ++ ++/* define it for debug trace */ ++/*#define FM_COMPAT_DBG*/ ++ ++#define _fm_cpt_prk(stage, format, arg...) \ ++ printk(stage "fm_cpt (cpu:%u): " format, raw_smp_processor_id(), ##arg) ++ ++#define _fm_cpt_inf(format, arg...) _fm_cpt_prk(KERN_INFO, format, ##arg) ++#define _fm_cpt_wrn(format, arg...) _fm_cpt_prk(KERN_WARNING, format, ##arg) ++#define _fm_cpt_err(format, arg...) _fm_cpt_prk(KERN_ERR, format, ##arg) ++ ++/* used for compat IOCTL debugging */ ++#if defined(FM_COMPAT_DBG) ++ #define _fm_cpt_dbg(from, format, arg...) \ ++ do{ \ ++ if (from == COMPAT_US_TO_K) \ ++ printk("fm_cpt to KS [%s:%u](cpu:%u) - " format, \ ++ __func__, __LINE__, raw_smp_processor_id(), ##arg); \ ++ else if (from == COMPAT_K_TO_US) \ ++ printk("fm_cpt to US [%s:%u](cpu:%u) - " format, \ ++ __func__, __LINE__, raw_smp_processor_id(), ##arg); \ ++ else \ ++ printk("fm_cpt [%s:%u](cpu:%u) - " format, \ ++ __func__, __LINE__, raw_smp_processor_id(), ##arg); \ ++ }while(0) ++#else ++# define _fm_cpt_dbg(arg...) ++#endif ++ ++/*TODO: per FMan module: ++ * ++ * Parser: FM_MAP_TYPE_PARSER_NODE, ++ * Kg: FM_MAP_TYPE_KG_NODE, ++ * Policer: FM_MAP_TYPE_POLICER_NODE ++ * Manip: FM_MAP_TYPE_MANIP_NODE ++ **/ ++enum fm_map_node_type { ++ FM_MAP_TYPE_UNSPEC = 0, ++ FM_MAP_TYPE_PCD_NODE, ++ ++ /* add types here, update the policy */ ++ ++ __FM_MAP_TYPE_AFTER_LAST, ++ FM_MAP_TYPE_MAX = __FM_MAP_TYPE_AFTER_LAST - 1 ++}; ++ ++void compat_del_ptr2id(void *p, enum fm_map_node_type); ++compat_uptr_t compat_add_ptr2id(void *p, enum fm_map_node_type); ++compat_uptr_t compat_get_ptr2id(void *p, enum fm_map_node_type); ++void *compat_get_id2ptr(compat_uptr_t comp, enum fm_map_node_type); ++ ++static inline compat_uptr_t compat_pcd_ptr2id(void *ptr) { ++ return (ptr)? compat_get_ptr2id(ptr, FM_MAP_TYPE_PCD_NODE) ++ : (compat_uptr_t) 0; ++} ++ ++static inline void *compat_pcd_id2ptr(compat_uptr_t id) { ++ return (id) ? compat_get_id2ptr(id, FM_MAP_TYPE_PCD_NODE) ++ : NULL; ++} ++ ++/* other similar inlines may be added as new nodes are added ++ to enum fm_map_node_type above... */ ++/* } mapping kernel pointers w/ UserSpace id's */ ++ ++/* pcd compat structures { */ ++typedef struct ioc_compat_fm_pcd_cc_node_remove_key_params_t { ++ compat_uptr_t id; ++ uint16_t key_indx; ++} ioc_compat_fm_pcd_cc_node_remove_key_params_t; ++ ++typedef union ioc_compat_fm_pcd_plcr_next_engine_params_u { ++ ioc_fm_pcd_done_action action; ++ compat_uptr_t p_profile; ++ compat_uptr_t p_direct_scheme; ++} ioc_compat_fm_pcd_plcr_next_engine_params_u; ++ ++typedef struct ioc_compat_fm_pcd_plcr_profile_params_t { ++ bool modify; ++ union { ++ struct { ++ ioc_fm_pcd_profile_type_selection profile_type; ++ compat_uptr_t p_fm_port; ++ uint16_t relative_profile_id; ++ } new_params; ++ compat_uptr_t p_profile; ++ } profile_select; ++ ioc_fm_pcd_plcr_algorithm_selection alg_selection; ++ ioc_fm_pcd_plcr_color_mode color_mode; ++ ++ union { ++ ioc_fm_pcd_plcr_color dflt_color; ++ ioc_fm_pcd_plcr_color override; ++ } color; ++ ++ ioc_fm_pcd_plcr_non_passthrough_alg_param_t non_passthrough_alg_param; ++ ++ ioc_fm_pcd_engine next_engine_on_green; ++ ioc_compat_fm_pcd_plcr_next_engine_params_u params_on_green; ++ ++ ioc_fm_pcd_engine next_engine_on_yellow; ++ ioc_compat_fm_pcd_plcr_next_engine_params_u params_on_yellow; ++ ++ ioc_fm_pcd_engine next_engine_on_red; ++ ioc_compat_fm_pcd_plcr_next_engine_params_u params_on_red; ++ ++ bool trap_profile_on_flow_A; ++ bool trap_profile_on_flow_B; ++ bool trap_profile_on_flow_C; ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_plcr_profile_params_t; ++ ++typedef struct ioc_compat_fm_obj_t { ++ compat_uptr_t obj; ++} ioc_compat_fm_obj_t; ++ ++typedef struct ioc_compat_fm_pcd_kg_scheme_select_t { ++ bool direct; ++ compat_uptr_t scheme_id; ++} ioc_compat_fm_pcd_kg_scheme_select_t; ++ ++typedef struct ioc_compat_fm_pcd_port_schemes_params_t { ++ uint8_t num_of_schemes; ++ compat_uptr_t scheme_ids[FM_PCD_KG_NUM_OF_SCHEMES]; ++} ioc_compat_fm_pcd_port_schemes_params_t; ++ ++#if (DPAA_VERSION >= 11) ++typedef struct ioc_compat_fm_port_vsp_alloc_params_t { ++ uint8_t num_of_profiles; /**< Number of Virtual Storage Profiles */ ++ uint8_t dflt_relative_id; /**< The default Virtual-Storage-Profile-id dedicated to Rx/OP port ++ The same default Virtual-Storage-Profile-id will be for coupled Tx port ++ if relevant function called for Rx port */ ++ compat_uptr_t p_fm_tx_port; /**< Handle to coupled Tx Port; not relevant for OP port. */ ++}ioc_compat_fm_port_vsp_alloc_params_t; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++typedef struct ioc_compat_fm_pcd_net_env_params_t { ++ uint8_t num_of_distinction_units; ++ ioc_fm_pcd_distinction_unit_t units[IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; /* same structure*/ ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_net_env_params_t; ++ ++typedef struct ioc_compat_fm_pcd_prs_sw_params_t { ++ bool override; ++ uint32_t size; ++ uint16_t base; ++ compat_uptr_t p_code; ++ uint32_t sw_prs_data_params[IOC_FM_PCD_PRS_NUM_OF_HDRS]; ++ uint8_t num_of_labels; ++ ioc_fm_pcd_prs_label_params_t labels_table[IOC_FM_PCD_PRS_NUM_OF_LABELS]; ++} ioc_compat_fm_pcd_prs_sw_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_next_kg_params_t { ++ bool override_fqid; ++ uint32_t new_fqid; ++#if DPAA_VERSION >= 11 ++ uint8_t new_relative_storage_profile_id; ++#endif ++ compat_uptr_t p_direct_scheme; ++} ioc_compat_fm_pcd_cc_next_kg_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_next_cc_params_t { ++ compat_uptr_t cc_node_id; ++} ioc_compat_fm_pcd_cc_next_cc_params_t; ++ ++#if DPAA_VERSION >= 11 ++typedef struct ioc_compat_fm_pcd_cc_next_fr_params_t { ++ compat_uptr_t frm_replic_id; ++} ioc_compat_fm_pcd_cc_next_fr_params_t; ++#endif /* DPAA_VERSION >= 11 */ ++ ++typedef struct ioc_compat_fm_pcd_cc_next_engine_params_t { ++ ioc_fm_pcd_engine next_engine; ++ union { ++ ioc_compat_fm_pcd_cc_next_cc_params_t cc_params; /**< compat structure*/ ++ ioc_fm_pcd_cc_next_plcr_params_t plcr_params; /**< same structure*/ ++ ioc_fm_pcd_cc_next_enqueue_params_t enqueue_params; /**< same structure*/ ++ ioc_compat_fm_pcd_cc_next_kg_params_t kg_params; /**< compat structure*/ ++#if DPAA_VERSION >= 11 ++ ioc_compat_fm_pcd_cc_next_fr_params_t fr_params; /**< compat structure*/ ++#endif /* DPAA_VERSION >= 11 */ ++ } params; ++ compat_uptr_t manip_id; ++ bool statistics_en; ++} ioc_compat_fm_pcd_cc_next_engine_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_grp_params_t { ++ uint8_t num_of_distinction_units; ++ uint8_t unit_ids [IOC_FM_PCD_MAX_NUM_OF_CC_UNITS]; ++ ioc_compat_fm_pcd_cc_next_engine_params_t next_engine_per_entries_in_grp[IOC_FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP]; ++} ioc_compat_fm_pcd_cc_grp_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_tree_params_t { ++ compat_uptr_t net_env_id; ++ uint8_t num_of_groups; ++ ioc_compat_fm_pcd_cc_grp_params_t fm_pcd_cc_group_params [IOC_FM_PCD_MAX_NUM_OF_CC_GROUPS]; ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_cc_tree_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t { ++ compat_uptr_t id; ++ uint8_t grp_indx; ++ uint8_t indx; ++ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params; ++} ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_key_params_t { ++ compat_uptr_t p_key; ++ compat_uptr_t p_mask; ++ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params; /**< compat structure*/ ++} ioc_compat_fm_pcd_cc_key_params_t; ++ ++typedef struct ioc_compat_keys_params_t { ++ uint16_t max_num_of_keys; ++ bool mask_support; ++ ioc_fm_pcd_cc_stats_mode statistics_mode; ++#if (DPAA_VERSION >= 11) ++ uint16_t frame_length_ranges[IOC_FM_PCD_CC_STATS_MAX_NUM_OF_FLR]; ++#endif /* (DPAA_VERSION >= 11) */ ++ uint16_t num_of_keys; ++ uint8_t key_size; ++ ioc_compat_fm_pcd_cc_key_params_t key_params[IOC_FM_PCD_MAX_NUM_OF_KEYS]; /**< compat structure*/ ++ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params_for_miss; /**< compat structure*/ ++} ioc_compat_keys_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_node_params_t { ++ ioc_fm_pcd_extract_entry_t extract_cc_params; /**< same structure*/ ++ ioc_compat_keys_params_t keys_params; /**< compat structure*/ ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_cc_node_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a hash table ++*//***************************************************************************/ ++typedef struct ioc_compat_fm_pcd_hash_table_params_t { ++ uint16_t max_num_of_keys; ++ ioc_fm_pcd_cc_stats_mode statistics_mode; ++ uint8_t kg_hash_shift; ++ uint16_t hash_res_mask; ++ uint8_t hash_shift; ++ uint8_t match_key_size; ++ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params_for_miss; ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_hash_table_params_t; ++ ++typedef struct ioc_compat_fm_pcd_hash_table_add_key_params_t { ++ compat_uptr_t p_hash_tbl; ++ uint8_t key_size; ++ ioc_compat_fm_pcd_cc_key_params_t key_params; ++} ioc_compat_fm_pcd_hash_table_add_key_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_node_modify_key_params_t { ++ compat_uptr_t id; ++ uint16_t key_indx; ++ uint8_t key_size; ++ compat_uptr_t p_key; ++ compat_uptr_t p_mask; ++} ioc_compat_fm_pcd_cc_node_modify_key_params_t; ++ ++typedef struct ioc_compat_fm_pcd_hash_table_remove_key_params_t { ++ compat_uptr_t p_hash_tbl; ++ uint8_t key_size; ++ compat_uptr_t p_key; ++} ioc_compat_fm_pcd_hash_table_remove_key_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t { ++ compat_uptr_t id; ++ uint16_t key_indx; ++ uint8_t key_size; ++ ioc_compat_fm_pcd_cc_key_params_t key_params; ++} ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t; ++ ++typedef struct ioc_compat_fm_port_pcd_plcr_params_t { ++ compat_uptr_t plcr_profile_id; ++} ioc_compat_fm_port_pcd_plcr_params_t; ++ ++typedef struct ioc_compat_fm_port_pcd_cc_params_t { ++ compat_uptr_t cc_tree_id; ++} ioc_compat_fm_port_pcd_cc_params_t; ++ ++typedef struct ioc_compat_fm_port_pcd_kg_params_t { ++ uint8_t num_of_schemes; ++ compat_uptr_t scheme_ids[FM_PCD_KG_NUM_OF_SCHEMES]; ++ bool direct_scheme; ++ compat_uptr_t direct_scheme_id; ++} ioc_compat_fm_port_pcd_kg_params_t; ++ ++typedef struct ioc_compat_fm_port_pcd_params_t { ++ ioc_fm_port_pcd_support pcd_support; ++ compat_uptr_t net_env_id; ++ compat_uptr_t p_prs_params; ++ compat_uptr_t p_cc_params; ++ compat_uptr_t p_kg_params; ++ compat_uptr_t p_plcr_params; ++ compat_uptr_t p_ip_reassembly_manip; ++#if DPAA_VERSION >= 11 ++ compat_uptr_t p_capwap_reassembly_manip; ++#endif ++} ioc_compat_fm_port_pcd_params_t; ++ ++typedef struct ioc_compat_fm_pcd_kg_cc_t { ++ compat_uptr_t tree_id; ++ uint8_t grp_id; ++ bool plcr_next; ++ bool bypass_plcr_profile_generation; ++ ioc_fm_pcd_kg_plcr_profile_t plcr_profile; ++} ioc_compat_fm_pcd_kg_cc_t; ++ ++typedef struct ioc_compat_fm_pcd_kg_scheme_params_t { ++ bool modify; ++ union { ++ uint8_t relative_scheme_id; ++ compat_uptr_t scheme_id; ++ } scm_id; ++ bool always_direct; ++ struct { ++ compat_uptr_t net_env_id; ++ uint8_t num_of_distinction_units; ++ uint8_t unit_ids[IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; ++ } net_env_params; ++ bool use_hash; ++ ioc_fm_pcd_kg_key_extract_and_hash_params_t key_extract_and_hash_params; ++ bool bypass_fqid_generation; ++ uint32_t base_fqid; ++ uint8_t num_of_used_extracted_ors; ++ ioc_fm_pcd_kg_extracted_or_params_t extracted_ors[IOC_FM_PCD_KG_NUM_OF_GENERIC_REGS]; ++#if DPAA_VERSION >= 11 ++ bool override_storage_profile; ++ ioc_fm_pcd_kg_storage_profile_t storage_profile; ++#endif /* DPAA_VERSION >= 11 */ ++ ioc_fm_pcd_engine next_engine; ++ union{ ++ ioc_fm_pcd_done_action done_action; ++ ioc_fm_pcd_kg_plcr_profile_t plcr_profile; ++ ioc_compat_fm_pcd_kg_cc_t cc; ++ } kg_next_engine_params; ++ ioc_fm_pcd_kg_scheme_counter_t scheme_counter; ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_kg_scheme_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t { ++ compat_uptr_t id; ++ uint16_t key_indx; ++ uint8_t key_size; ++ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params; ++} ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t; ++ ++typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_generic_params_t { ++ uint8_t offset; ++ uint8_t size; ++ bool replace; ++ compat_uptr_t p_data; ++} ioc_compat_fm_pcd_manip_hdr_insrt_generic_params_t; ++ ++typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_specific_l2_params_t { ++ ioc_fm_pcd_manip_hdr_insrt_specific_l2 specific_l2; ++ bool update; ++ uint8_t size; ++ compat_uptr_t p_data; ++} ioc_compat_fm_pcd_manip_hdr_insrt_specific_l2_params_t; ++ ++typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_t { ++ uint8_t size; /**< size of inserted section */ ++ compat_uptr_t p_data; /**< data to be inserted */ ++} ioc_compat_fm_pcd_manip_hdr_insrt_t; ++ ++#if (DPAA_VERSION >= 11) ++typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_ip_params_t { ++ bool calc_l4_checksum; /**< Calculate L4 checksum. */ ++ ioc_fm_pcd_manip_hdr_qos_mapping_mode mapping_mode; /**< TODO */ ++ uint8_t last_pid_offset; /**< the offset of the last Protocol within ++ the inserted header */ ++ uint16_t id; /**< 16 bit New IP ID */ ++ bool dont_frag_overwrite; ++ /**< IPv4 only. DF is overwritten with the hash-result next-to-last byte. ++ * This byte is configured to be overwritten when RPD is set. */ ++ uint8_t last_dst_offset; ++ /**< IPv6 only. if routing extension exist, user should set the offset of the destination address ++ * in order to calculate UDP checksum pseudo header; ++ * Otherwise set it to '0'. */ ++ ioc_compat_fm_pcd_manip_hdr_insrt_t insrt; /**< size and data to be inserted. */ ++} ioc_compat_fm_pcd_manip_hdr_insrt_ip_params_t; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_by_hdr_params_t { ++ ioc_fm_pcd_manip_hdr_insrt_by_hdr_type type; ++ union { ++ ioc_compat_fm_pcd_manip_hdr_insrt_specific_l2_params_t specific_l2_params; ++#if (DPAA_VERSION >= 11) ++ ioc_compat_fm_pcd_manip_hdr_insrt_ip_params_t ip_params; ++ ioc_compat_fm_pcd_manip_hdr_insrt_t insrt; ++#endif /* (DPAA_VERSION >= 11) */ ++ } u; ++} ioc_compat_fm_pcd_manip_hdr_insrt_by_hdr_params_t; ++ ++typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_params_t { ++ ioc_fm_pcd_manip_hdr_insrt_type type; ++ union { ++ ioc_compat_fm_pcd_manip_hdr_insrt_by_hdr_params_t by_hdr; ++ ioc_compat_fm_pcd_manip_hdr_insrt_generic_params_t generic; ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++#error "FM_CAPWAP_SUPPORT feature not supported!" ++ ioc_fm_pcd_manip_hdr_insrt_by_template_params_t by_template; ++#endif /* FM_CAPWAP_SUPPORT */ ++ } u; ++} ioc_compat_fm_pcd_manip_hdr_insrt_params_t; ++ ++typedef struct ioc_compat_fm_pcd_manip_hdr_params_t { ++ bool rmv; ++ ioc_fm_pcd_manip_hdr_rmv_params_t rmv_params; ++ bool insrt; ++ ioc_compat_fm_pcd_manip_hdr_insrt_params_t insrt_params; ++ bool field_update; ++ ioc_fm_pcd_manip_hdr_field_update_params_t field_update_params; ++ bool custom; ++ ioc_fm_pcd_manip_hdr_custom_params_t custom_params; ++ bool dont_parse_after_manip; ++} ioc_compat_fm_pcd_manip_hdr_params_t; ++ ++typedef struct ioc_compat_fm_pcd_manip_special_offload_params_t { ++ bool decryption; ++ bool ecn_copy; ++ bool dscp_copy; ++ bool variable_ip_hdr_len; ++ bool variable_ip_version; ++ uint8_t outer_ip_hdr_len; ++ uint16_t arw_size; ++ compat_uptr_t arw_addr; ++} ioc_compat_fm_pcd_manip_special_offload_params_t; ++ ++typedef struct ioc_compat_fm_pcd_manip_params_t { ++ ioc_fm_pcd_manip_type type; ++ union { ++ ioc_compat_fm_pcd_manip_hdr_params_t hdr; ++ ioc_fm_pcd_manip_reassem_params_t reassem; ++ ioc_fm_pcd_manip_frag_params_t frag; ++ ioc_compat_fm_pcd_manip_special_offload_params_t special_offload; ++ } u; ++ compat_uptr_t p_next_manip; ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++#error "FM_CAPWAP_SUPPORT feature not supported!" ++ bool frag_or_reasm; ++ ioc_fm_pcd_manip_frag_or_reasm_params_t frag_or_reasm_params; ++#endif /* FM_CAPWAP_SUPPORT */ ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_manip_params_t; ++ ++typedef struct ioc_compat_fm_pcd_manip_get_stats_t { ++ compat_uptr_t id; ++ ioc_fm_pcd_manip_stats_t stats; ++} ioc_compat_fm_pcd_manip_get_stats_t; ++ ++#if (DPAA_VERSION >= 11) ++typedef struct ioc_compat_fm_pcd_frm_replic_group_params_t { ++ uint8_t max_num_of_entries; ++ uint8_t num_of_entries; ++ ioc_compat_fm_pcd_cc_next_engine_params_t ++ next_engine_params[IOC_FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES]; ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_frm_replic_group_params_t; ++ ++typedef struct ioc_compat_fm_pcd_frm_replic_member_t { ++ compat_uptr_t h_replic_group; ++ uint16_t member_index; ++} ioc_compat_fm_pcd_frm_replic_member_t; ++ ++typedef struct ioc_compat_fm_pcd_frm_replic_member_params_t { ++ ioc_compat_fm_pcd_frm_replic_member_t member; ++ ioc_compat_fm_pcd_cc_next_engine_params_t next_engine_params; ++} ioc_compat_fm_pcd_frm_replic_member_params_t; ++ ++typedef struct ioc_compat_fm_vsp_params_t { ++ compat_uptr_t p_fm; /**< A handle to the FM object this VSP related to */ ++ ioc_fm_ext_pools ext_buf_pools; /**< Which external buffer pools are used ++ (up to FM_PORT_MAX_NUM_OF_EXT_POOLS), and their sizes. ++ parameter associated with Rx / OP port */ ++ uint16_t liodn_offset; /**< VSP's LIODN offset */ ++ struct { ++ ioc_fm_port_type port_type; /**< Port type */ ++ uint8_t port_id; /**< Port Id - relative to type */ ++ } port_params; ++ uint8_t relative_profile_id; /**< VSP Id - relative to VSP's range ++ defined in relevant FM object */ ++ compat_uptr_t id; /**< return value */ ++} ioc_compat_fm_vsp_params_t; ++ ++typedef struct ioc_compat_fm_buf_pool_depletion_params_t { ++ compat_uptr_t p_fm_vsp; ++ ioc_fm_buf_pool_depletion_t fm_buf_pool_depletion; ++} ioc_compat_fm_buf_pool_depletion_params_t; ++ ++typedef struct ioc_compat_fm_buffer_prefix_content_params_t { ++ compat_uptr_t p_fm_vsp; ++ ioc_fm_buffer_prefix_content_t fm_buffer_prefix_content; ++} ioc_compat_fm_buffer_prefix_content_params_t; ++ ++typedef struct ioc_compat_fm_vsp_config_no_sg_params_t { ++ compat_uptr_t p_fm_vsp; ++ bool no_sg; ++} ioc_compat_fm_vsp_config_no_sg_params_t; ++ ++typedef struct ioc_compat_fm_vsp_prs_result_params_t { ++ compat_uptr_t p_fm_vsp; ++ compat_uptr_t p_data; ++} ioc_compat_fm_vsp_prs_result_params_t; ++ ++#endif /* (DPAA_VERSION >= 11) */ ++typedef struct ioc_compat_fm_pcd_kg_scheme_spc_t { ++ uint32_t val; ++ compat_uptr_t id; ++} ioc_compat_fm_pcd_kg_scheme_spc_t; ++ ++typedef struct ioc_compat_fm_ctrl_mon_counters_params_t { ++ uint8_t fm_ctrl_index; ++ compat_uptr_t p_mon; ++} ioc_compat_fm_ctrl_mon_counters_params_t; ++ ++typedef struct ioc_compat_fm_pcd_cc_tbl_get_stats_t { ++ compat_uptr_t id; ++ uint16_t key_index; ++ ioc_fm_pcd_cc_key_statistics_t statistics; ++} ioc_compat_fm_pcd_cc_tbl_get_stats_t; ++ ++ ++/* } pcd compat structures */ ++ ++void compat_obj_delete( ++ ioc_compat_fm_obj_t *compat_id, ++ ioc_fm_obj_t *id); ++ ++/* pcd compat functions { */ ++void compat_copy_fm_pcd_plcr_profile( ++ ioc_compat_fm_pcd_plcr_profile_params_t *compat_param, ++ ioc_fm_pcd_plcr_profile_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_cc_key( ++ ioc_compat_fm_pcd_cc_key_params_t *compat_param, ++ ioc_fm_pcd_cc_key_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_cc_node_modify_key_and_next_engine( ++ ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *compat_param, ++ ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_cc_node_modify_next_engine( ++ ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *compat_param, ++ ioc_fm_pcd_cc_node_modify_next_engine_params_t *param, ++ uint8_t compat); ++ ++void compat_fm_pcd_cc_tree_modify_next_engine( ++ ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *compat_param, ++ ioc_fm_pcd_cc_tree_modify_next_engine_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_hash_table( ++ ioc_compat_fm_pcd_hash_table_params_t *compat_param, ++ ioc_fm_pcd_hash_table_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_cc_grp( ++ ioc_compat_fm_pcd_cc_grp_params_t *compat_param, ++ ioc_fm_pcd_cc_grp_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_cc_tree( ++ ioc_compat_fm_pcd_cc_tree_params_t *compat_param, ++ ioc_fm_pcd_cc_tree_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_cc_tbl_get_stats( ++ ioc_compat_fm_pcd_cc_tbl_get_stats_t *compat_param, ++ ioc_fm_pcd_cc_tbl_get_stats_t *param, ++ uint8_t compat); ++ ++void compat_fm_pcd_prs_sw( ++ ioc_compat_fm_pcd_prs_sw_params_t *compat_param, ++ ioc_fm_pcd_prs_sw_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_kg_scheme( ++ ioc_compat_fm_pcd_kg_scheme_params_t *compat_param, ++ ioc_fm_pcd_kg_scheme_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_kg_scheme_select( ++ ioc_compat_fm_pcd_kg_scheme_select_t *compat_param, ++ ioc_fm_pcd_kg_scheme_select_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_kg_schemes_params( ++ ioc_compat_fm_pcd_port_schemes_params_t *compat_param, ++ ioc_fm_pcd_port_schemes_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_port_pcd_kg( ++ ioc_compat_fm_port_pcd_kg_params_t *compat_param, ++ ioc_fm_port_pcd_kg_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_port_pcd( ++ ioc_compat_fm_port_pcd_params_t *compat_param, ++ ioc_fm_port_pcd_params_t *param, ++ uint8_t compat); ++ ++#if (DPAA_VERSION >= 11) ++void compat_copy_fm_port_vsp_alloc_params( ++ ioc_compat_fm_port_vsp_alloc_params_t *compat_param, ++ ioc_fm_port_vsp_alloc_params_t *param, ++ uint8_t compat); ++#endif /* (DPAA_VERSION >= 11) */ ++ ++void compat_copy_fm_pcd_net_env( ++ ioc_compat_fm_pcd_net_env_params_t *compat_param, ++ ioc_fm_pcd_net_env_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_cc_node_modify_key( ++ ioc_compat_fm_pcd_cc_node_modify_key_params_t *compat_param, ++ ioc_fm_pcd_cc_node_modify_key_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_keys( ++ ioc_compat_keys_params_t *compat_param, ++ ioc_keys_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_cc_node( ++ ioc_compat_fm_pcd_cc_node_params_t *compat_param, ++ ioc_fm_pcd_cc_node_params_t *param, ++ uint8_t compat); ++ ++void compat_fm_pcd_manip_set_node( ++ ioc_compat_fm_pcd_manip_params_t *compat_param, ++ ioc_fm_pcd_manip_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_manip_get_stats( ++ ioc_compat_fm_pcd_manip_get_stats_t *compat_param, ++ ioc_fm_pcd_manip_get_stats_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_port_pcd_modify_tree( ++ ioc_compat_fm_obj_t *compat_id, ++ ioc_fm_obj_t *id, ++ uint8_t compat); ++ ++#if (DPAA_VERSION >= 11) ++void compat_copy_fm_pcd_frm_replic_group_params( ++ ioc_compat_fm_pcd_frm_replic_group_params_t *compat_param, ++ ioc_fm_pcd_frm_replic_group_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_frm_replic_member( ++ ioc_compat_fm_pcd_frm_replic_member_t *compat_param, ++ ioc_fm_pcd_frm_replic_member_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_pcd_frm_replic_member_params( ++ ioc_compat_fm_pcd_frm_replic_member_params_t *compat_param, ++ ioc_fm_pcd_frm_replic_member_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_vsp_params( ++ ioc_compat_fm_vsp_params_t *compat_param, ++ ioc_fm_vsp_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_buf_pool_depletion_params( ++ ioc_compat_fm_buf_pool_depletion_params_t *compat_param, ++ ioc_fm_buf_pool_depletion_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_buffer_prefix_content_params( ++ ioc_compat_fm_buffer_prefix_content_params_t *compat_param, ++ ioc_fm_buffer_prefix_content_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_vsp_config_no_sg_params( ++ ioc_compat_fm_vsp_config_no_sg_params_t *compat_param, ++ ioc_fm_vsp_config_no_sg_params_t *param, ++ uint8_t compat); ++ ++void compat_copy_fm_vsp_prs_result_params( ++ ioc_compat_fm_vsp_prs_result_params_t *compat_param, ++ ioc_fm_vsp_prs_result_params_t *param, ++ uint8_t compat); ++ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++void compat_copy_fm_pcd_kg_scheme_spc( ++ ioc_compat_fm_pcd_kg_scheme_spc_t *compat_param, ++ ioc_fm_pcd_kg_scheme_spc_t *param, ++ uint8_t compat); ++ ++/* } pcd compat functions */ ++#endif +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_resources.h b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_resources.h +new file mode 100644 +index 0000000..1b72e1d +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_resources.h +@@ -0,0 +1,121 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/* ++ @File lnxwrp_resources.h ++ ++ @Description FMD wrapper resource allocation functions. ++ ++*/ ++ ++#ifndef LNXWRP_RESOURCES_H_ ++#define LNXWRP_RESOURCES_H_ ++ ++#if !defined(FMAN_RESOURCES_UNIT_TEST) ++#include "lnxwrp_fm.h" ++#else ++#include "lnxwrp_resources_ut.h" ++#endif ++ ++#define ROUND(X) ((2*(X)+1)/2) ++#define CEIL(X) ((X)+1) ++/* #define ROUND_DIV(X, Y) (((X)+(Y)/2)/(Y)) */ ++#define ROUND_DIV(X, Y) ((2*(X)+(Y))/(2*(Y))) ++#define CEIL_DIV(X, Y) (((X)+(Y)-1)/(Y)) ++ ++/* used for resource calculus */ ++#define DPDE_1G 2 /* DQDP 1g - from LLD: ++ DEFAULT_PORT_txFifoDeqPipelineDepth_1G */ ++#define DPDE_10G 8 /* DQDP 10g - from LLD: ++ DEFAULT_PORT_txFifoDeqPipelineDepth_10G */ ++ ++int fm_set_active_fman_ports(struct platform_device *of_dev, ++ t_LnxWrpFmDev *p_LnxWrpFmDev); ++ ++/* Calculate the fifosize based on MURAM allocation, number of ports, dpde ++ * value and s/g software support (! Kernel does not suport s/g). ++ * ++ * Algorithm summary: ++ * - Calculate the the minimum fifosize required for every type of port ++ * (TX,RX for 1G, 2.5G and 10G). ++ * - Set TX the minimum fifosize required. ++ * - Distribute the remaining buffers (after all TX were set) to RX ports ++ * based on: ++ * 1G RX = Remaining_buffers * 1/(1+2.5+10) ++ * 2.5G RX = Remaining_buffers * 2.5/(1+2.5+10) ++ * 10G RX = Remaining_buffers * 10/(1+2.5+10) ++ * - if the RX is smaller than the minimum required, then set the minimum ++ * required ++ * - In the end distribuite the leftovers if there are any (due to ++ * unprecise calculus) or if over allocation cat some buffers from all RX ++ * ports w/o pass over minimum required treshold, but if there must be ++ * pass the treshold in order to cat the over allocation ,then this ++ * configuration can not be set - KERN_ALERT. ++*/ ++int fm_precalculate_fifosizes(t_LnxWrpFmDev *p_LnxWrpFmDev, ++ int muram_fifo_size); ++ ++#if !defined(FMAN_RESOURCES_UNIT_TEST) ++int fm_config_precalculate_fifosize(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev); ++#endif ++ ++/* Compute FMan open DMA based on total number of open DMAs and ++ * number of available fman ports. ++ * ++ * By default 10g ports are set to input parameters. The other ports ++ * tries to keep the proportion rx=2tx open dmas or tresholds. ++ * ++ * If leftovers, then those will be set as shared. ++ * ++ * If after computing overflow appears, then it decrements open dma ++ * for all ports w/o cross the tresholds. If the tresholds are meet ++ * and is still overflow, then it returns error. ++*/ ++int fm_precalculate_open_dma(t_LnxWrpFmDev *p_LnxWrpFmDev, ++ int max_fm_open_dma, ++ int default_tx_10g_dmas, ++ int default_rx_10g_dmas, ++ int min_tx_10g_treshold, int min_rx_10g_treshold); ++ ++#if !defined(FMAN_RESOURCES_UNIT_TEST) ++int fm_config_precalculate_open_dma(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev); ++#endif ++ ++/* Compute FMan tnums based on available tnums and number of ports. ++ * Set defaults (minim tresholds) and then distribute leftovers.*/ ++int fm_precalculate_tnums(t_LnxWrpFmDev *p_LnxWrpFmDev, int max_fm_tnums); ++ ++#if !defined(FMAN_RESOURCES_UNIT_TEST) ++int fm_config_precalculate_tnums(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev); ++#endif ++ ++#endif /* LNXWRP_RESOURCES_H_ */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_resources_ut.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_resources_ut.c +new file mode 100644 +index 0000000..6c06a5a +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_resources_ut.c +@@ -0,0 +1,191 @@ ++/* Copyright (c) 2012 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * 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 "lnxwrp_resources.h" ++#include "lnxwrp_resources_ut.h" ++ ++#define KILOBYTE 0x400 /* 1024 */ ++ ++typedef enum e_board_type { ++ e_p3041, ++ e_p4080, ++ e_p5020, ++ e_p1023 ++} e_board_type; ++ ++uint8_t board_type; ++uint32_t muram_size = 0; ++uint32_t dmas_num = 0; ++uint32_t task_num = 0; ++uint32_t frame_size = 0; ++uint32_t oh_num = 0; ++uint32_t num_ports_1g = 0; ++uint32_t num_ports_10g = 0; ++uint32_t num_ports_2g5 = 0; ++uint32_t fsl_fman_phy_maxfrm = 0; ++uint32_t dpa_rx_extra_headroom = 0; ++ ++void show_help(void){ ++ printf(" help: \n"); ++ printf(" -b -f -o -g1" ++ " -g10 -g25 \n"); ++ printf(" Maxim num of DMAS availbale: P3/P4/P5:32 , P1023:16 \n"); ++ printf(" Maxim num of TNUMs availbale: P3/P4/P5:128, P1023:32 \n"); ++ printf(" Muram size: P3/P4/P5:160K, P1023:64K \n"); ++ printf(" Number of ports:\n"); ++ printf(" P3/P5: 5p 1g, 1p 10g, 7p oh \n"); ++ printf(" P4 : 4p 1g, 1p 10g, 7p oh \n"); ++ printf(" P1 : 2p 1g, 0p 10g, 4p oh \n"); ++ printf(" MTU: Default:1522, Jumbo:9600 \n"); ++} ++ ++int fm_set_param(t_LnxWrpFmDev *p_LnxWrpFmDev) { ++ struct fm_active_ports *fm_active_ports_info = NULL; ++ fm_active_ports_info = &p_LnxWrpFmDev->fm_active_ports_info; ++ ++ switch(board_type){ ++ case e_p3041: ++ case e_p5020: ++ muram_size = 160*KILOBYTE; ++ dmas_num = 32; ++ task_num = 128; ++ if ((num_ports_1g+num_ports_2g5) > 5 || num_ports_10g > 1 || oh_num > 7) ++ goto err_fm_set_param; ++ break; ++ case e_p4080: ++ muram_size = 160*KILOBYTE; ++ dmas_num = 32; ++ task_num = 128; ++ if ((num_ports_1g+num_ports_2g5) > 4 || num_ports_10g > 1 || oh_num > 7) ++ goto err_fm_set_param; ++ break; ++ case e_p1023: ++ muram_size = 64*KILOBYTE; ++ dmas_num = 16; ++ task_num = 128; ++ if ((num_ports_1g+num_ports_2g5) > 2 || oh_num > 4) ++ goto err_fm_set_param; ++ break; ++ default: ++ goto err_fm_set_param; ++ break; ++ } ++ ++ p_LnxWrpFmDev->id = 0; ++ fsl_fman_phy_maxfrm = frame_size; ++ dpa_rx_extra_headroom = 0; /* ATTENTION: can be != 0 */ ++ fm_active_ports_info->num_oh_ports = oh_num; ++ fm_active_ports_info->num_tx_ports = num_ports_1g; ++ fm_active_ports_info->num_rx_ports = num_ports_1g; ++ fm_active_ports_info->num_tx25_ports = num_ports_2g5; ++ fm_active_ports_info->num_rx25_ports = num_ports_2g5; ++ fm_active_ports_info->num_tx10_ports = num_ports_10g; ++ fm_active_ports_info->num_rx10_ports = num_ports_10g; ++ ++ return 0; ++ ++err_fm_set_param: ++ printf(" ERR: To many ports!!! \n"); ++ return -1; ++} ++ ++int main (int argc, char *argv[]){ ++ t_LnxWrpFmDev LnxWrpFmDev; ++ t_LnxWrpFmDev *p_LnxWrpFmDev = &LnxWrpFmDev; ++ int tokens_cnt = 1; ++ ++ char *token = NULL; ++ ++ while(tokens_cnt < argc) ++ { ++ token = argv[tokens_cnt++]; ++ if (strcmp(token, "-b") == 0){ ++ if(strcmp(argv[tokens_cnt],"p3") == 0) ++ board_type = e_p3041; ++ else if(strcmp(argv[tokens_cnt],"p4") == 0) ++ board_type = e_p4080; ++ else if(strcmp(argv[tokens_cnt],"p5") == 0) ++ board_type = e_p5020; ++ else if(strcmp(argv[tokens_cnt],"p1") == 0) ++ board_type = e_p1023; ++ else ++ show_help(); ++ tokens_cnt++; ++ } ++ else if(strcmp(token, "-d") == 0){ ++ dmas_num = atoi(argv[tokens_cnt++]); ++ } ++ else if(strcmp(token, "-t") == 0) ++ task_num = atoi(argv[tokens_cnt++]); ++ else if(strcmp(token, "-f") == 0) ++ frame_size = atoi(argv[tokens_cnt++]); ++ else if(strcmp(token, "-o") == 0) ++ oh_num = atoi(argv[tokens_cnt++]); ++ else if(strcmp(token, "-g1") == 0) ++ num_ports_1g = atoi(argv[tokens_cnt++]); ++ else if(strcmp(token, "-g10") == 0) ++ num_ports_10g = atoi(argv[tokens_cnt++]); ++ else if(strcmp(token, "-g25") == 0) ++ num_ports_2g5 = atoi(argv[tokens_cnt++]); ++ else { ++ show_help(); ++ return -1; ++ } ++ } ++ ++ if(fm_set_param(p_LnxWrpFmDev) < 0){ ++ show_help(); ++ return -1; ++ } ++ ++ if(fm_precalculate_fifosizes( ++ p_LnxWrpFmDev, ++ 128*KILOBYTE) ++ != 0) ++ return -1; ++ if(fm_precalculate_open_dma( ++ p_LnxWrpFmDev, ++ dmas_num, /* max open dmas:dpaa_integration_ext.h */ ++ FM_DEFAULT_TX10G_OPENDMA, /* default TX 10g open dmas */ ++ FM_DEFAULT_RX10G_OPENDMA, /* default RX 10g open dmas */ ++ FM_10G_OPENDMA_MIN_TRESHOLD,/* TX 10g minimum treshold */ ++ FM_10G_OPENDMA_MIN_TRESHOLD)/* RX 10g minimum treshold */ ++ != 0) ++ return -1; ++ if(fm_precalculate_tnums( ++ p_LnxWrpFmDev, ++ task_num) /* max TNUMS: dpa integration file. */ ++ != 0) ++ return -1; ++ ++ return 0; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_resources_ut.h b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_resources_ut.h +new file mode 100644 +index 0000000..063946e +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_resources_ut.h +@@ -0,0 +1,144 @@ ++/* Copyright (c) 2012 Freescale Semiconductor, Inc ++ * All rights reserved. ++ * ++ * 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 FM_RESS_TEST_H_ ++#define FM_RESS_TEST_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define _Packed ++#define _PackedType __attribute__ ((packed)) ++#define MAX(x, y) (((x) > (y)) ? (x) : (y)) ++#define MIN(x, y) (((x) < (y)) ? (x) : (y)) ++#define KERN_ALERT "" ++#define KERN_INFO "" ++#define ASSERT_COND assert ++#define printk printf ++#define NET_IP_ALIGN 0 ++#define FM_FIFO_ALLOCATION_OLD_ALG ++ ++#if defined(CONFIG_FMAN_DISABLE_OH_AND_DISTRIBUTE_RESOURCES) ++#define FM_10G_OPENDMA_MIN_TRESHOLD 8 /* 10g minimum treshold if only HC is enabled and no OH port enabled */ ++#define FM_OPENDMA_RX_TX_RAPORT 2 /* RX = 2*TX */ ++#else ++#define FM_10G_OPENDMA_MIN_TRESHOLD 7 /* 10g minimum treshold if 7 OH ports are enabled */ ++#define FM_OPENDMA_RX_TX_RAPORT 1 /* RX = TX */ ++#endif ++#define FM_DEFAULT_TX10G_OPENDMA 8 /* default TX 10g open dmas */ ++#define FM_DEFAULT_RX10G_OPENDMA 8 /* default RX 10g open dmas */ ++ ++/* information about all active ports for an FMan. ++ * !Some ports may be disabled by u-boot, thus will not be available */ ++struct fm_active_ports { ++ uint32_t num_oh_ports; ++ uint32_t num_tx_ports; ++ uint32_t num_rx_ports; ++ uint32_t num_tx25_ports; ++ uint32_t num_rx25_ports; ++ uint32_t num_tx10_ports; ++ uint32_t num_rx10_ports; ++}; ++ ++/* FMan resources precalculated at fm probe based ++ * on available FMan port. */ ++struct fm_resource_settings { ++ /* buffers - fifo sizes */ ++ uint32_t tx1g_num_buffers; ++ uint32_t rx1g_num_buffers; ++ uint32_t tx2g5_num_buffers; /* Not supported yet by LLD */ ++ uint32_t rx2g5_num_buffers; /* Not supported yet by LLD */ ++ uint32_t tx10g_num_buffers; ++ uint32_t rx10g_num_buffers; ++ uint32_t oh_num_buffers; ++ uint32_t shared_ext_buffers; ++ ++ ++ /* open DMAs */ ++ uint32_t tx_1g_dmas; ++ uint32_t rx_1g_dmas; ++ uint32_t tx_2g5_dmas; /* Not supported yet by LLD */ ++ uint32_t rx_2g5_dmas; /* Not supported yet by LLD */ ++ uint32_t tx_10g_dmas; ++ uint32_t rx_10g_dmas; ++ uint32_t oh_dmas; ++ uint32_t shared_ext_open_dma; ++ ++ /* Tnums */ ++ uint32_t tx_1g_tnums; ++ uint32_t rx_1g_tnums; ++ uint32_t tx_2g5_tnums; /* Not supported yet by LLD */ ++ uint32_t rx_2g5_tnums; /* Not supported yet by LLD */ ++ uint32_t tx_10g_tnums; ++ uint32_t rx_10g_tnums; ++ uint32_t oh_tnums; ++ uint32_t shared_ext_tnums; ++}; ++ ++typedef struct { ++ uint8_t id; ++ struct fm_active_ports fm_active_ports_info; ++ struct fm_resource_settings fm_resource_settings_info; ++} t_LnxWrpFmDev; ++ ++typedef struct { ++ uint8_t id; ++} t_LnxWrpFmPortDev; ++ ++typedef _Packed struct t_FmPrsResult { ++ volatile uint8_t lpid; /**< Logical port id */ ++ volatile uint8_t shimr; /**< Shim header result */ ++ volatile uint16_t l2r; /**< Layer 2 result */ ++ volatile uint16_t l3r; /**< Layer 3 result */ ++ volatile uint8_t l4r; /**< Layer 4 result */ ++ volatile uint8_t cplan; /**< Classification plan id */ ++ volatile uint16_t nxthdr; /**< Next Header */ ++ volatile uint16_t cksum; /**< Checksum */ ++ volatile uint32_t lcv; /**< LCV */ ++ volatile uint8_t shim_off[3]; /**< Shim offset */ ++ volatile uint8_t eth_off; /**< ETH offset */ ++ volatile uint8_t llc_snap_off; /**< LLC_SNAP offset */ ++ volatile uint8_t vlan_off[2]; /**< VLAN offset */ ++ volatile uint8_t etype_off; /**< ETYPE offset */ ++ volatile uint8_t pppoe_off; /**< PPP offset */ ++ volatile uint8_t mpls_off[2]; /**< MPLS offset */ ++ volatile uint8_t ip_off[2]; /**< IP offset */ ++ volatile uint8_t gre_off; /**< GRE offset */ ++ volatile uint8_t l4_off; /**< Layer 4 offset */ ++ volatile uint8_t nxthdr_off; /**< Parser end point */ ++} _PackedType t_FmPrsResult; ++ ++#endif +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_resources_ut.make b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_resources_ut.make +new file mode 100644 +index 0000000..58009cd +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_resources_ut.make +@@ -0,0 +1,28 @@ ++CC=gcc ++ ++LNXWRP_RESS_UT=lnxwrp_resources_ut ++OBJ=lnxwrp_resources ++ ++INC_PATH= ++LIB_PATH= ++ ++INC=$(addprefix -I,$(INC_PATH)) ++LIB=$(addprefix -L,$(LIB_PATH)) ++ ++CFLAGS= -gdwarf-2 -g -O0 -Wall ++XFLAGS= -DFMAN_RESOURCES_UNIT_TEST ++ ++all: $(LNXWRP_RESS_UT) ++ ++$(LNXWRP_RESS_UT):$(addsuffix .o,$(OBJ)) $(LNXWRP_RESS_UT).o ++ $(CC) -o $(LNXWRP_RESS_UT) $(LNXWRP_RESS_UT).o $(addsuffix .o,$(OBJ)) ++ ++%.o: %.c ++ @(echo " (CC) $@") ++ @($(CC) $(INC) $(CFLAGS) $(XFLAGS) -o $(@) -c $<) ++ ++.PHONY: clean ++ ++clean: ++ rm -f *.o ++ rm -f $(LNXWRP_RESS_UT) +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs.c +new file mode 100644 +index 0000000..813771b +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs.c +@@ -0,0 +1,60 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/* ++ @File lnxwrp_sysfs.c ++ ++ @Description FM wrapper sysfs related functions. ++ ++*/ ++ ++#include ++#include "lnxwrp_sysfs.h" ++ ++uint8_t fm_find_statistic_counter_by_name(const char *attr_name, ++ const struct sysfs_stats_t *sysfs_stats, ++ uint8_t *offset) ++{ ++ int i = 0; ++ ++ while (sysfs_stats[i].stat_name != NULL) { ++ if (strcmp(sysfs_stats[i].stat_name, attr_name) == 0) { ++ if (offset != NULL) ++ *offset = i; ++ return sysfs_stats[i].stat_counter; ++ } ++ ++ i++; ++ } ++ WARN(1, "FMD: Should never get here!"); ++ return 0; ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs.h b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs.h +new file mode 100644 +index 0000000..2098b24 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs.h +@@ -0,0 +1,60 @@ ++/* ++ * Copyright 2008-2012 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 LNXWRP_SYSFS_H_ ++#define LNXWRP_SYSFS_H_ ++ ++/* Linux Headers ------------------- */ ++#include ++ ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#include ++#endif /* MODVERSIONS */ ++ ++#include ++#include ++#include ++#include ++ ++struct sysfs_stats_t { ++ const char *stat_name; ++ uint8_t stat_counter; ++}; ++ ++uint8_t fm_find_statistic_counter_by_name(const char *attr_name, ++ const struct sysfs_stats_t *sysfs_stats, ++ uint8_t *offset); ++ ++#endif /* LNXWRP_SYSFS_H_ */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs_fm.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs_fm.c +new file mode 100644 +index 0000000..1badbf9 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs_fm.c +@@ -0,0 +1,1855 @@ ++/* ++ * Copyright 2008-2012 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 "lnxwrp_sysfs.h" ++#include "lnxwrp_sysfs_fm.h" ++#include "lnxwrp_fm.h" ++ ++#include "../../sdk_fman/Peripherals/FM/inc/fm_common.h" ++#include "../../sdk_fman/Peripherals/FM/Pcd/fm_pcd.h" ++#include "../../sdk_fman/Peripherals/FM/Pcd/fm_kg.h" ++#include "../../sdk_fman/Peripherals/FM/Pcd/fm_plcr.h" ++ ++#if defined(__ERR_MODULE__) ++#undef __ERR_MODULE__ ++#endif ++ ++#include "../../sdk_fman/Peripherals/FM/fm.h" ++#include ++ ++ ++static int fm_get_counter(void *h_fm, e_FmCounters cnt_e, uint32_t *cnt_val); ++ ++enum fm_dma_match_stats { ++ FM_DMA_COUNTERS_CMQ_NOT_EMPTY, ++ FM_DMA_COUNTERS_BUS_ERROR, ++ FM_DMA_COUNTERS_READ_BUF_ECC_ERROR, ++ FM_DMA_COUNTERS_WRITE_BUF_ECC_SYS_ERROR, ++ FM_DMA_COUNTERS_WRITE_BUF_ECC_FM_ERROR ++}; ++ ++static const struct sysfs_stats_t fm_sysfs_stats[] = { ++ /* FM statistics */ ++ { ++ .stat_name = "enq_total_frame", ++ .stat_counter = e_FM_COUNTERS_ENQ_TOTAL_FRAME, ++ }, ++ { ++ .stat_name = "deq_total_frame", ++ .stat_counter = e_FM_COUNTERS_DEQ_TOTAL_FRAME, ++ }, ++ { ++ .stat_name = "deq_0", ++ .stat_counter = e_FM_COUNTERS_DEQ_0, ++ }, ++ { ++ .stat_name = "deq_1", ++ .stat_counter = e_FM_COUNTERS_DEQ_1, ++ }, ++ { ++ .stat_name = "deq_2", ++ .stat_counter = e_FM_COUNTERS_DEQ_2, ++ }, ++ { ++ .stat_name = "deq_3", ++ .stat_counter = e_FM_COUNTERS_DEQ_3, ++ }, ++ { ++ .stat_name = "deq_from_default", ++ .stat_counter = e_FM_COUNTERS_DEQ_FROM_DEFAULT, ++ }, ++ { ++ .stat_name = "deq_from_context", ++ .stat_counter = e_FM_COUNTERS_DEQ_FROM_CONTEXT, ++ }, ++ { ++ .stat_name = "deq_from_fd", ++ .stat_counter = e_FM_COUNTERS_DEQ_FROM_FD, ++ }, ++ { ++ .stat_name = "deq_confirm", ++ .stat_counter = e_FM_COUNTERS_DEQ_CONFIRM, ++ }, ++ /* FM:DMA statistics */ ++ { ++ .stat_name = "cmq_not_empty", ++ .stat_counter = FM_DMA_COUNTERS_CMQ_NOT_EMPTY, ++ }, ++ { ++ .stat_name = "bus_error", ++ .stat_counter = FM_DMA_COUNTERS_BUS_ERROR, ++ }, ++ { ++ .stat_name = "read_buf_ecc_error", ++ .stat_counter = FM_DMA_COUNTERS_READ_BUF_ECC_ERROR, ++ }, ++ { ++ .stat_name = "write_buf_ecc_sys_error", ++ .stat_counter = FM_DMA_COUNTERS_WRITE_BUF_ECC_SYS_ERROR, ++ }, ++ { ++ .stat_name = "write_buf_ecc_fm_error", ++ .stat_counter = FM_DMA_COUNTERS_WRITE_BUF_ECC_FM_ERROR, ++ }, ++ /* FM:PCD statistics */ ++ { ++ .stat_name = "pcd_kg_total", ++ .stat_counter = e_FM_PCD_KG_COUNTERS_TOTAL, ++ }, ++ { ++ .stat_name = "pcd_plcr_yellow", ++ .stat_counter = e_FM_PCD_PLCR_COUNTERS_YELLOW, ++ }, ++ { ++ .stat_name = "pcd_plcr_red", ++ .stat_counter = e_FM_PCD_PLCR_COUNTERS_RED, ++ }, ++ { ++ .stat_name = "pcd_plcr_recolored_to_red", ++ .stat_counter = e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED, ++ }, ++ { ++ .stat_name = "pcd_plcr_recolored_to_yellow", ++ .stat_counter = e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW, ++ }, ++ { ++ .stat_name = "pcd_plcr_total", ++ .stat_counter = e_FM_PCD_PLCR_COUNTERS_TOTAL, ++ }, ++ { ++ .stat_name = "pcd_plcr_length_mismatch", ++ .stat_counter = e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH, ++ }, ++ { ++ .stat_name = "pcd_prs_parse_dispatch", ++ .stat_counter = e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH, ++ }, ++ { ++ .stat_name = "pcd_prs_l2_parse_result_returned", ++ .stat_counter = e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED, ++ }, ++ { ++ .stat_name = "pcd_prs_l3_parse_result_returned", ++ .stat_counter = e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED, ++ }, ++ { ++ .stat_name = "pcd_prs_l4_parse_result_returned", ++ .stat_counter = e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED, ++ }, ++ { ++ .stat_name = "pcd_prs_shim_parse_result_returned", ++ .stat_counter = e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED, ++ }, ++ { ++ .stat_name = "pcd_prs_l2_parse_result_returned_with_err", ++ .stat_counter = ++ e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR, ++ }, ++ { ++ .stat_name = "pcd_prs_l3_parse_result_returned_with_err", ++ .stat_counter = ++ e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR, ++ }, ++ { ++ .stat_name = "pcd_prs_l4_parse_result_returned_with_err", ++ .stat_counter = ++ e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR, ++ }, ++ { ++ .stat_name = "pcd_prs_shim_parse_result_returned_with_err", ++ .stat_counter = ++ e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR, ++ }, ++ { ++ .stat_name = "pcd_prs_soft_prs_cycles", ++ .stat_counter = e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES, ++ }, ++ { ++ .stat_name = "pcd_prs_soft_prs_stall_cycles", ++ .stat_counter = e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES, ++ }, ++ { ++ .stat_name = "pcd_prs_hard_prs_cycle_incl_stall_cycles", ++ .stat_counter = ++ e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES, ++ }, ++ { ++ .stat_name = "pcd_prs_muram_read_cycles", ++ .stat_counter = e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES, ++ }, ++ { ++ .stat_name = "pcd_prs_muram_read_stall_cycles", ++ .stat_counter = e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES, ++ }, ++ { ++ .stat_name = "pcd_prs_muram_write_cycles", ++ .stat_counter = e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES, ++ }, ++ { ++ .stat_name = "pcd_prs_muram_write_stall_cycles", ++ .stat_counter = e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES, ++ }, ++ { ++ .stat_name = "pcd_prs_fpm_command_stall_cycles", ++ .stat_counter = e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES, ++ }, ++ {} ++}; ++ ++ ++static ssize_t show_fm_risc_load(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++ unsigned long flags; ++ int m =0; ++ int err =0; ++ unsigned n = 0; ++ t_FmCtrlMon util; ++ uint8_t i =0 ; ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return -EINVAL; ++ ++ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_Dev) ++ return -EIO; ++ ++ local_irq_save(flags); ++ ++ /* Calculate risc load */ ++ FM_CtrlMonStart(p_wrp_fm_dev->h_Dev); ++ msleep(1000); ++ FM_CtrlMonStop(p_wrp_fm_dev->h_Dev); ++ ++ for (i = 0; i < FM_NUM_OF_CTRL; i++) { ++ err |= FM_CtrlMonGetCounters(p_wrp_fm_dev->h_Dev, i, &util); ++ m = snprintf(&buf[n],PAGE_SIZE,"\tRisc%u: util-%u%%, efficiency-%u%%\n", ++ i, util.percentCnt[0], util.percentCnt[1]); ++ n=m+n; ++ } ++ ++ local_irq_restore(flags); ++ ++ return n; ++} ++ ++/* Fm stats and regs dumps via sysfs */ ++static ssize_t show_fm_dma_stats(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++ t_FmDmaStatus dma_status; ++ unsigned long flags = 0; ++ unsigned n = 0; ++ uint8_t counter_value = 0, counter = 0; ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return -EINVAL; ++ ++ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_Dev) ++ return -EIO; ++ ++ counter = fm_find_statistic_counter_by_name( ++ attr->attr.name, ++ fm_sysfs_stats, NULL); ++ ++ local_irq_save(flags); ++ ++ memset(&dma_status, 0, sizeof(dma_status)); ++ FM_GetDmaStatus(p_wrp_fm_dev->h_Dev, &dma_status); ++ ++ switch (counter) { ++ case FM_DMA_COUNTERS_CMQ_NOT_EMPTY: ++ counter_value = dma_status.cmqNotEmpty; ++ break; ++ case FM_DMA_COUNTERS_BUS_ERROR: ++ counter_value = dma_status.busError; ++ break; ++ case FM_DMA_COUNTERS_READ_BUF_ECC_ERROR: ++ counter_value = dma_status.readBufEccError; ++ break; ++ case FM_DMA_COUNTERS_WRITE_BUF_ECC_SYS_ERROR: ++ counter_value = dma_status.writeBufEccSysError; ++ break; ++ case FM_DMA_COUNTERS_WRITE_BUF_ECC_FM_ERROR: ++ counter_value = dma_status.writeBufEccFmError; ++ break; ++ default: ++ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__, ++ __func__); ++ break; ++ }; ++ ++ n = snprintf(buf, PAGE_SIZE, "\tFM %u counter: %c\n", ++ p_wrp_fm_dev->id, counter_value ? 'T' : 'F'); ++ ++ local_irq_restore(flags); ++ ++ return n; ++} ++ ++static ssize_t show_fm_stats(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++ unsigned long flags = 0; ++ unsigned n = 0, cnt_e = 0; ++ uint32_t cnt_val; ++ int err; ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return -EINVAL; ++ ++ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_Dev) ++ return -EIO; ++ ++ cnt_e = fm_find_statistic_counter_by_name( ++ attr->attr.name, ++ fm_sysfs_stats, NULL); ++ ++ err = fm_get_counter(p_wrp_fm_dev->h_Dev, ++ (e_FmCounters) cnt_e, &cnt_val); ++ ++ if (err) ++ return err; ++ ++ local_irq_save(flags); ++ ++ n = snprintf(buf, PAGE_SIZE, "\tFM %d counter: %d\n", ++ p_wrp_fm_dev->id, cnt_val); ++ ++ local_irq_restore(flags); ++ ++ return n; ++} ++ ++static ssize_t show_fm_muram_free_sz(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++ unsigned long flags = 0; ++ unsigned n = 0; ++ uint64_t muram_free_size = 0; ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return -EINVAL; ++ ++ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_Dev) ++ return -EIO; ++ ++ muram_free_size = FM_MURAM_GetFreeMemSize(p_wrp_fm_dev->h_MuramDev); ++ ++ local_irq_save(flags); ++ ++ n = snprintf(buf, PAGE_SIZE, "\tFM %d muram_free_size: %lld\n", ++ p_wrp_fm_dev->id, muram_free_size); ++ ++ local_irq_restore(flags); ++ ++ return n; ++} ++ ++static ssize_t show_fm_ctrl_code_ver(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++ unsigned long flags = 0; ++ unsigned n = 0; ++ t_FmCtrlCodeRevisionInfo rv_info; ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return -EINVAL; ++ ++ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_Dev) ++ return -EIO; ++ ++ FM_GetFmanCtrlCodeRevision((t_Fm *)p_wrp_fm_dev->h_Dev, &rv_info); ++ ++ local_irq_save(flags); ++ ++ FM_DMP_LN(buf, n, "- FM %d ctrl code pkg info:\n", p_wrp_fm_dev->id); ++ FM_DMP_LN(buf, n, "Package rev: %d\n", rv_info.packageRev); ++ FM_DMP_LN(buf, n, "major rev: %d\n", rv_info.majorRev); ++ FM_DMP_LN(buf, n, "minor rev: %d\n", rv_info.minorRev); ++ ++ local_irq_restore(flags); ++ ++ return n; ++} ++ ++static ssize_t show_fm_pcd_stats(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++ unsigned long flags = 0; ++ unsigned n = 0, counter = 0; ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return -EINVAL; ++ ++ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_Dev || ++ !p_wrp_fm_dev->h_PcdDev) ++ return -EIO; ++ ++ counter = fm_find_statistic_counter_by_name( ++ attr->attr.name, ++ fm_sysfs_stats, NULL); ++ ++ local_irq_save(flags); ++ ++ n = snprintf(buf, PAGE_SIZE, "\tFM %d counter: %d\n", ++ p_wrp_fm_dev->id, ++ FM_PCD_GetCounter(p_wrp_fm_dev->h_PcdDev, ++ (e_FmPcdCounters) counter)); ++ ++ local_irq_restore(flags); ++ ++ return n; ++} ++ ++static ssize_t show_fm_tnum_dbg(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++#endif ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return -EINVAL; ++ ++ local_irq_save(flags); ++ ++ if (!p_wrp_fm_dev->active) ++ return -EIO; ++ else { ++ int tn_s; ++ ++ if (!sscanf(attr->attr.name, "tnum_dbg_%d", &tn_s)) ++ return -EINVAL; ++ ++ n = fm_dump_tnum_dbg(p_wrp_fm_dev->h_Dev, ++ tn_s, tn_s + 15, buf, n); ++ } ++ local_irq_restore(flags); ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ return n; ++} ++ ++static ssize_t show_fm_cls_plan(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++#endif ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return -EINVAL; ++ ++ local_irq_save(flags); ++ ++ n = snprintf(buf, PAGE_SIZE, "\n FM-KG classification plan dump.\n"); ++ ++ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_PcdDev) ++ return -EIO; ++ else { ++ int cpn; ++ ++ if (!sscanf(attr->attr.name, "cls_plan_%d", &cpn)) ++ return -EINVAL; ++ ++ n = fm_dump_cls_plan(p_wrp_fm_dev->h_PcdDev, cpn, buf, n); ++ } ++ local_irq_restore(flags); ++#else ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ return n; ++} ++ ++static ssize_t show_fm_profiles(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++#endif ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return -EINVAL; ++ ++ local_irq_save(flags); ++ ++ n = snprintf(buf, PAGE_SIZE, "FM policer profile dump.\n"); ++ ++ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_PcdDev) ++ return -EIO; ++ else { ++ int pn; ++ ++ if (!sscanf(attr->attr.name, "profile_%d", &pn)) ++ return -EINVAL; ++ ++ n = fm_profile_dump_regs(p_wrp_fm_dev->h_PcdDev, pn, buf, n); ++ } ++ local_irq_restore(flags); ++#else ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ return n; ++} ++ ++static ssize_t show_fm_schemes(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++#endif ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return -EINVAL; ++ ++ local_irq_save(flags); ++ ++ n = snprintf(buf, PAGE_SIZE, "FM-KG driver schemes dump.\n"); ++ ++ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_PcdDev) ++ return -EIO; ++ else { ++ int sn; ++ ++ if (!sscanf(attr->attr.name, "scheme_%d", &sn)) ++ return -EINVAL; ++ ++ n = fm_dump_scheme(p_wrp_fm_dev->h_PcdDev, sn, buf, n); ++ } ++ local_irq_restore(flags); ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ return n; ++} ++ ++/* FM */ ++static DEVICE_ATTR(enq_total_frame, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_total_frame, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(fm_risc_load_val, S_IRUGO, show_fm_risc_load, NULL); ++static DEVICE_ATTR(deq_0, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_1, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_2, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_3, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_from_default, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_from_context, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_from_fd, S_IRUGO, show_fm_stats, NULL); ++static DEVICE_ATTR(deq_confirm, S_IRUGO, show_fm_stats, NULL); ++/* FM:DMA */ ++static DEVICE_ATTR(cmq_not_empty, S_IRUGO, show_fm_dma_stats, NULL); ++static DEVICE_ATTR(bus_error, S_IRUGO, show_fm_dma_stats, NULL); ++static DEVICE_ATTR(read_buf_ecc_error, S_IRUGO, show_fm_dma_stats, NULL); ++static DEVICE_ATTR(write_buf_ecc_sys_error, S_IRUGO, show_fm_dma_stats, NULL); ++static DEVICE_ATTR(write_buf_ecc_fm_error, S_IRUGO, show_fm_dma_stats, NULL); ++/* FM:PCD */ ++static DEVICE_ATTR(pcd_kg_total, S_IRUGO, show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_plcr_yellow, S_IRUGO, show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_plcr_red, S_IRUGO, show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_plcr_recolored_to_red, S_IRUGO, show_fm_pcd_stats, ++ NULL); ++static DEVICE_ATTR(pcd_plcr_recolored_to_yellow, S_IRUGO, show_fm_pcd_stats, ++ NULL); ++static DEVICE_ATTR(pcd_plcr_total, S_IRUGO, show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_plcr_length_mismatch, S_IRUGO, show_fm_pcd_stats, ++ NULL); ++static DEVICE_ATTR(pcd_prs_parse_dispatch, S_IRUGO, show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_l2_parse_result_returned, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_l3_parse_result_returned, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_l4_parse_result_returned, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_shim_parse_result_returned, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_l2_parse_result_returned_with_err, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_l3_parse_result_returned_with_err, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_l4_parse_result_returned_with_err, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_shim_parse_result_returned_with_err, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_soft_prs_cycles, S_IRUGO, show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_soft_prs_stall_cycles, S_IRUGO, show_fm_pcd_stats, ++ NULL); ++static DEVICE_ATTR(pcd_prs_hard_prs_cycle_incl_stall_cycles, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_muram_read_cycles, S_IRUGO, show_fm_pcd_stats, ++ NULL); ++static DEVICE_ATTR(pcd_prs_muram_read_stall_cycles, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_muram_write_cycles, S_IRUGO, show_fm_pcd_stats, ++ NULL); ++static DEVICE_ATTR(pcd_prs_muram_write_stall_cycles, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++static DEVICE_ATTR(pcd_prs_fpm_command_stall_cycles, S_IRUGO, ++ show_fm_pcd_stats, NULL); ++ ++static DEVICE_ATTR(tnum_dbg_0, S_IRUGO, show_fm_tnum_dbg, NULL); ++static DEVICE_ATTR(tnum_dbg_16, S_IRUGO, show_fm_tnum_dbg, NULL); ++static DEVICE_ATTR(tnum_dbg_32, S_IRUGO, show_fm_tnum_dbg, NULL); ++static DEVICE_ATTR(tnum_dbg_48, S_IRUGO, show_fm_tnum_dbg, NULL); ++static DEVICE_ATTR(tnum_dbg_64, S_IRUGO, show_fm_tnum_dbg, NULL); ++static DEVICE_ATTR(tnum_dbg_80, S_IRUGO, show_fm_tnum_dbg, NULL); ++static DEVICE_ATTR(tnum_dbg_96, S_IRUGO, show_fm_tnum_dbg, NULL); ++static DEVICE_ATTR(tnum_dbg_112, S_IRUGO, show_fm_tnum_dbg, NULL); ++ ++static DEVICE_ATTR(cls_plan_0, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_1, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_2, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_3, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_4, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_5, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_6, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_7, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_8, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_9, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_10, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_11, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_12, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_13, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_14, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_15, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_16, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_17, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_18, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_19, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_20, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_21, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_22, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_23, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_24, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_25, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_26, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_27, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_28, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_29, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_30, S_IRUGO, show_fm_cls_plan, NULL); ++static DEVICE_ATTR(cls_plan_31, S_IRUGO, show_fm_cls_plan, NULL); ++ ++static DEVICE_ATTR(profile_0, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_1, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_2, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_3, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_4, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_5, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_6, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_7, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_8, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_9, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_10, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_11, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_12, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_13, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_14, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_15, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_16, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_17, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_18, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_19, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_20, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_21, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_22, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_23, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_24, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_25, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_26, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_27, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_28, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_29, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_30, S_IRUGO, show_fm_profiles, NULL); ++static DEVICE_ATTR(profile_31, S_IRUGO, show_fm_profiles, NULL); ++ ++static DEVICE_ATTR(scheme_0, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_1, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_2, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_3, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_4, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_5, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_6, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_7, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_8, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_9, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_10, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_11, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_12, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_13, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_14, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_15, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_16, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_17, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_18, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_19, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_20, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_21, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_22, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_23, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_24, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_25, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_26, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_27, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_28, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_29, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_30, S_IRUGO, show_fm_schemes, NULL); ++static DEVICE_ATTR(scheme_31, S_IRUGO, show_fm_schemes, NULL); ++ ++ ++static struct attribute *fm_dev_stats_attributes[] = { ++ &dev_attr_enq_total_frame.attr, ++ &dev_attr_deq_total_frame.attr, ++ &dev_attr_deq_0.attr, ++ &dev_attr_deq_1.attr, ++ &dev_attr_deq_2.attr, ++ &dev_attr_deq_3.attr, ++ &dev_attr_deq_from_default.attr, ++ &dev_attr_deq_from_context.attr, ++ &dev_attr_deq_from_fd.attr, ++ &dev_attr_deq_confirm.attr, ++ &dev_attr_cmq_not_empty.attr, ++ &dev_attr_bus_error.attr, ++ &dev_attr_read_buf_ecc_error.attr, ++ &dev_attr_write_buf_ecc_sys_error.attr, ++ &dev_attr_write_buf_ecc_fm_error.attr, ++ &dev_attr_pcd_kg_total.attr, ++ &dev_attr_pcd_plcr_yellow.attr, ++ &dev_attr_pcd_plcr_red.attr, ++ &dev_attr_pcd_plcr_recolored_to_red.attr, ++ &dev_attr_pcd_plcr_recolored_to_yellow.attr, ++ &dev_attr_pcd_plcr_total.attr, ++ &dev_attr_pcd_plcr_length_mismatch.attr, ++ &dev_attr_pcd_prs_parse_dispatch.attr, ++ &dev_attr_pcd_prs_l2_parse_result_returned.attr, ++ &dev_attr_pcd_prs_l3_parse_result_returned.attr, ++ &dev_attr_pcd_prs_l4_parse_result_returned.attr, ++ &dev_attr_pcd_prs_shim_parse_result_returned.attr, ++ &dev_attr_pcd_prs_l2_parse_result_returned_with_err.attr, ++ &dev_attr_pcd_prs_l3_parse_result_returned_with_err.attr, ++ &dev_attr_pcd_prs_l4_parse_result_returned_with_err.attr, ++ &dev_attr_pcd_prs_shim_parse_result_returned_with_err.attr, ++ &dev_attr_pcd_prs_soft_prs_cycles.attr, ++ &dev_attr_pcd_prs_soft_prs_stall_cycles.attr, ++ &dev_attr_pcd_prs_hard_prs_cycle_incl_stall_cycles.attr, ++ &dev_attr_pcd_prs_muram_read_cycles.attr, ++ &dev_attr_pcd_prs_muram_read_stall_cycles.attr, ++ &dev_attr_pcd_prs_muram_write_cycles.attr, ++ &dev_attr_pcd_prs_muram_write_stall_cycles.attr, ++ &dev_attr_pcd_prs_fpm_command_stall_cycles.attr, ++ NULL ++}; ++ ++static struct attribute *fm_dev_tnums_dbg_attributes[] = { ++ &dev_attr_tnum_dbg_0.attr, ++ &dev_attr_tnum_dbg_16.attr, ++ &dev_attr_tnum_dbg_32.attr, ++ &dev_attr_tnum_dbg_48.attr, ++ &dev_attr_tnum_dbg_64.attr, ++ &dev_attr_tnum_dbg_80.attr, ++ &dev_attr_tnum_dbg_96.attr, ++ &dev_attr_tnum_dbg_112.attr, ++ NULL ++}; ++ ++static struct attribute *fm_dev_cls_plans_attributes[] = { ++ &dev_attr_cls_plan_0.attr, ++ &dev_attr_cls_plan_1.attr, ++ &dev_attr_cls_plan_2.attr, ++ &dev_attr_cls_plan_3.attr, ++ &dev_attr_cls_plan_4.attr, ++ &dev_attr_cls_plan_5.attr, ++ &dev_attr_cls_plan_6.attr, ++ &dev_attr_cls_plan_7.attr, ++ &dev_attr_cls_plan_8.attr, ++ &dev_attr_cls_plan_9.attr, ++ &dev_attr_cls_plan_10.attr, ++ &dev_attr_cls_plan_11.attr, ++ &dev_attr_cls_plan_12.attr, ++ &dev_attr_cls_plan_13.attr, ++ &dev_attr_cls_plan_14.attr, ++ &dev_attr_cls_plan_15.attr, ++ &dev_attr_cls_plan_16.attr, ++ &dev_attr_cls_plan_17.attr, ++ &dev_attr_cls_plan_18.attr, ++ &dev_attr_cls_plan_19.attr, ++ &dev_attr_cls_plan_20.attr, ++ &dev_attr_cls_plan_21.attr, ++ &dev_attr_cls_plan_22.attr, ++ &dev_attr_cls_plan_23.attr, ++ &dev_attr_cls_plan_24.attr, ++ &dev_attr_cls_plan_25.attr, ++ &dev_attr_cls_plan_26.attr, ++ &dev_attr_cls_plan_27.attr, ++ &dev_attr_cls_plan_28.attr, ++ &dev_attr_cls_plan_29.attr, ++ &dev_attr_cls_plan_30.attr, ++ &dev_attr_cls_plan_31.attr, ++ NULL ++}; ++ ++static struct attribute *fm_dev_profiles_attributes[] = { ++ &dev_attr_profile_0.attr, ++ &dev_attr_profile_1.attr, ++ &dev_attr_profile_2.attr, ++ &dev_attr_profile_3.attr, ++ &dev_attr_profile_4.attr, ++ &dev_attr_profile_5.attr, ++ &dev_attr_profile_6.attr, ++ &dev_attr_profile_7.attr, ++ &dev_attr_profile_8.attr, ++ &dev_attr_profile_9.attr, ++ &dev_attr_profile_10.attr, ++ &dev_attr_profile_11.attr, ++ &dev_attr_profile_12.attr, ++ &dev_attr_profile_13.attr, ++ &dev_attr_profile_14.attr, ++ &dev_attr_profile_15.attr, ++ &dev_attr_profile_16.attr, ++ &dev_attr_profile_17.attr, ++ &dev_attr_profile_18.attr, ++ &dev_attr_profile_19.attr, ++ &dev_attr_profile_20.attr, ++ &dev_attr_profile_21.attr, ++ &dev_attr_profile_22.attr, ++ &dev_attr_profile_23.attr, ++ &dev_attr_profile_24.attr, ++ &dev_attr_profile_25.attr, ++ &dev_attr_profile_26.attr, ++ &dev_attr_profile_27.attr, ++ &dev_attr_profile_28.attr, ++ &dev_attr_profile_29.attr, ++ &dev_attr_profile_30.attr, ++ &dev_attr_profile_31.attr, ++ NULL ++}; ++ ++static struct attribute *fm_dev_schemes_attributes[] = { ++ &dev_attr_scheme_0.attr, ++ &dev_attr_scheme_1.attr, ++ &dev_attr_scheme_2.attr, ++ &dev_attr_scheme_3.attr, ++ &dev_attr_scheme_4.attr, ++ &dev_attr_scheme_5.attr, ++ &dev_attr_scheme_6.attr, ++ &dev_attr_scheme_7.attr, ++ &dev_attr_scheme_8.attr, ++ &dev_attr_scheme_9.attr, ++ &dev_attr_scheme_10.attr, ++ &dev_attr_scheme_11.attr, ++ &dev_attr_scheme_12.attr, ++ &dev_attr_scheme_13.attr, ++ &dev_attr_scheme_14.attr, ++ &dev_attr_scheme_15.attr, ++ &dev_attr_scheme_16.attr, ++ &dev_attr_scheme_17.attr, ++ &dev_attr_scheme_18.attr, ++ &dev_attr_scheme_19.attr, ++ &dev_attr_scheme_20.attr, ++ &dev_attr_scheme_21.attr, ++ &dev_attr_scheme_22.attr, ++ &dev_attr_scheme_23.attr, ++ &dev_attr_scheme_24.attr, ++ &dev_attr_scheme_25.attr, ++ &dev_attr_scheme_26.attr, ++ &dev_attr_scheme_27.attr, ++ &dev_attr_scheme_28.attr, ++ &dev_attr_scheme_29.attr, ++ &dev_attr_scheme_30.attr, ++ &dev_attr_scheme_31.attr, ++ NULL ++}; ++ ++static const struct attribute_group fm_dev_stats_attr_grp = { ++ .name = "statistics", ++ .attrs = fm_dev_stats_attributes ++}; ++ ++static const struct attribute_group fm_dev_tnums_dbg_attr_grp = { ++ .name = "tnums_dbg", ++ .attrs = fm_dev_tnums_dbg_attributes ++}; ++ ++static const struct attribute_group fm_dev_cls_plans_attr_grp = { ++ .name = "cls_plans", ++ .attrs = fm_dev_cls_plans_attributes ++}; ++ ++static const struct attribute_group fm_dev_schemes_attr_grp = { ++ .name = "schemes", ++ .attrs = fm_dev_schemes_attributes ++}; ++ ++static const struct attribute_group fm_dev_profiles_attr_grp = { ++ .name = "profiles", ++ .attrs = fm_dev_profiles_attributes ++}; ++ ++static ssize_t show_fm_regs(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++#endif ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return -EINVAL; ++ ++ local_irq_save(flags); ++ ++ n = snprintf(buf, PAGE_SIZE, "FM driver registers dump.\n"); ++ ++ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_Dev) ++ return -EIO; ++ else ++ n = fm_dump_regs(p_wrp_fm_dev->h_Dev, buf, n); ++ ++ local_irq_restore(flags); ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ return n; ++} ++ ++static ssize_t show_fm_kg_pe_regs(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++#endif ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return -EINVAL; ++ ++ local_irq_save(flags); ++ ++ n = snprintf(buf, PAGE_SIZE, ++ "\n FM-KG Port Partition Config registers dump.\n"); ++ ++ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_PcdDev) ++ return -EIO; ++ else ++ n = fm_kg_pe_dump_regs(p_wrp_fm_dev->h_PcdDev, buf, n); ++ ++ local_irq_restore(flags); ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ return n; ++} ++ ++static ssize_t show_fm_kg_regs(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++#endif ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return -EINVAL; ++ ++ local_irq_save(flags); ++ ++ n = snprintf(buf, PAGE_SIZE, "FM-KG registers dump.\n"); ++ ++ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_PcdDev) ++ return -EIO; ++ else ++ n = fm_kg_dump_regs(p_wrp_fm_dev->h_PcdDev, buf, n); ++ ++ local_irq_restore(flags); ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ return n; ++} ++ ++ ++static ssize_t show_fm_fpm_regs(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++#endif ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return -EINVAL; ++ ++ local_irq_save(flags); ++ ++ n = snprintf(buf, PAGE_SIZE, "FM-FPM registers dump.\n"); ++ ++ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_Dev) ++ return -EIO; ++ else ++ n = fm_fpm_dump_regs(p_wrp_fm_dev->h_Dev, buf, n); ++ ++ local_irq_restore(flags); ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ return n; ++} ++ ++static ssize_t show_prs_regs(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++#endif ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return -EINVAL; ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, "FM Policer registers dump.\n"); ++ ++ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_PcdDev) ++ return -EIO; ++ else ++ n = fm_prs_dump_regs(p_wrp_fm_dev->h_PcdDev, buf, n); ++ ++ local_irq_restore(flags); ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++ ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ return n; ++} ++ ++static ssize_t show_plcr_regs(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++#endif ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return -EINVAL; ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, "FM Policer registers dump.\n"); ++ ++ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_PcdDev) ++ return -EIO; ++ else ++ n = fm_plcr_dump_regs(p_wrp_fm_dev->h_PcdDev, buf, n); ++ ++ local_irq_restore(flags); ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++ ++#endif /* (defined(DEBUG_ERRORS) && ... */ ++ ++ return n; ++} ++ ++static DEVICE_ATTR(fm_regs, S_IRUGO, show_fm_regs, NULL); ++static DEVICE_ATTR(fm_fpm_regs, S_IRUGO, show_fm_fpm_regs, NULL); ++static DEVICE_ATTR(fm_kg_regs, S_IRUGO, show_fm_kg_regs, NULL); ++static DEVICE_ATTR(fm_kg_pe_regs, S_IRUGO, show_fm_kg_pe_regs, NULL); ++static DEVICE_ATTR(fm_plcr_regs, S_IRUGO, show_plcr_regs, NULL); ++static DEVICE_ATTR(fm_prs_regs, S_IRUGO, show_prs_regs, NULL); ++static DEVICE_ATTR(fm_muram_free_size, S_IRUGO, show_fm_muram_free_sz, NULL); ++static DEVICE_ATTR(fm_ctrl_code_ver, S_IRUGO, show_fm_ctrl_code_ver, NULL); ++ ++int fm_sysfs_create(struct device *dev) ++{ ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++ ++ if (dev == NULL) ++ return -EIO; ++ ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ ++ /* store to remove them when module is disabled */ ++ p_wrp_fm_dev->dev_attr_regs = &dev_attr_fm_regs; ++ p_wrp_fm_dev->dev_attr_risc_load = &dev_attr_fm_risc_load_val; ++ p_wrp_fm_dev->dev_fm_fpm_attr_regs = &dev_attr_fm_fpm_regs; ++ p_wrp_fm_dev->dev_fm_kg_attr_regs = &dev_attr_fm_kg_regs; ++ p_wrp_fm_dev->dev_fm_kg_pe_attr_regs = &dev_attr_fm_kg_pe_regs; ++ p_wrp_fm_dev->dev_plcr_attr_regs = &dev_attr_fm_plcr_regs; ++ p_wrp_fm_dev->dev_prs_attr_regs = &dev_attr_fm_prs_regs; ++ p_wrp_fm_dev->dev_attr_muram_free_size = &dev_attr_fm_muram_free_size; ++ p_wrp_fm_dev->dev_attr_fm_ctrl_code_ver = &dev_attr_fm_ctrl_code_ver; ++ ++ /* Create sysfs statistics group for FM module */ ++ if (sysfs_create_group(&dev->kobj, &fm_dev_stats_attr_grp) != 0) ++ return -EIO; ++ ++ if (sysfs_create_group(&dev->kobj, &fm_dev_schemes_attr_grp) != 0) ++ return -EIO; ++ ++ if (sysfs_create_group(&dev->kobj, &fm_dev_profiles_attr_grp) != 0) ++ return -EIO; ++ ++ if (sysfs_create_group(&dev->kobj, &fm_dev_tnums_dbg_attr_grp) != 0) ++ return -EIO; ++ ++ if (sysfs_create_group(&dev->kobj, &fm_dev_cls_plans_attr_grp) != 0) ++ return -EIO; ++ ++ /* Registers dump entry - in future will be moved to debugfs */ ++ if (device_create_file(dev, &dev_attr_fm_regs) != 0) ++ return -EIO; ++ ++ if (device_create_file(dev, &dev_attr_fm_risc_load_val) != 0) ++ return -EIO; ++ ++ if (device_create_file(dev, &dev_attr_fm_fpm_regs) != 0) ++ return -EIO; ++ ++ if (device_create_file(dev, &dev_attr_fm_kg_regs) != 0) ++ return -EIO; ++ ++ if (device_create_file(dev, &dev_attr_fm_kg_pe_regs) != 0) ++ return -EIO; ++ ++ if (device_create_file(dev, &dev_attr_fm_plcr_regs) != 0) ++ return -EIO; ++ ++ if (device_create_file(dev, &dev_attr_fm_prs_regs) != 0) ++ return -EIO; ++ ++ /* muram free size */ ++ if (device_create_file(dev, &dev_attr_fm_muram_free_size) != 0) ++ return -EIO; ++ ++ /* fm ctrl code version */ ++ if (device_create_file(dev, &dev_attr_fm_ctrl_code_ver) != 0) ++ return -EIO; ++ ++ return 0; ++} ++ ++void fm_sysfs_destroy(struct device *dev) ++{ ++ t_LnxWrpFmDev *p_wrp_fm_dev = NULL; ++ ++ if (WARN_ON(dev == NULL)) ++ return; ++ ++ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_wrp_fm_dev == NULL)) ++ return; ++ ++ sysfs_remove_group(&dev->kobj, &fm_dev_stats_attr_grp); ++ sysfs_remove_group(&dev->kobj, &fm_dev_schemes_attr_grp); ++ sysfs_remove_group(&dev->kobj, &fm_dev_profiles_attr_grp); ++ sysfs_remove_group(&dev->kobj, &fm_dev_cls_plans_attr_grp); ++ sysfs_remove_group(&dev->kobj, &fm_dev_tnums_dbg_attr_grp); ++ device_remove_file(dev, p_wrp_fm_dev->dev_attr_regs); ++ device_remove_file(dev, p_wrp_fm_dev->dev_fm_fpm_attr_regs); ++ device_remove_file(dev, p_wrp_fm_dev->dev_fm_kg_attr_regs); ++ device_remove_file(dev, p_wrp_fm_dev->dev_fm_kg_pe_attr_regs); ++ device_remove_file(dev, p_wrp_fm_dev->dev_plcr_attr_regs); ++ device_remove_file(dev, p_wrp_fm_dev->dev_prs_attr_regs); ++ device_remove_file(dev, p_wrp_fm_dev->dev_attr_muram_free_size); ++ device_remove_file(dev, p_wrp_fm_dev->dev_attr_fm_ctrl_code_ver); ++} ++ ++int fm_dump_regs(void *h_fm, char *buf, int nn) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_fm; ++ uint8_t i = 0; ++ int n = nn; ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ ++ FM_DMP_TITLE(buf, n, p_Fm->p_FmDmaRegs, "FM-DMA Regs"); ++ ++ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmsr); ++ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmemsr); ++ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmmr); ++ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmtr); ++ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmhy); ++ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmsetr); ++ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmtah); ++ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmtal); ++ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmtcid); ++ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmra); ++ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmrd); ++ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmwcr); ++ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmebcr); ++ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmdcr); ++ ++ FM_DMP_TITLE(buf, n, &p_Fm->p_FmDmaRegs->fmdmplr, "fmdmplr"); ++ ++ for (i = 0; i < FM_MAX_NUM_OF_HW_PORT_IDS / 2 ; ++i) ++ FM_DMP_MEM_32(buf, n, &p_Fm->p_FmDmaRegs->fmdmplr[i]); ++ ++ FM_DMP_TITLE(buf, n, p_Fm->p_FmBmiRegs, "FM-BMI COMMON Regs"); ++ FM_DMP_V32(buf, n, p_Fm->p_FmBmiRegs, fmbm_init); ++ FM_DMP_V32(buf, n, p_Fm->p_FmBmiRegs, fmbm_cfg1); ++ FM_DMP_V32(buf, n, p_Fm->p_FmBmiRegs, fmbm_cfg2); ++ FM_DMP_V32(buf, n, p_Fm->p_FmBmiRegs, fmbm_ievr); ++ FM_DMP_V32(buf, n, p_Fm->p_FmBmiRegs, fmbm_ier); ++ ++ FM_DMP_TITLE(buf, n, &p_Fm->p_FmBmiRegs->fmbm_arb, "fmbm_arb"); ++ for (i = 0; i < 8 ; ++i) ++ FM_DMP_MEM_32(buf, n, &p_Fm->p_FmBmiRegs->fmbm_arb[i]); ++ ++ FM_DMP_TITLE(buf, n, p_Fm->p_FmQmiRegs, "FM-QMI COMMON Regs"); ++ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_gc); ++ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_eie); ++ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_eien); ++ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_eif); ++ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_ie); ++ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_ien); ++ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_if); ++ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_gs); ++ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_etfc); ++ ++ return n; ++} ++ ++int fm_dump_tnum_dbg(void *h_fm, int tn_s, int tn_e, char *buf, int nn) ++{ ++ t_Fm *p_Fm = (t_Fm *)h_fm; ++ uint8_t i, j = 0; ++ int n = nn; ++ ++ FM_DMP_TITLE(buf, n, NULL, "Tnums and Tnum dbg regs %d - %d", ++ tn_s, tn_e); ++ ++ iowrite32be(tn_s << 24, &p_Fm->p_FmFpmRegs->fmfp_dra); ++ ++ mb(); ++ ++ for (j = tn_s; j <= tn_e; j++) { ++ FM_DMP_LN(buf, n, "> fmfp_ts[%d]\n", j); ++ FM_DMP_MEM_32(buf, n, &p_Fm->p_FmFpmRegs->fmfp_ts[j]); ++ FM_DMP_V32(buf, n, p_Fm->p_FmFpmRegs, fmfp_dra); ++ FM_DMP_LN(buf, n, "> fmfp_drd[0-3]\n"); ++ ++ for (i = 0; i < 4 ; ++i) ++ FM_DMP_MEM_32(buf, n, &p_Fm->p_FmFpmRegs->fmfp_drd[i]); ++ ++ FM_DMP_LN(buf, n, "\n"); ++ ++ } ++ ++ return n; ++} ++ ++int fm_dump_cls_plan(void *h_fm_pcd, int cpn, char *buf, int nn) ++{ ++ t_FmPcd *p_pcd = (t_FmPcd *)h_fm_pcd; ++ int i = 0; ++ uint32_t tmp; ++ unsigned long i_flg; ++ int n = nn; ++ u_FmPcdKgIndirectAccessRegs *idac; ++ spinlock_t *p_lk; ++ ++ p_lk = (spinlock_t *)p_pcd->p_FmPcdKg->h_HwSpinlock; ++ idac = p_pcd->p_FmPcdKg->p_IndirectAccessRegs; ++ ++ spin_lock_irqsave(p_lk, i_flg); ++ ++ /* Read ClsPlan Block Action Regs */ ++ tmp = (uint32_t)(FM_KG_KGAR_GO | ++ FM_KG_KGAR_READ | ++ FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY | ++ DUMMY_PORT_ID | ++ ((uint32_t)cpn << FM_PCD_KG_KGAR_NUM_SHIFT) | ++ FM_PCD_KG_KGAR_WSEL_MASK); ++ ++ if (fman_kg_write_ar_wait(p_pcd->p_FmPcdKg->p_FmPcdKgRegs, tmp)) { ++ FM_DMP_LN(buf, nn, "Keygen scheme access violation"); ++ spin_unlock_irqrestore(p_lk, i_flg); ++ return nn; ++ } ++ FM_DMP_TITLE(buf, n, &idac->clsPlanRegs, ++ "ClsPlan %d Indirect Access Regs", cpn); ++ ++ for (i = 0; i < 8; i++) ++ FM_DMP_MEM_32(buf, n, &idac->clsPlanRegs.kgcpe[i]); ++ ++ spin_unlock_irqrestore(p_lk, i_flg); ++ ++ return n; ++} ++ ++int fm_profile_dump_regs(void *h_fm_pcd, int ppn, char *buf, int nn) ++{ ++ t_FmPcd *p_pcd = (t_FmPcd *)h_fm_pcd; ++ t_FmPcdPlcrProfileRegs *p_prof_regs; ++ t_FmPcdPlcrRegs *p_plcr_regs; ++ t_FmPcdPlcr *p_plcr; ++ uint32_t tmp; ++ unsigned long i_flg; ++ int n = nn; ++ int toc = 10; ++ spinlock_t *p_lk; ++ ++ p_plcr = p_pcd->p_FmPcdPlcr; ++ p_prof_regs = &p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->profileRegs; ++ p_plcr_regs = p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs; ++ ++ p_lk = (spinlock_t *)((t_FmPcdPlcr *)p_plcr)->h_HwSpinlock; ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ FM_DMP_TITLE(buf, n, p_plcr_regs, "FM-PCD policer-profile regs"); ++ ++ tmp = (uint32_t)(FM_PCD_PLCR_PAR_GO | ++ FM_PCD_PLCR_PAR_R | ++ ((uint32_t)ppn << FM_PCD_PLCR_PAR_PNUM_SHIFT) | ++ FM_PCD_PLCR_PAR_PWSEL_MASK); ++ ++ spin_lock_irqsave(p_lk, i_flg); ++ ++ iowrite32be(tmp, &p_plcr_regs->fmpl_par); ++ ++ mb(); ++ ++ /* wait for the porfile regs to be present */ ++ do { ++ --toc; ++ udelay(10); ++ if (!toc) { ++ /* looks like PLCR_PAR_GO refuses to clear */ ++ spin_unlock_irqrestore(p_lk, i_flg); ++ FM_DMP_LN(buf, n, "Profile regs not accessible -"); ++ FM_DMP_LN(buf, n, " check profile init process\n"); ++ return n; ++ } ++ } while ((ioread32be(&p_plcr_regs->fmpl_par) & FM_PCD_PLCR_PAR_GO)); ++ ++ FM_DMP_TITLE(buf, n, p_prof_regs, "Profile %d regs", ppn); ++ ++ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pemode); ++ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pegnia); ++ FM_DMP_V32(buf, n, p_prof_regs, fmpl_peynia); ++ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pernia); ++ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pecir); ++ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pecbs); ++ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pepepir_eir); ++ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pepbs_ebs); ++ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pelts); ++ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pects); ++ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pepts_ets); ++ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pegpc); ++ FM_DMP_V32(buf, n, p_prof_regs, fmpl_peypc); ++ FM_DMP_V32(buf, n, p_prof_regs, fmpl_perpc); ++ FM_DMP_V32(buf, n, p_prof_regs, fmpl_perypc); ++ FM_DMP_V32(buf, n, p_prof_regs, fmpl_perrpc); ++ ++ spin_unlock_irqrestore(p_lk, i_flg); ++ ++ return n; ++} ++ ++int fm_dump_scheme(void *h_fm_pcd, int scnum, char *buf, int nn) ++{ ++ t_FmPcd *p_pcd = (t_FmPcd *)h_fm_pcd; ++ uint32_t tmp_ar; ++ unsigned long i_flg; ++ int i, n = nn; ++ spinlock_t *p_lk; ++ u_FmPcdKgIndirectAccessRegs *idac; ++ ++ idac = p_pcd->p_FmPcdKg->p_IndirectAccessRegs; ++ p_lk = (spinlock_t *)p_pcd->p_FmPcdKg->h_HwSpinlock; ++ ++ spin_lock_irqsave(p_lk, i_flg); ++ ++ tmp_ar = FmPcdKgBuildReadSchemeActionReg((uint8_t)scnum); ++ if (fman_kg_write_ar_wait(p_pcd->p_FmPcdKg->p_FmPcdKgRegs, tmp_ar)) { ++ FM_DMP_LN(buf, nn, ++ "Keygen scheme access violation or no such scheme"); ++ spin_unlock_irqrestore(p_lk, i_flg); ++ return nn; ++ } ++ ++ FM_DMP_TITLE(buf, n, &idac->schemeRegs, ++ "Scheme %d Indirect Access Regs", scnum); ++ ++ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_mode); ++ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_ekfc); ++ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_ekdv); ++ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_bmch); ++ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_bmcl); ++ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_fqb); ++ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_hc); ++ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_ppc); ++ ++ FM_DMP_TITLE(buf, n, &idac->schemeRegs.kgse_gec, "kgse_gec"); ++ ++ for (i = 0; i < FM_KG_NUM_OF_GENERIC_REGS; i++) ++ FM_DMP_MEM_32(buf, n, &idac->schemeRegs.kgse_gec[i]); ++ ++ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_spc); ++ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_dv0); ++ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_dv1); ++ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_ccbs); ++ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_mv); ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ ++ spin_unlock_irqrestore(p_lk, i_flg); ++ ++ return n; ++} ++ ++int fm_kg_pe_dump_regs(void *h_fm_pcd, char *buf, int nn) ++{ ++ t_FmPcd *p_pcd = (t_FmPcd *)h_fm_pcd; ++ int i = 0; ++ uint8_t prt_id = 0; ++ uint32_t tmp_ar; ++ unsigned long i_flg; ++ int n = nn; ++ u_FmPcdKgIndirectAccessRegs *idac; ++ t_FmPcdKg *p_kg; ++ spinlock_t *p_lk; ++ ++ p_kg = p_pcd->p_FmPcdKg; ++ idac = p_pcd->p_FmPcdKg->p_IndirectAccessRegs; ++ p_lk = (spinlock_t *)p_kg->h_HwSpinlock; ++ ++ spin_lock_irqsave(p_lk, i_flg); ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ ++ for (i = 0; i < FM_MAX_NUM_OF_PORTS; i++) { ++ SW_PORT_INDX_TO_HW_PORT_ID(prt_id, i); ++ ++ tmp_ar = FmPcdKgBuildReadPortSchemeBindActionReg(prt_id); ++ ++ if (fman_kg_write_ar_wait(p_kg->p_FmPcdKgRegs, tmp_ar)) { ++ FM_DMP_LN(buf, nn, "Keygen scheme access violation"); ++ spin_unlock_irqrestore(p_lk, i_flg); ++ return nn; ++ } ++ FM_DMP_TITLE(buf, n, &idac->portRegs, "Port %d regs", prt_id); ++ FM_DMP_V32(buf, n, &idac->portRegs, fmkg_pe_sp); ++ FM_DMP_V32(buf, n, &idac->portRegs, fmkg_pe_cpp); ++ } ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ ++ spin_unlock_irqrestore(p_lk, i_flg); ++ ++ return n; ++} ++ ++int fm_kg_dump_regs(void *h_fm_pcd, char *buf, int nn) ++{ ++ t_FmPcd *p_pcd = (t_FmPcd *)h_fm_pcd; ++ int n = nn; ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ FM_DMP_TITLE(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, ++ "FmPcdKgRegs Regs"); ++ ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_gcr); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_eer); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_eeer); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_seer); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_seeer); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_gsr); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_tpc); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_serc); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_fdor); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_gdv0r); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_gdv1r); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_feer); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_ar); ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ ++ return n; ++} ++ ++ ++int fm_fpm_dump_regs(void *h_fm, char *buf, int nn) ++{ ++ t_Fm *p_fm = (t_Fm *)h_fm; ++ uint8_t i; ++ int n = nn; ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ ++ FM_DMP_TITLE(buf, n, p_fm->p_FmFpmRegs, "FM-FPM Regs"); ++ ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_tnc); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_prc); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_brkc); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_mxd); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_dist1); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_dist2); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fm_epi); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fm_rie); ++ ++ FM_DMP_TITLE(buf, n, &p_fm->p_FmFpmRegs->fmfp_fcev, "fmfp_fcev"); ++ for (i = 0; i < 4; ++i) ++ FM_DMP_MEM_32(buf, n, &p_fm->p_FmFpmRegs->fmfp_fcev[i]); ++ ++ FM_DMP_TITLE(buf, n, &p_fm->p_FmFpmRegs->fmfp_cee, "fmfp_cee"); ++ for (i = 0; i < 4; ++i) ++ FM_DMP_MEM_32(buf, n, &p_fm->p_FmFpmRegs->fmfp_cee[i]); ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_tsc1); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_tsc2); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_tsp); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_tsf); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fm_rcr); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_extc); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_ext1); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_ext2); ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fm_ip_rev_1); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fm_ip_rev_2); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fm_rstc); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fm_cld); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fm_npi); ++ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_ee); ++ ++ FM_DMP_TITLE(buf, n, &p_fm->p_FmFpmRegs->fmfp_cev, "fmfp_cev"); ++ for (i = 0; i < 4; ++i) ++ FM_DMP_MEM_32(buf, n, &p_fm->p_FmFpmRegs->fmfp_cev[i]); ++ ++ FM_DMP_TITLE(buf, n, &p_fm->p_FmFpmRegs->fmfp_ps, "fmfp_ps"); ++ for (i = 0; i < 64; ++i) ++ FM_DMP_MEM_32(buf, n, &p_fm->p_FmFpmRegs->fmfp_ps[i]); ++ ++ return n; ++} ++ ++int fm_prs_dump_regs(void *h_fm_pcd, char *buf, int nn) ++{ ++ t_FmPcd *p_pcd = (t_FmPcd *)h_fm_pcd; ++ int n = nn; ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ ++ FM_DMP_TITLE(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, ++ "FM-PCD parser regs"); ++ ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_rpclim); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_rpimac); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, pmeec); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_pevr); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_pever); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_perr); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_perer); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_ppsc); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_pds); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_l2rrs); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_l3rrs); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_l4rrs); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_srrs); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_l2rres); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_l3rres); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_l4rres); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_srres); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_spcs); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_spscs); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_hxscs); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_mrcs); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_mwcs); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_mrscs); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_mwscs); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_fcscs); ++ ++ return n; ++} ++ ++int fm_plcr_dump_regs(void *h_fm_pcd, char *buf, int nn) ++{ ++ t_FmPcd *p_pcd = (t_FmPcd *)h_fm_pcd; ++ int i = 0; ++ int n = nn; ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ ++ FM_DMP_TITLE(buf, n, ++ p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, ++ "FM policer regs"); ++ ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_gcr); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_gsr); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_evr); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_ier); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_ifr); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_eevr); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_eier); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_eifr); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_rpcnt); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_ypcnt); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_rrpcnt); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_rypcnt); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_tpcnt); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_flmcnt); ++ ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_serc); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_upcr); ++ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_dpmr); ++ ++ FM_DMP_TITLE(buf, n, ++ &p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_pmr, ++ "fmpl_pmr"); ++ ++ for (i = 0; i < 63; ++i) ++ FM_DMP_MEM_32(buf, n, ++ &p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_pmr[i]); ++ ++ return n; ++} ++ ++int fm_get_counter(void *h_fm, e_FmCounters cnt_e, uint32_t *cnt_val) ++{ ++ t_Fm *p_fm = (t_Fm *)h_fm; ++ ++ /* When applicable (when there is an "enable counters" bit), ++ check that counters are enabled */ ++ ++ switch (cnt_e) { ++ case (e_FM_COUNTERS_DEQ_1): ++ case (e_FM_COUNTERS_DEQ_2): ++ case (e_FM_COUNTERS_DEQ_3): ++ if (p_fm->p_FmStateStruct->revInfo.majorRev >= 6) ++ return -EINVAL; /* counter not available */ ++ ++ case (e_FM_COUNTERS_ENQ_TOTAL_FRAME): ++ case (e_FM_COUNTERS_DEQ_TOTAL_FRAME): ++ case (e_FM_COUNTERS_DEQ_0): ++ case (e_FM_COUNTERS_DEQ_FROM_DEFAULT): ++ case (e_FM_COUNTERS_DEQ_FROM_CONTEXT): ++ case (e_FM_COUNTERS_DEQ_FROM_FD): ++ case (e_FM_COUNTERS_DEQ_CONFIRM): ++ if (!(ioread32be(&p_fm->p_FmQmiRegs->fmqm_gc) & ++ QMI_CFG_EN_COUNTERS)) ++ return -EINVAL; /* Requested counter not available */ ++ break; ++ default: ++ break; ++ } ++ ++ switch (cnt_e) { ++ case (e_FM_COUNTERS_ENQ_TOTAL_FRAME): ++ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_etfc); ++ return 0; ++ case (e_FM_COUNTERS_DEQ_TOTAL_FRAME): ++ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dtfc); ++ return 0; ++ case (e_FM_COUNTERS_DEQ_0): ++ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dc0); ++ return 0; ++ case (e_FM_COUNTERS_DEQ_1): ++ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dc1); ++ return 0; ++ case (e_FM_COUNTERS_DEQ_2): ++ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dc2); ++ return 0; ++ case (e_FM_COUNTERS_DEQ_3): ++ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dc3); ++ return 0; ++ case (e_FM_COUNTERS_DEQ_FROM_DEFAULT): ++ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dfdc); ++ return 0; ++ case (e_FM_COUNTERS_DEQ_FROM_CONTEXT): ++ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dfcc); ++ return 0; ++ case (e_FM_COUNTERS_DEQ_FROM_FD): ++ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dffc); ++ return 0; ++ case (e_FM_COUNTERS_DEQ_CONFIRM): ++ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dcc); ++ return 0; ++ } ++ /* should never get here */ ++ return -EINVAL; /* counter not available */ ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs_fm.h b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs_fm.h +new file mode 100644 +index 0000000..137653e +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs_fm.h +@@ -0,0 +1,136 @@ ++/* ++ * Copyright 2008-2012 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 LNXWRP_SYSFS_FM_H_ ++#define LNXWRP_SYSFS_FM_H_ ++ ++#include "lnxwrp_sysfs.h" ++ ++int fm_sysfs_create(struct device *dev); ++void fm_sysfs_destroy(struct device *dev); ++int fm_dump_regs(void *h_dev, char *buf, int nn); ++int fm_fpm_dump_regs(void *h_dev, char *buf, int nn); ++int fm_kg_dump_regs(void *h_pcd, char *buf, int nn); ++int fm_kg_pe_dump_regs(void *h_pcd, char *buf, int nn); ++int fm_dump_scheme(void *h_pcd, int scnum, char *buf, int nn); ++int fm_dump_tnum_dbg(void *h_fm, int tn_s, int tn_e, char *buf, int nn); ++int fm_dump_cls_plan(void *h_pcd, int cpn, char *buf, int nn); ++int fm_plcr_dump_regs(void *h_pcd, char *buf, int nn); ++int fm_prs_dump_regs(void *h_pcd, char *buf, int nn); ++int fm_profile_dump_regs(void *h_pcd, int ppnum, char *buf, int nn); ++ ++#define FM_DMP_PGSZ_ERR { \ ++ snprintf(&buf[PAGE_SIZE - 80], 70, \ ++ "\n Err: current sysfs buffer reached PAGE_SIZE\n");\ ++ n = PAGE_SIZE - 2; \ ++ } ++ ++#define FM_DMP_LN(buf, n, ...) \ ++ do { \ ++ int k, m = n; \ ++ m += k = snprintf(&buf[m], PAGE_SIZE - m, __VA_ARGS__); \ ++ if (k < 0 || m > PAGE_SIZE - 90) \ ++ FM_DMP_PGSZ_ERR \ ++ n = m; \ ++ } while (0) ++ ++#define FM_DMP_TITLE(buf, n, addr, ...) \ ++ do { \ ++ int k, m = n; \ ++ m += k = snprintf(&buf[m], PAGE_SIZE - m, "\n"); \ ++ if (k < 0 || m > PAGE_SIZE - 90) \ ++ FM_DMP_PGSZ_ERR \ ++ m += k = snprintf(&buf[m], PAGE_SIZE - m, __VA_ARGS__); \ ++ if (k < 0 || m > PAGE_SIZE - 90) \ ++ FM_DMP_PGSZ_ERR \ ++ if (addr) { \ ++ phys_addr_t pa; \ ++ pa = virt_to_phys(addr); \ ++ m += k = \ ++ snprintf(&buf[m], PAGE_SIZE - m, " (0x%lX)", \ ++ (long unsigned int)(pa)); \ ++ if (k < 0 || m > PAGE_SIZE - 90) \ ++ FM_DMP_PGSZ_ERR \ ++ } \ ++ m += k = snprintf(&buf[m], PAGE_SIZE - m, \ ++ "\n----------------------------------------\n\n"); \ ++ if (k < 0 || m > PAGE_SIZE - 90) \ ++ FM_DMP_PGSZ_ERR \ ++ n = m; \ ++ } while (0) ++ ++#define FM_DMP_SUBTITLE(buf, n, ...) \ ++ do { \ ++ int k, m = n; \ ++ m += k = snprintf(&buf[m], PAGE_SIZE - m, "------- "); \ ++ if (k < 0 || m > PAGE_SIZE - 90) \ ++ FM_DMP_PGSZ_ERR \ ++ m += k = snprintf(&buf[m], PAGE_SIZE - m, __VA_ARGS__); \ ++ if (k < 0 || m > PAGE_SIZE - 90) \ ++ FM_DMP_PGSZ_ERR \ ++ m += k = snprintf(&buf[m], PAGE_SIZE - m, "\n"); \ ++ if (k < 0 || m > PAGE_SIZE - 90) \ ++ FM_DMP_PGSZ_ERR \ ++ n = m; \ ++ } while (0) ++ ++#define FM_DMP_MEM_32(buf, n, addr) \ ++ { \ ++ uint32_t val; \ ++ phys_addr_t pa; \ ++ int k, m = n; \ ++ pa = virt_to_phys(addr); \ ++ val = ioread32be((addr)); \ ++ do { \ ++ m += k = snprintf(&buf[m], \ ++ PAGE_SIZE - m, "0x%010llX: 0x%08x\n", \ ++ pa, val); \ ++ if (k < 0 || m > PAGE_SIZE - 90) \ ++ FM_DMP_PGSZ_ERR \ ++ n += k; \ ++ } while (0) ;\ ++ } ++ ++#define FM_DMP_V32(buf, n, st, phrase) \ ++ do { \ ++ int k, m = n; \ ++ phys_addr_t pa = virt_to_phys(&((st)->phrase)); \ ++ k = snprintf(&buf[m], PAGE_SIZE - m, \ ++ "0x%010llX: 0x%08x%8s\t%s\n", (unsigned long long) pa, \ ++ ioread32be((uint32_t *)&((st)->phrase)), "", #phrase); \ ++ if (k < 0 || m > PAGE_SIZE - 90) \ ++ FM_DMP_PGSZ_ERR \ ++ n += k; \ ++ } while (0) ++ ++#endif /* LNXWRP_SYSFS_FM_H_ */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs_fm_port.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs_fm_port.c +new file mode 100644 +index 0000000..fb4e789 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs_fm_port.c +@@ -0,0 +1,1255 @@ ++/* ++ * Copyright 2008-2012 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 "lnxwrp_sysfs.h" ++#include "lnxwrp_fm.h" ++#include "debug_ext.h" ++#include "lnxwrp_sysfs_fm_port.h" ++#include "lnxwrp_sysfs_fm.h" ++ ++#include "../../sdk_fman/Peripherals/FM/Port/fm_port.h" ++#include "../../sdk_fman/Peripherals/FM/Port/fm_port_dsar.h" ++ ++#if defined(__ERR_MODULE__) ++#undef __ERR_MODULE__ ++#endif ++ ++#include "../../sdk_fman/Peripherals/FM/fm.h" ++ ++static const struct sysfs_stats_t portSysfsStats[] = { ++ /* RX/TX/OH common statistics */ ++ { ++ .stat_name = "port_frame", ++ .stat_counter = e_FM_PORT_COUNTERS_FRAME, ++ }, ++ { ++ .stat_name = "port_discard_frame", ++ .stat_counter = e_FM_PORT_COUNTERS_DISCARD_FRAME, ++ }, ++ { ++ .stat_name = "port_dealloc_buf", ++ .stat_counter = e_FM_PORT_COUNTERS_DEALLOC_BUF, ++ }, ++ { ++ .stat_name = "port_enq_total", ++ .stat_counter = e_FM_PORT_COUNTERS_ENQ_TOTAL, ++ }, ++ /* TX/OH */ ++ { ++ .stat_name = "port_length_err", ++ .stat_counter = e_FM_PORT_COUNTERS_LENGTH_ERR, ++ }, ++ { ++ .stat_name = "port_unsupprted_format", ++ .stat_counter = e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT, ++ }, ++ { ++ .stat_name = "port_deq_total", ++ .stat_counter = e_FM_PORT_COUNTERS_DEQ_TOTAL, ++ }, ++ { ++ .stat_name = "port_deq_from_default", ++ .stat_counter = e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT, ++ }, ++ { ++ .stat_name = "port_deq_confirm", ++ .stat_counter = e_FM_PORT_COUNTERS_DEQ_CONFIRM, ++ }, ++ /* RX/OH */ ++ { ++ .stat_name = "port_rx_bad_frame", ++ .stat_counter = e_FM_PORT_COUNTERS_RX_BAD_FRAME, ++ }, ++ { ++ .stat_name = "port_rx_large_frame", ++ .stat_counter = e_FM_PORT_COUNTERS_RX_LARGE_FRAME, ++ }, ++ { ++ .stat_name = "port_rx_out_of_buffers_discard", ++ .stat_counter = e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD, ++ }, ++ { ++ .stat_name = "port_rx_filter_frame", ++ .stat_counter = e_FM_PORT_COUNTERS_RX_FILTER_FRAME, ++ }, ++ /* TODO: Particular statistics for OH ports */ ++ {} ++}; ++ ++static ssize_t show_fm_port_stats(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev; ++ t_LnxWrpFmDev *p_LnxWrpFmDev; ++ unsigned long flags; ++ int n = 0; ++ uint8_t counter = 0; ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_LnxWrpFmPortDev == NULL)) ++ return -EINVAL; ++ ++ p_LnxWrpFmDev = (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev; ++ if (WARN_ON(p_LnxWrpFmDev == NULL)) ++ return -EINVAL; ++ ++ if (!p_LnxWrpFmDev->active || !p_LnxWrpFmDev->h_Dev) ++ return -EIO; ++ ++ if (!p_LnxWrpFmPortDev->h_Dev) { ++ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n"); ++ return n; ++ } ++ ++ counter = fm_find_statistic_counter_by_name( ++ attr->attr.name, ++ portSysfsStats, NULL); ++ ++ if (counter == e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR) { ++ uint32_t fmRev = 0; ++ fmRev = 0xffff & ++ ioread32(UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr + ++ 0x000c30c4)); ++ ++ if (fmRev == 0x0100) { ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "counter not available for revision 1\n"); ++ local_irq_restore(flags); ++ } ++ return n; ++ } ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, "\t%s counter: %u\n", ++ p_LnxWrpFmPortDev->name, ++ FM_PORT_GetCounter(p_LnxWrpFmPortDev->h_Dev, ++ (e_FmPortCounters) counter)); ++ local_irq_restore(flags); ++ ++ return n; ++} ++ ++/* FM PORT RX/TX/OH statistics */ ++static DEVICE_ATTR(port_frame, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_discard_frame, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_dealloc_buf, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_enq_total, S_IRUGO, show_fm_port_stats, NULL); ++/* FM PORT TX/OH statistics */ ++static DEVICE_ATTR(port_length_err, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_unsupprted_format, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_deq_total, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_deq_from_default, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_deq_confirm, S_IRUGO, show_fm_port_stats, NULL); ++/* FM PORT RX/OH statistics */ ++static DEVICE_ATTR(port_rx_bad_frame, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_rx_large_frame, S_IRUGO, show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_rx_out_of_buffers_discard, S_IRUGO, ++ show_fm_port_stats, NULL); ++static DEVICE_ATTR(port_rx_filter_frame, S_IRUGO, show_fm_port_stats, NULL); ++ ++/* FM PORT TX statistics */ ++static struct attribute *fm_tx_port_dev_stats_attributes[] = { ++ &dev_attr_port_frame.attr, ++ &dev_attr_port_discard_frame.attr, ++ &dev_attr_port_dealloc_buf.attr, ++ &dev_attr_port_enq_total.attr, ++ &dev_attr_port_length_err.attr, ++ &dev_attr_port_unsupprted_format.attr, ++ &dev_attr_port_deq_total.attr, ++ &dev_attr_port_deq_from_default.attr, ++ &dev_attr_port_deq_confirm.attr, ++ NULL ++}; ++ ++static const struct attribute_group fm_tx_port_dev_stats_attr_grp = { ++ .name = "statistics", ++ .attrs = fm_tx_port_dev_stats_attributes ++}; ++ ++/* FM PORT RX statistics */ ++static struct attribute *fm_rx_port_dev_stats_attributes[] = { ++ &dev_attr_port_frame.attr, ++ &dev_attr_port_discard_frame.attr, ++ &dev_attr_port_dealloc_buf.attr, ++ &dev_attr_port_enq_total.attr, ++ &dev_attr_port_rx_bad_frame.attr, ++ &dev_attr_port_rx_large_frame.attr, ++ &dev_attr_port_rx_out_of_buffers_discard.attr, ++ &dev_attr_port_rx_filter_frame.attr, ++ NULL ++}; ++ ++static const struct attribute_group fm_rx_port_dev_stats_attr_grp = { ++ .name = "statistics", ++ .attrs = fm_rx_port_dev_stats_attributes ++}; ++ ++/* TODO: add particular OH ports statistics */ ++static struct attribute *fm_oh_port_dev_stats_attributes[] = { ++ &dev_attr_port_frame.attr, ++ &dev_attr_port_discard_frame.attr, ++ &dev_attr_port_dealloc_buf.attr, ++ &dev_attr_port_enq_total.attr, ++ /*TX*/ &dev_attr_port_length_err.attr, ++ &dev_attr_port_unsupprted_format.attr, ++ &dev_attr_port_deq_total.attr, ++ &dev_attr_port_deq_from_default.attr, ++ &dev_attr_port_deq_confirm.attr, ++ /* &dev_attr_port_rx_bad_frame.attr, */ ++ /* &dev_attr_port_rx_large_frame.attr, */ ++ &dev_attr_port_rx_out_of_buffers_discard.attr, ++ /*&dev_attr_port_rx_filter_frame.attr, */ ++ NULL ++}; ++ ++static const struct attribute_group fm_oh_port_dev_stats_attr_grp = { ++ .name = "statistics", ++ .attrs = fm_oh_port_dev_stats_attributes ++}; ++ ++static ssize_t show_fm_port_regs(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = ++ (t_LnxWrpFmPortDev *) dev_get_drvdata(dev); ++#endif ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ local_irq_save(flags); ++ ++ if (!p_LnxWrpFmPortDev->h_Dev) { ++ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n"); ++ return n; ++ } else { ++ n = snprintf(buf, PAGE_SIZE, ++ "FM port driver registers dump.\n"); ++ n = fm_port_dump_regs(p_LnxWrpFmPortDev->h_Dev, buf, n); ++ } ++ ++ local_irq_restore(flags); ++ ++ return n; ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++ ++ return n; ++#endif ++} ++static int fm_port_dsar_dump_mem(void *h_dev, char *buf, int nn) ++{ ++ t_FmPort *p_FmPort; ++ t_Fm *p_Fm; ++ uint8_t hardwarePortId; ++ uint32_t *param_page; ++ t_ArCommonDesc *ArCommonDescPtr; ++ uint32_t *mem; ++ int i, n = nn; ++ ++ p_FmPort = (t_FmPort *)h_dev; ++ hardwarePortId = p_FmPort->hardwarePortId; ++ p_Fm = (t_Fm *)p_FmPort->h_Fm; ++ ++ if (!FM_PORT_IsInDsar(p_FmPort)) ++ { ++ FM_DMP_LN(buf, n, "port %u is not a DSAR port\n", ++ hardwarePortId); ++ return n; ++ } ++ FM_DMP_LN(buf, n, "port %u DSAR mem\n", hardwarePortId); ++ FM_DMP_LN(buf, n, "========================\n"); ++ ++ /* do I need request_mem_region here? */ ++ param_page = ioremap(p_FmPort->fmMuramPhysBaseAddr + ioread32be(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr), 4); ++ ArCommonDescPtr = (t_ArCommonDesc*)(ioremap(p_FmPort->fmMuramPhysBaseAddr + ioread32be(param_page), 300*4)); /* this should be changed*/ ++ mem = (uint32_t*)ArCommonDescPtr; ++ for (i = 0; i < 300; i+=4) ++ FM_DMP_LN(buf, n, "%08x: %08x %08x %08x %08x\n", i*4, mem[i], mem[i + 1], mem[i + 2], mem[i + 3]); ++ iounmap(ArCommonDescPtr); ++ iounmap(param_page); ++ return n; ++} ++ ++static int fm_port_dsar_dump_regs(void *h_dev, char *buf, int nn) ++{ ++ t_FmPort *p_FmPort; ++ t_Fm *p_Fm; ++ uint8_t hardwarePortId; ++ uint32_t *param_page; ++ t_ArCommonDesc *ArCommonDescPtr; ++ int i, n = nn; ++ ++ p_FmPort = (t_FmPort *)h_dev; ++ hardwarePortId = p_FmPort->hardwarePortId; ++ p_Fm = (t_Fm *)p_FmPort->h_Fm; ++ ++ if (!FM_PORT_IsInDsar(p_FmPort)) ++ { ++ FM_DMP_LN(buf, n, "port %u is not a DSAR port\n", ++ hardwarePortId); ++ return n; ++ } ++ FM_DMP_LN(buf, n, "port %u DSAR information\n", hardwarePortId); ++ FM_DMP_LN(buf, n, "========================\n"); ++ ++ /* do I need request_mem_region here? */ ++ param_page = ioremap(p_FmPort->fmMuramPhysBaseAddr + ioread32be(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr), 4); ++ ArCommonDescPtr = (t_ArCommonDesc*)(ioremap(p_FmPort->fmMuramPhysBaseAddr + ioread32be(param_page), sizeof(t_ArCommonDesc))); /* this should be changed*/ ++ FM_DMP_LN(buf, n, "Tx port: 0x%x\n", ArCommonDescPtr->arTxPort); ++ FM_DMP_LN(buf, n, "Active HPNIA: 0x%08x\n", ArCommonDescPtr->activeHPNIA); ++ FM_DMP_LN(buf, n, "Snmp port: 0x%x\n", ArCommonDescPtr->snmpPort); ++ FM_DMP_LN(buf, n, "MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", ArCommonDescPtr->macStationAddr[0], ++ ArCommonDescPtr->macStationAddr[1], ArCommonDescPtr->macStationAddr[2], ++ ArCommonDescPtr->macStationAddr[3], ArCommonDescPtr->macStationAddr[4], ++ ArCommonDescPtr->macStationAddr[5]); ++ FM_DMP_LN(buf, n, "filterControl: 0x%02x\n", ArCommonDescPtr->filterControl); ++ FM_DMP_LN(buf, n, "tcpControlPass: 0x%04x\n", ArCommonDescPtr->tcpControlPass); ++ FM_DMP_LN(buf, n, "ipProtocolTblSize: 0x%x\n", ArCommonDescPtr->ipProtocolTblSize); ++ FM_DMP_LN(buf, n, "udpPortTblSize: 0x%x\n", ArCommonDescPtr->udpPortTblSize); ++ FM_DMP_LN(buf, n, "tcpPortTblSize: 0x%x\n", ArCommonDescPtr->tcpPortTblSize); ++ if (ArCommonDescPtr->p_ArStats) ++ { ++ t_ArStatistics *arStatistics = (t_ArStatistics*) ++ ioremap(ioread32be(&ArCommonDescPtr->p_ArStats) + ++ p_FmPort->fmMuramPhysBaseAddr, ++ sizeof (t_ArStatistics)); ++ FM_DMP_LN(buf, n, "\nDSAR statistics\n"); ++ FM_DMP_LN(buf, n, "DSAR_Discarded: 0x%x\n", arStatistics->dsarDiscarded); ++ FM_DMP_LN(buf, n, "DSAR_Err_Discarded: 0x%x\n", arStatistics->dsarErrDiscarded); ++ FM_DMP_LN(buf, n, "DSAR_Frag_Discarded: 0x%x\n", arStatistics->dsarFragDiscarded); ++ FM_DMP_LN(buf, n, "DSAR_Tunnel_Discarded: 0x%x\n", arStatistics->dsarTunnelDiscarded); ++ FM_DMP_LN(buf, n, "DSAR_ARP_Discarded: 0x%x\n", arStatistics->dsarArpDiscarded); ++ FM_DMP_LN(buf, n, "DSAR_IP_Discarded: 0x%x\n", arStatistics->dsarIpDiscarded); ++ FM_DMP_LN(buf, n, "DSAR_TCP_Discarded: 0x%x\n", arStatistics->dsarTcpDiscarded); ++ FM_DMP_LN(buf, n, "DSAR_UDP_Discarded: 0x%x\n", arStatistics->dsarUdpDiscarded); ++ FM_DMP_LN(buf, n, "DSAR_ICMPv6_Checksum_Err: 0x%x\n", arStatistics->dsarIcmpV6ChecksumErr); ++ FM_DMP_LN(buf, n, "DSAR_ICMPv6_Other_Type: 0x%x\n", arStatistics->dsarIcmpV6OtherType); ++ FM_DMP_LN(buf, n, "DSAR_ICMPv4_Other_Type: 0x%x\n", arStatistics->dsarIcmpV4OtherType); ++ ++ iounmap(arStatistics); ++ } ++ if (ArCommonDescPtr->p_ArpDescriptor) ++ { ++ t_DsarArpDescriptor* ArpDescriptor = (t_DsarArpDescriptor*) ++ ioremap(ioread32be(&ArCommonDescPtr->p_ArpDescriptor) + ++ p_FmPort->fmMuramPhysBaseAddr, ++ sizeof (t_DsarArpDescriptor)); ++ FM_DMP_LN(buf, n, "\nARP\n"); ++ FM_DMP_LN(buf, n, "===\n"); ++ FM_DMP_LN(buf, n, "control bits 0x%04x\n", ArpDescriptor->control); ++ if (ArpDescriptor->numOfBindings) ++ { ++ char ip_str[100]; ++ t_DsarArpBindingEntry* bindings = ioremap( ++ ioread32be(&ArpDescriptor->p_Bindings) + ++ p_FmPort->fmMuramPhysBaseAddr, ++ ArpDescriptor->numOfBindings * ++ sizeof(t_DsarArpBindingEntry)); ++ uint8_t* ip_addr = (uint8_t*)&bindings->ipv4Addr; ++ FM_DMP_LN(buf, n, " ip vlan id\n"); ++ for (i = 0; i < ArpDescriptor->numOfBindings; i++) ++ { ++ n += snprintf(ip_str, 100, "%d.%d.%d.%d", ++ ip_addr[0], ip_addr[1], ++ ip_addr[2], ip_addr[3]); ++ FM_DMP_LN(buf, n, "%-15s 0x%x\n", ++ ip_str, bindings->vlanId); ++ } ++ iounmap(bindings); ++ } ++ if (ArpDescriptor->p_Statistics) ++ { ++ t_DsarArpStatistics* arpStats = ioremap( ++ ioread32be(&ArpDescriptor->p_Statistics) + ++ p_FmPort->fmMuramPhysBaseAddr, ++ sizeof(t_DsarArpStatistics)); ++ FM_DMP_LN(buf, n, "statistics\n"); ++ FM_DMP_LN(buf, n, "INVAL_CNT: 0x%x\n", arpStats->invalCnt); ++ FM_DMP_LN(buf, n, "ECHO_CNT: 0x%x\n", arpStats->echoCnt); ++ FM_DMP_LN(buf, n, "CD_CNT: 0x%x\n", arpStats->cdCnt); ++ FM_DMP_LN(buf, n, "AR_CNT: 0x%x\n", arpStats->arCnt); ++ FM_DMP_LN(buf, n, "RATM_CNT: 0x%x\n", arpStats->ratmCnt); ++ FM_DMP_LN(buf, n, "UKOP_CNT: 0x%x\n", arpStats->ukopCnt); ++ FM_DMP_LN(buf, n, "NMTP_CNT: 0x%x\n", arpStats->nmtpCnt); ++ FM_DMP_LN(buf, n, "NMVLAN_CNT: 0x%x\n", arpStats->nmVlanCnt); ++ iounmap(arpStats); ++ } ++ ++ iounmap(ArpDescriptor); ++ } ++ if (ArCommonDescPtr->p_IcmpV4Descriptor) ++ { ++ t_DsarIcmpV4Descriptor* ICMPV4Descriptor = ++ (t_DsarIcmpV4Descriptor*)ioremap(ioread32be( ++ &ArCommonDescPtr->p_IcmpV4Descriptor) + ++ p_FmPort->fmMuramPhysBaseAddr, ++ sizeof (t_DsarIcmpV4Descriptor)); ++ FM_DMP_LN(buf, n, "\nEcho ICMPv4\n"); ++ FM_DMP_LN(buf, n, "===========\n"); ++ FM_DMP_LN(buf, n, "control bits 0x%04x\n", ICMPV4Descriptor->control); ++ if (ICMPV4Descriptor->numOfBindings) ++ { ++ char ip_str[100]; ++ t_DsarArpBindingEntry* bindings = ioremap( ++ ioread32be(&ICMPV4Descriptor->p_Bindings) + ++ p_FmPort->fmMuramPhysBaseAddr, ++ ICMPV4Descriptor->numOfBindings * ++ sizeof(t_DsarArpBindingEntry)); ++ uint8_t* ip_addr = (uint8_t*)&bindings->ipv4Addr; ++ FM_DMP_LN(buf, n, " ip vlan id\n"); ++ for (i = 0; i < ICMPV4Descriptor->numOfBindings; i++) ++ { ++ n += snprintf(ip_str, 100, "%d.%d.%d.%d", ++ ip_addr[0], ip_addr[1], ++ ip_addr[2], ip_addr[3]); ++ FM_DMP_LN(buf, n, "%-15s 0x%x\n", ++ ip_str, bindings->vlanId); ++ } ++ iounmap(bindings); ++ } ++ if (ICMPV4Descriptor->p_Statistics) ++ { ++ t_DsarIcmpV4Statistics* icmpv4Stats = ioremap( ++ ioread32be(&ICMPV4Descriptor->p_Statistics) + ++ p_FmPort->fmMuramPhysBaseAddr, ++ sizeof(t_DsarIcmpV4Statistics)); ++ FM_DMP_LN(buf, n, "statistics\n"); ++ FM_DMP_LN(buf, n, "INVAL_CNT: 0x%x\n", icmpv4Stats->invalCnt); ++ FM_DMP_LN(buf, n, "NMVLAN_CNT: 0x%x\n", icmpv4Stats->nmVlanCnt); ++ FM_DMP_LN(buf, n, "NMIP_CNT: 0x%x\n", icmpv4Stats->nmIpCnt); ++ FM_DMP_LN(buf, n, "AR_CNT: 0x%x\n", icmpv4Stats->arCnt); ++ FM_DMP_LN(buf, n, "CSERR_CNT: 0x%x\n", icmpv4Stats->cserrCnt); ++ iounmap(icmpv4Stats); ++ } ++ iounmap(ICMPV4Descriptor); ++ } ++ if (ArCommonDescPtr->p_NdDescriptor) ++ { ++ t_DsarNdDescriptor *NDDescriptor = ++ (t_DsarNdDescriptor*)ioremap(ioread32be( ++ &ArCommonDescPtr->p_NdDescriptor) + p_FmPort-> ++ fmMuramPhysBaseAddr, sizeof (t_DsarNdDescriptor)); ++ FM_DMP_LN(buf, n, "\nNDP\n"); ++ FM_DMP_LN(buf, n, "===\n"); ++ FM_DMP_LN(buf, n, "control bits 0x%04x\n", NDDescriptor->control); ++ FM_DMP_LN(buf, n, "solicited address 0x%08x\n", NDDescriptor->solicitedAddr); ++ if (NDDescriptor->numOfBindings) ++ { ++ char ip_str[100]; ++ t_DsarIcmpV6BindingEntry* bindings = ioremap( ++ ioread32be(&NDDescriptor->p_Bindings) + ++ p_FmPort->fmMuramPhysBaseAddr, ++ NDDescriptor->numOfBindings * ++ sizeof(t_DsarIcmpV6BindingEntry)); ++ uint16_t* ip_addr = (uint16_t*)&bindings->ipv6Addr; ++ FM_DMP_LN(buf, n, " ip vlan id\n"); ++ for (i = 0; i < NDDescriptor->numOfBindings; i++) ++ { ++ n += snprintf(ip_str, 100, ++ "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", ++ ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3], ++ ip_addr[4], ip_addr[5], ip_addr[6], ip_addr[7]); ++ FM_DMP_LN(buf, n, "%s 0x%x\n", ip_str, bindings->vlanId); ++ } ++ iounmap(bindings); ++ } ++ if (NDDescriptor->p_Statistics) ++ { ++ t_NdStatistics* ndStats = ioremap( ++ ioread32be(&NDDescriptor->p_Statistics) + ++ p_FmPort->fmMuramPhysBaseAddr, ++ sizeof(t_NdStatistics)); ++ FM_DMP_LN(buf, n, "statistics\n"); ++ FM_DMP_LN(buf, n, "INVAL_CNT: 0x%x\n", ndStats->invalCnt); ++ FM_DMP_LN(buf, n, "NMVLAN_CNT: 0x%x\n", ndStats->nmVlanCnt); ++ FM_DMP_LN(buf, n, "NMIP_CNT: 0x%x\n", ndStats->nmIpCnt); ++ FM_DMP_LN(buf, n, "AR_CNT: 0x%x\n", ndStats->arCnt); ++ FM_DMP_LN(buf, n, "USADVERT_CNT: 0x%x\n", ndStats->usadvertCnt); ++ FM_DMP_LN(buf, n, "NMMCAST_CNT: 0x%x\n", ndStats->nmmcastCnt); ++ FM_DMP_LN(buf, n, "NSLLA_CNT: 0x%x\n", ndStats->nsllaCnt); ++ iounmap(ndStats); ++ } ++ iounmap(NDDescriptor); ++ } ++ if (ArCommonDescPtr->p_IcmpV6Descriptor) ++ { ++ t_DsarIcmpV6Descriptor *ICMPV6Descriptor = ++ (t_DsarIcmpV6Descriptor*)ioremap(ioread32be( ++ &ArCommonDescPtr->p_IcmpV6Descriptor) + p_FmPort-> ++ fmMuramPhysBaseAddr, sizeof (t_DsarIcmpV6Descriptor)); ++ FM_DMP_LN(buf, n, "\nEcho ICMPv6\n"); ++ FM_DMP_LN(buf, n, "===========\n"); ++ FM_DMP_LN(buf, n, "control bits 0x%04x\n", ICMPV6Descriptor->control); ++ if (ICMPV6Descriptor->numOfBindings) ++ { ++ char ip_str[100]; ++ t_DsarIcmpV6BindingEntry* bindings = ioremap( ++ ioread32be(&ICMPV6Descriptor->p_Bindings) + ++ p_FmPort->fmMuramPhysBaseAddr, ++ ICMPV6Descriptor->numOfBindings * ++ sizeof(t_DsarIcmpV6BindingEntry)); ++ uint16_t* ip_addr = (uint16_t*)&bindings->ipv6Addr; ++ FM_DMP_LN(buf, n, " ip vlan id\n"); ++ for (i = 0; i < ICMPV6Descriptor->numOfBindings; i++) ++ { ++ n += snprintf(ip_str, 100, ++ "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", ++ ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3], ++ ip_addr[4], ip_addr[5], ip_addr[6], ip_addr[7]); ++ FM_DMP_LN(buf, n, "%s 0x%x\n", ip_str, bindings->vlanId); ++ } ++ iounmap(bindings); ++ } ++ if (ICMPV6Descriptor->p_Statistics) ++ { ++ t_DsarIcmpV6Statistics* icmpv6Stats = ioremap( ++ ioread32be(&ICMPV6Descriptor->p_Statistics) + ++ p_FmPort->fmMuramPhysBaseAddr, ++ sizeof(t_DsarIcmpV6Statistics)); ++ FM_DMP_LN(buf, n, "statistics\n"); ++ FM_DMP_LN(buf, n, "INVAL_CNT: 0x%x\n", icmpv6Stats->invalCnt); ++ FM_DMP_LN(buf, n, "NMVLAN_CNT: 0x%x\n", icmpv6Stats->nmVlanCnt); ++ FM_DMP_LN(buf, n, "NMIP_CNT: 0x%x\n", icmpv6Stats->nmIpCnt); ++ FM_DMP_LN(buf, n, "AR_CNT: 0x%x\n", icmpv6Stats->arCnt); ++ iounmap(icmpv6Stats); ++ } ++ iounmap(ICMPV6Descriptor); ++ } ++ if (ArCommonDescPtr->p_SnmpDescriptor) ++ { ++ t_DsarSnmpDescriptor *SnmpDescriptor = ++ (t_DsarSnmpDescriptor*)ioremap(ioread32be( ++ &ArCommonDescPtr->p_SnmpDescriptor) + p_FmPort-> ++ fmMuramPhysBaseAddr, sizeof (t_DsarSnmpDescriptor)); ++ FM_DMP_LN(buf, n, "\nSNMP\n"); ++ FM_DMP_LN(buf, n, "===========\n"); ++ FM_DMP_LN(buf, n, "control bits 0x%04x\n", SnmpDescriptor->control); ++ FM_DMP_LN(buf, n, "max message length 0x%04x\n", SnmpDescriptor->maxSnmpMsgLength); ++ if (SnmpDescriptor->numOfIpv4Addresses) ++ { ++ char ip_str[100]; ++ t_DsarSnmpIpv4AddrTblEntry* addrs = ioremap( ++ ioread32be(&SnmpDescriptor->p_Ipv4AddrTbl) + ++ p_FmPort->fmMuramPhysBaseAddr, ++ SnmpDescriptor->numOfIpv4Addresses * ++ sizeof(t_DsarSnmpIpv4AddrTblEntry)); ++ uint8_t* ip_addr = (uint8_t*)&addrs->ipv4Addr; ++ FM_DMP_LN(buf, n, " ip vlan id\n"); ++ for (i = 0; i < SnmpDescriptor->numOfIpv4Addresses; i++) ++ { ++ n += snprintf(ip_str, 100, "%d.%d.%d.%d", ++ ip_addr[0], ip_addr[1], ++ ip_addr[2], ip_addr[3]); ++ FM_DMP_LN(buf, n, "%-15s 0x%x\n", ip_str, addrs->vlanId); ++ } ++ iounmap(addrs); ++ } ++ if (SnmpDescriptor->p_Statistics) ++ { ++ t_DsarSnmpStatistics* snmpStats = ioremap( ++ ioread32be(&SnmpDescriptor->p_Statistics) + ++ p_FmPort->fmMuramPhysBaseAddr, ++ sizeof(t_DsarSnmpStatistics)); ++ FM_DMP_LN(buf, n, "statistics\n"); ++ FM_DMP_LN(buf, n, "snmpErrCnt: 0x%x\n", snmpStats->snmpErrCnt); ++ FM_DMP_LN(buf, n, "snmpCommunityErrCnt: 0x%x\n", snmpStats->snmpCommunityErrCnt); ++ FM_DMP_LN(buf, n, "snmpTotalDiscardCnt: 0x%x\n", snmpStats->snmpTotalDiscardCnt); ++ FM_DMP_LN(buf, n, "snmpGetReqCnt: 0x%x\n", snmpStats->snmpGetReqCnt); ++ FM_DMP_LN(buf, n, "snmpGetNextReqCnt: 0x%x\n", snmpStats->snmpGetNextReqCnt); ++ iounmap(snmpStats); ++ } ++ iounmap(SnmpDescriptor); ++ } ++ iounmap(ArCommonDescPtr); ++ iounmap(param_page); ++ return n; ++} ++ ++static ssize_t show_fm_port_dsar_mem(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = ++ (t_LnxWrpFmPortDev *) dev_get_drvdata(dev); ++#endif ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ local_irq_save(flags); ++ ++ if (!p_LnxWrpFmPortDev->h_Dev) { ++ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n"); ++ return n; ++ } else { ++ n = snprintf(buf, PAGE_SIZE, ++ "FM port driver registers dump.\n"); ++ n = fm_port_dsar_dump_mem(p_LnxWrpFmPortDev->h_Dev, buf, n); ++ } ++ ++ local_irq_restore(flags); ++ ++ return n; ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++ ++ return n; ++#endif ++} ++ ++static ssize_t show_fm_port_dsar_regs(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = ++ (t_LnxWrpFmPortDev *) dev_get_drvdata(dev); ++#endif ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ local_irq_save(flags); ++ ++ if (!p_LnxWrpFmPortDev->h_Dev) { ++ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n"); ++ return n; ++ } else { ++ n = snprintf(buf, PAGE_SIZE, ++ "FM port driver registers dump.\n"); ++ n = fm_port_dsar_dump_regs(p_LnxWrpFmPortDev->h_Dev, buf, n); ++ } ++ ++ local_irq_restore(flags); ++ ++ return n; ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++ ++ return n; ++#endif ++} ++ ++#if (DPAA_VERSION >= 11) ++static ssize_t show_fm_port_ipv4_options(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = ++ (t_LnxWrpFmPortDev *) dev_get_drvdata(dev); ++#endif ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ local_irq_save(flags); ++ ++ if (!p_LnxWrpFmPortDev->h_Dev) { ++ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n"); ++ return n; ++ } else if (((t_FmPort *)p_LnxWrpFmPortDev->h_Dev)->p_ParamsPage ++ == NULL) { ++ n = snprintf(buf, PAGE_SIZE, ++ "\tPort: FMan-controller params page not set\n"); ++ return n; ++ } else { ++ n = snprintf(buf, PAGE_SIZE, ++ "Counter for fragmented pkt with IP header options\n"); ++ n = fm_port_dump_ipv4_opt(p_LnxWrpFmPortDev->h_Dev, buf, n); ++ } ++ ++ local_irq_restore(flags); ++ ++ return n; ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++ ++ return n; ++#endif ++} ++ ++#endif ++ ++static ssize_t show_fm_port_bmi_regs(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = ++ (t_LnxWrpFmPortDev *) dev_get_drvdata(dev); ++#endif ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ local_irq_save(flags); ++ ++ if (!p_LnxWrpFmPortDev->h_Dev) { ++ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n"); ++ return n; ++ } else { ++ n = snprintf(buf, PAGE_SIZE, ++ "FM port driver registers dump.\n"); ++ n = fm_port_dump_regs_bmi(p_LnxWrpFmPortDev->h_Dev, buf, n); ++ } ++ ++ local_irq_restore(flags); ++ ++ return n; ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++ ++ return n; ++#endif ++} ++ ++static ssize_t show_fm_port_qmi_regs(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ unsigned long flags; ++ unsigned n = 0; ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = ++ (t_LnxWrpFmPortDev *) dev_get_drvdata(dev); ++#endif ++ ++ if (attr == NULL || buf == NULL || dev == NULL) ++ return -EINVAL; ++ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ local_irq_save(flags); ++ ++ if (!p_LnxWrpFmPortDev->h_Dev) { ++ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n"); ++ return n; ++ } else { ++ n = snprintf(buf, PAGE_SIZE, ++ "FM port driver registers dump.\n"); ++ n = fm_port_dump_regs_qmi(p_LnxWrpFmPortDev->h_Dev, buf, n); ++ } ++ ++ local_irq_restore(flags); ++ ++ return n; ++#else ++ ++ local_irq_save(flags); ++ n = snprintf(buf, PAGE_SIZE, ++ "Debug level is too low to dump registers!!!\n"); ++ local_irq_restore(flags); ++ ++ return n; ++#endif ++} ++ ++static DEVICE_ATTR(fm_port_regs, S_IRUGO | S_IRUSR, show_fm_port_regs, NULL); ++static DEVICE_ATTR(fm_port_qmi_regs, S_IRUGO | S_IRUSR, show_fm_port_qmi_regs, NULL); ++static DEVICE_ATTR(fm_port_bmi_regs, S_IRUGO | S_IRUSR, show_fm_port_bmi_regs, NULL); ++#if (DPAA_VERSION >= 11) ++static DEVICE_ATTR(fm_port_ipv4_opt, S_IRUGO | S_IRUSR, show_fm_port_ipv4_options, NULL); ++#endif ++static DEVICE_ATTR(fm_port_dsar_regs, S_IRUGO | S_IRUSR, show_fm_port_dsar_regs, NULL); ++static DEVICE_ATTR(fm_port_dsar_mem, S_IRUGO | S_IRUSR, show_fm_port_dsar_mem, NULL); ++ ++int fm_port_sysfs_create(struct device *dev) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev; ++ ++ if (dev == NULL) ++ return -EINVAL; ++ ++ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_LnxWrpFmPortDev == NULL)) ++ return -EINVAL; ++ ++ /* store to remove them when module is disabled */ ++ p_LnxWrpFmPortDev->dev_attr_regs = &dev_attr_fm_port_regs; ++ p_LnxWrpFmPortDev->dev_attr_qmi_regs = &dev_attr_fm_port_qmi_regs; ++ p_LnxWrpFmPortDev->dev_attr_bmi_regs = &dev_attr_fm_port_bmi_regs; ++#if (DPAA_VERSION >= 11) ++ p_LnxWrpFmPortDev->dev_attr_ipv4_opt = &dev_attr_fm_port_ipv4_opt; ++#endif ++ p_LnxWrpFmPortDev->dev_attr_dsar_regs = &dev_attr_fm_port_dsar_regs; ++ p_LnxWrpFmPortDev->dev_attr_dsar_mem = &dev_attr_fm_port_dsar_mem; ++ /* Registers dump entry - in future will be moved to debugfs */ ++ if (device_create_file(dev, &dev_attr_fm_port_regs) != 0) ++ return -EIO; ++ if (device_create_file(dev, &dev_attr_fm_port_qmi_regs) != 0) ++ return -EIO; ++ if (device_create_file(dev, &dev_attr_fm_port_bmi_regs) != 0) ++ return -EIO; ++#if (DPAA_VERSION >= 11) ++ if (device_create_file(dev, &dev_attr_fm_port_ipv4_opt) != 0) ++ return -EIO; ++#endif ++ if (device_create_file(dev, &dev_attr_fm_port_dsar_regs) != 0) ++ return -EIO; ++ if (device_create_file(dev, &dev_attr_fm_port_dsar_mem) != 0) ++ return -EIO; ++ ++ /* FM Ports statistics */ ++ switch (p_LnxWrpFmPortDev->settings.param.portType) { ++ case e_FM_PORT_TYPE_TX: ++ case e_FM_PORT_TYPE_TX_10G: ++ if (sysfs_create_group ++ (&dev->kobj, &fm_tx_port_dev_stats_attr_grp) != 0) ++ return -EIO; ++ break; ++ case e_FM_PORT_TYPE_RX: ++ case e_FM_PORT_TYPE_RX_10G: ++ if (sysfs_create_group ++ (&dev->kobj, &fm_rx_port_dev_stats_attr_grp) != 0) ++ return -EIO; ++ break; ++ case e_FM_PORT_TYPE_DUMMY: ++ case e_FM_PORT_TYPE_OH_OFFLINE_PARSING: ++ if (sysfs_create_group ++ (&dev->kobj, &fm_oh_port_dev_stats_attr_grp) != 0) ++ return -EIO; ++ break; ++ default: ++ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__, ++ __func__); ++ return -EINVAL; ++ break; ++ }; ++ ++ return 0; ++} ++ ++void fm_port_sysfs_destroy(struct device *dev) ++{ ++ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = NULL; ++ ++ /* this function has never been tested !!! */ ++ ++ if (WARN_ON(dev == NULL)) ++ return; ++ ++ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) dev_get_drvdata(dev); ++ if (WARN_ON(p_LnxWrpFmPortDev == NULL)) ++ return; ++ ++ /* The name attribute will be freed also by these 2 functions? */ ++ switch (p_LnxWrpFmPortDev->settings.param.portType) { ++ case e_FM_PORT_TYPE_TX: ++ case e_FM_PORT_TYPE_TX_10G: ++ sysfs_remove_group(&dev->kobj, &fm_tx_port_dev_stats_attr_grp); ++ break; ++ case e_FM_PORT_TYPE_RX: ++ case e_FM_PORT_TYPE_RX_10G: ++ sysfs_remove_group(&dev->kobj, &fm_rx_port_dev_stats_attr_grp); ++ break; ++ case e_FM_PORT_TYPE_DUMMY: ++ case e_FM_PORT_TYPE_OH_OFFLINE_PARSING: ++ sysfs_remove_group(&dev->kobj, &fm_oh_port_dev_stats_attr_grp); ++ break; ++ default: ++ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__, ++ __func__); ++ break; ++ }; ++ ++ device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_regs); ++ device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_qmi_regs); ++ device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_bmi_regs); ++#if (DPAA_VERSION >= 11) ++ device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_ipv4_opt); ++#endif ++ device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_dsar_regs); ++ device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_dsar_mem); ++} ++ ++ ++int fm_port_dump_regs(void *h_dev, char *buf, int nn) ++{ ++ t_FmPort *p_FmPort; ++ t_Fm *p_Fm; ++ uint8_t hardwarePortId; ++ int n = nn; ++ ++ p_FmPort = (t_FmPort *)h_dev; ++ hardwarePortId = p_FmPort->hardwarePortId; ++ p_Fm = (t_Fm *)p_FmPort->h_Fm; ++ ++ FM_DMP_TITLE(buf, n, &p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId - 1], ++ "fmbm_pp for port %u", hardwarePortId); ++ FM_DMP_MEM_32(buf, n, ++ &p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId - 1]); ++ ++ FM_DMP_TITLE(buf, n, &p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId - 1], ++ "fmbm_pfs for port %u", hardwarePortId); ++ FM_DMP_MEM_32(buf, n, ++ &p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId - 1]); ++ ++ FM_DMP_TITLE(buf, n, ++ &p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId - 1], ++ "fmbm_spliodn for port %u", hardwarePortId); ++ FM_DMP_MEM_32(buf, n, ++ &p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId - 1]); ++ ++ FM_DMP_TITLE(buf, n, &p_Fm->p_FmFpmRegs->fmfp_ps[hardwarePortId], ++ "fmfp_psfor port %u", hardwarePortId); ++ FM_DMP_MEM_32(buf, n, &p_Fm->p_FmFpmRegs->fmfp_ps[hardwarePortId]); ++ ++ FM_DMP_TITLE(buf, n, &p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId / 2], ++ "fmdmplrfor port %u", hardwarePortId); ++ FM_DMP_MEM_32(buf, n, ++ &p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId / 2]); ++ return n; ++} ++ ++#if (DPAA_VERSION >= 11) ++ ++int fm_port_dump_ipv4_opt(void *h_dev, char *buf, int nn) ++{ ++ t_FmPort *p_FmPort; ++ int n = nn; ++ ++ p_FmPort = (t_FmPort *)h_dev; ++ ++ FM_DMP_V32(buf, n, p_FmPort->p_ParamsPage, ipfOptionsCounter); ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ ++ return n; ++} ++#endif ++ ++int fm_port_dump_regs_bmi(void *h_dev, char *buf, int nn) ++{ ++ t_FmPort *p_FmPort; ++ u_FmPortBmiRegs *p_bmi; ++ ++ char arr[20]; ++ uint8_t flag; ++ int i = 0; ++ int n = nn; ++ ++ p_FmPort = (t_FmPort *)h_dev; ++ p_bmi = p_FmPort->p_FmPortBmiRegs; ++ ++ memset(arr, 0, sizeof(arr)); ++ switch (p_FmPort->portType) { ++ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): ++ strcpy(arr, "OFFLINE-PARSING"); ++ flag = 0; ++ break; ++ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): ++ strcpy(arr, "HOST-COMMAND"); ++ flag = 0; ++ break; ++ case (e_FM_PORT_TYPE_RX): ++ strcpy(arr, "RX"); ++ flag = 1; ++ break; ++ case (e_FM_PORT_TYPE_RX_10G): ++ strcpy(arr, "RX-10G"); ++ flag = 1; ++ break; ++ case (e_FM_PORT_TYPE_TX): ++ strcpy(arr, "TX"); ++ flag = 2; ++ break; ++ case (e_FM_PORT_TYPE_TX_10G): ++ strcpy(arr, "TX-10G"); ++ flag = 2; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ FM_DMP_TITLE(buf, n, NULL, ++ "FMan-Port (%s #%d) registers:", ++ arr, p_FmPort->portId); ++ ++ FM_DMP_TITLE(buf, n, p_bmi, "Bmi Port Regs"); ++ ++ switch (flag) { ++ case (0): ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ocfg); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ost); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_oda); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_oicp); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofdne); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofne); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofca); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofpne); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_opso); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_opp); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_occb); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_oim); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofp); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofed); ++ ++ FM_DMP_TITLE(buf, n, ++ &(p_bmi->ohPortBmiRegs.fmbm_oprai), "fmbm_oprai"); ++ for (i = 0; i < FM_PORT_PRS_RESULT_NUM_OF_WORDS; ++i) { ++ FM_DMP_MEM_32(buf, n, ++ &(p_bmi->ohPortBmiRegs.fmbm_oprai[i])); ++ } ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofqid); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_oefqid); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofsdm); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofsem); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofene); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_orlmts); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_orlmt); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ocmne); ++ { ++#ifndef FM_NO_OP_OBSERVED_POOLS ++ if (p_FmPort->fmRevInfo.majorRev == 4) { ++ FM_DMP_TITLE(buf, n, ++ &p_bmi->ohPortBmiRegs.fmbm_oebmpi, ++ "fmbm_oebmpi"); ++ ++ for (i = 0; i < FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS; ++i) { ++ FM_DMP_MEM_32(buf, n, ++ &(p_bmi->ohPortBmiRegs.fmbm_oebmpi[i])); ++ } ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ocgm); ++ } ++#endif /* !FM_NO_OP_OBSERVED_POOLS */ ++ } ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ostc); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofrc); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofdc); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofledc); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofufdc); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_offc); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofwdc); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofldec); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_opc); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_opcp); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_occn); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_otuc); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_oduc); ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofuc); ++ FM_DMP_TITLE(buf, n, &(p_bmi->ohPortBmiRegs.fmbm_odcfg), ++ "fmbm_odcfg"); ++ for (i = 0; i < 3; ++i) { ++ FM_DMP_MEM_32(buf, n, ++ &(p_bmi->ohPortBmiRegs.fmbm_odcfg[i])); ++ } ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ ++ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ogpr); ++ break; ++ case (1): ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rcfg); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rst); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rda); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfp); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_reth); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfed); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_ricp); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rebm); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfne); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfca); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfpne); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rpso); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rpp); ++ FM_DMP_TITLE(buf, n, &(p_bmi->rxPortBmiRegs.fmbm_rprai), ++ "fmbm_rprai"); ++ for (i = 0; i < FM_PORT_PRS_RESULT_NUM_OF_WORDS; ++i) { ++ FM_DMP_MEM_32(buf, n, ++ &(p_bmi->rxPortBmiRegs.fmbm_rprai[i])); ++ } ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfqid); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_refqid); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfsdm); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfsem); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfene); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rcmne); ++ FM_DMP_TITLE(buf, n, &p_bmi->rxPortBmiRegs.fmbm_ebmpi, ++ "fmbm_ebmpi"); ++ for (i = 0; i < FM_PORT_MAX_NUM_OF_EXT_POOLS; ++i) { ++ FM_DMP_MEM_32(buf, n, ++ &(p_bmi->rxPortBmiRegs.fmbm_ebmpi[i])); ++ } ++ FM_DMP_TITLE(buf, n, &p_bmi->rxPortBmiRegs.fmbm_acnt, ++ "fmbm_acnt"); ++ for (i = 0; i < FM_PORT_MAX_NUM_OF_EXT_POOLS; ++i) { ++ FM_DMP_MEM_32(buf, n, ++ &(p_bmi->rxPortBmiRegs.fmbm_acnt[i])); ++ } ++ FM_DMP_TITLE(buf, n, &p_bmi->rxPortBmiRegs.fmbm_rcgm, ++ "fmbm_rcgm"); ++ for (i = 0; i < FM_PORT_NUM_OF_CONGESTION_GRPS / 32; ++i) { ++ FM_DMP_MEM_32(buf, n, ++ &(p_bmi->rxPortBmiRegs.fmbm_rcgm[i])); ++ } ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rmpd); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rstc); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfrc); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfbc); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rlfc); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rffc); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfcd); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfldec); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rodc); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rpc); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rpcp); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rccn); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rtuc); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rrquc); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rduc); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfuc); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rpac); ++ FM_DMP_TITLE(buf, n, &(p_bmi->rxPortBmiRegs.fmbm_rdcfg), ++ "fmbm_rdcfg"); ++ for (i = 0; i < 3; ++i) { ++ FM_DMP_MEM_32(buf, n, ++ &(p_bmi->rxPortBmiRegs.fmbm_rdcfg[i])); ++ } ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rgpr); ++ break; ++ case (2): ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tcfg); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tst); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tda); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfp); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfed); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_ticp); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfdne); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfca); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tcfqid); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfeqid); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfene); ++#if (DPAA_VERSION >= 11) ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfne); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tcmne); ++#endif /* (DPAA_VERSION >= 11) */ ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_trlmts); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_trlmt); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tstc); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfrc); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfdc); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfledc); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfufdc); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tpc); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tpcp); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tccn); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_ttuc); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_ttcquc); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tduc); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfuc); ++ FM_DMP_TITLE(buf, n, &(p_bmi->txPortBmiRegs.fmbm_tdcfg), ++ "fmbm_tdcfg"); ++ for (i = 0; i < 3 ; ++i) { ++ FM_DMP_MEM_32(buf, n, ++ &(p_bmi->txPortBmiRegs.fmbm_tdcfg[i])); ++ } ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tgpr); ++ break; ++ } ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ ++ return n; ++} ++ ++int fm_port_dump_regs_qmi(void *h_dev, char *buf, int nn) ++{ ++ t_FmPort *p_FmPort; ++ int n = nn; ++ ++ p_FmPort = (t_FmPort *)h_dev; ++ ++ FM_DMP_TITLE(buf, n, p_FmPort->p_FmPortQmiRegs, "Qmi Port Regs"); ++ ++ FM_DMP_V32(buf, n, p_FmPort->p_FmPortQmiRegs, fmqm_pnc); ++ FM_DMP_V32(buf, n, p_FmPort->p_FmPortQmiRegs, fmqm_pns); ++ FM_DMP_V32(buf, n, p_FmPort->p_FmPortQmiRegs, fmqm_pnts); ++ FM_DMP_V32(buf, n, p_FmPort->p_FmPortQmiRegs, fmqm_pnen); ++ FM_DMP_V32(buf, n, p_FmPort->p_FmPortQmiRegs, fmqm_pnetfc); ++ FM_DMP_V32(buf, n, ++ &p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs, fmqm_pndn); ++ FM_DMP_V32(buf, n, ++ &p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs, fmqm_pndc); ++ FM_DMP_V32(buf, n, ++ &p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs, fmqm_pndtfc); ++ FM_DMP_V32(buf, n, ++ &p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs, fmqm_pndfdc); ++ FM_DMP_V32(buf, n, ++ &p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs, fmqm_pndcc); ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ ++ return n; ++} ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs_fm_port.h b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs_fm_port.h +new file mode 100644 +index 0000000..1e7636f +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_sysfs_fm_port.h +@@ -0,0 +1,56 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/* ++ @File lnxwrp_sysfs_fm_port.h ++ ++ @Description FM port sysfs functions. ++ ++*/ ++ ++#ifndef LNXWRP_SYSFS_FM_PORT_H_ ++#define LNXWRP_SYSFS_FM_PORT_H_ ++ ++#include "lnxwrp_sysfs.h" ++ ++int fm_port_sysfs_create(struct device *dev); ++void fm_port_sysfs_destroy(struct device *dev); ++ ++int fm_port_dump_regs(void *h_dev, char *buf, int n); ++int fm_port_dump_regs_bmi(void *h_dev, char *buf, int n); ++int fm_port_dump_regs_qmi(void *h_dev, char *buf, int n); ++ ++#if (DPAA_VERSION >= 11) ++int fm_port_dump_ipv4_opt(void *h_dev, char *buf, int n); ++#endif ++ ++#endif /* LNXWRP_SYSFS_FM_PORT_H_ */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/xx/Makefile b/drivers/net/ethernet/freescale/sdk_fman/src/xx/Makefile +new file mode 100644 +index 0000000..1545c8b +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/xx/Makefile +@@ -0,0 +1,11 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++ccflags-y += -DVERSION=\"\" ++# ++#Include netcomm SW specific definitions ++include $(srctree)/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk ++ ++obj-y += fsl-ncsw-xx.o ++fsl-ncsw-xx-objs := xx_linux.o udivdi3.o \ ++ module_strings.o +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/xx/module_strings.c b/drivers/net/ethernet/freescale/sdk_fman/src/xx/module_strings.c +new file mode 100644 +index 0000000..98c64fb +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/xx/module_strings.c +@@ -0,0 +1,45 @@ ++/* ++ * Copyright 2012 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. ++ */ ++ ++/* Module names for debug messages */ ++const char *moduleStrings[] = ++{ ++ "", /* MODULE_UNKNOWN */ ++ "FM", /* MODULE_FM */ ++ "FM-MURAM", /* MODULE_FM_MURAM */ ++ "FM-PCD", /* MODULE_FM_PCD */ ++ "FM-RTC", /* MODULE_FM_RTC */ ++ "FM-MAC", /* MODULE_FM_MAC */ ++ "FM-Port", /* MODULE_FM_PORT */ ++ "MM", /* MODULE_MM */ ++ "FM-SP" /* MODULE_FM_SP */ ++}; +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/xx/udivdi3.c b/drivers/net/ethernet/freescale/sdk_fman/src/xx/udivdi3.c +new file mode 100644 +index 0000000..419e27e +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/xx/udivdi3.c +@@ -0,0 +1,132 @@ ++/* ++ * Copyright 2008-2012 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 ++ ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#include ++#endif /* MODVERSIONS */ ++ ++#include ++#include ++#include ++ ++ ++#define BITS_PER_UNIT 8 ++#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT) ++ ++ ++typedef unsigned int UQItype __attribute__ ((mode (QI))); ++typedef int SItype __attribute__ ((mode (SI))); ++typedef unsigned int USItype __attribute__ ((mode (SI))); ++typedef int DItype __attribute__ ((mode (DI))); ++typedef int word_type __attribute__ ((mode (__word__))); ++typedef unsigned int UDItype __attribute__ ((mode (DI))); ++ ++struct DIstruct {SItype low, high;}; ++ ++typedef union ++{ ++ struct DIstruct s; ++ DItype ll; ++} DIunion; ++ ++ ++/* bit divisor, dividend and result. dynamic precision */ ++static __inline__ uint64_t _div64_64(uint64_t dividend, uint64_t divisor) ++{ ++ uint32_t d = divisor; ++ ++ if (divisor > 0xffffffffULL) ++ { ++ unsigned int shift = fls(divisor >> 32); ++ ++ d = divisor >> shift; ++ dividend >>= shift; ++ } ++ ++ /* avoid 64 bit division if possible */ ++ if (dividend >> 32) ++ do_div(dividend, d); ++ else ++ dividend = (uint32_t) dividend / d; ++ ++ return dividend; ++} ++ ++UDItype __udivdi3 (UDItype n, UDItype d) ++{ ++ return _div64_64(n, d); ++} ++ ++DItype __divdi3 (DItype n, DItype d) ++{ ++ DItype sign = 1; ++ if (n<0) ++ { ++ sign *= -1; ++ n *= -1; ++ } ++ if (d<0) ++ { ++ sign *= -1; ++ d *= -1; ++ } ++ return sign*_div64_64((UDItype)n, (UDItype)d); ++} ++ ++UDItype __umoddi3 (UDItype n, UDItype d) ++{ ++ return n-(_div64_64(n, d)*d); ++} ++ ++#ifdef MODULE ++word_type __ucmpdi2 (DItype a, DItype b) ++{ ++ DIunion au, bu; ++ ++ au.ll = a, bu.ll = b; ++ ++ if ((USItype) au.s.high < (USItype) bu.s.high) ++ return 0; ++ else if ((USItype) au.s.high > (USItype) bu.s.high) ++ return 2; ++ if ((USItype) au.s.low < (USItype) bu.s.low) ++ return 0; ++ else if ((USItype) au.s.low > (USItype) bu.s.low) ++ return 2; ++ return 1; ++} ++#endif /* MODULE */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/xx/xx_linux.c b/drivers/net/ethernet/freescale/sdk_fman/src/xx/xx_linux.c +new file mode 100644 +index 0000000..d5c639a +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/xx/xx_linux.c +@@ -0,0 +1,887 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/**************************************************************************//** ++ @File xx_linux.c ++ ++ @Description XX routines implementation for Linux. ++*//***************************************************************************/ ++#include ++ ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#include ++#endif /* MODVERSIONS */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#ifdef BIGPHYSAREA_ENABLE ++#include ++#endif /* BIGPHYSAREA_ENABLE */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "list_ext.h" ++#include "mm_ext.h" ++#include "sys_io_ext.h" ++#include "xx.h" ++ ++ ++#define __ERR_MODULE__ MODULE_UNKNOWN ++ ++#ifdef BIGPHYSAREA_ENABLE ++#define MAX_ALLOCATION_SIZE 128 * 1024 /* Maximum size allocated with kmalloc is 128K */ ++ ++ ++/* TODO: large allocations => use big phys area */ ++/****************************************************************************** ++ * routine: get_nr_pages ++ * ++ * description: ++ * calculates the number of memory pages for a given size (in bytes) ++ * ++ * arguments: ++ * size - the number of bytes ++ * ++ * return code: ++ * The number of pages ++ * ++ *****************************************************************************/ ++static __inline__ uint32_t get_nr_pages (uint32_t size) ++{ ++ return (uint32_t)((size >> PAGE_SHIFT) + (size & PAGE_SHIFT ? 1 : 0)); ++} ++ ++static bool in_big_phys_area (uint32_t addr) ++{ ++ uint32_t base, size; ++ ++ bigphysarea_get_details (&base, &size); ++ return ((addr >= base) && (addr < base + size)); ++} ++#endif /* BIGPHYSAREA_ENABLE */ ++ ++void * xx_Malloc(uint32_t n) ++{ ++ void *a; ++ uint32_t flags; ++ ++ flags = XX_DisableAllIntr(); ++#ifdef BIGPHYSAREA_ENABLE ++ if (n >= MAX_ALLOCATION_SIZE) ++ a = (void*)bigphysarea_alloc_pages(get_nr_pages(n), 0, GFP_ATOMIC); ++ else ++#endif /* BIGPHYSAREA_ENABLE */ ++ a = (void *)kmalloc((uint32_t)n, GFP_ATOMIC); ++ if (!a) ++ XX_Print("No memory for XX_Malloc\n"); ++ XX_RestoreAllIntr(flags); ++ ++ return a; ++} ++ ++void xx_Free(void *p) ++{ ++#ifdef BIGPHYSAREA_ENABLE ++ if (in_big_phys_area ((uint32_t)p)) ++ bigphysarea_free_pages(p); ++ else ++#endif /* BIGPHYSAREA_ENABLE */ ++ kfree(p); ++} ++ ++void XX_Exit(int status) ++{ ++ WARN(1, "\n\nFMD: fatal error, driver can't go on!!!\n\n"); ++} ++ ++#define BUF_SIZE 512 ++void XX_Print(char *str, ...) ++{ ++ va_list args; ++#ifdef CONFIG_SMP ++ char buf[BUF_SIZE]; ++#endif /* CONFIG_SMP */ ++ ++ va_start(args, str); ++#ifdef CONFIG_SMP ++ if (vsnprintf (buf, BUF_SIZE, str, args) >= BUF_SIZE) ++ printk(KERN_WARNING "Illegal string to print!\n more than %d characters.\n\tString was not printed completelly.\n", BUF_SIZE); ++ printk(KERN_CRIT "cpu%d/%d: %s", get_hard_smp_processor_id(raw_smp_processor_id()), raw_smp_processor_id(), buf); ++#else ++ vprintk(str, args); ++#endif /* CONFIG_SMP */ ++ va_end(args); ++} ++ ++void XX_Fprint(void *file, char *str, ...) ++{ ++ va_list args; ++#ifdef CONFIG_SMP ++ char buf[BUF_SIZE]; ++#endif /* CONFIG_SMP */ ++ ++ va_start(args, str); ++#ifdef CONFIG_SMP ++ if (vsnprintf (buf, BUF_SIZE, str, args) >= BUF_SIZE) ++ printk(KERN_WARNING "Illegal string to print!\n more than %d characters.\n\tString was not printed completelly.\n", BUF_SIZE); ++ printk (KERN_CRIT "cpu%d/%d: %s",hard_smp_processor_id(), smp_processor_id(), buf); ++ ++#else ++ vprintk(str, args); ++#endif /* CONFIG_SMP */ ++ va_end(args); ++} ++ ++#ifdef DEBUG_XX_MALLOC ++typedef void (*t_ffn)(void *); ++typedef struct { ++ t_ffn f_free; ++ void *mem; ++ char *fname; ++ int fline; ++ uint32_t size; ++ t_List node; ++} t_MemDebug; ++#define MEMDBG_OBJECT(p_List) LIST_OBJECT(p_List, t_MemDebug, node) ++ ++LIST(memDbgLst); ++ ++ ++void * XX_MallocDebug(uint32_t size, char *fname, int line) ++{ ++ void *mem; ++ t_MemDebug *p_MemDbg; ++ ++ p_MemDbg = (t_MemDebug *)xx_Malloc(sizeof(t_MemDebug)); ++ if (p_MemDbg == NULL) ++ return NULL; ++ ++ mem = xx_Malloc(size); ++ if (mem == NULL) ++ { ++ XX_Free(p_MemDbg); ++ return NULL; ++ } ++ ++ INIT_LIST(&p_MemDbg->node); ++ p_MemDbg->f_free = xx_Free; ++ p_MemDbg->mem = mem; ++ p_MemDbg->fname = fname; ++ p_MemDbg->fline = line; ++ p_MemDbg->size = size+sizeof(t_MemDebug); ++ LIST_AddToTail(&p_MemDbg->node, &memDbgLst); ++ ++ return mem; ++} ++ ++void * XX_MallocSmartDebug(uint32_t size, ++ int memPartitionId, ++ uint32_t align, ++ char *fname, ++ int line) ++{ ++ void *mem; ++ t_MemDebug *p_MemDbg; ++ ++ p_MemDbg = (t_MemDebug *)XX_Malloc(sizeof(t_MemDebug)); ++ if (p_MemDbg == NULL) ++ return NULL; ++ ++ mem = xx_MallocSmart((uint32_t)size, memPartitionId, align); ++ if (mem == NULL) ++ { ++ XX_Free(p_MemDbg); ++ return NULL; ++ } ++ ++ INIT_LIST(&p_MemDbg->node); ++ p_MemDbg->f_free = xx_FreeSmart; ++ p_MemDbg->mem = mem; ++ p_MemDbg->fname = fname; ++ p_MemDbg->fline = line; ++ p_MemDbg->size = size+sizeof(t_MemDebug); ++ LIST_AddToTail(&p_MemDbg->node, &memDbgLst); ++ ++ return mem; ++} ++ ++static void debug_free(void *mem) ++{ ++ t_List *p_MemDbgLh = NULL; ++ t_MemDebug *p_MemDbg; ++ bool found = FALSE; ++ ++ if (LIST_IsEmpty(&memDbgLst)) ++ { ++ REPORT_ERROR(MAJOR, E_ALREADY_FREE, ("Unbalanced free (0x%08x)", mem)); ++ return; ++ } ++ ++ LIST_FOR_EACH(p_MemDbgLh, &memDbgLst) ++ { ++ p_MemDbg = MEMDBG_OBJECT(p_MemDbgLh); ++ if (p_MemDbg->mem == mem) ++ { ++ found = TRUE; ++ break; ++ } ++ } ++ ++ if (!found) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_FOUND, ++ ("Attempt to free unallocated address (0x%08x)",mem)); ++ dump_stack(); ++ return; ++ } ++ ++ LIST_Del(p_MemDbgLh); ++ p_MemDbg->f_free(mem); ++ p_MemDbg->f_free(p_MemDbg); ++} ++ ++void XX_FreeSmart(void *p) ++{ ++ debug_free(p); ++} ++ ++ ++void XX_Free(void *p) ++{ ++ debug_free(p); ++} ++ ++#else /* not DEBUG_XX_MALLOC */ ++void * XX_Malloc(uint32_t size) ++{ ++ return xx_Malloc(size); ++} ++ ++void * XX_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment) ++{ ++ return xx_MallocSmart(size,memPartitionId, alignment); ++} ++ ++void XX_FreeSmart(void *p) ++{ ++ xx_FreeSmart(p); ++} ++ ++ ++void XX_Free(void *p) ++{ ++ xx_Free(p); ++} ++#endif /* not DEBUG_XX_MALLOC */ ++ ++ ++#if (defined(REPORT_EVENTS) && (REPORT_EVENTS > 0)) ++void XX_EventById(uint32_t event, t_Handle appId, uint16_t flags, char *msg) ++{ ++ e_Event eventCode = (e_Event)event; ++ ++ UNUSED(eventCode); ++ UNUSED(appId); ++ UNUSED(flags); ++ UNUSED(msg); ++} ++#endif /* (defined(REPORT_EVENTS) && ... */ ++ ++ ++uint32_t XX_DisableAllIntr(void) ++{ ++ unsigned long flags; ++ ++#ifdef local_irq_save_nort ++ local_irq_save_nort(flags); ++#else ++ local_irq_save(flags); ++#endif ++ ++ return (uint32_t)flags; ++} ++ ++void XX_RestoreAllIntr(uint32_t flags) ++{ ++#ifdef local_irq_restore_nort ++ local_irq_restore_nort((unsigned long)flags); ++#else ++ local_irq_restore((unsigned long)flags); ++#endif ++} ++ ++t_Error XX_Call( uint32_t qid, t_Error (* f)(t_Handle), t_Handle id, t_Handle appId, uint16_t flags ) ++{ ++ UNUSED(qid); ++ UNUSED(appId); ++ UNUSED(flags); ++ ++ return f(id); ++} ++ ++int XX_IsICacheEnable(void) ++{ ++ return TRUE; ++} ++ ++int XX_IsDCacheEnable(void) ++{ ++ return TRUE; ++} ++ ++ ++typedef struct { ++ t_Isr *f_Isr; ++ t_Handle handle; ++} t_InterruptHandler; ++ ++ ++t_Handle interruptHandlers[0x00010000]; ++ ++ ++t_Error XX_SetIntr(int irq, t_Isr *f_Isr, t_Handle handle) ++{ ++/* not used */ ++ return E_OK; ++} ++ ++t_Error XX_FreeIntr(int irq) ++{ ++ t_InterruptHandler *p_IntrHndl = interruptHandlers[irq]; ++ free_irq(GetDeviceIrqNum(irq), p_IntrHndl); ++ XX_Free(p_IntrHndl); ++ interruptHandlers[irq] = 0; ++ return E_OK; ++} ++ ++t_Error XX_EnableIntr(int irq) ++{ ++ enable_irq(GetDeviceIrqNum(irq)); ++ return E_OK; ++} ++ ++t_Error XX_DisableIntr(int irq) ++{ ++ disable_irq(GetDeviceIrqNum(irq)); ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* Tasklet Service Routines */ ++/*****************************************************************************/ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++typedef struct ++{ ++ t_Handle h_Data; ++ void (*f_Callback) (void *); ++ struct delayed_work dwork; ++} t_Tasklet; ++ ++static void GenericTaskletCallback(struct work_struct *p_Work) ++{ ++ t_Tasklet *p_Task = container_of(p_Work, t_Tasklet, dwork.work); ++ ++ p_Task->f_Callback(p_Task->h_Data); ++} ++#endif /* LINUX_VERSION_CODE */ ++ ++ ++t_TaskletHandle XX_InitTasklet (void (*routine)(void *), void *data) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ struct work_struct *p_Task; ++ p_Task = (struct work_struct *)XX_Malloc(sizeof(struct work_struct)); ++ INIT_WORK(p_Task, routine, data); ++#else ++ t_Tasklet *p_Task = (t_Tasklet *)XX_Malloc(sizeof(t_Tasklet)); ++ p_Task->h_Data = data; ++ p_Task->f_Callback = routine; ++ INIT_DELAYED_WORK(&p_Task->dwork, GenericTaskletCallback); ++#endif /* LINUX_VERSION_CODE */ ++ ++ return (t_TaskletHandle)p_Task; ++} ++ ++ ++void XX_FreeTasklet (t_TaskletHandle h_Tasklet) ++{ ++ if (h_Tasklet) ++ XX_Free(h_Tasklet); ++} ++ ++int XX_ScheduleTask(t_TaskletHandle h_Tasklet, int immediate) ++{ ++ int ans; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ if (immediate) ++ ans = schedule_work(h_Tasklet); ++ else ++ ans = schedule_delayed_work(h_Tasklet, 1); ++#else ++ if (immediate) ++ ans = schedule_delayed_work(&((t_Tasklet *)h_Tasklet)->dwork, 0); ++ else ++ ans = schedule_delayed_work(&((t_Tasklet *)h_Tasklet)->dwork, HZ); ++#endif /* LINUX_VERSION_CODE */ ++ ++ return ans; ++} ++ ++void XX_FlushScheduledTasks(void) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ++ flush_scheduled_tasks(); ++#else ++ flush_scheduled_work(); ++#endif /* LINUX_VERSION_CODE */ ++} ++ ++int XX_TaskletIsQueued(t_TaskletHandle h_Tasklet) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ return (int)(((struct work_struct *)h_Tasklet)->pending); ++#else ++ return (int)delayed_work_pending(&((t_Tasklet *)h_Tasklet)->dwork); ++#endif /* LINUX_VERSION_CODE */ ++} ++ ++void XX_SetTaskletData(t_TaskletHandle h_Tasklet, t_Handle data) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ++ ((struct tq_struct *)h_Tasklet)->data = data; ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ ((struct work_struct *)h_Tasklet)->data = data; ++#else ++ ((t_Tasklet *)h_Tasklet)->h_Data = data; ++#endif /* LINUX_VERSION_CODE */ ++} ++ ++t_Handle XX_GetTaskletData(t_TaskletHandle h_Tasklet) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ return (t_Handle)(((struct work_struct *)h_Tasklet)->data); ++#else ++ return ((t_Tasklet *)h_Tasklet)->h_Data; ++#endif /* LINUX_VERSION_CODE */ ++} ++ ++ ++/*****************************************************************************/ ++/* Spinlock Service Routines */ ++/*****************************************************************************/ ++ ++t_Handle XX_InitSpinlock(void) ++{ ++ spinlock_t *p_Spinlock = (spinlock_t *)XX_Malloc(sizeof(spinlock_t)); ++ if (!p_Spinlock) ++ return NULL; ++ ++ spin_lock_init(p_Spinlock); ++ ++ return (t_Handle)p_Spinlock; ++} ++ ++void XX_FreeSpinlock(t_Handle h_Spinlock) ++{ ++ if (h_Spinlock) ++ XX_Free(h_Spinlock); ++} ++ ++void XX_LockSpinlock(t_Handle h_Spinlock) ++{ ++ spin_lock((spinlock_t *)h_Spinlock); ++} ++ ++void XX_UnlockSpinlock(t_Handle h_Spinlock) ++{ ++ spin_unlock((spinlock_t *)h_Spinlock); ++} ++ ++uint32_t XX_LockIntrSpinlock(t_Handle h_Spinlock) ++{ ++ unsigned long intrFlags; ++ spin_lock_irqsave((spinlock_t *)h_Spinlock, intrFlags); ++ return intrFlags; ++} ++ ++void XX_UnlockIntrSpinlock(t_Handle h_Spinlock, uint32_t intrFlags) ++{ ++ spin_unlock_irqrestore((spinlock_t *)h_Spinlock, (unsigned long)intrFlags); ++} ++ ++ ++/*****************************************************************************/ ++/* Timers Service Routines */ ++/*****************************************************************************/ ++/* The time now is in mili sec. resolution */ ++uint32_t XX_CurrentTime(void) ++{ ++ return (jiffies*1000)/HZ; ++} ++ ++ ++t_Handle XX_CreateTimer(void) ++{ ++ struct timer_list *p_Timer = (struct timer_list *)XX_Malloc(sizeof(struct timer_list)); ++ if (p_Timer) ++ { ++ memset(p_Timer, 0, sizeof(struct timer_list)); ++ init_timer(p_Timer); ++ } ++ return (t_Handle)p_Timer; ++} ++ ++void XX_FreeTimer(t_Handle h_Timer) ++{ ++ if (h_Timer) ++ XX_Free(h_Timer); ++} ++ ++void XX_StartTimer(t_Handle h_Timer, ++ uint32_t msecs, ++ bool periodic, ++ void (*f_TimerExpired)(t_Handle), ++ t_Handle h_Arg) ++{ ++ int tmp_jiffies = (msecs*HZ)/1000; ++ struct timer_list *p_Timer = (struct timer_list *)h_Timer; ++ ++ SANITY_CHECK_RETURN((periodic == FALSE), E_NOT_SUPPORTED); ++ ++ p_Timer->function = (void (*)(unsigned long))f_TimerExpired; ++ p_Timer->data = (unsigned long)h_Arg; ++ if ((msecs*HZ)%1000) ++ tmp_jiffies++; ++ p_Timer->expires = (jiffies + tmp_jiffies); ++ ++ add_timer((struct timer_list *)h_Timer); ++} ++ ++void XX_SetTimerData(t_Handle h_Timer, t_Handle data) ++{ ++ struct timer_list *p_Timer = (struct timer_list *)h_Timer; ++ ++ p_Timer->data = (unsigned long)data; ++} ++ ++t_Handle XX_GetTimerData(t_Handle h_Timer) ++{ ++ struct timer_list *p_Timer = (struct timer_list *)h_Timer; ++ ++ return (t_Handle)p_Timer->data; ++} ++ ++uint32_t XX_GetExpirationTime(t_Handle h_Timer) ++{ ++ struct timer_list *p_Timer = (struct timer_list *)h_Timer; ++ ++ return (uint32_t)p_Timer->expires; ++} ++ ++void XX_StopTimer(t_Handle h_Timer) ++{ ++ del_timer((struct timer_list *)h_Timer); ++} ++ ++void XX_ModTimer(t_Handle h_Timer, uint32_t msecs) ++{ ++ int tmp_jiffies = (msecs*HZ)/1000; ++ ++ if ((msecs*HZ)%1000) ++ tmp_jiffies++; ++ mod_timer((struct timer_list *)h_Timer, jiffies + tmp_jiffies); ++} ++ ++int XX_TimerIsActive(t_Handle h_Timer) ++{ ++ return timer_pending((struct timer_list *)h_Timer); ++} ++ ++uint32_t XX_Sleep(uint32_t msecs) ++{ ++ int tmp_jiffies = (msecs*HZ)/1000; ++ ++ if ((msecs*HZ)%1000) ++ tmp_jiffies++; ++ return schedule_timeout(tmp_jiffies); ++} ++ ++/*BEWARE!!!!! UDelay routine is BUSY WAITTING!!!!!*/ ++void XX_UDelay(uint32_t usecs) ++{ ++ udelay(usecs); ++} ++ ++/* TODO: verify that these are correct */ ++#define MSG_BODY_SIZE 512 ++typedef t_Error (t_MsgHandler) (t_Handle h_Mod, uint32_t msgId, uint8_t msgBody[MSG_BODY_SIZE]); ++typedef void (t_MsgCompletionCB) (t_Handle h_Arg, uint8_t msgBody[MSG_BODY_SIZE]); ++t_Error XX_SendMessage(char *p_DestAddr, ++ uint32_t msgId, ++ uint8_t msgBody[MSG_BODY_SIZE], ++ t_MsgCompletionCB *f_CompletionCB, ++ t_Handle h_CBArg); ++ ++typedef struct { ++ char *p_Addr; ++ t_MsgHandler *f_MsgHandlerCB; ++ t_Handle h_Mod; ++ t_List node; ++} t_MsgHndlr; ++#define MSG_HNDLR_OBJECT(ptr) LIST_OBJECT(ptr, t_MsgHndlr, node) ++ ++LIST(msgHndlrList); ++ ++static void EnqueueMsgHndlr(t_MsgHndlr *p_MsgHndlr) ++{ ++ uint32_t intFlags; ++ ++ intFlags = XX_DisableAllIntr(); ++ LIST_AddToTail(&p_MsgHndlr->node, &msgHndlrList); ++ XX_RestoreAllIntr(intFlags); ++} ++/* TODO: add this for multi-platform support ++static t_MsgHndlr * DequeueMsgHndlr(void) ++{ ++ t_MsgHndlr *p_MsgHndlr = NULL; ++ uint32_t intFlags; ++ ++ intFlags = XX_DisableAllIntr(); ++ if (!LIST_IsEmpty(&msgHndlrList)) ++ { ++ p_MsgHndlr = MSG_HNDLR_OBJECT(msgHndlrList.p_Next); ++ LIST_DelAndInit(&p_MsgHndlr->node); ++ } ++ XX_RestoreAllIntr(intFlags); ++ ++ return p_MsgHndlr; ++} ++*/ ++static t_MsgHndlr * FindMsgHndlr(char *p_Addr) ++{ ++ t_MsgHndlr *p_MsgHndlr; ++ t_List *p_Pos; ++ ++ LIST_FOR_EACH(p_Pos, &msgHndlrList) ++ { ++ p_MsgHndlr = MSG_HNDLR_OBJECT(p_Pos); ++ if (strstr(p_MsgHndlr->p_Addr, p_Addr)) ++ return p_MsgHndlr; ++ } ++ ++ return NULL; ++} ++ ++t_Error XX_RegisterMessageHandler (char *p_Addr, t_MsgHandler *f_MsgHandlerCB, t_Handle h_Mod) ++{ ++ t_MsgHndlr *p_MsgHndlr; ++ uint32_t len; ++ ++ p_MsgHndlr = (t_MsgHndlr*)XX_Malloc(sizeof(t_MsgHndlr)); ++ if (!p_MsgHndlr) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("message handler object!!!")); ++ memset(p_MsgHndlr, 0, sizeof(t_MsgHndlr)); ++ ++ len = strlen(p_Addr); ++ p_MsgHndlr->p_Addr = (char*)XX_Malloc(len+1); ++ strncpy(p_MsgHndlr->p_Addr,p_Addr, (uint32_t)(len+1)); ++ ++ p_MsgHndlr->f_MsgHandlerCB = f_MsgHandlerCB; ++ p_MsgHndlr->h_Mod = h_Mod; ++ INIT_LIST(&p_MsgHndlr->node); ++ EnqueueMsgHndlr(p_MsgHndlr); ++ ++ return E_OK; ++} ++ ++t_Error XX_UnregisterMessageHandler (char *p_Addr) ++{ ++ t_MsgHndlr *p_MsgHndlr = FindMsgHndlr(p_Addr); ++ if (!p_MsgHndlr) ++ RETURN_ERROR(MINOR, E_NO_DEVICE, ("message handler not found in list!!!")); ++ ++ LIST_Del(&p_MsgHndlr->node); ++ XX_Free(p_MsgHndlr->p_Addr); ++ XX_Free(p_MsgHndlr); ++ ++ return E_OK; ++} ++ ++t_Error XX_SendMessage(char *p_DestAddr, ++ uint32_t msgId, ++ uint8_t msgBody[MSG_BODY_SIZE], ++ t_MsgCompletionCB *f_CompletionCB, ++ t_Handle h_CBArg) ++{ ++ t_Error ans; ++ t_MsgHndlr *p_MsgHndlr = FindMsgHndlr(p_DestAddr); ++ if (!p_MsgHndlr) ++ RETURN_ERROR(MINOR, E_NO_DEVICE, ("message handler not found in list!!!")); ++ ++ ans = p_MsgHndlr->f_MsgHandlerCB(p_MsgHndlr->h_Mod, msgId, msgBody); ++ ++ if (f_CompletionCB) ++ f_CompletionCB(h_CBArg, msgBody); ++ ++ return ans; ++} ++ ++t_Error XX_IpcRegisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH], ++ t_IpcMsgHandler *f_MsgHandler, ++ t_Handle h_Module, ++ uint32_t replyLength) ++{ ++ UNUSED(addr);UNUSED(f_MsgHandler);UNUSED(h_Module);UNUSED(replyLength); ++ return E_OK; ++} ++ ++t_Error XX_IpcUnregisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH]) ++{ ++ UNUSED(addr); ++ return E_OK; ++} ++ ++ ++t_Error XX_IpcSendMessage(t_Handle h_Session, ++ uint8_t *p_Msg, ++ uint32_t msgLength, ++ uint8_t *p_Reply, ++ uint32_t *p_ReplyLength, ++ t_IpcMsgCompletion *f_Completion, ++ t_Handle h_Arg) ++{ ++ UNUSED(h_Session); UNUSED(p_Msg); UNUSED(msgLength); UNUSED(p_Reply); ++ UNUSED(p_ReplyLength); UNUSED(f_Completion); UNUSED(h_Arg); ++ return E_OK; ++} ++ ++t_Handle XX_IpcInitSession(char destAddr[XX_IPC_MAX_ADDR_NAME_LENGTH], ++ char srcAddr[XX_IPC_MAX_ADDR_NAME_LENGTH]) ++{ ++ UNUSED(destAddr); UNUSED(srcAddr); ++ return E_OK; ++} ++ ++/*Forced to introduce due to PRINT_FMT_PARAMS define*/ ++uint32_t E500_GetId(void) ++{ ++ return raw_smp_processor_id(); ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) ++int GetDeviceIrqNum(int irq) ++{ ++ struct device_node *iPar; ++ struct irq_domain *irqHost; ++ uint32_t hwIrq; ++ ++ /* Get the interrupt controller */ ++ iPar = of_find_node_by_name(NULL, "mpic"); ++ hwIrq = 0; ++ ++ ASSERT_COND(iPar != NULL); ++ /* Get the irq host */ ++ irqHost = irq_find_host(iPar); ++ of_node_put(iPar); ++ ++ /* Create irq mapping */ ++ return irq_create_mapping(irqHost, hwIrq); ++} ++#else ++#error "kernel not supported!!!" ++#endif /* LINUX_VERSION_CODE */ ++ ++void * XX_PhysToVirt(physAddress_t addr) ++{ ++ return UINT_TO_PTR(SYS_PhysToVirt((uint64_t)addr)); ++} ++ ++physAddress_t XX_VirtToPhys(void * addr) ++{ ++ return (physAddress_t)SYS_VirtToPhys(PTR_TO_UINT(addr)); ++} ++ ++void * xx_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment) ++{ ++ uintptr_t *returnCode, tmp; ++ ++ if (alignment < sizeof(uintptr_t)) ++ alignment = sizeof(uintptr_t); ++ size += alignment + sizeof(returnCode); ++ tmp = (uintptr_t)xx_Malloc(size); ++ if (tmp == 0) ++ return NULL; ++ returnCode = (uintptr_t*)((tmp + alignment + sizeof(returnCode)) & ~((uintptr_t)alignment - 1)); ++ *(returnCode - 1) = tmp; ++ ++ return (void*)returnCode; ++} ++ ++void xx_FreeSmart(void *p) ++{ ++ xx_Free((void*)(*((uintptr_t *)(p) - 1))); ++} +diff --git a/include/uapi/linux/fmd/Kbuild b/include/uapi/linux/fmd/Kbuild +new file mode 100644 +index 0000000..56a2040 +--- /dev/null ++++ b/include/uapi/linux/fmd/Kbuild +@@ -0,0 +1,5 @@ ++header-y += integrations/ ++header-y += Peripherals/ ++ ++header-y += ioctls.h ++header-y += net_ioctls.h +diff --git a/include/uapi/linux/fmd/Peripherals/Kbuild b/include/uapi/linux/fmd/Peripherals/Kbuild +new file mode 100644 +index 0000000..43883ef +--- /dev/null ++++ b/include/uapi/linux/fmd/Peripherals/Kbuild +@@ -0,0 +1,4 @@ ++header-y += fm_ioctls.h ++header-y += fm_port_ioctls.h ++header-y += fm_pcd_ioctls.h ++header-y += fm_test_ioctls.h +diff --git a/include/uapi/linux/fmd/Peripherals/fm_ioctls.h b/include/uapi/linux/fmd/Peripherals/fm_ioctls.h +new file mode 100644 +index 0000000..e0c2dd3 +--- /dev/null ++++ b/include/uapi/linux/fmd/Peripherals/fm_ioctls.h +@@ -0,0 +1,628 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++/**************************************************************************//** ++ @File fm_ioctls.h ++ ++ @Description FM Char device ioctls ++*//***************************************************************************/ ++#ifndef __FM_IOCTLS_H ++#define __FM_IOCTLS_H ++ ++ ++/**************************************************************************//** ++ @Group lnx_ioctl_FM_grp Frame Manager Linux IOCTL API ++ ++ @Description FM Linux ioctls definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Collection FM IOCTL device ('/dev') definitions ++*//***************************************************************************/ ++#define DEV_FM_NAME "fm" /**< Name of the FM chardev */ ++ ++#define DEV_FM_MINOR_BASE 0 ++#define DEV_FM_PCD_MINOR_BASE (DEV_FM_MINOR_BASE + 1) /*/dev/fmx-pcd */ ++#define DEV_FM_OH_PORTS_MINOR_BASE (DEV_FM_PCD_MINOR_BASE + 1) /*/dev/fmx-port-ohy */ ++#define DEV_FM_RX_PORTS_MINOR_BASE (DEV_FM_OH_PORTS_MINOR_BASE + FM_MAX_NUM_OF_OH_PORTS) /*/dev/fmx-port-rxy */ ++#define DEV_FM_TX_PORTS_MINOR_BASE (DEV_FM_RX_PORTS_MINOR_BASE + FM_MAX_NUM_OF_RX_PORTS) /*/dev/fmx-port-txy */ ++#define DEV_FM_MAX_MINORS (DEV_FM_TX_PORTS_MINOR_BASE + FM_MAX_NUM_OF_TX_PORTS) ++ ++#define FM_IOC_NUM(n) (n) ++#define FM_PCD_IOC_NUM(n) (n+20) ++#define FM_PORT_IOC_NUM(n) (n+70) ++/* @} */ ++ ++#define IOC_FM_MAX_NUM_OF_PORTS 64 ++ ++ ++/**************************************************************************//** ++ @Description Enum for defining port types ++ (must match enum e_FmPortType defined in fm_ext.h) ++*//***************************************************************************/ ++typedef enum ioc_fm_port_type { ++ e_IOC_FM_PORT_TYPE_OH_OFFLINE_PARSING = 0, /**< Offline parsing port */ ++ e_IOC_FM_PORT_TYPE_RX, /**< 1G Rx port */ ++ e_IOC_FM_PORT_TYPE_RX_10G, /**< 10G Rx port */ ++ e_IOC_FM_PORT_TYPE_TX, /**< 1G Tx port */ ++ e_IOC_FM_PORT_TYPE_TX_10G, /**< 10G Tx port */ ++ e_IOC_FM_PORT_TYPE_DUMMY ++} ioc_fm_port_type; ++ ++ ++/**************************************************************************//** ++ @Group lnx_ioctl_FM_lib_grp FM library ++ ++ @Description FM API functions, definitions and enums ++ The FM module is the main driver module and is a mandatory module ++ for FM driver users. Before any further module initialization, ++ this module must be initialized. ++ The FM is a "single-tone" module. It is responsible of the common ++ HW modules: FPM, DMA, common QMI, common BMI initializations and ++ run-time control routines. This module must be initialized always ++ when working with any of the FM modules. ++ NOTE - We assumes that the FML will be initialize only by core No. 0! ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description FM Exceptions ++*//***************************************************************************/ ++typedef enum ioc_fm_exceptions { ++ e_IOC_FM_EX_DMA_BUS_ERROR, /**< DMA bus error. */ ++ e_IOC_EX_DMA_READ_ECC, /**< Read Buffer ECC error (Valid for FM rev < 6)*/ ++ e_IOC_EX_DMA_SYSTEM_WRITE_ECC, /**< Write Buffer ECC error on system side (Valid for FM rev < 6)*/ ++ e_IOC_EX_DMA_FM_WRITE_ECC, /**< Write Buffer ECC error on FM side (Valid for FM rev < 6)*/ ++ e_IOC_EX_DMA_SINGLE_PORT_ECC, /**< Single Port ECC error on FM side (Valid for FM rev > 6)*/ ++ e_IOC_EX_FPM_STALL_ON_TASKS, /**< Stall of tasks on FPM */ ++ e_IOC_EX_FPM_SINGLE_ECC, /**< Single ECC on FPM. */ ++ e_IOC_EX_FPM_DOUBLE_ECC, /**< Double ECC error on FPM ram access */ ++ e_IOC_EX_QMI_SINGLE_ECC, /**< Single ECC on QMI. */ ++ e_IOC_EX_QMI_DOUBLE_ECC, /**< Double bit ECC occurred on QMI */ ++ e_IOC_EX_QMI_DEQ_FROM_UNKNOWN_PORTID,/**< Dequeue from unknown port id */ ++ e_IOC_EX_BMI_LIST_RAM_ECC, /**< Linked List RAM ECC error */ ++ e_IOC_EX_BMI_STORAGE_PROFILE_ECC, /**< Storage Profile ECC Error */ ++ e_IOC_EX_BMI_STATISTICS_RAM_ECC, /**< Statistics Count RAM ECC Error Enable */ ++ e_IOC_EX_BMI_DISPATCH_RAM_ECC, /**< Dispatch RAM ECC Error Enable */ ++ e_IOC_EX_IRAM_ECC, /**< Double bit ECC occurred on IRAM*/ ++ e_IOC_EX_MURAM_ECC /**< Double bit ECC occurred on MURAM*/ ++} ioc_fm_exceptions; ++ ++/**************************************************************************//** ++ @Group lnx_ioctl_FM_runtime_control_grp FM Runtime Control Unit ++ ++ @Description FM Runtime control unit API functions, definitions and enums. ++ The FM driver provides a set of control routines for each module. ++ These routines may only be called after the module was fully ++ initialized (both configuration and initialization routines were ++ called). They are typically used to get information from hardware ++ (status, counters/statistics, revision etc.), to modify a current ++ state or to force/enable a required action. Run-time control may ++ be called whenever necessary and as many times as needed. ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Collection General FM defines. ++ *//***************************************************************************/ ++#define IOC_FM_MAX_NUM_OF_VALID_PORTS (FM_MAX_NUM_OF_OH_PORTS + \ ++ FM_MAX_NUM_OF_1G_RX_PORTS + \ ++ FM_MAX_NUM_OF_10G_RX_PORTS + \ ++ FM_MAX_NUM_OF_1G_TX_PORTS + \ ++ FM_MAX_NUM_OF_10G_TX_PORTS) ++/* @} */ ++ ++/**************************************************************************//** ++ @Description Structure for Port bandwidth requirement. Port is identified ++ by type and relative id. ++ (must be identical to t_FmPortBandwidth defined in fm_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_port_bandwidth_t { ++ ioc_fm_port_type type; /**< FM port type */ ++ uint8_t relative_port_id; /**< Type relative port id */ ++ uint8_t bandwidth; /**< bandwidth - (in term of percents) */ ++} ioc_fm_port_bandwidth_t; ++ ++/**************************************************************************//** ++ @Description A Structure containing an array of Port bandwidth requirements. ++ The user should state the ports requiring bandwidth in terms of ++ percentage - i.e. all port's bandwidths in the array must add ++ up to 100. ++ (must be identical to t_FmPortsBandwidthParams defined in fm_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_port_bandwidth_params { ++ uint8_t num_of_ports; ++ /**< num of ports listed in the array below */ ++ ioc_fm_port_bandwidth_t ports_bandwidths[IOC_FM_MAX_NUM_OF_VALID_PORTS]; ++ /**< for each port, it's bandwidth (all port's ++ bandwidths must add up to 100.*/ ++} ioc_fm_port_bandwidth_params; ++ ++/**************************************************************************//** ++ @Description enum for defining FM counters ++*//***************************************************************************/ ++typedef enum ioc_fm_counters { ++ e_IOC_FM_COUNTERS_ENQ_TOTAL_FRAME, /**< QMI total enqueued frames counter */ ++ e_IOC_FM_COUNTERS_DEQ_TOTAL_FRAME, /**< QMI total dequeued frames counter */ ++ e_IOC_FM_COUNTERS_DEQ_0, /**< QMI 0 frames from QMan counter */ ++ e_IOC_FM_COUNTERS_DEQ_1, /**< QMI 1 frames from QMan counter */ ++ e_IOC_FM_COUNTERS_DEQ_2, /**< QMI 2 frames from QMan counter */ ++ e_IOC_FM_COUNTERS_DEQ_3, /**< QMI 3 frames from QMan counter */ ++ e_IOC_FM_COUNTERS_DEQ_FROM_DEFAULT, /**< QMI dequeue from default queue counter */ ++ e_IOC_FM_COUNTERS_DEQ_FROM_CONTEXT, /**< QMI dequeue from FQ context counter */ ++ e_IOC_FM_COUNTERS_DEQ_FROM_FD, /**< QMI dequeue from FD command field counter */ ++ e_IOC_FM_COUNTERS_DEQ_CONFIRM, /**< QMI dequeue confirm counter */ ++} ioc_fm_counters; ++ ++typedef struct ioc_fm_obj_t { ++ void *obj; ++} ioc_fm_obj_t; ++ ++/**************************************************************************//** ++ @Description A structure for returning revision information ++ (must match struct t_FmRevisionInfo declared in fm_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_revision_info_t { ++ uint8_t major; /**< Major revision */ ++ uint8_t minor; /**< Minor revision */ ++} ioc_fm_revision_info_t; ++ ++/**************************************************************************//** ++ @Description A structure for FM counters ++*//***************************************************************************/ ++typedef struct ioc_fm_counters_params_t { ++ ioc_fm_counters cnt; /**< The requested counter */ ++ uint32_t val; /**< The requested value to get/set from/into the counter */ ++} ioc_fm_counters_params_t; ++ ++typedef union ioc_fm_api_version_t { ++ struct { ++ uint8_t major; ++ uint8_t minor; ++ uint8_t respin; ++ uint8_t reserved; ++ } version; ++ uint32_t ver; ++} ioc_fm_api_version_t; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description A structure of information about each of the external ++ buffer pools used by a port or storage-profile. ++ (must be identical to t_FmExtPoolParams defined in fm_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_ext_pool_params { ++ uint8_t id; /**< External buffer pool id */ ++ uint16_t size; /**< External buffer pool buffer size */ ++} ioc_fm_ext_pool_params; ++ ++/**************************************************************************//** ++ @Description A structure for informing the driver about the external ++ buffer pools allocated in the BM and used by a port or a ++ storage-profile. ++ (must be identical to t_FmExtPools defined in fm_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_ext_pools { ++ uint8_t num_of_pools_used; /**< Number of pools use by this port */ ++ ioc_fm_ext_pool_params ext_buf_pool[FM_PORT_MAX_NUM_OF_EXT_POOLS]; ++ /**< Parameters for each port */ ++} ioc_fm_ext_pools; ++ ++typedef struct ioc_fm_vsp_params_t { ++ void *p_fm; /**< A handle to the FM object this VSP related to */ ++ ioc_fm_ext_pools ext_buf_pools; /**< Which external buffer pools are used ++ (up to FM_PORT_MAX_NUM_OF_EXT_POOLS), and their sizes. ++ parameter associated with Rx / OP port */ ++ uint16_t liodn_offset; /**< VSP's LIODN offset */ ++ struct { ++ ioc_fm_port_type port_type; /**< Port type */ ++ uint8_t port_id; /**< Port Id - relative to type */ ++ } port_params; ++ uint8_t relative_profile_id; /**< VSP Id - relative to VSP's range ++ defined in relevant FM object */ ++ void *id; /**< return value */ ++} ioc_fm_vsp_params_t; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Description A structure for defining BM pool depletion criteria ++*//***************************************************************************/ ++typedef struct ioc_fm_buf_pool_depletion_t { ++ bool pools_grp_mode_enable; /**< select mode in which pause frames will be sent after ++ a number of pools (all together!) are depleted */ ++ uint8_t num_of_pools; /**< the number of depleted pools that will invoke ++ pause frames transmission. */ ++ bool pools_to_consider[BM_MAX_NUM_OF_POOLS]; ++ /**< For each pool, TRUE if it should be considered for ++ depletion (Note - this pool must be used by this port!). */ ++ bool single_pool_mode_enable; /**< select mode in which pause frames will be sent after ++ a single-pool is depleted; */ ++ bool pools_to_consider_for_single_mode[BM_MAX_NUM_OF_POOLS]; ++ /**< For each pool, TRUE if it should be considered for ++ depletion (Note - this pool must be used by this port!) */ ++#if (DPAA_VERSION >= 11) ++ bool pfc_priorities_en[FM_MAX_NUM_OF_PFC_PRIORITIES]; ++ /**< This field is used by the MAC as the Priority Enable Vector in the PFC frame ++ which is transmitted */ ++#endif /* (DPAA_VERSION >= 11) */ ++} ioc_fm_buf_pool_depletion_t; ++ ++#if (DPAA_VERSION >= 11) ++typedef struct ioc_fm_buf_pool_depletion_params_t { ++ void *p_fm_vsp; ++ ioc_fm_buf_pool_depletion_t fm_buf_pool_depletion; ++} ioc_fm_buf_pool_depletion_params_t; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++typedef struct ioc_fm_buffer_prefix_content_t { ++ uint16_t priv_data_size; /**< Number of bytes to be left at the beginning ++ of the external buffer; Note that the private-area will ++ start from the base of the buffer address. */ ++ bool pass_prs_result; /**< TRUE to pass the parse result to/from the FM; ++ User may use FM_PORT_GetBufferPrsResult() in order to ++ get the parser-result from a buffer. */ ++ bool pass_time_stamp; /**< TRUE to pass the timeStamp to/from the FM ++ User may use FM_PORT_GetBufferTimeStamp() in order to ++ get the parser-result from a buffer. */ ++ bool pass_hash_result; /**< TRUE to pass the KG hash result to/from the FM ++ User may use FM_PORT_GetBufferHashResult() in order to ++ get the parser-result from a buffer. */ ++ bool pass_all_other_pcd_info; /**< Add all other Internal-Context information: ++ AD, hash-result, key, etc. */ ++ uint16_t data_align; /**< 0 to use driver's default alignment [64], ++ other value for selecting a data alignment (must be a power of 2); ++ if write optimization is used, must be >= 16. */ ++ uint8_t manip_extra_space; /**< Maximum extra size needed (insertion-size minus removal-size); ++ Note that this field impacts the size of the buffer-prefix ++ (i.e. it pushes the data offset); ++ This field is irrelevant if DPAA_VERSION==10 */ ++} ioc_fm_buffer_prefix_content_t; ++ ++typedef struct ioc_fm_buffer_prefix_content_params_t { ++ void *p_fm_vsp; ++ ioc_fm_buffer_prefix_content_t fm_buffer_prefix_content; ++} ioc_fm_buffer_prefix_content_params_t; ++ ++#if (DPAA_VERSION >= 11) ++typedef struct ioc_fm_vsp_config_no_sg_params_t { ++ void *p_fm_vsp; ++ bool no_sg; ++} ioc_fm_vsp_config_no_sg_params_t; ++ ++typedef struct ioc_fm_vsp_prs_result_params_t { ++ void *p_fm_vsp; ++ void *p_data; ++} ioc_fm_vsp_prs_result_params_t; ++#endif ++ ++typedef struct fm_ctrl_mon_t { ++ uint8_t percent_cnt[2]; ++} fm_ctrl_mon_t; ++ ++typedef struct ioc_fm_ctrl_mon_counters_params_t { ++ uint8_t fm_ctrl_index; ++ fm_ctrl_mon_t *p_mon; ++} ioc_fm_ctrl_mon_counters_params_t; ++ ++/**************************************************************************//** ++ @Function FM_IOC_SET_PORTS_BANDWIDTH ++ ++ @Description Sets relative weights between ports when accessing common resources. ++ ++ @Param[in] ioc_fm_port_bandwidth_params Port bandwidth percentages, ++ their sum must equal 100. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++#define FM_IOC_SET_PORTS_BANDWIDTH _IOW(FM_IOC_TYPE_BASE, FM_IOC_NUM(2), ioc_fm_port_bandwidth_params) ++ ++/**************************************************************************//** ++ @Function FM_IOC_GET_REVISION ++ ++ @Description Returns the FM revision ++ ++ @Param[out] ioc_fm_revision_info_t A structure of revision information parameters. ++ ++ @Return None. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++#define FM_IOC_GET_REVISION _IOR(FM_IOC_TYPE_BASE, FM_IOC_NUM(3), ioc_fm_revision_info_t) ++ ++/**************************************************************************//** ++ @Function FM_IOC_GET_COUNTER ++ ++ @Description Reads one of the FM counters. ++ ++ @Param[in,out] ioc_fm_counters_params_t The requested counter parameters. ++ ++ @Return Counter's current value. ++ ++ @Cautions Allowed only following FM_Init(). ++ Note that it is user's responsibilty to call this routine only ++ for enabled counters, and there will be no indication if a ++ disabled counter is accessed. ++*//***************************************************************************/ ++#define FM_IOC_GET_COUNTER _IOWR(FM_IOC_TYPE_BASE, FM_IOC_NUM(4), ioc_fm_counters_params_t) ++ ++/**************************************************************************//** ++ @Function FM_IOC_SET_COUNTER ++ ++ @Description Sets a value to an enabled counter. Use "0" to reset the counter. ++ ++ @Param[in] ioc_fm_counters_params_t The requested counter parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++#define FM_IOC_SET_COUNTER _IOW(FM_IOC_TYPE_BASE, FM_IOC_NUM(5), ioc_fm_counters_params_t) ++ ++/**************************************************************************//** ++ @Function FM_IOC_FORCE_INTR ++ ++ @Description Causes an interrupt event on the requested source. ++ ++ @Param[in] ioc_fm_exceptions An exception to be forced. ++ ++ @Return E_OK on success; Error code if the exception is not enabled, ++ or is not able to create interrupt. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++#define FM_IOC_FORCE_INTR _IOW(FM_IOC_TYPE_BASE, FM_IOC_NUM(6), ioc_fm_exceptions) ++ ++/**************************************************************************//** ++ @Function FM_IOC_GET_API_VERSION ++ ++ @Description Reads the FMD IOCTL API version. ++ ++ @Param[in,out] ioc_fm_api_version_t The requested counter parameters. ++ ++ @Return Version's value. ++*//***************************************************************************/ ++#define FM_IOC_GET_API_VERSION _IOR(FM_IOC_TYPE_BASE, FM_IOC_NUM(7), ioc_fm_api_version_t) ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Function FM_VSP_Config ++ ++ @Description Creates descriptor for the FM VSP module. ++ ++ The routine returns a handle (descriptor) to the FM VSP object. ++ This descriptor must be passed as first parameter to all other ++ FM VSP function calls. ++ ++ No actual initialization or configuration of FM hardware is ++ done by this routine. ++ ++ at Param[in] p_FmVspParams Pointer to data structure of parameters ++ ++ @Retval Handle to FM VSP object, or NULL for Failure. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_IOC_VSP_CONFIG_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_IOC_NUM(8), ioc_compat_fm_vsp_params_t) ++#endif ++#define FM_IOC_VSP_CONFIG _IOWR(FM_IOC_TYPE_BASE, FM_IOC_NUM(8), ioc_fm_vsp_params_t) ++ ++/**************************************************************************//** ++ @Function FM_VSP_Init ++ ++ @Description Initializes the FM VSP module ++ ++ @Param[in] h_FmVsp - FM VSP module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_IOC_VSP_INIT_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_IOC_NUM(9), ioc_compat_fm_obj_t) ++#endif ++#define FM_IOC_VSP_INIT _IOW(FM_IOC_TYPE_BASE, FM_IOC_NUM(9), ioc_fm_obj_t) ++ ++/**************************************************************************//** ++ @Function FM_VSP_Free ++ ++ @Description Frees all resources that were assigned to FM VSP module. ++ ++ Calling this routine invalidates the descriptor. ++ ++ @Param[in] h_FmVsp - FM VSP module descriptor ++ ++ @Return E_OK on success; Error code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_IOC_VSP_FREE_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_IOC_NUM(10), ioc_compat_fm_obj_t) ++#endif ++#define FM_IOC_VSP_FREE _IOW(FM_IOC_TYPE_BASE, FM_IOC_NUM(10), ioc_fm_obj_t) ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigPoolDepletion ++ ++ @Description Calling this routine enables pause frame generation depending on the ++ depletion status of BM pools. It also defines the conditions to activate ++ this functionality. By default, this functionality is disabled. ++ ++ @Param[in] ioc_fm_buf_pool_depletion_params_t A structure holding the required parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_IOC_VSP_CONFIG_POOL_DEPLETION_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_IOC_NUM(11), ioc_compat_fm_buf_pool_depletion_params_t) ++#endif ++#define FM_IOC_VSP_CONFIG_POOL_DEPLETION _IOW(FM_IOC_TYPE_BASE, FM_IOC_NUM(11), ioc_fm_buf_pool_depletion_params_t) ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigBufferPrefixContent ++ ++ @Description Defines the structure, size and content of the application buffer. ++ ++ The prefix will ++ In VSPs defined for Tx ports, if 'passPrsResult', the application ++ should set a value to their offsets in the prefix of ++ the FM will save the first 'privDataSize', than, ++ depending on 'passPrsResult' and 'passTimeStamp', copy parse result ++ and timeStamp, and the packet itself (in this order), to the ++ application buffer, and to offset. ++ ++ Calling this routine changes the buffer margins definitions ++ in the internal driver data base from its default ++ configuration: Data size: [DEFAULT_FM_SP_bufferPrefixContent_privDataSize] ++ Pass Parser result: [DEFAULT_FM_SP_bufferPrefixContent_passPrsResult]. ++ Pass timestamp: [DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp]. ++ ++ @Param[in] ioc_fm_buffer_prefix_content_params_t A structure holding the required parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_IOC_VSP_CONFIG_BUFFER_PREFIX_CONTENT_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_IOC_NUM(12), ioc_compat_fm_buffer_prefix_content_params_t) ++#endif ++#define FM_IOC_VSP_CONFIG_BUFFER_PREFIX_CONTENT _IOW(FM_IOC_TYPE_BASE, FM_IOC_NUM(12), ioc_fm_buffer_prefix_content_params_t) ++ ++/**************************************************************************//** ++ @Function FM_VSP_ConfigNoScatherGather ++ ++ @Description Calling this routine changes the possibility to receive S/G frame ++ in the internal driver data base ++ from its default configuration: optimize = [DEFAULT_FM_SP_noScatherGather] ++ ++ @Param[in] ioc_fm_vsp_config_no_sg_params_t A structure holding the required parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_IOC_VSP_CONFIG_NO_SG_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_IOC_NUM(13), ioc_compat_fm_vsp_config_no_sg_params_t) ++#endif ++#define FM_IOC_VSP_CONFIG_NO_SG _IOW(FM_IOC_TYPE_BASE, FM_IOC_NUM(13), ioc_fm_vsp_config_no_sg_params_t) ++ ++/**************************************************************************//** ++ @Function FM_VSP_GetBufferPrsResult ++ ++ @Description Returns the pointer to the parse result in the data buffer. ++ In Rx ports this is relevant after reception, if parse ++ result is configured to be part of the data passed to the ++ application. For non Rx ports it may be used to get the pointer ++ of the area in the buffer where parse result should be ++ initialized - if so configured. ++ See FM_VSP_ConfigBufferPrefixContent for data buffer prefix ++ configuration. ++ ++ @Param[in] ioc_fm_vsp_prs_result_params_t A structure holding the required parameters. ++ ++ @Return Parse result pointer on success, NULL if parse result was not ++ configured for this port. ++ ++ @Cautions Allowed only following FM_VSP_Init(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_IOC_VSP_GET_BUFFER_PRS_RESULT_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_IOC_NUM(14), ioc_compat_fm_vsp_prs_result_params_t) ++#endif ++#define FM_IOC_VSP_GET_BUFFER_PRS_RESULT _IOWR(FM_IOC_TYPE_BASE, FM_IOC_NUM(14), ioc_fm_vsp_prs_result_params_t) ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Function FM_CtrlMonStart ++ ++ @Description Start monitoring utilization of all available FM controllers. ++ ++ In order to obtain FM controllers utilization the following sequence ++ should be used: ++ -# FM_CtrlMonStart() ++ -# FM_CtrlMonStop() ++ -# FM_CtrlMonGetCounters() - issued for each FM controller ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++#define FM_IOC_CTRL_MON_START _IO(FM_IOC_TYPE_BASE, FM_IOC_NUM(15)) ++ ++ ++/**************************************************************************//** ++ @Function FM_CtrlMonStop ++ ++ @Description Stop monitoring utilization of all available FM controllers. ++ ++ In order to obtain FM controllers utilization the following sequence ++ should be used: ++ -# FM_CtrlMonStart() ++ -# FM_CtrlMonStop() ++ -# FM_CtrlMonGetCounters() - issued for each FM controller ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++#define FM_IOC_CTRL_MON_STOP _IO(FM_IOC_TYPE_BASE, FM_IOC_NUM(16)) ++ ++/**************************************************************************//** ++ @Function FM_CtrlMonGetCounters ++ ++ @Description Obtain FM controller utilization parameters. ++ ++ In order to obtain FM controllers utilization the following sequence ++ should be used: ++ -# FM_CtrlMonStart() ++ -# FM_CtrlMonStop() ++ -# FM_CtrlMonGetCounters() - issued for each FM controller ++ ++ @Param[in] ioc_fm_ctrl_mon_counters_params_t A structure holding the required parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_IOC_CTRL_MON_GET_COUNTERS_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_IOC_NUM(17), ioc_compat_fm_ctrl_mon_counters_params_t) ++#endif ++#define FM_IOC_CTRL_MON_GET_COUNTERS _IOW(FM_IOC_TYPE_BASE, FM_IOC_NUM(17), ioc_fm_ctrl_mon_counters_params_t) ++ ++/** @} */ /* end of lnx_ioctl_FM_runtime_control_grp group */ ++/** @} */ /* end of lnx_ioctl_FM_lib_grp group */ ++/** @} */ /* end of lnx_ioctl_FM_grp */ ++ ++#define FMD_API_VERSION_MAJOR 21 ++#define FMD_API_VERSION_MINOR 1 ++#define FMD_API_VERSION_RESPIN 0 ++ ++#endif /* __FM_IOCTLS_H */ +diff --git a/include/uapi/linux/fmd/Peripherals/fm_pcd_ioctls.h b/include/uapi/linux/fmd/Peripherals/fm_pcd_ioctls.h +new file mode 100644 +index 0000000..d13e878 +--- /dev/null ++++ b/include/uapi/linux/fmd/Peripherals/fm_pcd_ioctls.h +@@ -0,0 +1,3084 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/****************************************************************************** ++ @File fm_pcd_ioctls.h ++ ++ @Description FM PCD ... ++*//***************************************************************************/ ++#ifndef __FM_PCD_IOCTLS_H ++#define __FM_PCD_IOCTLS_H ++ ++#include "net_ioctls.h" ++#include "fm_ioctls.h" ++ ++ ++/**************************************************************************//** ++ ++ @Group lnx_ioctl_FM_grp Frame Manager Linux IOCTL API ++ ++ @Description Frame Manager Linux ioctls definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group lnx_ioctl_FM_PCD_grp FM PCD ++ ++ @Description Frame Manager PCD API functions, definitions and enums ++ ++ The FM PCD module is responsible for the initialization of all ++ global classifying FM modules. This includes the parser general and ++ common registers, the key generator global and common registers, ++ and the policer global and common registers. ++ In addition, the FM PCD SW module will initialize all required ++ key generator schemes, coarse classification flows, and policer ++ profiles. When an FM module is configured to work with one of these ++ entities, it will register to it using the FM PORT API. The PCD ++ module will manage the PCD resources - i.e. resource management of ++ KeyGen schemes, etc. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Collection General PCD defines ++*//***************************************************************************/ ++#define IOC_FM_PCD_MAX_NUM_OF_PRIVATE_HDRS 2 /**< Number of units/headers saved for user */ ++ ++#define IOC_FM_PCD_PRS_NUM_OF_HDRS 16 /**< Number of headers supported by HW parser */ ++#define IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS (32 - IOC_FM_PCD_MAX_NUM_OF_PRIVATE_HDRS) ++ /**< Number of distinction units is limited by ++ register size (32 bits) minus reserved bits ++ for private headers. */ ++#define IOC_FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS 4 /**< Maximum number of interchangeable headers ++ in a distinction unit */ ++#define IOC_FM_PCD_KG_NUM_OF_GENERIC_REGS 8 /**< Total number of generic KeyGen registers */ ++#define IOC_FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY 35 /**< Max number allowed on any configuration; ++ For HW implementation reasons, in most ++ cases less than this will be allowed; The ++ driver will return an initialization error ++ if resource is unavailable. */ ++#define IOC_FM_PCD_KG_NUM_OF_EXTRACT_MASKS 4 /**< Total number of masks allowed on KeyGen extractions. */ ++#define IOC_FM_PCD_KG_NUM_OF_DEFAULT_GROUPS 16 /**< Number of default value logical groups */ ++ ++#define IOC_FM_PCD_PRS_NUM_OF_LABELS 32 /**< Maximum number of SW parser labels */ ++#define IOC_FM_PCD_SW_PRS_SIZE 0x00000800 /**< Total size of SW parser area */ ++ ++#define IOC_FM_PCD_MAX_MANIP_INSRT_TEMPLATE_SIZE 128 /**< Maximum size of insertion template for ++ insert manipulation */ ++ ++#if DPAA_VERSION >= 11 ++#define IOC_FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES 64 /**< Maximum possible entries for frame replicator group */ ++#endif /* DPAA_VERSION >= 11 */ ++/* @} */ ++ ++#ifdef FM_CAPWAP_SUPPORT ++#error "FM_CAPWAP_SUPPORT not implemented!" ++#endif ++ ++ ++/**************************************************************************//** ++ @Group lnx_ioctl_FM_PCD_init_grp FM PCD Initialization Unit ++ ++ @Description Frame Manager PCD Initialization Unit API ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description PCD counters ++ (must match enum e_FmPcdCounters defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_counters { ++ e_IOC_FM_PCD_KG_COUNTERS_TOTAL, /**< KeyGen counter */ ++ e_IOC_FM_PCD_PLCR_COUNTERS_RED, /**< Policer counter - counts the total number of RED packets that exit the Policer. */ ++ e_IOC_FM_PCD_PLCR_COUNTERS_YELLOW, /**< Policer counter - counts the total number of YELLOW packets that exit the Policer. */ ++ e_IOC_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED, /**< Policer counter - counts the number of packets that changed color to RED by the Policer; ++ This is a subset of e_IOC_FM_PCD_PLCR_COUNTERS_RED packet count, indicating active color changes. */ ++ e_IOC_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW, /**< Policer counter - counts the number of packets that changed color to YELLOW by the Policer; ++ This is a subset of e_IOC_FM_PCD_PLCR_COUNTERS_YELLOW packet count, indicating active color changes. */ ++ e_IOC_FM_PCD_PLCR_COUNTERS_TOTAL, /**< Policer counter - counts the total number of packets passed in the Policer. */ ++ e_IOC_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH, /**< Policer counter - counts the number of packets with length mismatch. */ ++ e_IOC_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH, /**< Parser counter - counts the number of times the parser block is dispatched. */ ++ e_IOC_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED, /**< Parser counter - counts the number of times L2 parse result is returned (including errors). */ ++ e_IOC_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED, /**< Parser counter - counts the number of times L3 parse result is returned (including errors). */ ++ e_IOC_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED, /**< Parser counter - counts the number of times L4 parse result is returned (including errors). */ ++ e_IOC_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED, /**< Parser counter - counts the number of times SHIM parse result is returned (including errors). */ ++ e_IOC_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR, /**< Parser counter - counts the number of times L2 parse result is returned with errors. */ ++ e_IOC_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR, /**< Parser counter - counts the number of times L3 parse result is returned with errors. */ ++ e_IOC_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR, /**< Parser counter - counts the number of times L4 parse result is returned with errors. */ ++ e_IOC_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR, /**< Parser counter - counts the number of times SHIM parse result is returned with errors. */ ++ e_IOC_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES, /**< Parser counter - counts the number of cycles spent executing soft parser instruction (including stall cycles). */ ++ e_IOC_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES, /**< Parser counter - counts the number of cycles stalled waiting for parser internal memory reads while executing soft parser instruction. */ ++ e_IOC_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES, /**< Parser counter - counts the number of cycles spent executing hard parser (including stall cycles). */ ++ e_IOC_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES, /**< MURAM counter - counts the number of cycles while performing FMan Memory read. */ ++ e_IOC_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES, /**< MURAM counter - counts the number of cycles stalled while performing FMan Memory read. */ ++ e_IOC_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES, /**< MURAM counter - counts the number of cycles while performing FMan Memory write. */ ++ e_IOC_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES, /**< MURAM counter - counts the number of cycles stalled while performing FMan Memory write. */ ++ e_IOC_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES /**< FPM counter - counts the number of cycles stalled while performing a FPM Command. */ ++} ioc_fm_pcd_counters; ++ ++/**************************************************************************//** ++ @Description PCD interrupts ++ (must match enum e_FmPcdExceptions defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_exceptions { ++ e_IOC_FM_PCD_KG_EXCEPTION_DOUBLE_ECC, /**< KeyGen double-bit ECC error is detected on internal memory read access. */ ++ e_IOC_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW, /**< KeyGen scheme configuration error indicating a key size larger than 56 bytes. */ ++ e_IOC_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC, /**< Policer double-bit ECC error has been detected on PRAM read access. */ ++ e_IOC_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR, /**< Policer access to a non-initialized profile has been detected. */ ++ e_IOC_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE, /**< Policer RAM self-initialization complete */ ++ e_IOC_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE, /**< Policer atomic action complete */ ++ e_IOC_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC, /**< Parser double-bit ECC error */ ++ e_IOC_FM_PCD_PRS_EXCEPTION_SINGLE_ECC /**< Parser single-bit ECC error */ ++} ioc_fm_pcd_exceptions; ++ ++/** @} */ /* end of lnx_ioctl_FM_PCD_init_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group lnx_ioctl_FM_PCD_Runtime_grp FM PCD Runtime Unit ++ ++ @Description Frame Manager PCD Runtime Unit ++ ++ The runtime control allows creation of PCD infrastructure modules ++ such as Network Environment Characteristics, Classification Plan ++ Groups and Coarse Classification Trees. ++ It also allows on-the-fly initialization, modification and removal ++ of PCD modules such as KeyGen schemes, coarse classification nodes ++ and Policer profiles. ++ ++ In order to explain the programming model of the PCD driver interface ++ a few terms should be explained, and will be used below. ++ - Distinction Header - One of the 16 protocols supported by the FM parser, ++ or one of the SHIM headers (1 or 2). May be a header with a special ++ option (see below). ++ - Interchangeable Headers Group - This is a group of Headers recognized ++ by either one of them. For example, if in a specific context the user ++ chooses to treat IPv4 and IPV6 in the same way, they may create an ++ interchangeable Headers Unit consisting of these 2 headers. ++ - A Distinction Unit - a Distinction Header or an Interchangeable Headers ++ Group. ++ - Header with special option - applies to Ethernet, MPLS, VLAN, IPv4 and ++ IPv6, includes multicast, broadcast and other protocol specific options. ++ In terms of hardware it relates to the options available in the classification ++ plan. ++ - Network Environment Characteristics - a set of Distinction Units that define ++ the total recognizable header selection for a certain environment. This is ++ NOT the list of all headers that will ever appear in a flow, but rather ++ everything that needs distinction in a flow, where distinction is made by KeyGen ++ schemes and coarse classification action descriptors. ++ ++ The PCD runtime modules initialization is done in stages. The first stage after ++ initializing the PCD module itself is to establish a Network Flows Environment ++ Definition. The application may choose to establish one or more such environments. ++ Later, when needed, the application will have to state, for some of its modules, ++ to which single environment it belongs. ++ ++ @{ ++*//***************************************************************************/ ++ ++ ++/**************************************************************************//** ++ @Description structure for FM counters ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_counters_params_t { ++ ioc_fm_pcd_counters cnt; /**< The requested counter */ ++ uint32_t val; /**< The requested value to get/set from/into the counter */ ++} ioc_fm_pcd_counters_params_t; ++ ++/**************************************************************************//** ++ @Description structure for FM exception definitios ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_exception_params_t { ++ ioc_fm_pcd_exceptions exception; /**< The requested exception */ ++ bool enable; /**< TRUE to enable interrupt, FALSE to mask it. */ ++} ioc_fm_pcd_exception_params_t; ++ ++/**************************************************************************//** ++ @Description A structure for SW parser labels ++ (must be identical to struct t_FmPcdPrsLabelParams defined in fm_pcd_ext.h) ++ *//***************************************************************************/ ++typedef struct ioc_fm_pcd_prs_label_params_t { ++ uint32_t instruction_offset; /**< SW parser label instruction offset (2 bytes ++ resolution), relative to Parser RAM. */ ++ ioc_net_header_type hdr; /**< The existence of this header will invoke ++ the SW parser code. */ ++ uint8_t index_per_hdr; /**< Normally 0, if more than one SW parser ++ attachments for the same header, use this ++ index to distinguish between them. */ ++} ioc_fm_pcd_prs_label_params_t; ++ ++/**************************************************************************//** ++ @Description A structure for SW parser ++ (Must match struct t_FmPcdPrsSwParams defined in fm_pcd_ext.h) ++ *//***************************************************************************/ ++typedef struct ioc_fm_pcd_prs_sw_params_t { ++ bool override; /**< FALSE to invoke a check that nothing else ++ was loaded to this address, including ++ internal patches. ++ TRUE to override any existing code.*/ ++ uint32_t size; /**< SW parser code size */ ++ uint16_t base; /**< SW parser base (in instruction counts! ++ must be larger than 0x20)*/ ++ uint8_t *p_code; /**< SW parser code */ ++ uint32_t sw_prs_data_params[IOC_FM_PCD_PRS_NUM_OF_HDRS]; ++ /**< SW parser data (parameters) */ ++ uint8_t num_of_labels; /**< Number of labels for SW parser. */ ++ ioc_fm_pcd_prs_label_params_t labels_table[IOC_FM_PCD_PRS_NUM_OF_LABELS]; ++ /**< SW parser labels table, ++ containing num_of_labels entries */ ++} ioc_fm_pcd_prs_sw_params_t; ++ ++/**************************************************************************//** ++ @Description A structure to set the a KeyGen default value ++ *//***************************************************************************/ ++typedef struct ioc_fm_pcd_kg_dflt_value_params_t { ++ uint8_t valueId; /**< 0,1 - one of 2 global default values */ ++ uint32_t value; /**< The requested default value */ ++} ioc_fm_pcd_kg_dflt_value_params_t; ++ ++ ++/**************************************************************************//** ++ @Function FM_PCD_Enable ++ ++ @Description This routine should be called after PCD is initialized for enabling all ++ PCD engines according to their existing configuration. ++ ++ @Return 0 on success; Error code otherwise. ++ ++ @Cautions Allowed only when PCD is disabled. ++*//***************************************************************************/ ++#define FM_PCD_IOC_ENABLE _IO(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(1)) ++ ++/**************************************************************************//** ++ @Function FM_PCD_Disable ++ ++ @Description This routine may be called when PCD is enabled in order to ++ disable all PCD engines. It may be called ++ only when none of the ports in the system are using the PCD. ++ ++ @Return 0 on success; Error code otherwise. ++ ++ @Cautions Allowed only when PCD is enabled. ++*//***************************************************************************/ ++#define FM_PCD_IOC_DISABLE _IO(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(2)) ++ ++ /**************************************************************************//** ++ @Function FM_PCD_PrsLoadSw ++ ++ @Description This routine may be called only when all ports in the ++ system are actively using the classification plan scheme. ++ In such cases it is recommended in order to save resources. ++ The driver automatically saves 8 classification plans for ++ ports that do NOT use the classification plan mechanism, to ++ avoid this (in order to save those entries) this routine may ++ be called. ++ ++ @Param[in] ioc_fm_pcd_prs_sw_params_t A pointer to the image of the software parser code. ++ ++ @Return 0 on success; Error code otherwise. ++ ++ @Cautions Allowed only when PCD is disabled. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_PRS_LOAD_SW_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(3), ioc_compat_fm_pcd_prs_sw_params_t) ++#endif ++#define FM_PCD_IOC_PRS_LOAD_SW _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(3), ioc_fm_pcd_prs_sw_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgSetDfltValue ++ ++ @Description Calling this routine sets a global default value to be used ++ by the KeyGen when parser does not recognize a required ++ field/header. ++ By default default values are 0. ++ ++ @Param[in] ioc_fm_pcd_kg_dflt_value_params_t A pointer to a structure with the relevant parameters ++ ++ @Return 0 on success; Error code otherwise. ++ ++ @Cautions Allowed only when PCD is disabled. ++*//***************************************************************************/ ++#define FM_PCD_IOC_KG_SET_DFLT_VALUE _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(6), ioc_fm_pcd_kg_dflt_value_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgSetAdditionalDataAfterParsing ++ ++ @Description Calling this routine allows the keygen to access data past ++ the parser finishing point. ++ ++ @Param[in] uint8_t payload-offset; the number of bytes beyond the parser location. ++ ++ @Return 0 on success; Error code otherwise. ++ ++ @Cautions Allowed only when PCD is disabled. ++*//***************************************************************************/ ++#define FM_PCD_IOC_KG_SET_ADDITIONAL_DATA_AFTER_PARSING _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(7), uint8_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_SetException ++ ++ @Description Calling this routine enables/disables PCD interrupts. ++ ++ @Param[in] ioc_fm_pcd_exception_params_t Arguments struct with exception to be enabled/disabled. ++ ++ @Return 0 on success; Error code otherwise. ++*//***************************************************************************/ ++#define FM_PCD_IOC_SET_EXCEPTION _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(8), ioc_fm_pcd_exception_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_GetCounter ++ ++ @Description Reads one of the FM PCD counters. ++ ++ @Param[in,out] ioc_fm_pcd_counters_params_t The requested counter parameters. ++ ++ @Return 0 on success; Error code otherwise. ++ ++ @Cautions Note that it is user's responsibilty to call this routine only ++ for enabled counters, and there will be no indication if a ++ disabled counter is accessed. ++*//***************************************************************************/ ++#define FM_PCD_IOC_GET_COUNTER _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(9), ioc_fm_pcd_counters_params_t) ++ ++/**************************************************************************//** ++ ++ @Function FM_PCD_KgSchemeGetCounter ++ ++ @Description Reads scheme packet counter. ++ ++ @Param[in] h_Scheme scheme handle as returned by FM_PCD_KgSchemeSet(). ++ ++ @Return Counter's current value. ++ ++ @Cautions Allowed only following FM_PCD_Init() & FM_PCD_KgSchemeSet(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_KG_SCHEME_GET_CNTR_COMPAT _IOR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(4), ioc_compat_fm_pcd_kg_scheme_spc_t) ++#endif ++#define FM_PCD_IOC_KG_SCHEME_GET_CNTR _IOR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(4), ioc_fm_pcd_kg_scheme_spc_t) ++ ++#if 0 ++TODO: unused IOCTL ++/**************************************************************************//** ++ @Function FM_PCD_ModifyCounter ++ ++ @Description Writes a value to an enabled counter. Use "0" to reset the counter. ++ ++ @Param[in] ioc_fm_pcd_counters_params_t - The requested counter parameters. ++ ++ @Return 0 on success; Error code otherwise. ++*//***************************************************************************/ ++#define FM_PCD_IOC_MODIFY_COUNTER _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(10), ioc_fm_pcd_counters_params_t) ++#define FM_PCD_IOC_SET_COUNTER FM_PCD_IOC_MODIFY_COUNTER ++#endif ++ ++/**************************************************************************//** ++ @Function FM_PCD_ForceIntr ++ ++ @Description Causes an interrupt event on the requested source. ++ ++ @Param[in] ioc_fm_pcd_exceptions - An exception to be forced. ++ ++ @Return 0 on success; error code if the exception is not enabled, ++ or is not able to create interrupt. ++*//***************************************************************************/ ++#define FM_PCD_IOC_FORCE_INTR _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(11), ioc_fm_pcd_exceptions) ++ ++/**************************************************************************//** ++ @Collection Definitions of coarse classification parameters as required by KeyGen ++ (when coarse classification is the next engine after this scheme). ++*//***************************************************************************/ ++#define IOC_FM_PCD_MAX_NUM_OF_CC_TREES 8 ++#define IOC_FM_PCD_MAX_NUM_OF_CC_GROUPS 16 ++#define IOC_FM_PCD_MAX_NUM_OF_CC_UNITS 4 ++#define IOC_FM_PCD_MAX_NUM_OF_KEYS 256 ++#define IOC_FM_PCD_MAX_NUM_OF_FLOWS (4*KILOBYTE) ++#define IOC_FM_PCD_MAX_SIZE_OF_KEY 56 ++#define IOC_FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP 16 ++#define IOC_FM_PCD_LAST_KEY_INDEX 0xffff ++#define IOC_FM_PCD_MANIP_DSCP_VALUES 64 ++/* @} */ ++ ++/**************************************************************************//** ++ @Collection A set of definitions to allow protocol ++ special option description. ++*//***************************************************************************/ ++typedef uint32_t ioc_protocol_opt_t; /**< A general type to define a protocol option. */ ++ ++typedef ioc_protocol_opt_t ioc_eth_protocol_opt_t; /**< Ethernet protocol options. */ ++#define IOC_ETH_BROADCAST 0x80000000 /**< Ethernet Broadcast. */ ++#define IOC_ETH_MULTICAST 0x40000000 /**< Ethernet Multicast. */ ++ ++typedef ioc_protocol_opt_t ioc_vlan_protocol_opt_t; /**< Vlan protocol options. */ ++#define IOC_VLAN_STACKED 0x20000000 /**< Stacked VLAN. */ ++ ++typedef ioc_protocol_opt_t ioc_mpls_protocol_opt_t; /**< MPLS protocol options. */ ++#define IOC_MPLS_STACKED 0x10000000 /**< Stacked MPLS. */ ++ ++typedef ioc_protocol_opt_t ioc_ipv4_protocol_opt_t; /**< IPv4 protocol options. */ ++#define IOC_IPV4_BROADCAST_1 0x08000000 /**< IPv4 Broadcast. */ ++#define IOC_IPV4_MULTICAST_1 0x04000000 /**< IPv4 Multicast. */ ++#define IOC_IPV4_UNICAST_2 0x02000000 /**< Tunneled IPv4 - Unicast. */ ++#define IOC_IPV4_MULTICAST_BROADCAST_2 0x01000000 /**< Tunneled IPv4 - Broadcast/Multicast. */ ++ ++#define IOC_IPV4_FRAG_1 0x00000008 /**< IPV4 reassembly option. ++ IPV4 Reassembly manipulation requires network ++ environment with IPV4 header and IPV4_FRAG_1 option */ ++ ++typedef ioc_protocol_opt_t ioc_ipv6_protocol_opt_t; /**< IPv6 protocol options. */ ++#define IOC_IPV6_MULTICAST_1 0x00800000 /**< IPv6 Multicast. */ ++#define IOC_IPV6_UNICAST_2 0x00400000 /**< Tunneled IPv6 - Unicast. */ ++#define IOC_IPV6_MULTICAST_2 0x00200000 /**< Tunneled IPv6 - Multicast. */ ++ ++#define IOC_IPV6_FRAG_1 0x00000004 /**< IPV6 reassembly option. ++ IPV6 Reassembly manipulation requires network ++ environment with IPV6 header and IPV6_FRAG_1 option */ ++#if (DPAA_VERSION >= 11) ++typedef ioc_protocol_opt_t ioc_capwap_protocol_opt_t; /**< CAPWAP protocol options. */ ++#define CAPWAP_FRAG_1 0x00000008 /**< CAPWAP reassembly option. ++ CAPWAP Reassembly manipulation requires network ++ environment with CAPWAP header and CAPWAP_FRAG_1 option; ++ in case where fragment found, the fragment-extension offset ++ may be found at 'shim2' (in parser-result). */ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/* @} */ ++ ++#define IOC_FM_PCD_MANIP_MAX_HDR_SIZE 256 ++#define IOC_FM_PCD_MANIP_DSCP_TO_VLAN_TRANS 64 ++/**************************************************************************//** ++ @Collection A set of definitions to support Header Manipulation selection. ++*//***************************************************************************/ ++typedef uint32_t ioc_hdr_manip_flags_t; /**< A general type to define a HMan update command flags. */ ++ ++typedef ioc_hdr_manip_flags_t ioc_ipv4_hdr_manip_update_flags_t; /**< IPv4 protocol HMan update command flags. */ ++ ++#define IOC_HDR_MANIP_IPV4_TOS 0x80000000 /**< update TOS with the given value ('tos' field ++ of ioc_fm_pcd_manip_hdr_field_update_ipv4_t) */ ++#define IOC_HDR_MANIP_IPV4_ID 0x40000000 /**< update IP ID with the given value ('id' field ++ of ioc_fm_pcd_manip_hdr_field_update_ipv4_t) */ ++#define IOC_HDR_MANIP_IPV4_TTL 0x20000000 /**< Decrement TTL by 1 */ ++#define IOC_HDR_MANIP_IPV4_SRC 0x10000000 /**< update IP source address with the given value ++ ('src' field of ioc_fm_pcd_manip_hdr_field_update_ipv4_t) */ ++#define IOC_HDR_MANIP_IPV4_DST 0x08000000 /**< update IP destination address with the given value ++ ('dst' field of ioc_fm_pcd_manip_hdr_field_update_ipv4_t) */ ++ ++typedef ioc_hdr_manip_flags_t ioc_ipv6_hdr_manip_update_flags_t; /**< IPv6 protocol HMan update command flags. */ ++ ++#define IOC_HDR_MANIP_IPV6_TC 0x80000000 /**< update Traffic Class address with the given value ++ ('traffic_class' field of ioc_fm_pcd_manip_hdr_field_update_ipv6_t) */ ++#define IOC_HDR_MANIP_IPV6_HL 0x40000000 /**< Decrement Hop Limit by 1 */ ++#define IOC_HDR_MANIP_IPV6_SRC 0x20000000 /**< update IP source address with the given value ++ ('src' field of ioc_fm_pcd_manip_hdr_field_update_ipv6_t) */ ++#define IOC_HDR_MANIP_IPV6_DST 0x10000000 /**< update IP destination address with the given value ++ ('dst' field of ioc_fm_pcd_manip_hdr_field_update_ipv6_t) */ ++ ++typedef ioc_hdr_manip_flags_t ioc_tcp_udp_hdr_manip_update_flags_t;/**< TCP/UDP protocol HMan update command flags. */ ++ ++#define IOC_HDR_MANIP_TCP_UDP_SRC 0x80000000 /**< update TCP/UDP source address with the given value ++ ('src' field of ioc_fm_pcd_manip_hdr_field_update_tcp_udp_t) */ ++#define IOC_HDR_MANIP_TCP_UDP_DST 0x40000000 /**< update TCP/UDP destination address with the given value ++ ('dst' field of ioc_fm_pcd_manip_hdr_field_update_tcp_udp_t) */ ++#define IOC_HDR_MANIP_TCP_UDP_CHECKSUM 0x20000000 /**< update TCP/UDP checksum */ ++ ++/* @} */ ++ ++/**************************************************************************//** ++ @Description A type used for returning the order of the key extraction. ++ each value in this array represents the index of the extraction ++ command as defined by the user in the initialization extraction array. ++ The valid size of this array is the user define number of extractions ++ required (also marked by the second '0' in this array). ++*//***************************************************************************/ ++typedef uint8_t ioc_fm_pcd_kg_key_order_t [IOC_FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY]; ++ ++/**************************************************************************//** ++ @Description All PCD engines ++ (must match enum e_FmPcdEngine defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_engine { ++ e_IOC_FM_PCD_INVALID = 0, /**< Invalid PCD engine */ ++ e_IOC_FM_PCD_DONE, /**< No PCD Engine indicated */ ++ e_IOC_FM_PCD_KG, /**< KeyGen */ ++ e_IOC_FM_PCD_CC, /**< Coarse Classifier */ ++ e_IOC_FM_PCD_PLCR, /**< Policer */ ++ e_IOC_FM_PCD_PRS, /**< Parser */ ++#if DPAA_VERSION >= 11 ++ e_IOC_FM_PCD_FR, /**< Frame Replicator */ ++#endif /* DPAA_VERSION >= 11 */ ++ e_IOC_FM_PCD_HASH /**< Hash Table */ ++} ioc_fm_pcd_engine; ++ ++/**************************************************************************//** ++ @Description An enum for selecting extraction by header types ++ (Must match enum e_FmPcdExtractByHdrType defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_extract_by_hdr_type { ++ e_IOC_FM_PCD_EXTRACT_FROM_HDR, /**< Extract bytes from header */ ++ e_IOC_FM_PCD_EXTRACT_FROM_FIELD, /**< Extract bytes from header field */ ++ e_IOC_FM_PCD_EXTRACT_FULL_FIELD /**< Extract a full field */ ++} ioc_fm_pcd_extract_by_hdr_type; ++ ++/**************************************************************************//** ++ @Description An enum for selecting extraction source (when it is not the header) ++ (Must match enum e_FmPcdExtractFrom defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_extract_from { ++ e_IOC_FM_PCD_EXTRACT_FROM_FRAME_START, /**< KG & CC: Extract from beginning of frame */ ++ e_IOC_FM_PCD_EXTRACT_FROM_DFLT_VALUE, /**< KG only: Extract from a default value */ ++ e_IOC_FM_PCD_EXTRACT_FROM_CURR_END_OF_PARSE, /**< KG only: Extract from the point where parsing had finished */ ++ e_IOC_FM_PCD_EXTRACT_FROM_KEY, /**< CC only: Field where saved KEY */ ++ e_IOC_FM_PCD_EXTRACT_FROM_HASH, /**< CC only: Field where saved HASH */ ++ e_IOC_FM_PCD_EXTRACT_FROM_PARSE_RESULT, /**< KG & CC: Extract from the parser result */ ++ e_IOC_FM_PCD_EXTRACT_FROM_ENQ_FQID, /**< KG & CC: Extract from enqueue FQID */ ++ e_IOC_FM_PCD_EXTRACT_FROM_FLOW_ID /**< CC only: Field where saved Dequeue FQID */ ++} ioc_fm_pcd_extract_from; ++ ++/**************************************************************************//** ++ @Description An enum for selecting extraction type ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_extract_type { ++ e_IOC_FM_PCD_EXTRACT_BY_HDR, /**< Extract according to header */ ++ e_IOC_FM_PCD_EXTRACT_NON_HDR, /**< Extract from data that is not the header */ ++ e_IOC_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO /**< Extract private info as specified by user */ ++} ioc_fm_pcd_extract_type; ++ ++/**************************************************************************//** ++ @Description An enum for selecting a default ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_kg_extract_dflt_select { ++ e_IOC_FM_PCD_KG_DFLT_GBL_0, /**< Default selection is KG register 0 */ ++ e_IOC_FM_PCD_KG_DFLT_GBL_1, /**< Default selection is KG register 1 */ ++ e_IOC_FM_PCD_KG_DFLT_PRIVATE_0, /**< Default selection is a per scheme register 0 */ ++ e_IOC_FM_PCD_KG_DFLT_PRIVATE_1, /**< Default selection is a per scheme register 1 */ ++ e_IOC_FM_PCD_KG_DFLT_ILLEGAL /**< Illegal selection */ ++} ioc_fm_pcd_kg_extract_dflt_select; ++ ++/**************************************************************************//** ++ @Description Enumeration type defining all default groups - each group shares ++ a default value, one of four user-initialized values. ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_kg_known_fields_dflt_types { ++ e_IOC_FM_PCD_KG_MAC_ADDR, /**< MAC Address */ ++ e_IOC_FM_PCD_KG_TCI, /**< TCI field */ ++ e_IOC_FM_PCD_KG_ENET_TYPE, /**< ENET Type */ ++ e_IOC_FM_PCD_KG_PPP_SESSION_ID, /**< PPP Session id */ ++ e_IOC_FM_PCD_KG_PPP_PROTOCOL_ID, /**< PPP Protocol id */ ++ e_IOC_FM_PCD_KG_MPLS_LABEL, /**< MPLS label */ ++ e_IOC_FM_PCD_KG_IP_ADDR, /**< IP addr */ ++ e_IOC_FM_PCD_KG_PROTOCOL_TYPE, /**< Protocol type */ ++ e_IOC_FM_PCD_KG_IP_TOS_TC, /**< TOS or TC */ ++ e_IOC_FM_PCD_KG_IPV6_FLOW_LABEL, /**< IPV6 flow label */ ++ e_IOC_FM_PCD_KG_IPSEC_SPI, /**< IPSEC SPI */ ++ e_IOC_FM_PCD_KG_L4_PORT, /**< L4 Port */ ++ e_IOC_FM_PCD_KG_TCP_FLAG, /**< TCP Flag */ ++ e_IOC_FM_PCD_KG_GENERIC_FROM_DATA, /**< grouping implemented by SW, ++ any data extraction that is not the full ++ field described above */ ++ e_IOC_FM_PCD_KG_GENERIC_FROM_DATA_NO_V, /**< grouping implemented by SW, ++ any data extraction without validation */ ++ e_IOC_FM_PCD_KG_GENERIC_NOT_FROM_DATA /**< grouping implemented by SW, ++ extraction from parser result or ++ direct use of default value */ ++} ioc_fm_pcd_kg_known_fields_dflt_types; ++ ++/**************************************************************************//** ++ @Description Enumeration type for defining header index for scenarios with ++ multiple (tunneled) headers ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_hdr_index { ++ e_IOC_FM_PCD_HDR_INDEX_NONE = 0, /**< used when multiple headers not used, also ++ to specify regular IP (not tunneled). */ ++ e_IOC_FM_PCD_HDR_INDEX_1, /**< may be used for VLAN, MPLS, tunneled IP */ ++ e_IOC_FM_PCD_HDR_INDEX_2, /**< may be used for MPLS, tunneled IP */ ++ e_IOC_FM_PCD_HDR_INDEX_3, /**< may be used for MPLS */ ++ e_IOC_FM_PCD_HDR_INDEX_LAST = 0xFF /**< may be used for VLAN, MPLS */ ++} ioc_fm_pcd_hdr_index; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the policer profile functional type ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_profile_type_selection { ++ e_IOC_FM_PCD_PLCR_PORT_PRIVATE, /**< Port dedicated profile */ ++ e_IOC_FM_PCD_PLCR_SHARED /**< Shared profile (shared within partition) */ ++} ioc_fm_pcd_profile_type_selection; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the policer profile algorithm ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_plcr_algorithm_selection { ++ e_IOC_FM_PCD_PLCR_PASS_THROUGH, /**< Policer pass through */ ++ e_IOC_FM_PCD_PLCR_RFC_2698, /**< Policer algorithm RFC 2698 */ ++ e_IOC_FM_PCD_PLCR_RFC_4115 /**< Policer algorithm RFC 4115 */ ++} ioc_fm_pcd_plcr_algorithm_selection; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting a policer profile color mode ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_plcr_color_mode { ++ e_IOC_FM_PCD_PLCR_COLOR_BLIND, /**< Color blind */ ++ e_IOC_FM_PCD_PLCR_COLOR_AWARE /**< Color aware */ ++} ioc_fm_pcd_plcr_color_mode; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting a policer profile color ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_plcr_color { ++ e_IOC_FM_PCD_PLCR_GREEN, /**< Green */ ++ e_IOC_FM_PCD_PLCR_YELLOW, /**< Yellow */ ++ e_IOC_FM_PCD_PLCR_RED, /**< Red */ ++ e_IOC_FM_PCD_PLCR_OVERRIDE /**< Color override */ ++} ioc_fm_pcd_plcr_color; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the policer profile packet frame length selector ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_plcr_frame_length_select { ++ e_IOC_FM_PCD_PLCR_L2_FRM_LEN, /**< L2 frame length */ ++ e_IOC_FM_PCD_PLCR_L3_FRM_LEN, /**< L3 frame length */ ++ e_IOC_FM_PCD_PLCR_L4_FRM_LEN, /**< L4 frame length */ ++ e_IOC_FM_PCD_PLCR_FULL_FRM_LEN /**< Full frame length */ ++} ioc_fm_pcd_plcr_frame_length_select; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting roll-back frame ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_plcr_roll_back_frame_select { ++ e_IOC_FM_PCD_PLCR_ROLLBACK_L2_FRM_LEN, /**< Rollback L2 frame length */ ++ e_IOC_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN /**< Rollback Full frame length */ ++} ioc_fm_pcd_plcr_roll_back_frame_select; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the policer profile packet or byte mode ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_plcr_rate_mode { ++ e_IOC_FM_PCD_PLCR_BYTE_MODE, /**< Byte mode */ ++ e_IOC_FM_PCD_PLCR_PACKET_MODE /**< Packet mode */ ++} ioc_fm_pcd_plcr_rate_mode; ++ ++/**************************************************************************//** ++ @Description Enumeration type for defining action of frame ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_done_action { ++ e_IOC_FM_PCD_ENQ_FRAME = 0, /**< Enqueue frame */ ++ e_IOC_FM_PCD_DROP_FRAME /**< Drop frame */ ++} ioc_fm_pcd_done_action; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the policer counter ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_plcr_profile_counters { ++ e_IOC_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER, /**< Green packets counter */ ++ e_IOC_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER, /**< Yellow packets counter */ ++ e_IOC_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER, /**< Red packets counter */ ++ e_IOC_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER, /**< Recolored yellow packets counter */ ++ e_IOC_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER /**< Recolored red packets counter */ ++} ioc_fm_pcd_plcr_profile_counters; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting the PCD action after extraction ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_action { ++ e_IOC_FM_PCD_ACTION_NONE, /**< NONE */ ++ e_IOC_FM_PCD_ACTION_EXACT_MATCH, /**< Exact match on the selected extraction*/ ++ e_IOC_FM_PCD_ACTION_INDEXED_LOOKUP /**< Indexed lookup on the selected extraction*/ ++} ioc_fm_pcd_action; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of insert manipulation ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_hdr_insrt_type { ++ e_IOC_FM_PCD_MANIP_INSRT_GENERIC, /**< Insert according to offset & size */ ++ e_IOC_FM_PCD_MANIP_INSRT_BY_HDR, /**< Insert according to protocol */ ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++ e_IOC_FM_PCD_MANIP_INSRT_BY_TEMPLATE /**< Insert template to start of frame */ ++#endif /* FM_CAPWAP_SUPPORT */ ++} ioc_fm_pcd_manip_hdr_insrt_type; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of remove manipulation ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_hdr_rmv_type { ++ e_IOC_FM_PCD_MANIP_RMV_GENERIC, /**< Remove according to offset & size */ ++ e_IOC_FM_PCD_MANIP_RMV_BY_HDR /**< Remove according to offset & size */ ++} ioc_fm_pcd_manip_hdr_rmv_type; ++ ++/**************************************************************************//** ++ @Description An enum for selecting specific L2 fields removal ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_hdr_rmv_specific_l2 { ++ e_IOC_FM_PCD_MANIP_HDR_RMV_ETHERNET, /**< Ethernet/802.3 MAC */ ++ e_IOC_FM_PCD_MANIP_HDR_RMV_STACKED_QTAGS, /**< stacked QTags */ ++ e_IOC_FM_PCD_MANIP_HDR_RMV_ETHERNET_AND_MPLS, /**< MPLS and Ethernet/802.3 MAC header until ++ the header which follows the MPLS header */ ++ e_IOC_FM_PCD_MANIP_HDR_RMV_MPLS /**< Remove MPLS header (Unlimited MPLS labels) */ ++} ioc_fm_pcd_manip_hdr_rmv_specific_l2; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting specific fields updates ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_hdr_field_update_type { ++ e_IOC_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN, /**< VLAN updates */ ++ e_IOC_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4, /**< IPV4 updates */ ++ e_IOC_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6, /**< IPV6 updates */ ++ e_IOC_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP, /**< TCP_UDP updates */ ++} ioc_fm_pcd_manip_hdr_field_update_type; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting VLAN updates ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_hdr_field_update_vlan { ++ e_IOC_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_VPRI, /**< Replace VPri of outer most VLAN tag. */ ++ e_IOC_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN /**< DSCP to VLAN priority bits translation */ ++} ioc_fm_pcd_manip_hdr_field_update_vlan; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting specific L2 fields removal ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_hdr_insrt_specific_l2 { ++ e_IOC_FM_PCD_MANIP_HDR_INSRT_MPLS /**< Insert MPLS header (Unlimited MPLS labels) */ ++} ioc_fm_pcd_manip_hdr_insrt_specific_l2; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description Enumeration type for selecting QoS mapping mode ++ ++ Note: In all cases except 'e_FM_PCD_MANIP_HDR_QOS_MAPPING_NONE' ++ User should instruct the port to read the parser-result ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_hdr_qos_mapping_mode { ++ e_IOC_FM_PCD_MANIP_HDR_QOS_MAPPING_NONE = 0, /**< No mapping, QoS field will not be changed */ ++ e_IOC_FM_PCD_MANIP_HDR_QOS_MAPPING_AS_IS, /**< QoS field will be overwritten by the last byte in the parser-result. */ ++} ioc_fm_pcd_manip_hdr_qos_mapping_mode; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting QoS source ++ ++ Note: In all cases except 'e_FM_PCD_MANIP_HDR_QOS_SRC_NONE' ++ User should left room for the parser-result on input/output buffer ++ and instruct the port to read/write the parser-result to the buffer (RPD should be set) ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_hdr_qos_src { ++ e_IOC_FM_PCD_MANIP_HDR_QOS_SRC_NONE = 0, /**< TODO */ ++ e_IOC_FM_PCD_MANIP_HDR_QOS_SRC_USER_DEFINED, /**< QoS will be taken from the last byte in the parser-result. */ ++} ioc_fm_pcd_manip_hdr_qos_src; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of header insertion ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_hdr_insrt_by_hdr_type { ++ e_IOC_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2, /**< Specific L2 fields insertion */ ++#if (DPAA_VERSION >= 11) ++ e_IOC_FM_PCD_MANIP_INSRT_BY_HDR_IP, /**< IP insertion */ ++ e_IOC_FM_PCD_MANIP_INSRT_BY_HDR_UDP, /**< UDP insertion */ ++ e_IOC_FM_PCD_MANIP_INSRT_BY_HDR_UDP_LITE, /**< UDP lite insertion */ ++ e_IOC_FM_PCD_MANIP_INSRT_BY_HDR_CAPWAP /**< CAPWAP insertion */ ++#endif /* (DPAA_VERSION >= 11) */ ++} ioc_fm_pcd_manip_hdr_insrt_by_hdr_type; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting specific custom command ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_hdr_custom_type { ++ e_IOC_FM_PCD_MANIP_HDR_CUSTOM_IP_REPLACE, /**< Replace IPv4/IPv6 */ ++} ioc_fm_pcd_manip_hdr_custom_type; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting specific custom command ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_hdr_custom_ip_replace { ++ e_IOC_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV4_BY_IPV6, /**< Replace IPv4 by IPv6 */ ++ e_IOC_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4 /**< Replace IPv6 by IPv4 */ ++} ioc_fm_pcd_manip_hdr_custom_ip_replace; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of header removal ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_hdr_rmv_by_hdr_type { ++ e_IOC_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2 = 0, /**< Specific L2 fields removal */ ++#if (DPAA_VERSION >= 11) ++ e_IOC_FM_PCD_MANIP_RMV_BY_HDR_CAPWAP, /**< CAPWAP removal */ ++#endif /* (DPAA_VERSION >= 11) */ ++#if (DPAA_VERSION >= 11) || ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++ e_IOC_FM_PCD_MANIP_RMV_BY_HDR_FROM_START, /**< Locate from data that is not the header */ ++#endif /* (DPAA_VERSION >= 11) || ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) */ ++} ioc_fm_pcd_manip_hdr_rmv_by_hdr_type; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of timeout mode ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_reassem_time_out_mode { ++ e_IOC_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAMES, /**< Limits the time of the reassembly process ++ from the first fragment to the last */ ++ e_IOC_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAG /**< Limits the time of receiving the fragment */ ++} ioc_fm_pcd_manip_reassem_time_out_mode; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of WaysNumber mode ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_reassem_ways_number { ++ e_IOC_FM_PCD_MANIP_ONE_WAY_HASH = 1, /**< One way hash */ ++ e_IOC_FM_PCD_MANIP_TWO_WAYS_HASH, /**< Two ways hash */ ++ e_IOC_FM_PCD_MANIP_THREE_WAYS_HASH, /**< Three ways hash */ ++ e_IOC_FM_PCD_MANIP_FOUR_WAYS_HASH, /**< Four ways hash */ ++ e_IOC_FM_PCD_MANIP_FIVE_WAYS_HASH, /**< Five ways hash */ ++ e_IOC_FM_PCD_MANIP_SIX_WAYS_HASH, /**< Six ways hash */ ++ e_IOC_FM_PCD_MANIP_SEVEN_WAYS_HASH, /**< Seven ways hash */ ++ e_IOC_FM_PCD_MANIP_EIGHT_WAYS_HASH /**< Eight ways hash */ ++} ioc_fm_pcd_manip_reassem_ways_number; ++ ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of statistics mode ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_stats { ++ e_IOC_FM_PCD_STATS_PER_FLOWID = 0 /**< Flow ID is used as index for getting statistics */ ++} ioc_fm_pcd_stats; ++#endif ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting manipulation type ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_type { ++ e_IOC_FM_PCD_MANIP_HDR = 0, /**< Header manipulation */ ++ e_IOC_FM_PCD_MANIP_REASSEM, /**< Reassembly */ ++ e_IOC_FM_PCD_MANIP_FRAG, /**< Fragmentation */ ++ e_IOC_FM_PCD_MANIP_SPECIAL_OFFLOAD /**< Special Offloading */ ++} ioc_fm_pcd_manip_type; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of statistics mode ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_cc_stats_mode { ++ e_IOC_FM_PCD_CC_STATS_MODE_NONE = 0, /**< No statistics support */ ++ e_IOC_FM_PCD_CC_STATS_MODE_FRAME, /**< Frame count statistics */ ++ e_IOC_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME, /**< Byte and frame count statistics */ ++#if (DPAA_VERSION >= 11) ++ e_IOC_FM_PCD_CC_STATS_MODE_RMON, /**< Byte and frame length range count statistics */ ++#endif /* (DPAA_VERSION >= 11) */ ++} ioc_fm_pcd_cc_stats_mode; ++ ++/**************************************************************************//** ++ @Description Enumeration type for determining the action in case an IP packet ++ is larger than MTU but its DF (Don't Fragment) bit is set. ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_dont_frag_action { ++ e_IOC_FM_PCD_MANIP_DISCARD_PACKET = 0, /**< Discard packet */ ++ e_IOC_FM_PCD_MANIP_ENQ_TO_ERR_Q_OR_DISCARD_PACKET = e_IOC_FM_PCD_MANIP_DISCARD_PACKET, ++ /**< Obsolete, cannot enqueue to error queue; ++ In practice, selects to discard packets; ++ Will be removed in the future */ ++ e_IOC_FM_PCD_MANIP_FRAGMENT_PACKECT, /**< Fragment packet and continue normal processing */ ++ e_IOC_FM_PCD_MANIP_CONTINUE_WITHOUT_FRAG /**< Continue normal processing without fragmenting the packet */ ++} ioc_fm_pcd_manip_dont_frag_action; ++ ++/**************************************************************************//** ++ @Description Enumeration type for selecting type of special offload manipulation ++*//***************************************************************************/ ++typedef enum ioc_fm_pcd_manip_special_offload_type { ++ e_IOC_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC, /**< IPSec offload manipulation */ ++#if (DPAA_VERSION >= 11) ++ e_IOC_FM_PCD_MANIP_SPECIAL_OFFLOAD_CAPWAP /**< CAPWAP offload manipulation */ ++#endif /* (DPAA_VERSION >= 11) */ ++} ioc_fm_pcd_manip_special_offload_type; ++ ++/**************************************************************************//** ++ @Description A union of protocol dependent special options ++ (Must match union u_FmPcdHdrProtocolOpt defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef union ioc_fm_pcd_hdr_protocol_opt_u { ++ ioc_eth_protocol_opt_t eth_opt; /**< Ethernet options */ ++ ioc_vlan_protocol_opt_t vlan_opt; /**< Vlan options */ ++ ioc_mpls_protocol_opt_t mpls_opt; /**< MPLS options */ ++ ioc_ipv4_protocol_opt_t ipv4_opt; /**< IPv4 options */ ++ ioc_ipv6_protocol_opt_t ipv6_opt; /**< IPv6 options */ ++#if (DPAA_VERSION >= 11) ++ ioc_capwap_protocol_opt_t capwap_opt; /**< CAPWAP options */ ++#endif /* (DPAA_VERSION >= 11) */ ++} ioc_fm_pcd_hdr_protocol_opt_u; ++ ++/**************************************************************************//** ++ @Description A union holding all known protocol fields ++*//***************************************************************************/ ++typedef union ioc_fm_pcd_fields_u { ++ ioc_header_field_eth_t eth; /**< Ethernet */ ++ ioc_header_field_vlan_t vlan; /**< VLAN */ ++ ioc_header_field_llc_snap_t llc_snap; /**< LLC SNAP */ ++ ioc_header_field_pppoe_t pppoe; /**< PPPoE */ ++ ioc_header_field_mpls_t mpls; /**< MPLS */ ++ ioc_header_field_ip_t ip; /**< IP */ ++ ioc_header_field_ipv4_t ipv4; /**< IPv4 */ ++ ioc_header_field_ipv6_t ipv6; /**< IPv6 */ ++ ioc_header_field_udp_t udp; /**< UDP */ ++ ioc_header_field_udp_lite_t udp_lite; /**< UDP_Lite */ ++ ioc_header_field_tcp_t tcp; /**< TCP */ ++ ioc_header_field_sctp_t sctp; /**< SCTP */ ++ ioc_header_field_dccp_t dccp; /**< DCCP */ ++ ioc_header_field_gre_t gre; /**< GRE */ ++ ioc_header_field_minencap_t minencap; /**< Minimal Encapsulation */ ++ ioc_header_field_ipsec_ah_t ipsec_ah; /**< IPSec AH */ ++ ioc_header_field_ipsec_esp_t ipsec_esp; /**< IPSec ESP */ ++ ioc_header_field_udp_encap_esp_t udp_encap_esp; /**< UDP Encapsulation ESP */ ++} ioc_fm_pcd_fields_u; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header extraction for key generation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_from_hdr_t { ++ uint8_t size; /**< Size in byte */ ++ uint8_t offset; /**< Byte offset */ ++} ioc_fm_pcd_from_hdr_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining field extraction for key generation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_from_field_t { ++ ioc_fm_pcd_fields_u field; /**< Field selection */ ++ uint8_t size; /**< Size in byte */ ++ uint8_t offset; /**< Byte offset */ ++} ioc_fm_pcd_from_field_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a single network environment unit ++ A distinction unit should be defined if it will later be used ++ by one or more PCD engines to distinguish between flows. ++ (Must match struct t_FmPcdDistinctionUnit defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_distinction_unit_t { ++ struct { ++ ioc_net_header_type hdr; /**< One of the headers supported by the FM */ ++ ioc_fm_pcd_hdr_protocol_opt_u opt; /**< Select only one option! */ ++ } hdrs[IOC_FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS]; ++} ioc_fm_pcd_distinction_unit_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining all different distinction units supported ++ by a specific PCD Network Environment Characteristics module. ++ ++ Each unit represent a protocol or a group of protocols that may ++ be used later by the different PCD engines to distinguish between flows. ++ (Must match struct t_FmPcdNetEnvParams defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_net_env_params_t { ++ uint8_t num_of_distinction_units;/**< Number of different units to be identified */ ++ ioc_fm_pcd_distinction_unit_t units[IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; ++ /**< An array of num_of_distinction_units of the ++ different units to be identified */ ++ void *id; /**< Output parameter; Returns the net-env Id to be used */ ++} ioc_fm_pcd_net_env_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a single extraction action when ++ creating a key ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_extract_entry_t { ++ ioc_fm_pcd_extract_type type; /**< Extraction type select */ ++ union { ++ struct { ++ ioc_net_header_type hdr; /**< Header selection */ ++ bool ignore_protocol_validation; ++ /**< Ignore protocol validation */ ++ ioc_fm_pcd_hdr_index hdr_index; /**< Relevant only for MPLS, VLAN and tunneled ++ IP. Otherwise should be cleared.*/ ++ ioc_fm_pcd_extract_by_hdr_type type; /**< Header extraction type select */ ++ union { ++ ioc_fm_pcd_from_hdr_t from_hdr; /**< Extract bytes from header parameters */ ++ ioc_fm_pcd_from_field_t from_field; /**< Extract bytes from field parameters */ ++ ioc_fm_pcd_fields_u full_field; /**< Extract full field parameters */ ++ } extract_by_hdr_type; ++ } extract_by_hdr; /**< Used when type = e_IOC_FM_PCD_KG_EXTRACT_BY_HDR */ ++ struct { ++ ioc_fm_pcd_extract_from src; /**< Non-header extraction source */ ++ ioc_fm_pcd_action action; /**< Relevant for CC Only */ ++ uint16_t ic_indx_mask; /**< Relevant only for CC when ++ action = e_IOC_FM_PCD_ACTION_INDEXED_LOOKUP; ++ Note that the number of bits that are set within ++ this mask must be log2 of the CC-node 'num_of_keys'. ++ Note that the mask cannot be set on the lower bits. */ ++ uint8_t offset; /**< Byte offset */ ++ uint8_t size; /**< Size in bytes */ ++ } extract_non_hdr; /**< Used when type = e_IOC_FM_PCD_KG_EXTRACT_NON_HDR */ ++ } extract_params; ++} ioc_fm_pcd_extract_entry_t; ++ ++/**************************************************************************//** ++ @Description A structure for defining masks for each extracted ++ field in the key. ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_kg_extract_mask_t { ++ uint8_t extract_array_index; /**< Index in the extraction array, as initialized by user */ ++ uint8_t offset; /**< Byte offset */ ++ uint8_t mask; /**< A byte mask (selected bits will be ignored) */ ++} ioc_fm_pcd_kg_extract_mask_t; ++ ++/**************************************************************************//** ++ @Description A structure for defining default selection per groups ++ of fields ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_kg_extract_dflt_t { ++ ioc_fm_pcd_kg_known_fields_dflt_types type; /**< Default type select*/ ++ ioc_fm_pcd_kg_extract_dflt_select dflt_select; /**< Default register select */ ++} ioc_fm_pcd_kg_extract_dflt_t; ++ ++ ++/**************************************************************************//** ++ @Description A structure for defining all parameters needed for ++ generation a key and using a hash function ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_kg_key_extract_and_hash_params_t { ++ uint32_t private_dflt0; /**< Scheme default register 0 */ ++ uint32_t private_dflt1; /**< Scheme default register 1 */ ++ uint8_t num_of_used_extracts; /**< defines the valid size of the following array */ ++ ioc_fm_pcd_extract_entry_t extract_array [IOC_FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY]; ++ /**< An array of extraction definitions. */ ++ uint8_t num_of_used_dflts; /**< defines the valid size of the following array */ ++ ioc_fm_pcd_kg_extract_dflt_t dflts[IOC_FM_PCD_KG_NUM_OF_DEFAULT_GROUPS]; ++ /**< For each extraction used in this scheme, specify the required ++ default register to be used when header is not found. ++ types not specified in this array will get undefined value. */ ++ uint8_t num_of_used_masks; /**< Defines the valid size of the following array */ ++ ioc_fm_pcd_kg_extract_mask_t masks[IOC_FM_PCD_KG_NUM_OF_EXTRACT_MASKS]; ++ uint8_t hash_shift; /**< Hash result right shift. ++ Selects the 24 bits out of the 64 hash result. ++ 0 means using the 24 LSB's, otherwise use the ++ 24 LSB's after shifting right.*/ ++ uint32_t hash_distribution_num_of_fqids; /**< must be > 1 and a power of 2. Represents the range ++ of queues for the key and hash functionality */ ++ uint8_t hash_distribution_fqids_shift; /**< selects the FQID bits that will be effected by the hash */ ++ bool symmetric_hash; /**< TRUE to generate the same hash for frames with swapped source and ++ destination fields on all layers; If TRUE, driver will check that for ++ all layers, if SRC extraction is selected, DST extraction must also be ++ selected, and vice versa. */ ++} ioc_fm_pcd_kg_key_extract_and_hash_params_t; ++ ++/**************************************************************************//** ++ @Description A structure of parameters for defining a single ++ Qid mask (extracted OR). ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_kg_extracted_or_params_t { ++ ioc_fm_pcd_extract_type type; /**< Extraction type select */ ++ union { ++ struct { /**< used when type = e_IOC_FM_PCD_KG_EXTRACT_BY_HDR */ ++ ioc_net_header_type hdr; ++ ioc_fm_pcd_hdr_index hdr_index; /**< Relevant only for MPLS, VLAN and tunneled ++ IP. Otherwise should be cleared.*/ ++ bool ignore_protocol_validation; ++ ++ } extract_by_hdr; ++ ioc_fm_pcd_extract_from src; /**< used when type = e_IOC_FM_PCD_KG_EXTRACT_NON_HDR */ ++ } extract_params; ++ uint8_t extraction_offset; /**< Offset for extraction */ ++ ioc_fm_pcd_kg_extract_dflt_select dflt_value; /**< Select register from which extraction is taken if ++ field not found */ ++ uint8_t mask; /**< Mask LSB byte of extraction (specified bits are ignored) */ ++ uint8_t bit_offset_in_fqid; /**< 0-31, Selects which bits of the 24 FQID bits to effect using ++ the extracted byte; Assume byte is placed as the 8 MSB's in ++ a 32 bit word where the lower bits ++ are the FQID; i.e if bitOffsetInFqid=1 than its LSB ++ will effect the FQID MSB, if bitOffsetInFqid=24 than the ++ extracted byte will effect the 8 LSB's of the FQID, ++ if bitOffsetInFqid=31 than the byte's MSB will effect ++ the FQID's LSB; 0 means - no effect on FQID; ++ Note that one, and only one of ++ bitOffsetInFqid or bitOffsetInPlcrProfile must be set (i.e, ++ extracted byte must effect either FQID or Policer profile).*/ ++ uint8_t bit_offset_in_plcr_profile; ++ /**< 0-15, Selects which bits of the 8 policer profile id bits to ++ effect using the extracted byte; Assume byte is placed ++ as the 8 MSB's in a 16 bit word where the lower bits ++ are the policer profile id; i.e if bitOffsetInPlcrProfile=1 ++ than its LSB will effect the profile MSB, if bitOffsetInFqid=8 ++ than the extracted byte will effect the whole policer profile id, ++ if bitOffsetInFqid=15 than the byte's MSB will effect ++ the Policer Profile id's LSB; ++ 0 means - no effect on policer profile; Note that one, and only one of ++ bitOffsetInFqid or bitOffsetInPlcrProfile must be set (i.e, ++ extracted byte must effect either FQID or Policer profile).*/ ++} ioc_fm_pcd_kg_extracted_or_params_t; ++ ++/**************************************************************************//** ++ @Description A structure for configuring scheme counter ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_kg_scheme_counter_t { ++ bool update; /**< FALSE to keep the current counter state ++ and continue from that point, TRUE to update/reset ++ the counter when the scheme is written. */ ++ uint32_t value; /**< If update=TRUE, this value will be written into the ++ counter; clear this field to reset the counter. */ ++} ioc_fm_pcd_kg_scheme_counter_t; ++ ++ ++/**************************************************************************//** ++ @Description A structure for retrieving FMKG_SE_SPC ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_kg_scheme_spc_t { ++ uint32_t val; /**< return value */ ++ void *id; /**< scheme handle */ ++} ioc_fm_pcd_kg_scheme_spc_t; ++ ++/**************************************************************************//** ++ @Description A structure for defining policer profile parameters as required by keygen ++ (when policer is the next engine after this scheme). ++ (Must match struct t_FmPcdKgPlcrProfile defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_kg_plcr_profile_t { ++ bool shared_profile; /**< TRUE if this profile is shared between ports ++ (i.e. managed by master partition) May not be TRUE ++ if profile is after Coarse Classification*/ ++ bool direct; /**< If TRUE, direct_relative_profile_id only selects the profile ++ id, if FALSE fqid_offset_relative_profile_id_base is used ++ together with fqid_offset_shift and num_of_profiles ++ parameters, to define a range of profiles from ++ which the KeyGen result will determine the ++ destination policer profile. */ ++ union { ++ uint16_t direct_relative_profile_id; /**< Used if 'direct' is TRUE, to select policer profile. ++ This parameter should indicate the policer profile offset within the port's ++ policer profiles or SHARED window. */ ++ struct { ++ uint8_t fqid_offset_shift; /**< Shift of KG results without the qid base */ ++ uint8_t fqid_offset_relative_profile_id_base; ++ /**< OR of KG results without the qid base ++ This parameter should indicate the policer profile ++ offset within the port's policer profiles window ++ or SHARED window depends on shared_profile */ ++ uint8_t num_of_profiles; /**< Range of profiles starting at base */ ++ } indirect_profile; /**< Indirect profile parameters */ ++ } profile_select; /**< Direct/indirect profile selection and parameters */ ++} ioc_fm_pcd_kg_plcr_profile_t; ++ ++#if DPAA_VERSION >= 11 ++/**************************************************************************//** ++ @Description Parameters for configuring a storage profile for a KeyGen scheme. ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_kg_storage_profile_t { ++ bool direct; /**< If TRUE, directRelativeProfileId only selects the ++ profile id; ++ If FALSE, fqidOffsetRelativeProfileIdBase is used ++ together with fqidOffsetShift and numOfProfiles ++ parameters to define a range of profiles from which ++ the KeyGen result will determine the destination ++ storage profile. */ ++ union { ++ uint16_t direct_relative_profileId; /**< Used when 'direct' is TRUE, to select a storage profile; ++ should indicate the storage profile offset within the ++ port's storage profiles window. */ ++ struct { ++ uint8_t fqid_offset_shift; /**< Shift of KeyGen results without the FQID base */ ++ uint8_t fqid_offset_relative_profile_id_base; ++ /**< OR of KeyGen results without the FQID base; ++ should indicate the policer profile offset within the ++ port's storage profiles window. */ ++ uint8_t num_of_profiles; /**< Range of profiles starting at base. */ ++ } indirect_profile; /**< Indirect profile parameters. */ ++ } profile_select; /**< Direct/indirect profile selection and parameters. */ ++} ioc_fm_pcd_kg_storage_profile_t; ++#endif /* DPAA_VERSION >= 11 */ ++ ++/**************************************************************************//** ++ @Description Parameters for defining CC as the next engine after KeyGen ++ (Must match struct t_FmPcdKgCc defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_kg_cc_t { ++ void *tree_id; /**< CC Tree id */ ++ uint8_t grp_id; /**< CC group id within the CC tree */ ++ bool plcr_next; /**< TRUE if after CC, in case of data frame, ++ policing is required. */ ++ bool bypass_plcr_profile_generation; ++ /**< TRUE to bypass KeyGen policer profile generation; ++ selected profile is the one set at port initialization. */ ++ ioc_fm_pcd_kg_plcr_profile_t plcr_profile; /**< Valid only if plcr_next = TRUE and ++ bypass_plcr_profile_generation = FALSE */ ++} ioc_fm_pcd_kg_cc_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining initializing a KeyGen scheme ++ (Must match struct t_FmPcdKgSchemeParams defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_kg_scheme_params_t { ++ bool modify; /**< TRUE to change an existing scheme */ ++ union { ++ uint8_t relative_scheme_id; ++ /**< if modify=FALSE: partition-relative scheme id */ ++ void *scheme_id; /**< if modify=TRUE: the id of an existing scheme */ ++ } scm_id; ++ bool always_direct; /**< This scheme is reached only directly, i.e. no need ++ for match vector; KeyGen will ignore it when matching */ ++ struct { /**< HL relevant only if always_direct=FALSE */ ++ void *net_env_id; /**< The id of the Network Environment as returned ++ by FM_PCD_NetEnvCharacteristicsSet() */ ++ uint8_t num_of_distinction_units; ++ /**< Number of NetEnv units listed in unit_ids array */ ++ uint8_t unit_ids[IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; ++ /**< Indexes as passed to SetNetEnvCharacteristics (?) array */ ++ } net_env_params; ++ bool use_hash; /**< use the KG Hash functionality */ ++ ioc_fm_pcd_kg_key_extract_and_hash_params_t key_extract_and_hash_params; ++ /**< used only if useHash = TRUE */ ++ bool bypass_fqid_generation; ++ /**< Normally - FALSE, TRUE to avoid FQID update in the IC; ++ In such a case FQID after KG will be the default FQID ++ defined for the relevant port, or the FQID defined by CC ++ in cases where CC was the previous engine. */ ++ uint32_t base_fqid; /**< Base FQID; Relevant only if bypass_fqid_generation = FALSE; ++ If hash is used and an even distribution is expected ++ according to hash_distribution_num_of_fqids, base_fqid must be aligned to ++ hash_distribution_num_of_fqids. */ ++ uint8_t num_of_used_extracted_ors; ++ /**< Number of FQID masks listed in extracted_ors array*/ ++ ioc_fm_pcd_kg_extracted_or_params_t extracted_ors[IOC_FM_PCD_KG_NUM_OF_GENERIC_REGS]; ++ /**< IOC_FM_PCD_KG_NUM_OF_GENERIC_REGS ++ registers are shared between qid_masks ++ functionality and some of the extraction ++ actions; Normally only some will be used ++ for qid_mask. Driver will return error if ++ resource is full at initialization time. */ ++#if DPAA_VERSION >= 11 ++ bool override_storage_profile; ++ /**< TRUE if KeyGen override previously decided storage profile */ ++ ioc_fm_pcd_kg_storage_profile_t storage_profile;/**< Used when override_storage_profile=TRUE */ ++#endif /* DPAA_VERSION >= 11 */ ++ ioc_fm_pcd_engine next_engine; /**< may be BMI, PLCR or CC */ ++ union { /**< depends on nextEngine */ ++ ioc_fm_pcd_done_action done_action; /**< Used when next engine is BMI (done) */ ++ ioc_fm_pcd_kg_plcr_profile_t plcr_profile; /**< Used when next engine is PLCR */ ++ ioc_fm_pcd_kg_cc_t cc; /**< Used when next engine is CC */ ++ } kg_next_engine_params; ++ ioc_fm_pcd_kg_scheme_counter_t scheme_counter; /**< A structure of parameters for updating ++ the scheme counter */ ++ void *id; /**< Returns the scheme Id to be used */ ++} ioc_fm_pcd_kg_scheme_params_t; ++ ++/**************************************************************************//** ++ @Collection ++*//***************************************************************************/ ++#if DPAA_VERSION >= 11 ++#define IOC_FM_PCD_CC_STATS_MAX_NUM_OF_FLR 10 /* Maximal supported number of frame length ranges */ ++#define IOC_FM_PCD_CC_STATS_FLR_SIZE 2 /* Size in bytes of a frame length range limit */ ++#endif /* DPAA_VERSION >= 11 */ ++#define IOC_FM_PCD_CC_STATS_FLR_COUNT_SIZE 4 /* Size in bytes of a frame length range counter */ ++/* @} */ ++ ++/**************************************************************************//** ++ @Description Parameters for defining CC as the next engine after a CC node. ++ (Must match struct t_FmPcdCcNextCcParams defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_cc_next_cc_params_t { ++ void *cc_node_id; /**< Id of the next CC node */ ++} ioc_fm_pcd_cc_next_cc_params_t; ++ ++#if DPAA_VERSION >= 11 ++/**************************************************************************//** ++ @Description A structure for defining Frame Replicator as the next engine after a CC node. ++ (Must match struct t_FmPcdCcNextFrParams defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_cc_next_fr_params_t { ++ void* frm_replic_id; /**< The id of the next frame replicator group */ ++} ioc_fm_pcd_cc_next_fr_params_t; ++#endif /* DPAA_VERSION >= 11 */ ++ ++/**************************************************************************//** ++ @Description A structure for defining PLCR params when PLCR is the ++ next engine after a CC node ++ (Must match struct t_FmPcdCcNextPlcrParams defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_cc_next_plcr_params_t { ++ bool override_params; /**< TRUE if CC override previously decided parameters*/ ++ bool shared_profile; /**< Relevant only if overrideParams=TRUE: ++ TRUE if this profile is shared between ports */ ++ uint16_t new_relative_profile_id; /**< Relevant only if overrideParams=TRUE: ++ (otherwise profile id is taken from keygen); ++ This parameter should indicate the policer ++ profile offset within the port's ++ policer profiles or from SHARED window.*/ ++ uint32_t new_fqid; /**< Relevant only if overrideParams=TRUE: ++ FQID for enquing the frame; ++ In earlier chips if policer next engine is KEYGEN, ++ this parameter can be 0, because the KEYGEN always decides ++ the enqueue FQID.*/ ++#if DPAA_VERSION >= 11 ++ uint8_t new_relative_storage_profile_id; ++ /**< Indicates the relative storage profile offset within ++ the port's storage profiles window; ++ Relevant only if the port was configured with VSP. */ ++#endif /* DPAA_VERSION >= 11 */ ++} ioc_fm_pcd_cc_next_plcr_params_t; ++ ++/**************************************************************************//** ++ @Description A structure for defining enqueue params when BMI is the ++ next engine after a CC node ++ (Must match struct t_FmPcdCcNextEnqueueParams defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_cc_next_enqueue_params_t { ++ ioc_fm_pcd_done_action action; /**< Action - when next engine is BMI (done) */ ++ bool override_fqid; /**< TRUE if CC override previously decided fqid and vspid, ++ relevant if action = e_IOC_FM_PCD_ENQ_FRAME */ ++ uint32_t new_fqid; /**< Valid if overrideFqid=TRUE, FQID for enqueuing the frame ++ (otherwise FQID is taken from KeyGen), ++ relevant if action = e_IOC_FM_PCD_ENQ_FRAME*/ ++#if DPAA_VERSION >= 11 ++ uint8_t new_relative_storage_profile_id; ++ /**< Valid if override_fqid=TRUE, Indicates the relative virtual ++ storage profile offset within the port's storage profiles ++ window; Relevant only if the port was configured with VSP. */ ++#endif /* DPAA_VERSION >= 11 */ ++ ++} ioc_fm_pcd_cc_next_enqueue_params_t; ++ ++/**************************************************************************//** ++ @Description A structure for defining KG params when KG is the next engine after a CC node ++ (Must match struct t_FmPcdCcNextKgParams defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_cc_next_kg_params_t { ++ bool override_fqid; /**< TRUE if CC override previously decided fqid and vspid, ++ Note - this parameters are irrelevant for earlier chips */ ++ uint32_t new_fqid; /**< Valid if overrideFqid=TRUE, FQID for enqueuing the frame ++ (otherwise FQID is taken from KeyGen), ++ Note - this parameters are irrelevant for earlier chips */ ++#if DPAA_VERSION >= 11 ++ uint8_t new_relative_storage_profile_id; ++ /**< Valid if override_fqid=TRUE, Indicates the relative virtual ++ storage profile offset within the port's storage profiles ++ window; Relevant only if the port was configured with VSP. */ ++#endif /* DPAA_VERSION >= 11 */ ++ void *p_direct_scheme; /**< Direct scheme id to go to. */ ++} ioc_fm_pcd_cc_next_kg_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining the next engine after a CC node. ++ (Must match struct t_FmPcdCcNextEngineParams defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_cc_next_engine_params_t { ++ ioc_fm_pcd_engine next_engine; /**< User has to initialize parameters ++ according to nextEngine definition */ ++ union { ++ ioc_fm_pcd_cc_next_cc_params_t cc_params; /**< Parameters in case next engine is CC */ ++ ioc_fm_pcd_cc_next_plcr_params_t plcr_params; /**< Parameters in case next engine is PLCR */ ++ ioc_fm_pcd_cc_next_enqueue_params_t enqueue_params; /**< Parameters in case next engine is BMI */ ++ ioc_fm_pcd_cc_next_kg_params_t kg_params; /**< Parameters in case next engine is KG */ ++#if DPAA_VERSION >= 11 ++ ioc_fm_pcd_cc_next_fr_params_t fr_params; /**< Parameters in case next engine is FR */ ++#endif /* DPAA_VERSION >= 11 */ ++ } params; /**< Union used for all the next-engine parameters options */ ++ void *manip_id; /**< Handle to Manipulation object. ++ Relevant if next engine is of type result ++ (e_IOC_FM_PCD_PLCR, e_IOC_FM_PCD_KG, e_IOC_FM_PCD_DONE) */ ++ bool statistics_en; /**< If TRUE, statistics counters are incremented ++ for each frame passing through this ++ Coarse Classification entry. */ ++} ioc_fm_pcd_cc_next_engine_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a single CC key ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_cc_key_params_t { ++ uint8_t *p_key; /**< pointer to the key of the size defined in key_size */ ++ uint8_t *p_mask; /**< pointer to the Mask per key of the size defined ++ in keySize. p_key and p_mask (if defined) has to be ++ of the same size defined in the key_size */ ++ ioc_fm_pcd_cc_next_engine_params_t cc_next_engine_params; ++ /**< parameters for the next for the defined Key in p_key */ ++ ++} ioc_fm_pcd_cc_key_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining CC keys parameters ++ The driver supports two methods for CC node allocation: dynamic and static. ++ Static mode was created in order to prevent runtime alloc/free ++ of FMan memory (MURAM), which may cause fragmentation; in this mode, ++ the driver automatically allocates the memory according to ++ 'max_num_of_keys' parameter. The driver calculates the maximal memory ++ size that may be used for this CC-Node taking into consideration ++ 'mask_support' and 'statistics_mode' parameters. ++ When 'action' = e_IOC_FM_PCD_ACTION_INDEXED_LOOKUP in the extraction ++ parameters of this node, 'max_num_of_keys' must be equal to 'num_of_keys'. ++ In dynamic mode, 'max_num_of_keys' must be zero. At initialization, ++ all required structures are allocated according to 'num_of_keys' ++ parameter. During runtime modification, these structures are ++ re-allocated according to the updated number of keys. ++ ++ Please note that 'action' and 'ic_indx_mask' mentioned in the ++ specific parameter explanations are passed in the extraction ++ parameters of the node (fields of extractccparams.extractnonhdr). ++*//***************************************************************************/ ++typedef struct ioc_keys_params_t { ++ uint16_t max_num_of_keys;/**< Maximum number of keys that will (ever) be used in this CC-Node; ++ A value of zero may be used for dynamic memory allocation. */ ++ bool mask_support; /**< This parameter is relevant only if a node is initialized with ++ action = e_IOC_FM_PCD_ACTION_EXACT_MATCH and max_num_of_keys > 0; ++ Should be TRUE to reserve table memory for key masks, even if ++ initial keys do not contain masks, or if the node was initialized ++ as 'empty' (without keys); this will allow user to add keys with ++ masks at runtime. */ ++ ioc_fm_pcd_cc_stats_mode statistics_mode;/**< Determines the supported statistics mode for all node's keys. ++ To enable statistics gathering, statistics should be enabled per ++ every key, using 'statistics_en' in next engine parameters structure ++ of that key; ++ If 'max_num_of_keys' is set, all required structures will be ++ preallocated for all keys. */ ++#if (DPAA_VERSION >= 11) ++ uint16_t frame_length_ranges[IOC_FM_PCD_CC_STATS_MAX_NUM_OF_FLR]; ++ /**< Relevant only for 'RMON' statistics mode ++ (this feature is supported only on B4860 device); ++ Holds a list of programmable thresholds. For each received frame, ++ its length in bytes is examined against these range thresholds and ++ the appropriate counter is incremented by 1. For example, to belong ++ to range i, the following should hold: ++ range i-1 threshold < frame length <= range i threshold ++ Each range threshold must be larger then its preceding range ++ threshold. Last range threshold must be 0xFFFF. */ ++#endif /* (DPAA_VERSION >= 11) */ ++ uint16_t num_of_keys; /**< Number of initial keys; ++ Note that in case of 'action' = e_IOC_FM_PCD_ACTION_INDEXED_LOOKUP, ++ this field should be power-of-2 of the number of bits that are ++ set in 'ic_indx_mask'. */ ++ uint8_t key_size; /**< Size of key - for extraction of type FULL_FIELD, 'key_size' has ++ to be the standard size of the selected key; For other extraction ++ types, 'key_size' has to be as size of extraction; When 'action' = ++ e_IOC_FM_PCD_ACTION_INDEXED_LOOKUP, 'keySize' must be 2. */ ++ ioc_fm_pcd_cc_key_params_t key_params[IOC_FM_PCD_MAX_NUM_OF_KEYS]; ++ /**< An array with 'num_of_keys' entries, each entry specifies the ++ corresponding key parameters; ++ When 'action' = e_IOC_FM_PCD_ACTION_EXACT_MATCH, this value must not ++ exceed 255 (IOC_FM_PCD_MAX_NUM_OF_KEYS-1) as the last entry is saved ++ for the 'miss' entry. */ ++ ioc_fm_pcd_cc_next_engine_params_t cc_next_engine_params_for_miss; ++ /**< Parameters for defining the next engine when a key is not matched; ++ Not relevant if action = e_IOC_FM_PCD_ACTION_INDEXED_LOOKUP. */ ++} ioc_keys_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a CC node ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_cc_node_params_t { ++ ioc_fm_pcd_extract_entry_t extract_cc_params; /**< Extraction parameters */ ++ ioc_keys_params_t keys_params; /**< Keys definition matching the selected extraction */ ++ void *id; /**< Output parameter; returns the CC node Id to be used */ ++} ioc_fm_pcd_cc_node_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a hash table ++ (Must match struct t_FmPcdHashTableParams defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_hash_table_params_t { ++ uint16_t max_num_of_keys; /**< Maximum Number Of Keys that will (ever) be used in this Hash-table */ ++ ioc_fm_pcd_cc_stats_mode statistics_mode; /**< If not e_IOC_FM_PCD_CC_STATS_MODE_NONE, the required structures for the ++ requested statistics mode will be allocated according to max_num_of_keys. */ ++ uint8_t kg_hash_shift; /**< KG-Hash-shift as it was configured in the KG-scheme ++ that leads to this hash-table. */ ++ uint16_t hash_res_mask; /**< Mask that will be used on the hash-result; ++ The number-of-sets for this hash will be calculated ++ as (2^(number of bits set in 'hash_res_mask')); ++ The 4 lower bits must be cleared. */ ++ uint8_t hash_shift; /**< Byte offset from the beginning of the KeyGen hash result to the ++ 2-bytes to be used as hash index. */ ++ uint8_t match_key_size; /**< Size of the exact match keys held by the hash buckets */ ++ ++ ioc_fm_pcd_cc_next_engine_params_t cc_next_engine_params_for_miss; ++ /**< Parameters for defining the next engine when a key is not matched */ ++ void *id; ++} ioc_fm_pcd_hash_table_params_t; ++ ++/**************************************************************************//** ++ @Description A structure with the arguments for the FM_PCD_HashTableAddKey ioctl() call ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_hash_table_add_key_params_t { ++ void *p_hash_tbl; ++ uint8_t key_size; ++ ioc_fm_pcd_cc_key_params_t key_params; ++} ioc_fm_pcd_hash_table_add_key_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a CC tree group. ++ ++ This structure defines a CC group in terms of NetEnv units ++ and the action to be taken in each case. The unit_ids list must ++ be given in order from low to high indices. ++ ++ ioc_fm_pcd_cc_next_engine_params_t is a list of 2^num_of_distinction_units ++ structures where each defines the next action to be taken for ++ each units combination. for example: ++ num_of_distinction_units = 2 ++ unit_ids = {1,3} ++ next_engine_per_entries_in_grp[0] = ioc_fm_pcd_cc_next_engine_params_t for the case that ++ unit 1 - not found; unit 3 - not found; ++ next_engine_per_entries_in_grp[1] = ioc_fm_pcd_cc_next_engine_params_t for the case that ++ unit 1 - not found; unit 3 - found; ++ next_engine_per_entries_in_grp[2] = ioc_fm_pcd_cc_next_engine_params_t for the case that ++ unit 1 - found; unit 3 - not found; ++ next_engine_per_entries_in_grp[3] = ioc_fm_pcd_cc_next_engine_params_t for the case that ++ unit 1 - found; unit 3 - found; ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_cc_grp_params_t { ++ uint8_t num_of_distinction_units; /**< Up to 4 */ ++ uint8_t unit_ids [IOC_FM_PCD_MAX_NUM_OF_CC_UNITS]; ++ /**< Indexes of the units as defined in ++ FM_PCD_NetEnvCharacteristicsSet() */ ++ ioc_fm_pcd_cc_next_engine_params_t next_engine_per_entries_in_grp[IOC_FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP]; ++ /**< Maximum entries per group is 16 */ ++} ioc_fm_pcd_cc_grp_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining the CC tree groups ++ (Must match struct t_FmPcdCcTreeParams defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_cc_tree_params_t { ++ void *net_env_id; /**< Id of the Network Environment as returned ++ by FM_PCD_NetEnvCharacteristicsSet() */ ++ uint8_t num_of_groups; /**< Number of CC groups within the CC tree */ ++ ioc_fm_pcd_cc_grp_params_t fm_pcd_cc_group_params [IOC_FM_PCD_MAX_NUM_OF_CC_GROUPS]; ++ /**< Parameters for each group. */ ++ void *id; /**< Output parameter; Returns the tree Id to be used */ ++} ioc_fm_pcd_cc_tree_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining policer byte rate ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_plcr_byte_rate_mode_param_t { ++ ioc_fm_pcd_plcr_frame_length_select frame_length_selection; /**< Frame length selection */ ++ ioc_fm_pcd_plcr_roll_back_frame_select roll_back_frame_selection; /**< relevant option only e_IOC_FM_PCD_PLCR_L2_FRM_LEN, ++ e_IOC_FM_PCD_PLCR_FULL_FRM_LEN */ ++} ioc_fm_pcd_plcr_byte_rate_mode_param_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining the policer profile (based on ++ RFC-2698 or RFC-4115 attributes). ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_plcr_non_passthrough_alg_param_t { ++ ioc_fm_pcd_plcr_rate_mode rate_mode; /**< Byte / Packet */ ++ ioc_fm_pcd_plcr_byte_rate_mode_param_t byte_mode_param; /**< Valid for Byte NULL for Packet */ ++ uint32_t committed_info_rate; /**< KBits/Sec or Packets/Sec */ ++ uint32_t committed_burst_size; /**< KBits or Packets */ ++ uint32_t peak_or_excess_info_rate; /**< KBits/Sec or Packets/Sec */ ++ uint32_t peak_or_excess_burst_size; /**< KBits or Packets */ ++} ioc_fm_pcd_plcr_non_passthrough_alg_param_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining the next engine after policer ++*//***************************************************************************/ ++typedef union ioc_fm_pcd_plcr_next_engine_params_u { ++ ioc_fm_pcd_done_action action; /**< Action - when next engine is BMI (done) */ ++ void *p_profile; /**< Policer profile handle - used when next engine ++ is PLCR, must be a SHARED profile */ ++ void *p_direct_scheme; /**< Direct scheme select - when next engine is Keygen */ ++} ioc_fm_pcd_plcr_next_engine_params_u; ++ ++typedef struct ioc_fm_pcd_port_params_t { ++ ioc_fm_port_type port_type; /**< Type of port for this profile */ ++ uint8_t port_id; /**< FM-Port id of port for this profile */ ++} ioc_fm_pcd_port_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining the policer profile entry ++ (Must match struct t_FmPcdPlcrProfileParams defined in fm_pcd_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_plcr_profile_params_t { ++ bool modify; /**< TRUE to change an existing profile */ ++ union { ++ struct { ++ ioc_fm_pcd_profile_type_selection profile_type; /**< Type of policer profile */ ++ ioc_fm_pcd_port_params_t *p_fm_port; /**< Relevant for per-port profiles only */ ++ uint16_t relative_profile_id; /**< Profile id - relative to shared group or to port */ ++ } new_params; /**< Use it when modify = FALSE */ ++ void *p_profile; /**< A handle to a profile - use it when modify=TRUE */ ++ } profile_select; ++ ioc_fm_pcd_plcr_algorithm_selection alg_selection; /**< Profile Algorithm PASS_THROUGH, RFC_2698, RFC_4115 */ ++ ioc_fm_pcd_plcr_color_mode color_mode; /**< COLOR_BLIND, COLOR_AWARE */ ++ ++ union { ++ ioc_fm_pcd_plcr_color dflt_color; /**< For Color-Blind Pass-Through mode; the policer will re-color ++ any incoming packet with the default value. */ ++ ioc_fm_pcd_plcr_color override; /**< For Color-Aware modes; the profile response to a ++ pre-color value of 2'b11. */ ++ } color; ++ ++ ioc_fm_pcd_plcr_non_passthrough_alg_param_t non_passthrough_alg_param; /**< RFC2698 or RFC4115 parameters */ ++ ++ ioc_fm_pcd_engine next_engine_on_green; /**< Next engine for green-colored frames */ ++ ioc_fm_pcd_plcr_next_engine_params_u params_on_green; /**< Next engine parameters for green-colored frames */ ++ ++ ioc_fm_pcd_engine next_engine_on_yellow; /**< Next engine for yellow-colored frames */ ++ ioc_fm_pcd_plcr_next_engine_params_u params_on_yellow; /**< Next engine parameters for yellow-colored frames */ ++ ++ ioc_fm_pcd_engine next_engine_on_red; /**< Next engine for red-colored frames */ ++ ioc_fm_pcd_plcr_next_engine_params_u params_on_red; /**< Next engine parameters for red-colored frames */ ++ ++ bool trap_profile_on_flow_A; /**< Obsolete - do not use */ ++ bool trap_profile_on_flow_B; /**< Obsolete - do not use */ ++ bool trap_profile_on_flow_C; /**< Obsolete - do not use */ ++ ++ void *id; /**< output parameter; Returns the profile Id to be used */ ++} ioc_fm_pcd_plcr_profile_params_t; ++ ++/**************************************************************************//** ++ @Description A structure for modifying CC tree next engine ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_cc_tree_modify_next_engine_params_t { ++ void *id; /**< CC tree Id to be used */ ++ uint8_t grp_indx; /**< A Group index in the tree */ ++ uint8_t indx; /**< Entry index in the group defined by grp_index */ ++ ioc_fm_pcd_cc_next_engine_params_t cc_next_engine_params; ++ /**< Parameters for the next for the defined Key in the p_Key */ ++} ioc_fm_pcd_cc_tree_modify_next_engine_params_t; ++ ++/**************************************************************************//** ++ @Description A structure for modifying CC node next engine ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_cc_node_modify_next_engine_params_t { ++ void *id; /**< CC node Id to be used */ ++ uint16_t key_indx; /**< Key index for Next Engine Params modifications; ++ NOTE: This parameter is IGNORED for miss-key! */ ++ uint8_t key_size; /**< Key size of added key */ ++ ioc_fm_pcd_cc_next_engine_params_t cc_next_engine_params; ++ /**< parameters for the next for the defined Key in the p_Key */ ++} ioc_fm_pcd_cc_node_modify_next_engine_params_t; ++ ++/**************************************************************************//** ++ @Description A structure for remove CC node key ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_cc_node_remove_key_params_t { ++ void *id; /**< CC node Id to be used */ ++ uint16_t key_indx; /**< Key index for Next Engine Params modifications; ++ NOTE: This parameter is IGNORED for miss-key! */ ++} ioc_fm_pcd_cc_node_remove_key_params_t; ++ ++/**************************************************************************//** ++ @Description A structure for modifying CC node key and next engine ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t { ++ void *id; /**< CC node Id to be used */ ++ uint16_t key_indx; /**< Key index for Next Engine Params modifications; ++ NOTE: This parameter is IGNORED for miss-key! */ ++ uint8_t key_size; /**< Key size of added key */ ++ ioc_fm_pcd_cc_key_params_t key_params; /**< it's array with numOfKeys entries each entry in ++ the array of the type ioc_fm_pcd_cc_key_params_t */ ++} ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t; ++ ++/**************************************************************************//** ++ @Description A structure for modifying CC node key ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_cc_node_modify_key_params_t { ++ void *id; /**< CC node Id to be used */ ++ uint16_t key_indx; /**< Key index for Next Engine Params modifications; ++ NOTE: This parameter is IGNORED for miss-key! */ ++ uint8_t key_size; /**< Key size of added key */ ++ uint8_t *p_key; /**< Pointer to the key of the size defined in key_size */ ++ uint8_t *p_mask; /**< Pointer to the Mask per key of the size defined ++ in keySize. p_Key and p_Mask (if defined) have to be ++ of the same size as defined in the key_size */ ++} ioc_fm_pcd_cc_node_modify_key_params_t; ++ ++/**************************************************************************//** ++ @Description A structure with the arguments for the FM_PCD_HashTableRemoveKey ioctl() call ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_hash_table_remove_key_params_t { ++ void *p_hash_tbl; /**< The id of the hash table */ ++ uint8_t key_size; /**< The size of the key to remove */ ++ uint8_t *p_key; /**< Pointer to the key to remove */ ++} ioc_fm_pcd_hash_table_remove_key_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for selecting a location for requested manipulation ++*//***************************************************************************/ ++typedef struct ioc_fm_manip_hdr_info_t { ++ ioc_net_header_type hdr; /**< Header selection */ ++ ioc_fm_pcd_hdr_index hdr_index; /**< Relevant only for MPLS, VLAN and tunneled IP. Otherwise should be cleared. */ ++ bool by_field; /**< TRUE if the location of manipulation is according to some field in the specific header*/ ++ ioc_fm_pcd_fields_u full_field; /**< Relevant only when by_field = TRUE: Extract field */ ++} ioc_fm_manip_hdr_info_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header removal by header type ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_rmv_by_hdr_params_t { ++ ioc_fm_pcd_manip_hdr_rmv_by_hdr_type type; /**< Selection of header removal location */ ++ union { ++#if ((DPAA_VERSION == 10) && defined(FM_CAPWAP_SUPPORT)) ++ struct { ++ bool include;/**< If FALSE, remove until the specified header (not including the header); ++ If TRUE, remove also the specified header. */ ++ ioc_fm_manip_hdr_info_t hdr_info; ++ } from_start_by_hdr; /**< Relevant when type = e_IOC_FM_PCD_MANIP_RMV_BY_HDR_FROM_START */ ++#endif /* FM_CAPWAP_SUPPORT */ ++#if (DPAA_VERSION >= 11) ++ ioc_fm_manip_hdr_info_t hdr_info; /**< Relevant when type = e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START */ ++#endif /* (DPAA_VERSION >= 11) */ ++ ioc_fm_pcd_manip_hdr_rmv_specific_l2 specific_l2;/**< Relevant when type = e_IOC_FM_PCD_MANIP_BY_HDR_SPECIFIC_L2; ++ Defines which L2 headers to remove. */ ++ } u; ++} ioc_fm_pcd_manip_hdr_rmv_by_hdr_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for configuring IP fragmentation manipulation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_frag_ip_params_t { ++ uint16_t size_for_fragmentation; /**< If length of the frame is greater than this value, ++ IP fragmentation will be executed.*/ ++#if DPAA_VERSION == 10 ++ uint8_t scratch_bpid; /**< Absolute buffer pool id according to BM configuration.*/ ++#endif /* DPAA_VERSION == 10 */ ++ bool sg_bpid_en; /**< Enable a dedicated buffer pool id for the Scatter/Gather buffer allocation; ++ If disabled, the Scatter/Gather buffer will be allocated from the same pool as the ++ received frame's buffer. */ ++ uint8_t sg_bpid; /**< Scatter/Gather buffer pool id; ++ This parameter is relevant when 'sg_bpid_en=TRUE'; ++ Same LIODN number is used for these buffers as for the received frames buffers, so buffers ++ of this pool need to be allocated in the same memory area as the received buffers. ++ If the received buffers arrive from different sources, the Scatter/Gather BP id should be ++ mutual to all these sources. */ ++ ioc_fm_pcd_manip_dont_frag_action dont_frag_action; /**< Dont Fragment Action - If an IP packet is larger ++ than MTU and its DF bit is set, then this field will ++ determine the action to be taken.*/ ++} ioc_fm_pcd_manip_frag_ip_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for configuring IP reassembly manipulation. ++ ++ This is a common structure for both IPv4 and IPv6 reassembly ++ manipulation. For reassembly of both IPv4 and IPv6, make sure to ++ set the 'hdr' field in ioc_fm_pcd_manip_reassem_params_t to IOC_HEADER_TYPE_IPv6. ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_reassem_ip_params_t { ++ uint8_t relative_scheme_id[2]; /**< Partition relative scheme id: ++ relativeSchemeId[0] - Relative scheme ID for IPV4 Reassembly manipulation; ++ relativeSchemeId[1] - Relative scheme ID for IPV6 Reassembly manipulation; ++ NOTE: The following comment is relevant only for FMAN v2 devices: ++ Relative scheme ID for IPv4/IPv6 Reassembly manipulation must be smaller than ++ the user schemes id to ensure that the reassembly's schemes will be first match. ++ The remaining schemes, if defined, should have higher relative scheme ID. */ ++#if DPAA_VERSION >= 11 ++ uint32_t non_consistent_sp_fqid; /**< In case that other fragments of the frame corresponds to different storage ++ profile than the opening fragment (Non-Consistent-SP state) ++ then one of two possible scenarios occurs: ++ if 'nonConsistentSpFqid != 0', the reassembled frame will be enqueued to ++ this fqid, otherwise a 'Non Consistent SP' bit will be set in the FD[status].*/ ++#else ++ uint8_t sg_bpid; /**< Buffer pool id for the S/G frame created by the reassembly process */ ++#endif /* DPAA_VERSION >= 11 */ ++ uint8_t data_mem_id; /**< Memory partition ID for the IPR's external tables structure */ ++ uint16_t data_liodn_offset; /**< LIODN offset for access the IPR's external tables structure. */ ++ uint16_t min_frag_size[2]; /**< Minimum fragment size: ++ minFragSize[0] - for ipv4, minFragSize[1] - for ipv6 */ ++ ioc_fm_pcd_manip_reassem_ways_number num_of_frames_per_hash_entry[2]; ++ /**< Number of frames per hash entry needed for reassembly process: ++ numOfFramesPerHashEntry[0] - for ipv4 (max value is e_IOC_FM_PCD_MANIP_EIGHT_WAYS_HASH); ++ numOfFramesPerHashEntry[1] - for ipv6 (max value is e_IOC_FM_PCD_MANIP_SIX_WAYS_HASH). */ ++ uint16_t max_num_frames_in_process;/**< Number of frames which can be processed by Reassembly in the same time; ++ Must be power of 2; ++ In the case numOfFramesPerHashEntry == e_IOC_FM_PCD_MANIP_FOUR_WAYS_HASH, ++ maxNumFramesInProcess has to be in the range of 4 - 512; ++ In the case numOfFramesPerHashEntry == e_IOC_FM_PCD_MANIP_EIGHT_WAYS_HASH, ++ maxNumFramesInProcess has to be in the range of 8 - 2048. */ ++ ioc_fm_pcd_manip_reassem_time_out_mode time_out_mode; /**< Expiration delay initialized by Reassembly process */ ++ uint32_t fqid_for_time_out_frames;/**< FQID in which time out frames will enqueue during Time Out Process */ ++ uint32_t timeout_threshold_for_reassm_process; ++ /**< Represents the time interval in microseconds which defines ++ if opened frame (at least one fragment was processed but not all the fragments)is found as too old*/ ++} ioc_fm_pcd_manip_reassem_ip_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining IPSEC manipulation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_special_offload_ipsec_params_t { ++ bool decryption; /**< TRUE if being used in decryption direction; ++ FALSE if being used in encryption direction. */ ++ bool ecn_copy; /**< TRUE to copy the ECN bits from inner/outer to outer/inner ++ (direction depends on the 'decryption' field). */ ++ bool dscp_copy; /**< TRUE to copy the DSCP bits from inner/outer to outer/inner ++ (direction depends on the 'decryption' field). */ ++ bool variable_ip_hdr_len; /**< TRUE for supporting variable IP header length in decryption. */ ++ bool variable_ip_version; /**< TRUE for supporting both IP version on the same SA in encryption */ ++ uint8_t outer_ip_hdr_len; /**< If 'variable_ip_version == TRUE' than this field must be set to non-zero value; ++ It is specifies the length of the outer IP header that was configured in the ++ corresponding SA. */ ++ uint16_t arw_size; /**< if <> '0' then will perform ARW check for this SA; ++ The value must be a multiplication of 16 */ ++ void *arw_addr; /**< if arwSize <> '0' then this field must be set to non-zero value; ++ MUST be allocated from FMAN's MURAM that the post-sec op-port belong ++ Must be 4B aligned. Required MURAM size is '(NEXT_POWER_OF_2(arwSize+32))/8+4' Bytes */ ++} ioc_fm_pcd_manip_special_offload_ipsec_params_t; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description Parameters for configuring CAPWAP fragmentation manipulation ++ ++ Restrictions: ++ - Maximum number of fragments per frame is 16. ++ - Transmit confirmation is not supported. ++ - Fragmentation nodes must be set as the last PCD action (i.e. the ++ corresponding CC node key must have next engine set to e_FM_PCD_DONE). ++ - Only BMan buffers shall be used for frames to be fragmented. ++ - NOTE: The following comment is relevant only for FMAN v3 devices: IPF ++ does not support VSP. Therefore, on the same port where we have IPF we ++ cannot support VSP. ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_frag_capwap_params_t { ++ uint16_t size_for_fragmentation; /**< If length of the frame is greater than this value, ++ CAPWAP fragmentation will be executed.*/ ++ bool sg_bpid_en; /**< Enable a dedicated buffer pool id for the Scatter/Gather buffer allocation; ++ If disabled, the Scatter/Gather buffer will be allocated from the same pool as the ++ received frame's buffer. */ ++ uint8_t sg_bpid; /**< Scatter/Gather buffer pool id; ++ This parameters is relevant when 'sgBpidEn=TRUE'; ++ Same LIODN number is used for these buffers as for the received frames buffers, so buffers ++ of this pool need to be allocated in the same memory area as the received buffers. ++ If the received buffers arrive from different sources, the Scatter/Gather BP id should be ++ mutual to all these sources. */ ++ bool compress_mode_en; /**< CAPWAP Header Options Compress Enable mode; ++ When this mode is enabled then only the first fragment include the CAPWAP header options ++ field (if user provides it in the input frame) and all other fragments exclude the CAPWAP ++ options field (CAPWAP header is updated accordingly).*/ ++} ioc_fm_pcd_manip_frag_capwap_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for configuring CAPWAP reassembly manipulation. ++ ++ Restrictions: ++ - Application must define one scheme to catch the reassembled frames. ++ - Maximum number of fragments per frame is 16. ++ ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_reassem_capwap_params_t { ++ uint8_t relative_scheme_id; /**< Partition relative scheme id; ++ NOTE: this id must be smaller than the user schemes id to ensure that the reassembly scheme will be first match; ++ Rest schemes, if defined, should have higher relative scheme ID. */ ++ uint8_t data_mem_id; /**< Memory partition ID for the IPR's external tables structure */ ++ uint16_t data_liodn_offset; /**< LIODN offset for access the IPR's external tables structure. */ ++ uint16_t max_reassembled_frame_length;/**< The maximum CAPWAP reassembled frame length in bytes; ++ If maxReassembledFrameLength == 0, any successful reassembled frame length is ++ considered as a valid length; ++ if maxReassembledFrameLength > 0, a successful reassembled frame which its length ++ exceeds this value is considered as an error frame (FD status[CRE] bit is set). */ ++ ioc_fm_pcd_manip_reassem_ways_number num_of_frames_per_hash_entry; ++ /**< Number of frames per hash entry needed for reassembly process */ ++ uint16_t max_num_frames_in_process; /**< Number of frames which can be processed by reassembly in the same time; ++ Must be power of 2; ++ In the case numOfFramesPerHashEntry == e_FM_PCD_MANIP_FOUR_WAYS_HASH, ++ maxNumFramesInProcess has to be in the range of 4 - 512; ++ In the case numOfFramesPerHashEntry == e_FM_PCD_MANIP_EIGHT_WAYS_HASH, ++ maxNumFramesInProcess has to be in the range of 8 - 2048. */ ++ ioc_fm_pcd_manip_reassem_time_out_mode time_out_mode; /**< Expiration delay initialized by Reassembly process */ ++ uint32_t fqid_for_time_out_frames; /**< FQID in which time out frames will enqueue during Time Out Process; ++ Recommended value for this field is 0; in this way timed-out frames will be discarded */ ++ uint32_t timeout_threshold_for_reassm_process; ++ /**< Represents the time interval in microseconds which defines ++ if opened frame (at least one fragment was processed but not all the fragments)is found as too old*/ ++} ioc_fm_pcd_manip_reassem_capwap_params_t; ++ ++/**************************************************************************//** ++ @Description structure for defining CAPWAP manipulation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_special_offload_capwap_params_t { ++ bool dtls; /**< TRUE if continue to SEC DTLS encryption */ ++ ioc_fm_pcd_manip_hdr_qos_src qos_src; /**< TODO */ ++} ioc_fm_pcd_manip_special_offload_capwap_params_t; ++ ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Description Parameters for defining special offload manipulation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_special_offload_params_t { ++ ioc_fm_pcd_manip_special_offload_type type; /**< Type of special offload manipulation */ ++ union ++ { ++ ioc_fm_pcd_manip_special_offload_ipsec_params_t ipsec; /**< Parameters for IPSec; Relevant when ++ type = e_IOC_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC */ ++ ++#if (DPAA_VERSION >= 11) ++ ioc_fm_pcd_manip_special_offload_capwap_params_t capwap; /**< Parameters for CAPWAP; Relevant when ++ type = e_FM_PCD_MANIP_SPECIAL_OFFLOAD_CAPWAP */ ++#endif /* (DPAA_VERSION >= 11) */ ++ } u; ++} ioc_fm_pcd_manip_special_offload_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining generic removal manipulation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_rmv_generic_params_t { ++ uint8_t offset; /**< Offset from beginning of header to the start ++ location of the removal */ ++ uint8_t size; /**< Size of removed section */ ++} ioc_fm_pcd_manip_hdr_rmv_generic_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining insertion manipulation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_insrt_t { ++ uint8_t size; /**< size of inserted section */ ++ uint8_t *p_data; /**< data to be inserted */ ++} ioc_fm_pcd_manip_hdr_insrt_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining generic insertion manipulation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_insrt_generic_params_t { ++ uint8_t offset; /**< Offset from beginning of header to the start ++ location of the insertion */ ++ uint8_t size; /**< Size of inserted section */ ++ bool replace; /**< TRUE to override (replace) existing data at ++ 'offset', FALSE to insert */ ++ uint8_t *p_data; /**< Pointer to data to be inserted */ ++} ioc_fm_pcd_manip_hdr_insrt_generic_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation VLAN DSCP To Vpri translation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_field_update_vlan_dscp_to_vpri_t { ++ uint8_t dscp_to_vpri_table[IOC_FM_PCD_MANIP_DSCP_TO_VLAN_TRANS]; ++ /**< A table of VPri values for each DSCP value; ++ The index is the D_SCP value (0-0x3F) and the ++ value is the corresponding VPRI (0-15). */ ++ uint8_t vpri_def_val; /**< 0-7, Relevant only if if update_type = ++ e_IOC_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN, ++ this field is the Q Tag default value if the ++ IP header is not found. */ ++} ioc_fm_pcd_manip_hdr_field_update_vlan_dscp_to_vpri_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation VLAN fields updates ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_field_update_vlan_t { ++ ioc_fm_pcd_manip_hdr_field_update_vlan update_type; /**< Selects VLAN update type */ ++ union { ++ uint8_t vpri; /**< 0-7, Relevant only if If update_type = ++ e_IOC_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_PRI, this ++ is the new VLAN pri. */ ++ ioc_fm_pcd_manip_hdr_field_update_vlan_dscp_to_vpri_t dscp_to_vpri; ++ /**< Parameters structure, Relevant only if update_type = ++ e_IOC_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN. */ ++ } u; ++} ioc_fm_pcd_manip_hdr_field_update_vlan_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation IPV4 fields updates ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_field_update_ipv4_t { ++ ioc_ipv4_hdr_manip_update_flags_t valid_updates; /**< ORed flag, selecting the required updates */ ++ uint8_t tos; /**< 8 bit New TOS; Relevant if valid_updates contains ++ IOC_HDR_MANIP_IPV4_TOS */ ++ uint16_t id; /**< 16 bit New IP ID; Relevant only if valid_updates ++ contains IOC_HDR_MANIP_IPV4_ID */ ++ uint32_t src; /**< 32 bit New IP SRC; Relevant only if valid_updates ++ contains IOC_HDR_MANIP_IPV4_SRC */ ++ uint32_t dst; /**< 32 bit New IP DST; Relevant only if valid_updates ++ contains IOC_HDR_MANIP_IPV4_DST */ ++} ioc_fm_pcd_manip_hdr_field_update_ipv4_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation IPV6 fields updates ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_field_update_ipv6_t { ++ ioc_ipv6_hdr_manip_update_flags_t valid_updates; /**< ORed flag, selecting the required updates */ ++ uint8_t traffic_class; /**< 8 bit New Traffic Class; Relevant if valid_updates contains ++ IOC_HDR_MANIP_IPV6_TC */ ++ uint8_t src[IOC_NET_HEADER_FIELD_IPv6_ADDR_SIZE]; ++ /**< 16 byte new IP SRC; Relevant only if valid_updates ++ contains IOC_HDR_MANIP_IPV6_SRC */ ++ uint8_t dst[IOC_NET_HEADER_FIELD_IPv6_ADDR_SIZE]; ++ /**< 16 byte new IP DST; Relevant only if valid_updates ++ contains IOC_HDR_MANIP_IPV6_DST */ ++} ioc_fm_pcd_manip_hdr_field_update_ipv6_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation TCP/UDP fields updates ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_field_update_tcp_udp_t { ++ ioc_tcp_udp_hdr_manip_update_flags_t valid_updates; /**< ORed flag, selecting the required updates */ ++ uint16_t src; /**< 16 bit New TCP/UDP SRC; Relevant only if valid_updates ++ contains IOC_HDR_MANIP_TCP_UDP_SRC */ ++ uint16_t dst; /**< 16 bit New TCP/UDP DST; Relevant only if valid_updates ++ contains IOC_HDR_MANIP_TCP_UDP_DST */ ++} ioc_fm_pcd_manip_hdr_field_update_tcp_udp_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation fields updates ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_field_update_params_t { ++ ioc_fm_pcd_manip_hdr_field_update_type type; /**< Type of header field update manipulation */ ++ union { ++ ioc_fm_pcd_manip_hdr_field_update_vlan_t vlan; /**< Parameters for VLAN update. Relevant when ++ type = e_IOC_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN */ ++ ioc_fm_pcd_manip_hdr_field_update_ipv4_t ipv4; /**< Parameters for IPv4 update. Relevant when ++ type = e_IOC_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4 */ ++ ioc_fm_pcd_manip_hdr_field_update_ipv6_t ipv6; /**< Parameters for IPv6 update. Relevant when ++ type = e_IOC_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6 */ ++ ioc_fm_pcd_manip_hdr_field_update_tcp_udp_t tcp_udp;/**< Parameters for TCP/UDP update. Relevant when ++ type = e_IOC_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP */ ++ } u; ++} ioc_fm_pcd_manip_hdr_field_update_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining custom header manipulation for IP replacement ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_custom_ip_hdr_replace_t { ++ ioc_fm_pcd_manip_hdr_custom_ip_replace replace_type; /**< Selects replace update type */ ++ bool dec_ttl_hl; /**< Decrement TTL (IPV4) or Hop limit (IPV6) by 1 */ ++ bool update_ipv4_id; /**< Relevant when replace_type = ++ e_IOC_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4 */ ++ uint16_t id; /**< 16 bit New IP ID; Relevant only if ++ update_ipv4_id = TRUE */ ++ uint8_t hdr_size; /**< The size of the new IP header */ ++ uint8_t hdr[IOC_FM_PCD_MANIP_MAX_HDR_SIZE]; ++ /**< The new IP header */ ++} ioc_fm_pcd_manip_hdr_custom_ip_hdr_replace_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining custom header manipulation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_custom_params_t { ++ ioc_fm_pcd_manip_hdr_custom_type type; /**< Type of header field update manipulation */ ++ union { ++ ioc_fm_pcd_manip_hdr_custom_ip_hdr_replace_t ip_hdr_replace; ++ /**< Parameters IP header replacement */ ++ } u; ++} ioc_fm_pcd_manip_hdr_custom_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining specific L2 insertion manipulation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_insrt_specific_l2_params_t { ++ ioc_fm_pcd_manip_hdr_insrt_specific_l2 specific_l2; /**< Selects which L2 headers to insert */ ++ bool update; /**< TRUE to update MPLS header */ ++ uint8_t size; /**< size of inserted section */ ++ uint8_t *p_data; /**< data to be inserted */ ++} ioc_fm_pcd_manip_hdr_insrt_specific_l2_params_t; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description Parameters for defining IP insertion manipulation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_insrt_ip_params_t { ++ bool calc_l4_checksum; /**< Calculate L4 checksum. */ ++ ioc_fm_pcd_manip_hdr_qos_mapping_mode mapping_mode; /**< TODO */ ++ uint8_t last_pid_offset; /**< the offset of the last Protocol within ++ the inserted header */ ++ uint16_t id; /**< 16 bit New IP ID */ ++ bool dont_frag_overwrite; ++ /**< IPv4 only. DF is overwritten with the hash-result next-to-last byte. ++ * This byte is configured to be overwritten when RPD is set. */ ++ uint8_t last_dst_offset; ++ /**< IPv6 only. if routing extension exist, user should set the offset of the destination address ++ * in order to calculate UDP checksum pseudo header; ++ * Otherwise set it to '0'. */ ++ ioc_fm_pcd_manip_hdr_insrt_t insrt; /**< size and data to be inserted. */ ++} ioc_fm_pcd_manip_hdr_insrt_ip_params_t; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Description Parameters for defining header insertion manipulation by header type ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_insrt_by_hdr_params_t { ++ ioc_fm_pcd_manip_hdr_insrt_by_hdr_type type; /**< Selects manipulation type */ ++ union { ++ ioc_fm_pcd_manip_hdr_insrt_specific_l2_params_t specific_l2_params; ++ /**< Used when type = e_IOC_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2: ++ Selects which L2 headers to remove */ ++#if (DPAA_VERSION >= 11) ++ ioc_fm_pcd_manip_hdr_insrt_ip_params_t ip_params; /**< Used when type = e_FM_PCD_MANIP_INSRT_BY_HDR_IP */ ++ ioc_fm_pcd_manip_hdr_insrt_t insrt; /**< Used when type is one of e_FM_PCD_MANIP_INSRT_BY_HDR_UDP, ++ e_FM_PCD_MANIP_INSRT_BY_HDR_UDP_LITE, or ++ e_FM_PCD_MANIP_INSRT_BY_HDR_CAPWAP */ ++#endif /* (DPAA_VERSION >= 11) */ ++ } u; ++} ioc_fm_pcd_manip_hdr_insrt_by_hdr_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header insertion manipulation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_insrt_params_t { ++ ioc_fm_pcd_manip_hdr_insrt_type type; /**< Type of insertion manipulation */ ++ union { ++ ioc_fm_pcd_manip_hdr_insrt_by_hdr_params_t by_hdr; /**< Parameters for defining header insertion manipulation by header type, ++ relevant if 'type' = e_IOC_FM_PCD_MANIP_INSRT_BY_HDR */ ++ ioc_fm_pcd_manip_hdr_insrt_generic_params_t generic;/**< Parameters for defining generic header insertion manipulation, ++ relevant if type = e_IOC_FM_PCD_MANIP_INSRT_GENERIC */ ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++ ioc_fm_pcd_manip_hdr_insrt_by_template_params_t by_template; ++ /**< Parameters for defining header insertion manipulation by template, ++ relevant if 'type' = e_IOC_FM_PCD_MANIP_INSRT_BY_TEMPLATE */ ++#endif /* FM_CAPWAP_SUPPORT */ ++ } u; ++} ioc_fm_pcd_manip_hdr_insrt_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header removal manipulation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_rmv_params_t { ++ ioc_fm_pcd_manip_hdr_rmv_type type; /**< Type of header removal manipulation */ ++ union { ++ ioc_fm_pcd_manip_hdr_rmv_by_hdr_params_t by_hdr; /**< Parameters for defining header removal manipulation by header type, ++ relevant if type = e_IOC_FM_PCD_MANIP_RMV_BY_HDR */ ++ ioc_fm_pcd_manip_hdr_rmv_generic_params_t generic; /**< Parameters for defining generic header removal manipulation, ++ relevant if type = e_IOC_FM_PCD_MANIP_RMV_GENERIC */ ++ } u; ++} ioc_fm_pcd_manip_hdr_rmv_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining header manipulation node ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_hdr_params_t { ++ bool rmv; /**< TRUE, to define removal manipulation */ ++ ioc_fm_pcd_manip_hdr_rmv_params_t rmv_params; /**< Parameters for removal manipulation, relevant if 'rmv' = TRUE */ ++ ++ bool insrt; /**< TRUE, to define insertion manipulation */ ++ ioc_fm_pcd_manip_hdr_insrt_params_t insrt_params; /**< Parameters for insertion manipulation, relevant if 'insrt' = TRUE */ ++ ++ bool field_update; /**< TRUE, to define field update manipulation */ ++ ioc_fm_pcd_manip_hdr_field_update_params_t field_update_params; /**< Parameters for field update manipulation, relevant if 'fieldUpdate' = TRUE */ ++ ++ bool custom; /**< TRUE, to define custom manipulation */ ++ ioc_fm_pcd_manip_hdr_custom_params_t custom_params; /**< Parameters for custom manipulation, relevant if 'custom' = TRUE */ ++ ++ bool dont_parse_after_manip;/**< FALSE to activate the parser a second time after ++ completing the manipulation on the frame */ ++} ioc_fm_pcd_manip_hdr_params_t; ++ ++ ++/**************************************************************************//** ++ @Description structure for defining fragmentation manipulation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_frag_params_t { ++ ioc_net_header_type hdr; /**< Header selection */ ++ union { ++#if (DPAA_VERSION >= 11) ++ ioc_fm_pcd_manip_frag_capwap_params_t capwap_frag; /**< Parameters for defining CAPWAP fragmentation, ++ relevant if 'hdr' = HEADER_TYPE_CAPWAP */ ++#endif /* (DPAA_VERSION >= 11) */ ++ ioc_fm_pcd_manip_frag_ip_params_t ip_frag; /**< Parameters for defining IP fragmentation, ++ relevant if 'hdr' = HEADER_TYPE_Ipv4 or HEADER_TYPE_Ipv6 */ ++ } u; ++} ioc_fm_pcd_manip_frag_params_t; ++ ++/**************************************************************************//** ++ @Description structure for defining reassemble manipulation ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_reassem_params_t { ++ ioc_net_header_type hdr; /**< Header selection */ ++ union { ++#if (DPAA_VERSION >= 11) ++ ioc_fm_pcd_manip_reassem_capwap_params_t capwap_reassem; /**< Parameters for defining CAPWAP reassembly, ++ relevant if 'hdr' = HEADER_TYPE_CAPWAP */ ++#endif /* (DPAA_VERSION >= 11) */ ++ ioc_fm_pcd_manip_reassem_ip_params_t ip_reassem; /**< Parameters for defining IP reassembly, ++ relevant if 'hdr' = HEADER_TYPE_Ipv4 or HEADER_TYPE_Ipv6 */ ++ } u; ++} ioc_fm_pcd_manip_reassem_params_t; ++ ++/**************************************************************************//** ++ @Description Parameters for defining a manipulation node ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_params_t { ++ ioc_fm_pcd_manip_type type; /**< Selects type of manipulation node */ ++ union { ++ ioc_fm_pcd_manip_hdr_params_t hdr; /**< Parameters for defining header manipulation node */ ++ ioc_fm_pcd_manip_reassem_params_t reassem;/**< Parameters for defining reassembly manipulation node */ ++ ioc_fm_pcd_manip_frag_params_t frag; /**< Parameters for defining fragmentation manipulation node */ ++ ioc_fm_pcd_manip_special_offload_params_t special_offload;/**< Parameters for defining special offload manipulation node */ ++ } u; ++ void *p_next_manip;/**< Handle to another (previously defined) manipulation node; ++ Allows concatenation of manipulation actions ++ This parameter is optional and may be NULL. */ ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++ bool frag_or_reasm;/**< TRUE, if defined fragmentation/reassembly manipulation */ ++ ioc_fm_pcd_manip_frag_or_reasm_params_t frag_or_reasm_params;/**< Parameters for fragmentation/reassembly manipulation, ++ relevant if frag_or_reasm = TRUE */ ++#endif /* FM_CAPWAP_SUPPORT */ ++ void *id; ++} ioc_fm_pcd_manip_params_t; ++ ++/**************************************************************************//** ++ @Description Structure for retrieving IP reassembly statistics ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_reassem_ip_stats_t { ++ /* common counters for both IPv4 and IPv6 */ ++ uint32_t timeout; /**< Counts the number of TimeOut occurrences */ ++ uint32_t rfd_pool_busy; /**< Counts the number of failed attempts to allocate ++ a Reassembly Frame Descriptor */ ++ uint32_t internal_buffer_busy; /**< Counts the number of times an internal buffer busy occurred */ ++ uint32_t external_buffer_busy; /**< Counts the number of times external buffer busy occurred */ ++ uint32_t sg_fragments; /**< Counts the number of Scatter/Gather fragments */ ++ uint32_t dma_semaphore_depletion; /**< Counts the number of failed attempts to allocate a DMA semaphore */ ++#if (DPAA_VERSION >= 11) ++ uint32_t non_consistent_sp; /**< Counts the number of Non Consistent Storage Profile events for ++ successfully reassembled frames */ ++#endif /* (DPAA_VERSION >= 11) */ ++struct { ++ uint32_t successfully_reassembled; /**< Counts the number of successfully reassembled frames */ ++ uint32_t valid_fragments; /**< Counts the total number of valid fragments that ++ have been processed for all frames */ ++ uint32_t processed_fragments; /**< Counts the number of processed fragments ++ (valid and error fragments) for all frames */ ++ uint32_t malformed_fragments; /**< Counts the number of malformed fragments processed for all frames */ ++ uint32_t discarded_fragments; /**< Counts the number of fragments discarded by the reassembly process */ ++ uint32_t auto_learn_busy; /**< Counts the number of times a busy condition occurs when attempting ++ to access an IP-Reassembly Automatic Learning Hash set */ ++ uint32_t more_than16fragments; /**< Counts the fragment occurrences in which the number of fragments-per-frame ++ exceeds 16 */ ++ } specific_hdr_statistics[2]; /**< slot '0' is for IPv4, slot '1' is for IPv6 */ ++} ioc_fm_pcd_manip_reassem_ip_stats_t; ++ ++/**************************************************************************//** ++ @Description Structure for retrieving IP fragmentation statistics ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_frag_ip_stats_t { ++ uint32_t total_frames; /**< Number of frames that passed through the manipulation node */ ++ uint32_t fragmented_frames; /**< Number of frames that were fragmented */ ++ uint32_t generated_fragments; /**< Number of fragments that were generated */ ++} ioc_fm_pcd_manip_frag_ip_stats_t; ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Description Structure for retrieving CAPWAP reassembly statistics ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_reassem_capwap_stats_t { ++ uint32_t timeout; /**< Counts the number of timeout occurrences */ ++ uint32_t rfd_pool_busy; /**< Counts the number of failed attempts to allocate ++ a Reassembly Frame Descriptor */ ++ uint32_t internal_buffer_busy; /**< Counts the number of times an internal buffer busy occurred */ ++ uint32_t external_buffer_busy; /**< Counts the number of times external buffer busy occurred */ ++ uint32_t sg_fragments; /**< Counts the number of Scatter/Gather fragments */ ++ uint32_t dma_semaphore_depletion; /**< Counts the number of failed attempts to allocate a DMA semaphore */ ++ uint32_t successfully_reassembled; /**< Counts the number of successfully reassembled frames */ ++ uint32_t valid_fragments; /**< Counts the total number of valid fragments that ++ have been processed for all frames */ ++ uint32_t processed_fragments; /**< Counts the number of processed fragments ++ (valid and error fragments) for all frames */ ++ uint32_t malformed_fragments; /**< Counts the number of malformed fragments processed for all frames */ ++ uint32_t autoLearn_busy; /**< Counts the number of times a busy condition occurs when attempting ++ to access an Reassembly Automatic Learning Hash set */ ++ uint32_t discarded_fragments; /**< Counts the number of fragments discarded by the reassembly process */ ++ uint32_t more_than16fragments; /**< Counts the fragment occurrences in which the number of fragments-per-frame ++ exceeds 16 */ ++ uint32_t exceed_max_reassembly_frame_len;/**< ounts the number of times that a successful reassembled frame ++ length exceeds MaxReassembledFrameLength value */ ++} ioc_fm_pcd_manip_reassem_capwap_stats_t; ++ ++/**************************************************************************//** ++ @Description Structure for retrieving CAPWAP fragmentation statistics ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_frag_capwap_stats_t { ++ uint32_t total_frames; /**< Number of frames that passed through the manipulation node */ ++ uint32_t fragmented_frames; /**< Number of frames that were fragmented */ ++ uint32_t generated_fragments; /**< Number of fragments that were generated */ ++#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) ++ uint8_t sg_allocation_failure; /**< Number of allocation failure of s/g buffers */ ++#endif /* (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) */ ++} ioc_fm_pcd_manip_frag_capwap_stats_t; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Description Structure for retrieving reassembly statistics ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_reassem_stats_t { ++ union { ++ ioc_fm_pcd_manip_reassem_ip_stats_t ip_reassem; /**< Structure for IP reassembly statistics */ ++#if (DPAA_VERSION >= 11) ++ ioc_fm_pcd_manip_reassem_capwap_stats_t capwap_reassem; /**< Structure for CAPWAP reassembly statistics */ ++#endif /* (DPAA_VERSION >= 11) */ ++ } u; ++} ioc_fm_pcd_manip_reassem_stats_t; ++ ++/**************************************************************************//** ++ @Description structure for retrieving fragmentation statistics ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_frag_stats_t { ++ union { ++ ioc_fm_pcd_manip_frag_ip_stats_t ip_frag; /**< Structure for IP fragmentation statistics */ ++#if (DPAA_VERSION >= 11) ++ ioc_fm_pcd_manip_frag_capwap_stats_t capwap_frag; /**< Structure for CAPWAP fragmentation statistics */ ++#endif /* (DPAA_VERSION >= 11) */ ++ } u; ++} ioc_fm_pcd_manip_frag_stats_t; ++ ++/**************************************************************************//** ++ @Description structure for defining manipulation statistics ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_stats_t { ++ union { ++ ioc_fm_pcd_manip_reassem_stats_t reassem; /**< Structure for reassembly statistics */ ++ ioc_fm_pcd_manip_frag_stats_t frag; /**< Structure for fragmentation statistics */ ++ } u; ++} ioc_fm_pcd_manip_stats_t; ++ ++/**************************************************************************//** ++ @Description Parameters for acquiring manipulation statistics ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_manip_get_stats_t { ++ void *id; ++ ioc_fm_pcd_manip_stats_t stats; ++} ioc_fm_pcd_manip_get_stats_t; ++ ++#if DPAA_VERSION >= 11 ++/**************************************************************************//** ++ @Description Parameters for defining frame replicator group and its members ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_frm_replic_group_params_t { ++ uint8_t max_num_of_entries; /**< Maximal number of members in the group - must be at least two */ ++ uint8_t num_of_entries; /**< Number of members in the group - must be at least 1 */ ++ ioc_fm_pcd_cc_next_engine_params_t next_engine_params[IOC_FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES]; ++ /**< Array of members' parameters */ ++ void *id; ++} ioc_fm_pcd_frm_replic_group_params_t; ++ ++typedef struct ioc_fm_pcd_frm_replic_member_t { ++ void *h_replic_group; ++ uint16_t member_index; ++} ioc_fm_pcd_frm_replic_member_t; ++ ++typedef struct ioc_fm_pcd_frm_replic_member_params_t { ++ ioc_fm_pcd_frm_replic_member_t member; ++ ioc_fm_pcd_cc_next_engine_params_t next_engine_params; ++} ioc_fm_pcd_frm_replic_member_params_t; ++#endif /* DPAA_VERSION >= 11 */ ++ ++ ++typedef struct ioc_fm_pcd_cc_key_statistics_t { ++ uint32_t byte_count; /**< This counter reflects byte count of frames that ++ were matched by this key. */ ++ uint32_t frame_count; /**< This counter reflects count of frames that ++ were matched by this key. */ ++#if (DPAA_VERSION >= 11) ++ uint32_t frame_length_range_count[IOC_FM_PCD_CC_STATS_MAX_NUM_OF_FLR]; ++ /**< These counters reflect how many frames matched ++ this key in 'RMON' statistics mode: ++ Each counter holds the number of frames of a ++ specific frames length range, according to the ++ ranges provided at initialization. */ ++#endif /* (DPAA_VERSION >= 11) */ ++} ioc_fm_pcd_cc_key_statistics_t; ++ ++ ++typedef struct ioc_fm_pcd_cc_tbl_get_stats_t { ++ void *id; ++ uint16_t key_index; ++ ioc_fm_pcd_cc_key_statistics_t statistics; ++} ioc_fm_pcd_cc_tbl_get_stats_t; ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableGetKeyStatistics ++ ++ @Description This routine may be used to get statistics counters of specific key ++ in a CC Node. ++ ++ If 'e_FM_PCD_CC_STATS_MODE_FRAME' and ++ 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, ++ these counters reflect how many frames passed that were matched ++ this key; The total frames count will be returned in the counter ++ of the first range (as only one frame length range was defined). ++ If 'e_FM_PCD_CC_STATS_MODE_RMON' was set for this node, the total ++ frame count will be separated to frame length counters, based on ++ provided frame length ranges. ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[in] keyIndex Key index for adding ++ @Param[out] p_KeyStatistics Key statistics counters ++ ++ @Return The specific key statistics. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(). ++*//***************************************************************************/ ++ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_MATCH_TABLE_GET_KEY_STAT_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(12), ioc_compat_fm_pcd_cc_tbl_get_stats_t) ++#endif ++#define FM_PCD_IOC_MATCH_TABLE_GET_KEY_STAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(12), ioc_fm_pcd_cc_tbl_get_stats_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableGetMissStatistics ++ ++ @Description This routine may be used to get statistics counters of miss entry ++ in a CC Node. ++ ++ If 'e_FM_PCD_CC_STATS_MODE_FRAME' and ++ 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, ++ these counters reflect how many frames were not matched to any ++ existing key and therefore passed through the miss entry; The ++ total frames count will be returned in the counter of the ++ first range (as only one frame length range was defined). ++ ++ @Param[in] h_CcNode A handle to the node ++ @Param[out] p_MissStatistics Statistics counters for 'miss' ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(). ++*//***************************************************************************/ ++ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_MATCH_TABLE_GET_MISS_STAT_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(13), ioc_compat_fm_pcd_cc_tbl_get_stats_t) ++#endif ++#define FM_PCD_IOC_MATCH_TABLE_GET_MISS_STAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(13), ioc_fm_pcd_cc_tbl_get_stats_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableGetMissStatistics ++ ++ @Description This routine may be used to get statistics counters of 'miss' ++ entry of the a hash table. ++ ++ If 'e_FM_PCD_CC_STATS_MODE_FRAME' and ++ 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node, ++ these counters reflect how many frames were not matched to any ++ existing key and therefore passed through the miss entry; ++ ++ @Param[in] h_HashTbl A handle to a hash table ++ @Param[out] p_MissStatistics Statistics counters for 'miss' ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_HASH_TABLE_GET_MISS_STAT_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(14), ioc_compat_fm_pcd_cc_tbl_get_stats_t) ++#endif ++#define FM_PCD_IOC_HASH_TABLE_GET_MISS_STAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(14), ioc_fm_pcd_cc_tbl_get_stats_t) ++ ++ ++/**************************************************************************//** ++ @Function FM_PCD_NetEnvCharacteristicsSet ++ ++ @Description Define a set of Network Environment Characteristics. ++ ++ When setting an environment it is important to understand its ++ application. It is not meant to describe the flows that will run ++ on the ports using this environment, but what the user means TO DO ++ with the PCD mechanisms in order to parse-classify-distribute those ++ frames. ++ By specifying a distinction unit, the user means it would use that option ++ for distinction between frames at either a KeyGen scheme or a coarse ++ classification action descriptor. Using interchangeable headers to define a ++ unit means that the user is indifferent to which of the interchangeable ++ headers is present in the frame, and wants the distinction to be based ++ on the presence of either one of them. ++ ++ Depending on context, there are limitations to the use of environments. A ++ port using the PCD functionality is bound to an environment. Some or even ++ all ports may share an environment but also an environment per port is ++ possible. When initializing a scheme, a classification plan group (see below), ++ or a coarse classification tree, one of the initialized environments must be ++ stated and related to. When a port is bound to a scheme, a classification ++ plan group, or a coarse classification tree, it MUST be bound to the same ++ environment. ++ ++ The different PCD modules, may relate (for flows definition) ONLY on ++ distinction units as defined by their environment. When initializing a ++ scheme for example, it may not choose to select IPV4 as a match for ++ recognizing flows unless it was defined in the relating environment. In ++ fact, to guide the user through the configuration of the PCD, each module's ++ characterization in terms of flows is not done using protocol names, but using ++ environment indexes. ++ ++ In terms of HW implementation, the list of distinction units sets the LCV vectors ++ and later used for match vector, classification plan vectors and coarse classification ++ indexing. ++ ++ @Param[in,out] ioc_fm_pcd_net_env_params_t A structure defining the distiction units for this configuration. ++ ++ @Return 0 on success; Error code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_NET_ENV_CHARACTERISTICS_SET_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(20), ioc_compat_fm_pcd_net_env_params_t) ++#endif ++#define FM_PCD_IOC_NET_ENV_CHARACTERISTICS_SET _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(20), ioc_fm_pcd_net_env_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_NetEnvCharacteristicsDelete ++ ++ @Description Deletes a set of Network Environment Charecteristics. ++ ++ @Param[in] ioc_fm_obj_t - The id of a Network Environment object. ++ ++ @Return 0 on success; Error code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_NET_ENV_CHARACTERISTICS_DELETE_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(21), ioc_compat_fm_obj_t) ++#endif ++#define FM_PCD_IOC_NET_ENV_CHARACTERISTICS_DELETE _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(21), ioc_fm_obj_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgSchemeSet ++ ++ @Description Initializing or modifying and enabling a scheme for the KeyGen. ++ This routine should be called for adding or modifying a scheme. ++ When a scheme needs modifying, the API requires that it will be ++ rewritten. In such a case 'modify' should be TRUE. If the ++ routine is called for a valid scheme and 'modify' is FALSE, ++ it will return error. ++ ++ @Param[in,out] ioc_fm_pcd_kg_scheme_params_t A structure of parameters for defining the scheme ++ ++ @Return 0 on success; Error code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_KG_SCHEME_SET_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(24), ioc_compat_fm_pcd_kg_scheme_params_t) ++#endif ++#define FM_PCD_IOC_KG_SCHEME_SET _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(24), ioc_fm_pcd_kg_scheme_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_KgSchemeDelete ++ ++ @Description Deleting an initialized scheme. ++ ++ @Param[in] ioc_fm_obj_t scheme id as initalized by application at FM_PCD_IOC_KG_SET_SCHEME ++ ++ @Return 0 on success; Error code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_KG_SCHEME_DELETE_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(25), ioc_compat_fm_obj_t) ++#endif ++#define FM_PCD_IOC_KG_SCHEME_DELETE _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(25), ioc_fm_obj_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_CcRootBuild ++ ++ @Description This routine must be called to define a complete coarse ++ classification tree. This is the way to define coarse ++ classification to a certain flow - the KeyGen schemes ++ may point only to trees defined in this way. ++ ++ @Param[in,out] ioc_fm_pcd_cc_tree_params_t A structure of parameters to define the tree. ++ ++ @Return 0 on success; Error code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_CC_ROOT_BUILD_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(26), compat_uptr_t) ++#endif ++#define FM_PCD_IOC_CC_ROOT_BUILD _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(26), void *) /* workaround ...*/ ++ ++/**************************************************************************//** ++ @Function FM_PCD_CcRootDelete ++ ++ @Description Deleting a built tree. ++ ++ @Param[in] ioc_fm_obj_t - The id of a CC tree. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_CC_ROOT_DELETE_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(27), ioc_compat_fm_obj_t) ++#endif ++#define FM_PCD_IOC_CC_ROOT_DELETE _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(27), ioc_fm_obj_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableSet ++ ++ @Description This routine should be called for each CC (coarse classification) ++ node. The whole CC tree should be built bottom up so that each ++ node points to already defined nodes. p_NodeId returns the node ++ Id to be used by other nodes. ++ ++ @Param[in,out] ioc_fm_pcd_cc_node_params_t A structure for defining the CC node params ++ ++ @Return 0 on success; Error code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_MATCH_TABLE_SET_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(28), compat_uptr_t) ++#endif ++#define FM_PCD_IOC_MATCH_TABLE_SET _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(28), void *) /* workaround ...*/ ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableDelete ++ ++ @Description Deleting a built node. ++ ++ @Param[in] ioc_fm_obj_t - The id of a CC node. ++ ++ @Return 0 on success; Error code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_MATCH_TABLE_DELETE_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(29), ioc_compat_fm_obj_t) ++#endif ++#define FM_PCD_IOC_MATCH_TABLE_DELETE _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(29), ioc_fm_obj_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_CcRootModifyNextEngine ++ ++ @Description Modify the Next Engine Parameters in the entry of the tree. ++ ++ @Param[in] ioc_fm_pcd_cc_tree_modify_next_engine_params_t - Pointer to a structure with the relevant parameters ++ ++ @Return 0 on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_CcRootBuild(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_CC_ROOT_MODIFY_NEXT_ENGINE_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(30), ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t) ++#endif ++#define FM_PCD_IOC_CC_ROOT_MODIFY_NEXT_ENGINE _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(30), ioc_fm_pcd_cc_tree_modify_next_engine_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableModifyNextEngine ++ ++ @Description Modify the Next Engine Parameters in the relevant key entry of the node. ++ ++ @Param[in] ioc_fm_pcd_cc_node_modify_next_engine_params_t A pointer to a structure with the relevant parameters ++ ++ @Return 0 on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_MATCH_TABLE_MODIFY_NEXT_ENGINE_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(31), ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t) ++#endif ++#define FM_PCD_IOC_MATCH_TABLE_MODIFY_NEXT_ENGINE _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(31), ioc_fm_pcd_cc_node_modify_next_engine_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableModifyMissNextEngine ++ ++ @Description Modify the Next Engine Parameters of the Miss key case of the node. ++ ++ @Param[in] ioc_fm_pcd_cc_node_modify_next_engine_params_t - Pointer to a structure with the relevant parameters ++ ++ @Return 0 on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_MATCH_TABLE_MODIFY_MISS_NEXT_ENGINE_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(32), ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t) ++#endif ++#define FM_PCD_IOC_MATCH_TABLE_MODIFY_MISS_NEXT_ENGINE _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(32), ioc_fm_pcd_cc_node_modify_next_engine_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableRemoveKey ++ ++ @Description Remove the key (including next engine parameters of this key) ++ defined by the index of the relevant node. ++ ++ @Param[in] ioc_fm_pcd_cc_node_remove_key_params_t A pointer to a structure with the relevant parameters ++ ++ @Return 0 on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_PCD_MatchTableSet() has been called for this ++ node and for all of the nodes that lead to it. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_MATCH_TABLE_REMOVE_KEY_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(33), ioc_compat_fm_pcd_cc_node_remove_key_params_t) ++#endif ++#define FM_PCD_IOC_MATCH_TABLE_REMOVE_KEY _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(33), ioc_fm_pcd_cc_node_remove_key_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableAddKey ++ ++ @Description Add the key (including next engine parameters of this key in the ++ index defined by the keyIndex. Note that 'FM_PCD_LAST_KEY_INDEX' ++ may be used when the user doesn't care about the position of the ++ key in the table - in that case, the key will be automatically ++ added by the driver in the last available entry. ++ ++ @Param[in] ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t A pointer to a structure with the relevant parameters ++ ++ @Return 0 on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_PCD_MatchTableSet() has been called for this ++ node and for all of the nodes that lead to it. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_MATCH_TABLE_ADD_KEY_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(34), ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t) ++#endif ++#define FM_PCD_IOC_MATCH_TABLE_ADD_KEY _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(34), ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableModifyKeyAndNextEngine ++ ++ @Description Modify the key and Next Engine Parameters of this key in the index defined by key_index. ++ ++ @Param[in] ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t A pointer to a structure with the relevant parameters ++ ++ @Return 0 on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_MatchTableSet() not only of the relevnt node but also ++ the node that points to this node ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_AND_NEXT_ENGINE_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(35), ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t) ++#endif ++#define FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_AND_NEXT_ENGINE _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(35), ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_MatchTableModifyKey ++ ++ @Description Modify the key at the index defined by key_index. ++ ++ @Param[in] ioc_fm_pcd_cc_node_modify_key_params_t - Pointer to a structure with the relevant parameters ++ ++ @Return 0 on success; Error code otherwise. ++ ++ @Cautions Allowed only after FM_PCD_MatchTableSet() has been called for this ++ node and for all of the nodes that lead to it. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(36), ioc_compat_fm_pcd_cc_node_modify_key_params_t) ++#endif ++#define FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(36), ioc_fm_pcd_cc_node_modify_key_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableSet ++ ++ @Description This routine initializes a hash table structure. ++ KeyGen hash result determines the hash bucket. ++ Next, KeyGen key is compared against all keys of this ++ bucket (exact match). ++ Number of sets (number of buckets) of the hash equals to the ++ number of 1-s in 'hash_res_mask' in the provided parameters. ++ Number of hash table ways is then calculated by dividing ++ 'max_num_of_keys' equally between the hash sets. This is the maximal ++ number of keys that a hash bucket may hold. ++ The hash table is initialized empty and keys may be ++ added to it following the initialization. Keys masks are not ++ supported in current hash table implementation. ++ The initialized hash table can be integrated as a node in a ++ CC tree. ++ ++ @Param[in,out] ioc_fm_pcd_hash_table_params_t - Pointer to a structure with the relevant parameters ++ ++ @Return 0 on success; Error code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_HASH_TABLE_SET_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(37), ioc_compat_fm_pcd_hash_table_params_t) ++#endif ++#define FM_PCD_IOC_HASH_TABLE_SET _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(37), ioc_fm_pcd_hash_table_params_t) ++ ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableDelete ++ ++ @Description This routine deletes the provided hash table and released all ++ its allocated resources. ++ ++ @Param[in] ioc_fm_obj_t - The ID of a hash table. ++ ++ @Return 0 on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_HASH_TABLE_DELETE_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(37), ioc_compat_fm_obj_t) ++#endif ++#define FM_PCD_IOC_HASH_TABLE_DELETE _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(37), ioc_fm_obj_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableAddKey ++ ++ @Description This routine adds the provided key (including next engine ++ parameters of this key) to the hash table. ++ The key is added as the last key of the bucket that it is ++ mapped to. ++ ++ @Param[in] ioc_fm_pcd_hash_table_add_key_params_t - Pointer to a structure with the relevant parameters ++ ++ @Return 0 on success; error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_HASH_TABLE_ADD_KEY_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(39), ioc_compat_fm_pcd_hash_table_add_key_params_t) ++#endif ++#define FM_PCD_IOC_HASH_TABLE_ADD_KEY _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(39), ioc_fm_pcd_hash_table_add_key_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_HashTableRemoveKey ++ ++ @Description This routine removes the requested key (including next engine ++ parameters of this key) from the hash table. ++ ++ @Param[in] ioc_fm_pcd_hash_table_remove_key_params_t - Pointer to a structure with the relevant parameters ++ ++ @Return 0 on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_HashTableSet(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_HASH_TABLE_REMOVE_KEY_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(40), ioc_compat_fm_pcd_hash_table_remove_key_params_t) ++#endif ++#define FM_PCD_IOC_HASH_TABLE_REMOVE_KEY _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(40), ioc_fm_pcd_hash_table_remove_key_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_PlcrProfileSet ++ ++ @Description Sets a profile entry in the policer profile table. ++ The routine overrides any existing value. ++ ++ @Param[in,out] ioc_fm_pcd_plcr_profile_params_t A structure of parameters for defining a ++ policer profile entry. ++ ++ @Return 0 on success; Error code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_PLCR_PROFILE_SET_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(41), ioc_compat_fm_pcd_plcr_profile_params_t) ++#endif ++#define FM_PCD_IOC_PLCR_PROFILE_SET _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(41), ioc_fm_pcd_plcr_profile_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_PlcrProfileDelete ++ ++ @Description Delete a profile entry in the policer profile table. ++ The routine set entry to invalid. ++ ++ @Param[in] ioc_fm_obj_t The id of a policer profile. ++ ++ @Return 0 on success; Error code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_PLCR_PROFILE_DELETE_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(41), ioc_compat_fm_obj_t) ++#endif ++#define FM_PCD_IOC_PLCR_PROFILE_DELETE _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(41), ioc_fm_obj_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_ManipNodeSet ++ ++ @Description This routine should be called for defining a manipulation ++ node. A manipulation node must be defined before the CC node ++ that precedes it. ++ ++ @Param[in] ioc_fm_pcd_manip_params_t - A structure of parameters defining the manipulation ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_MANIP_NODE_SET_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(43), ioc_compat_fm_pcd_manip_params_t) ++#endif ++#define FM_PCD_IOC_MANIP_NODE_SET _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(43), ioc_fm_pcd_manip_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_ManipNodeReplace ++ ++ @Description Change existing manipulation node to be according to new requirement. ++ (Here, it's implemented as a variant of the same IOCTL as for ++ FM_PCD_ManipNodeSet(), and one that when called, the 'id' member ++ in its 'ioc_fm_pcd_manip_params_t' argument is set to contain ++ the manip node's handle) ++ ++ @Param[in] ioc_fm_pcd_manip_params_t - A structure of parameters defining the manipulation ++ ++ @Return 0 on success; error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_ManipNodeSet(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_MANIP_NODE_REPLACE_COMPAT FM_PCD_IOC_MANIP_NODE_SET_COMPAT ++#endif ++#define FM_PCD_IOC_MANIP_NODE_REPLACE FM_PCD_IOC_MANIP_NODE_SET ++ ++/**************************************************************************//** ++ @Function FM_PCD_ManipNodeDelete ++ ++ @Description Delete an existing manipulation node. ++ ++ @Param[in] ioc_fm_obj_t The id of the manipulation node to delete. ++ ++ @Return 0 on success; error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_ManipNodeSet(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_MANIP_NODE_DELETE_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(44), ioc_compat_fm_obj_t) ++#endif ++#define FM_PCD_IOC_MANIP_NODE_DELETE _IOW(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(44), ioc_fm_obj_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_ManipGetStatistics ++ ++ @Description Retrieve the manipulation statistics. ++ ++ @Param[in] h_ManipNode A handle to a manipulation node. ++ @Param[out] p_FmPcdManipStats A structure for retrieving the manipulation statistics ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_ManipNodeSet(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_MANIP_GET_STATS_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(50), ioc_compat_fm_pcd_manip_get_stats_t) ++#endif ++#define FM_PCD_IOC_MANIP_GET_STATS _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(50), ioc_fm_pcd_manip_get_stats_t) ++ ++/**************************************************************************//** ++ at Function FM_PCD_SetAdvancedOffloadSupport ++ ++ at Description This routine must be called in order to support the following features: ++ IP-fragmentation, IP-reassembly, IPsec, Header-manipulation, frame-replicator. ++ ++ at Param[in] h_FmPcd FM PCD module descriptor. ++ ++ at Return 0 on success; error code otherwise. ++ ++ at Cautions Allowed only when PCD is disabled. ++*//***************************************************************************/ ++#define FM_PCD_IOC_SET_ADVANCED_OFFLOAD_SUPPORT _IO(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(45)) ++ ++#if (DPAA_VERSION >= 11) ++/**************************************************************************//** ++ @Function FM_PCD_FrmReplicSetGroup ++ ++ @Description Initialize a Frame Replicator group. ++ ++ @Param[in] h_FmPcd FM PCD module descriptor. ++ @Param[in] p_FrmReplicGroupParam A structure of parameters for the initialization of ++ the frame replicator group. ++ ++ @Return A handle to the initialized object on success; NULL code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_Init(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_FRM_REPLIC_GROUP_SET_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(46), ioc_compat_fm_pcd_frm_replic_group_params_t) ++#endif ++#define FM_PCD_IOC_FRM_REPLIC_GROUP_SET _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(46), ioc_fm_pcd_frm_replic_group_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_FrmReplicDeleteGroup ++ ++ @Description Delete a Frame Replicator group. ++ ++ @Param[in] h_FrmReplicGroup A handle to the frame replicator group. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_FrmReplicSetGroup(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_FRM_REPLIC_GROUP_DELETE_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(47), ioc_compat_fm_obj_t) ++#endif ++#define FM_PCD_IOC_FRM_REPLIC_GROUP_DELETE _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(47), ioc_fm_obj_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_FrmReplicAddMember ++ ++ @Description Add the member in the index defined by the memberIndex. ++ ++ @Param[in] h_FrmReplicGroup A handle to the frame replicator group. ++ @Param[in] memberIndex member index for adding. ++ @Param[in] p_MemberParams A pointer to the new member parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_FrmReplicSetGroup() of this group. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_FRM_REPLIC_MEMBER_ADD_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(48), ioc_compat_fm_pcd_frm_replic_member_params_t) ++#endif ++#define FM_PCD_IOC_FRM_REPLIC_MEMBER_ADD _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(48), ioc_fm_pcd_frm_replic_member_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PCD_FrmReplicRemoveMember ++ ++ @Description Remove the member defined by the index from the relevant group. ++ ++ @Param[in] h_FrmReplicGroup A handle to the frame replicator group. ++ @Param[in] memberIndex member index for removing. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PCD_FrmReplicSetGroup() of this group. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_FRM_REPLIC_MEMBER_REMOVE_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(49), ioc_compat_fm_pcd_frm_replic_member_t) ++#endif ++#define FM_PCD_IOC_FRM_REPLIC_MEMBER_REMOVE _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(49), ioc_fm_pcd_frm_replic_member_t) ++ ++#endif ++ ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++/**************************************************************************//** ++ @Function FM_PCD_StatisticsSetNode ++ ++ @Description This routine should be called for defining a statistics node. ++ ++ @Param[in,out] ioc_fm_pcd_stats_params_t A structure of parameters defining the statistics ++ ++ @Return 0 on success; Error code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_STATISTICS_SET_NODE_COMPAT _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(45), void *) ++#endif ++#define FM_PCD_IOC_STATISTICS_SET_NODE _IOWR(FM_IOC_TYPE_BASE, FM_PCD_IOC_NUM(45), void *) ++ ++#endif /* FM_CAPWAP_SUPPORT */ ++ ++#ifdef NCSW_BACKWARD_COMPATIBLE_API ++#if defined(CONFIG_COMPAT) ++#define FM_PCD_IOC_SET_NET_ENV_CHARACTERISTICS_COMPAT \ ++ FM_PCD_IOC_NET_ENV_CHARACTERISTICS_SET_COMPAT ++#define FM_PCD_IOC_DELETE_NET_ENV_CHARACTERISTICS_COMPAT \ ++ FM_PCD_IOC_NET_ENV_CHARACTERISTICS_DELETE_COMPAT ++#define FM_PCD_IOC_KG_SET_SCHEME_COMPAT FM_PCD_IOC_KG_SCHEME_SET_COMPAT ++#define FM_PCD_IOC_KG_DEL_SCHEME_COMPAT FM_PCD_IOC_KG_SCHEME_DELETE_COMPAT ++#define FM_PCD_IOC_CC_BUILD_TREE_COMPAT FM_PCD_IOC_CC_ROOT_BUILD_COMPAT ++#define FM_PCD_IOC_CC_DELETE_TREE_COMPAT FM_PCD_IOC_CC_ROOT_DELETE_COMPAT ++#define FM_PCD_IOC_CC_DELETE_NODE_COMPAT FM_PCD_IOC_MATCH_TABLE_DELETE_COMPAT ++#define FM_PCD_IOC_CC_TREE_MODIFY_NEXT_ENGINE_COMPAT \ ++ FM_PCD_IOC_CC_ROOT_MODIFY_NEXT_ENGINE_COMPAT ++#define FM_PCD_IOC_CC_NODE_MODIFY_NEXT_ENGINE_COMPAT \ ++ FM_PCD_IOC_MATCH_TABLE_MODIFY_NEXT_ENGINE_COMPAT ++#define FM_PCD_IOC_CC_NODE_MODIFY_MISS_NEXT_ENGINE_COMPAT \ ++ FM_PCD_IOC_MATCH_TABLE_MODIFY_MISS_NEXT_ENGINE_COMPAT ++#define FM_PCD_IOC_CC_NODE_REMOVE_KEY_COMPAT FM_PCD_IOC_MATCH_TABLE_REMOVE_KEY_COMPAT ++#define FM_PCD_IOC_CC_NODE_ADD_KEY_COMPAT FM_PCD_IOC_MATCH_TABLE_ADD_KEY_COMPAT ++#define FM_PCD_IOC_CC_NODE_MODIFY_KEY_AND_NEXT_ENGINE_COMPAT \ ++ FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_AND_NEXT_ENGINE_COMPAT ++#define FM_PCD_IOC_CC_NODE_MODIFY_KEY_COMPAT FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_COMPAT ++#define FM_PCD_IOC_PLCR_SET_PROFILE_COMPAT FM_PCD_IOC_PLCR_PROFILE_SET_COMPAT ++#define FM_PCD_IOC_PLCR_DEL_PROFILE_COMPAT FM_PCD_IOC_PLCR_PROFILE_DELETE_COMPAT ++#define FM_PCD_IOC_MANIP_SET_NODE_COMPAT FM_PCD_IOC_MANIP_NODE_SET_COMPAT ++#define FM_PCD_IOC_MANIP_DELETE_NODE_COMPAT FM_PCD_IOC_MANIP_NODE_DELETE_COMPAT ++#endif ++#define FM_PCD_IOC_SET_NET_ENV_CHARACTERISTICS FM_PCD_IOC_NET_ENV_CHARACTERISTICS_SET ++#define FM_PCD_IOC_DELETE_NET_ENV_CHARACTERISTICS \ ++ FM_PCD_IOC_NET_ENV_CHARACTERISTICS_DELETE ++#define FM_PCD_IOC_KG_SET_SCHEME FM_PCD_IOC_KG_SCHEME_SET ++#define FM_PCD_IOC_KG_DEL_SCHEME FM_PCD_IOC_KG_SCHEME_DELETE ++#define FM_PCD_IOC_CC_BUILD_TREE FM_PCD_IOC_CC_ROOT_BUILD ++#define FM_PCD_IOC_CC_DELETE_TREE FM_PCD_IOC_CC_ROOT_DELETE ++#define FM_PCD_IOC_CC_DELETE_NODE FM_PCD_IOC_MATCH_TABLE_DELETE ++#define FM_PCD_IOC_CC_TREE_MODIFY_NEXT_ENGINE FM_PCD_IOC_CC_ROOT_MODIFY_NEXT_ENGINE ++#define FM_PCD_IOC_CC_NODE_MODIFY_NEXT_ENGINE FM_PCD_IOC_MATCH_TABLE_MODIFY_NEXT_ENGINE ++#define FM_PCD_IOC_CC_NODE_MODIFY_MISS_NEXT_ENGINE \ ++ FM_PCD_IOC_MATCH_TABLE_MODIFY_MISS_NEXT_ENGINE ++#define FM_PCD_IOC_CC_NODE_REMOVE_KEY FM_PCD_IOC_MATCH_TABLE_REMOVE_KEY ++#define FM_PCD_IOC_CC_NODE_ADD_KEY FM_PCD_IOC_MATCH_TABLE_ADD_KEY ++#define FM_PCD_IOC_CC_NODE_MODIFY_KEY_AND_NEXT_ENGINE \ ++ FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_AND_NEXT_ENGINE ++#define FM_PCD_IOC_CC_NODE_MODIFY_KEY FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY ++#define FM_PCD_IOC_PLCR_SET_PROFILE FM_PCD_IOC_PLCR_PROFILE_SET ++#define FM_PCD_IOC_PLCR_DEL_PROFILE FM_PCD_IOC_PLCR_PROFILE_DELETE ++#define FM_PCD_IOC_MANIP_SET_NODE FM_PCD_IOC_MANIP_NODE_SET ++#define FM_PCD_IOC_MANIP_DELETE_NODE FM_PCD_IOC_MANIP_NODE_DELETE ++#endif /* NCSW_BACKWARD_COMPATIBLE_API */ ++ ++#endif /* __FM_PCD_IOCTLS_H */ ++/** @} */ /* end of lnx_ioctl_FM_PCD_Runtime_grp group */ ++/** @} */ /* end of lnx_ioctl_FM_PCD_grp group */ ++/** @} */ /* end of lnx_ioctl_FM_grp group */ +diff --git a/include/uapi/linux/fmd/Peripherals/fm_port_ioctls.h b/include/uapi/linux/fmd/Peripherals/fm_port_ioctls.h +new file mode 100644 +index 0000000..a2f6110 +--- /dev/null ++++ b/include/uapi/linux/fmd/Peripherals/fm_port_ioctls.h +@@ -0,0 +1,948 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++/****************************************************************************** ++ @File fm_port_ioctls.h ++ ++ @Description FM Port routines ++*//***************************************************************************/ ++#ifndef __FM_PORT_IOCTLS_H ++#define __FM_PORT_IOCTLS_H ++ ++#include "enet_ext.h" ++#include "net_ioctls.h" ++#include "fm_ioctls.h" ++#include "fm_pcd_ioctls.h" ++ ++ ++/**************************************************************************//** ++ ++ @Group lnx_ioctl_FM_grp Frame Manager Linux IOCTL API ++ ++ @Description FM Linux ioctls definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Group lnx_ioctl_FM_PORT_grp FM Port ++ ++ @Description FM Port API ++ ++ The FM uses a general module called "port" to represent a Tx port ++ (MAC), an Rx port (MAC), offline parsing flow or host command ++ flow. There may be up to 17 (may change) ports in an FM - 5 Tx ++ ports (4 for the 1G MACs, 1 for the 10G MAC), 5 Rx Ports, and 7 ++ Host command/Offline parsing ports. The SW driver manages these ++ ports as sub-modules of the FM, i.e. after an FM is initialized, ++ its ports may be initialized and operated upon. ++ ++ The port is initialized aware of its type, but other functions on ++ a port may be indifferent to its type. When necessary, the driver ++ verifies coherency and returns error if applicable. ++ ++ On initialization, user specifies the port type and it's index ++ (relative to the port's type). Host command and Offline parsing ++ ports share the same id range, I.e user may not initialized host ++ command port 0 and offline parsing port 0. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description An enum for defining port PCD modes. ++ (Must match enum e_FmPortPcdSupport defined in fm_port_ext.h) ++ ++ This enum defines the superset of PCD engines support - i.e. not ++ all engines have to be used, but all have to be enabled. The real ++ flow of a specific frame depends on the PCD configuration and the ++ frame headers and payload. ++ Note: the first engine and the first engine after the parser (if ++ exists) should be in order, the order is important as it will ++ define the flow of the port. However, as for the rest engines ++ (the ones that follows), the order is not important anymore as ++ it is defined by the PCD graph itself. ++*//***************************************************************************/ ++typedef enum ioc_fm_port_pcd_support { ++ e_IOC_FM_PORT_PCD_SUPPORT_NONE = 0 /**< BMI to BMI, PCD is not used */ ++ , e_IOC_FM_PORT_PCD_SUPPORT_PRS_ONLY /**< Use only Parser */ ++ , e_IOC_FM_PORT_PCD_SUPPORT_PLCR_ONLY /**< Use only Policer */ ++ , e_IOC_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR /**< Use Parser and Policer */ ++ , e_IOC_FM_PORT_PCD_SUPPORT_PRS_AND_KG /**< Use Parser and Keygen */ ++ , e_IOC_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC /**< Use Parser, Keygen and Coarse Classification */ ++ , e_IOC_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR ++ /**< Use all PCD engines */ ++ , e_IOC_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR /**< Use Parser, Keygen and Policer */ ++ , e_IOC_FM_PORT_PCD_SUPPORT_PRS_AND_CC /**< Use Parser and Coarse Classification */ ++ , e_IOC_FM_PORT_PCD_SUPPORT_PRS_AND_CC_AND_PLCR /**< Use Parser and Coarse Classification and Policer */ ++ , e_IOC_FM_PORT_PCD_SUPPORT_CC_ONLY /**< Use only Coarse Classification */ ++#if (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) ++ , e_IOC_FM_PORT_PCD_SUPPORT_CC_AND_KG /**< Use Coarse Classification,and Keygen */ ++ , e_IOC_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR /**< Use Coarse Classification, Keygen and Policer */ ++#endif /* FM_CAPWAP_SUPPORT */ ++} ioc_fm_port_pcd_support; ++ ++ ++/**************************************************************************//** ++ @Collection FM Frame error ++*//***************************************************************************/ ++typedef uint32_t ioc_fm_port_frame_err_select_t; /**< typedef for defining Frame Descriptor errors */ ++ ++/* @} */ ++ ++ ++/**************************************************************************//** ++ @Description An enum for defining Dual Tx rate limiting scale. ++ (Must match e_FmPortDualRateLimiterScaleDown defined in fm_port_ext.h) ++*//***************************************************************************/ ++typedef enum ioc_fm_port_dual_rate_limiter_scale_down { ++ e_IOC_FM_PORT_DUAL_RATE_LIMITER_NONE = 0, /**< Use only single rate limiter */ ++ e_IOC_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_2, /**< Divide high rate limiter by 2 */ ++ e_IOC_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_4, /**< Divide high rate limiter by 4 */ ++ e_IOC_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_8 /**< Divide high rate limiter by 8 */ ++} ioc_fm_port_dual_rate_limiter_scale_down; ++ ++/**************************************************************************//** ++ @Description A structure for defining Tx rate limiting ++ (Must match struct t_FmPortRateLimit defined in fm_port_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_port_rate_limit_t { ++ uint16_t max_burst_size; /**< in KBytes for Tx ports, in frames ++ for offline parsing ports. (note that ++ for early chips burst size is ++ rounded up to a multiply of 1000 frames).*/ ++ uint32_t rate_limit; /**< in Kb/sec for Tx ports, in frame/sec for ++ offline parsing ports. Rate limit refers to ++ data rate (rather than line rate). */ ++ ioc_fm_port_dual_rate_limiter_scale_down rate_limit_divider; /**< For offline parsing ports only. Not-valid ++ for some earlier chip revisions */ ++} ioc_fm_port_rate_limit_t; ++ ++ ++ ++/**************************************************************************//** ++ @Group lnx_ioctl_FM_PORT_runtime_control_grp FM Port Runtime Control Unit ++ ++ @Description FM Port Runtime control unit API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description An enum for defining FM Port counters. ++ (Must match enum e_FmPortCounters defined in fm_port_ext.h) ++*//***************************************************************************/ ++typedef enum ioc_fm_port_counters { ++ e_IOC_FM_PORT_COUNTERS_CYCLE, /**< BMI performance counter */ ++ e_IOC_FM_PORT_COUNTERS_TASK_UTIL, /**< BMI performance counter */ ++ e_IOC_FM_PORT_COUNTERS_QUEUE_UTIL, /**< BMI performance counter */ ++ e_IOC_FM_PORT_COUNTERS_DMA_UTIL, /**< BMI performance counter */ ++ e_IOC_FM_PORT_COUNTERS_FIFO_UTIL, /**< BMI performance counter */ ++ e_IOC_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION, /**< BMI Rx only performance counter */ ++ e_IOC_FM_PORT_COUNTERS_FRAME, /**< BMI statistics counter */ ++ e_IOC_FM_PORT_COUNTERS_DISCARD_FRAME, /**< BMI statistics counter */ ++ e_IOC_FM_PORT_COUNTERS_DEALLOC_BUF, /**< BMI deallocate buffer statistics counter */ ++ e_IOC_FM_PORT_COUNTERS_RX_BAD_FRAME, /**< BMI Rx only statistics counter */ ++ e_IOC_FM_PORT_COUNTERS_RX_LARGE_FRAME, /**< BMI Rx only statistics counter */ ++ e_IOC_FM_PORT_COUNTERS_RX_FILTER_FRAME, /**< BMI Rx & OP only statistics counter */ ++ e_IOC_FM_PORT_COUNTERS_RX_LIST_DMA_ERR, /**< BMI Rx, OP & HC only statistics counter */ ++ e_IOC_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD, /**< BMI Rx, OP & HC statistics counter */ ++ e_IOC_FM_PORT_COUNTERS_PREPARE_TO_ENQUEUE_COUNTER, /**< BMI Rx, OP & HC only statistics counter */ ++ e_IOC_FM_PORT_COUNTERS_WRED_DISCARD, /**< BMI OP & HC only statistics counter */ ++ e_IOC_FM_PORT_COUNTERS_LENGTH_ERR, /**< BMI non-Rx statistics counter */ ++ e_IOC_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT, /**< BMI non-Rx statistics counter */ ++ e_IOC_FM_PORT_COUNTERS_DEQ_TOTAL, /**< QMI total QM dequeues counter */ ++ e_IOC_FM_PORT_COUNTERS_ENQ_TOTAL, /**< QMI total QM enqueues counter */ ++ e_IOC_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT, /**< QMI counter */ ++ e_IOC_FM_PORT_COUNTERS_DEQ_CONFIRM /**< QMI counter */ ++} ioc_fm_port_counters; ++ ++typedef struct ioc_fm_port_bmi_stats_t { ++ uint32_t cnt_cycle; ++ uint32_t cnt_task_util; ++ uint32_t cnt_queue_util; ++ uint32_t cnt_dma_util; ++ uint32_t cnt_fifo_util; ++ uint32_t cnt_rx_pause_activation; ++ uint32_t cnt_frame; ++ uint32_t cnt_discard_frame; ++ uint32_t cnt_dealloc_buf; ++ uint32_t cnt_rx_bad_frame; ++ uint32_t cnt_rx_large_frame; ++ uint32_t cnt_rx_filter_frame; ++ uint32_t cnt_rx_list_dma_err; ++ uint32_t cnt_rx_out_of_buffers_discard; ++ uint32_t cnt_wred_discard; ++ uint32_t cnt_length_err; ++ uint32_t cnt_unsupported_format; ++} ioc_fm_port_bmi_stats_t; ++ ++/**************************************************************************//** ++ @Description Structure for Port id parameters. ++ (Description may be inaccurate; ++ must match struct t_FmPortCongestionGrps defined in fm_port_ext.h) ++ ++ Fields commented 'IN' are passed by the port module to be used ++ by the FM module. ++ Fields commented 'OUT' will be filled by FM before returning to port. ++*//***************************************************************************/ ++typedef struct ioc_fm_port_congestion_groups_t { ++ uint16_t num_of_congestion_grps_to_consider; /**< The number of required congestion groups ++ to define the size of the following array */ ++ uint8_t congestion_grps_to_consider [FM_PORT_NUM_OF_CONGESTION_GRPS]; ++ /**< An array of CG indexes; ++ Note that the size of the array should be ++ 'num_of_congestion_grps_to_consider'. */ ++#if DPAA_VERSION >= 11 ++ bool pfc_priorities_enable[FM_PORT_NUM_OF_CONGESTION_GRPS][FM_MAX_NUM_OF_PFC_PRIORITIES]; ++ /**< A matrix that represents the map between the CG ids ++ defined in 'congestion_grps_to_consider' to the priorities ++ mapping array. */ ++#endif /* DPAA_VERSION >= 11 */ ++} ioc_fm_port_congestion_groups_t; ++ ++ ++ ++/**************************************************************************//** ++ @Function FM_PORT_Disable ++ ++ @Description Gracefully disable an FM port. The port will not start new tasks after all ++ tasks associated with the port are terminated. ++ ++ @Return 0 on success; error code otherwise. ++ ++ @Cautions This is a blocking routine, it returns after port is ++ gracefully stopped, i.e. the port will not except new frames, ++ but it will finish all frames or tasks which were already began ++*//***************************************************************************/ ++#define FM_PORT_IOC_DISABLE _IO(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(1)) ++ ++/**************************************************************************//** ++ @Function FM_PORT_Enable ++ ++ @Description A runtime routine provided to allow disable/enable of port. ++ ++ @Return 0 on success; error code otherwise. ++*//***************************************************************************/ ++#define FM_PORT_IOC_ENABLE _IO(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(2)) ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetRateLimit ++ ++ @Description Calling this routine enables rate limit algorithm. ++ By default, this functionality is disabled. ++ Note that rate-limit mechanism uses the FM time stamp. ++ The selected rate limit specified here would be ++ rounded DOWN to the nearest 16M. ++ ++ May be used for Tx and offline parsing ports only ++ ++ @Param[in] ioc_fm_port_rate_limit A structure of rate limit parameters ++ ++ @Return 0 on success; error code otherwise. ++*//***************************************************************************/ ++#define FM_PORT_IOC_SET_RATE_LIMIT _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(3), ioc_fm_port_rate_limit_t) ++ ++/**************************************************************************//** ++ @Function FM_PORT_DeleteRateLimit ++ ++ @Description Calling this routine disables the previously enabled rate limit. ++ ++ May be used for Tx and offline parsing ports only ++ ++ @Return 0 on success; error code otherwise. ++*//***************************************************************************/ ++#define FM_PORT_IOC_DELETE_RATE_LIMIT _IO(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(5)) ++#define FM_PORT_IOC_REMOVE_RATE_LIMIT FM_PORT_IOC_DELETE_RATE_LIMIT ++ ++ ++/**************************************************************************//** ++ @Function FM_PORT_AddCongestionGrps ++ ++ @Description This routine effects the corresponding Tx port. ++ It should be called in order to enable pause ++ frame transmission in case of congestion in one or more ++ of the congestion groups relevant to this port. ++ Each call to this routine may add one or more congestion ++ groups to be considered relevant to this port. ++ ++ May be used for Rx, or RX+OP ports only (depending on chip) ++ ++ @Param[in] ioc_fm_port_congestion_groups_t - A pointer to an array of ++ congestion group ids to consider. ++ ++ @Return 0 on success; error code otherwise. ++*//***************************************************************************/ ++#define FM_PORT_IOC_ADD_CONGESTION_GRPS _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(34), ioc_fm_port_congestion_groups_t) ++ ++/**************************************************************************//** ++ @Function FM_PORT_RemoveCongestionGrps ++ ++ @Description This routine effects the corresponding Tx port. It should be ++ called when congestion groups were ++ defined for this port and are no longer relevant, or pause ++ frames transmitting is not required on their behalf. ++ Each call to this routine may remove one or more congestion ++ groups to be considered relevant to this port. ++ ++ May be used for Rx, or RX+OP ports only (depending on chip) ++ ++ @Param[in] ioc_fm_port_congestion_groups_t - A pointer to an array of ++ congestion group ids to consider. ++ ++ @Return 0 on success; error code otherwise. ++*//***************************************************************************/ ++#define FM_PORT_IOC_REMOVE_CONGESTION_GRPS _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(35), ioc_fm_port_congestion_groups_t) ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetErrorsRoute ++ ++ @Description Errors selected for this routine will cause a frame with that error ++ to be enqueued to error queue. ++ Errors not selected for this routine will cause a frame with that error ++ to be enqueued to the one of the other port queues. ++ By default all errors are defined to be enqueued to error queue. ++ Errors that were configured to be discarded (at initialization) ++ may not be selected here. ++ ++ May be used for Rx and offline parsing ports only ++ ++ @Param[in] ioc_fm_port_frame_err_select_t A list of errors to enqueue to error queue ++ ++ @Return 0 on success; error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++ (szbs001: How is it possible to have one function that needs to be ++ called BEFORE FM_PORT_Init() implemented as an ioctl, ++ which will ALWAYS be called AFTER the FM_PORT_Init() ++ for that port!?!?!?!???!?!??!?!?) ++*//***************************************************************************/ ++#define FM_PORT_IOC_SET_ERRORS_ROUTE _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(4), ioc_fm_port_frame_err_select_t) ++ ++ ++/**************************************************************************//** ++ @Group lnx_ioctl_FM_PORT_pcd_runtime_control_grp FM Port PCD Runtime Control Unit ++ ++ @Description FM Port PCD Runtime control unit API functions, definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description A structure defining the KG scheme after the parser. ++ (Must match struct t_FmPcdKgSchemeSelect defined in fm_port_ext.h) ++ ++ This is relevant only to change scheme selection mode - from ++ direct to indirect and vice versa, or when the scheme is selected directly, ++ to select the scheme id. ++ ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_kg_scheme_select_t { ++ bool direct; /**< TRUE to use 'scheme_id' directly, FALSE to use LCV.*/ ++ void *scheme_id; /**< Relevant for 'direct'=TRUE only. ++ 'scheme_id' selects the scheme after parser. */ ++} ioc_fm_pcd_kg_scheme_select_t; ++ ++/**************************************************************************//** ++ @Description Scheme IDs structure ++ (Must match struct t_FmPcdPortSchemesParams defined in fm_port_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_port_schemes_params_t { ++ uint8_t num_of_schemes; /**< Number of schemes for port to be bound to. */ ++ void *scheme_ids[FM_PCD_KG_NUM_OF_SCHEMES]; /**< Array of 'num_of_schemes' schemes for the ++ port to be bound to */ ++} ioc_fm_pcd_port_schemes_params_t; ++ ++/**************************************************************************//** ++ @Description A union for defining port protocol parameters for parser ++ (Must match union u_FmPcdHdrPrsOpts defined in fm_port_ext.h) ++*//***************************************************************************/ ++typedef union ioc_fm_pcd_hdr_prs_opts_u { ++ /* MPLS */ ++ struct { ++ bool label_interpretation_enable;/**< When this bit is set, the last MPLS label will be ++ interpreted as described in HW spec table. When the bit ++ is cleared, the parser will advance to MPLS next parse */ ++ ioc_net_header_type next_parse; /**< must be equal or higher than IPv4 */ ++ } mpls_prs_options; ++ ++ /* VLAN */ ++ struct { ++ uint16_t tag_protocol_id1; /**< User defined Tag Protocol Identifier, to be recognized ++ on VLAN TAG on top of 0x8100 and 0x88A8 */ ++ uint16_t tag_protocol_id2; /**< User defined Tag Protocol Identifier, to be recognized ++ on VLAN TAG on top of 0x8100 and 0x88A8 */ ++ } vlan_prs_options; ++ ++ /* PPP */ ++ struct{ ++ bool enable_mtu_check; /**< Check validity of MTU according to RFC2516 */ ++ } pppoe_prs_options; ++ ++ /* IPV6 */ ++ struct { ++ bool routing_hdr_disable; /**< Disable routing header */ ++ } ipv6_prs_options; ++ ++ /* UDP */ ++ struct { ++ bool pad_ignore_checksum; /**< TRUE to ignore pad in checksum */ ++ } udp_prs_options; ++ ++ /* TCP */ ++ struct { ++ bool pad_ignore_checksum; /**< TRUE to ignore pad in checksum */ ++ } tcp_prs_options; ++} ioc_fm_pcd_hdr_prs_opts_u; ++ ++/**************************************************************************//** ++ @Description A structure for defining each header for the parser ++ (must match struct t_FmPcdPrsAdditionalHdrParams defined in fm_port_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_prs_additional_hdr_params_t { ++ ioc_net_header_type hdr; /**< Selected header */ ++ bool err_disable; /**< TRUE to disable error indication */ ++ bool soft_prs_enable; /**< Enable jump to SW parser when this ++ header is recognized by the HW parser. */ ++ uint8_t index_per_hdr; /**< Normally 0, if more than one sw parser ++ attachments exists for the same header, ++ (in the main sw parser code) use this ++ index to distinguish between them. */ ++ bool use_prs_opts; /**< TRUE to use parser options. */ ++ ioc_fm_pcd_hdr_prs_opts_u prs_opts; /**< A unuion according to header type, ++ defining the parser options selected.*/ ++} ioc_fm_pcd_prs_additional_hdr_params_t; ++ ++/**************************************************************************//** ++ @Description A structure for defining port PCD parameters ++ (Must match t_FmPortPcdPrsParams defined in fm_port_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_port_pcd_prs_params_t { ++ uint8_t prs_res_priv_info; /**< The private info provides a method of inserting ++ port information into the parser result. This information ++ may be extracted by KeyGen and be used for frames ++ distribution when a per-port distinction is required, ++ it may also be used as a port logical id for analyzing ++ incoming frames. */ ++ uint8_t parsing_offset; /**< Number of bytes from begining of packet to start parsing */ ++ ioc_net_header_type first_prs_hdr; /**< The type of the first header axpected at 'parsing_offset' */ ++ bool include_in_prs_statistics; /**< TRUE to include this port in the parser statistics */ ++ uint8_t num_of_hdrs_with_additional_params; ++ /**< Normally 0, some headers may get special parameters */ ++ ioc_fm_pcd_prs_additional_hdr_params_t additional_params[IOC_FM_PCD_PRS_NUM_OF_HDRS]; ++ /**< 'num_of_hdrs_with_additional_params' structures ++ additional parameters for each header that requires them */ ++ bool set_vlan_tpid1; /**< TRUE to configure user selection of Ethertype to ++ indicate a VLAN tag (in addition to the TPID values ++ 0x8100 and 0x88A8). */ ++ uint16_t vlan_tpid1; /**< extra tag to use if set_vlan_tpid1=TRUE. */ ++ bool set_vlan_tpid2; /**< TRUE to configure user selection of Ethertype to ++ indicate a VLAN tag (in addition to the TPID values ++ 0x8100 and 0x88A8). */ ++ uint16_t vlan_tpid2; /**< extra tag to use if set_vlan_tpid1=TRUE. */ ++} ioc_fm_port_pcd_prs_params_t; ++ ++/**************************************************************************//** ++ @Description A structure for defining coarse alassification parameters ++ (Must match t_FmPortPcdCcParams defined in fm_port_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_port_pcd_cc_params_t { ++ void *cc_tree_id; /**< CC tree id */ ++} ioc_fm_port_pcd_cc_params_t; ++ ++/**************************************************************************//** ++ @Description A structure for defining keygen parameters ++ (Must match t_FmPortPcdKgParams defined in fm_port_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_port_pcd_kg_params_t { ++ uint8_t num_of_schemes; /**< Number of schemes for port to be bound to. */ ++ void *scheme_ids[FM_PCD_KG_NUM_OF_SCHEMES]; ++ /**< Array of 'num_of_schemes' schemes for the ++ port to be bound to */ ++ bool direct_scheme; /**< TRUE for going from parser to a specific scheme, ++ regardless of parser result */ ++ void *direct_scheme_id; /**< Scheme id, as returned by FM_PCD_KgSetScheme; ++ relevant only if direct=TRUE. */ ++} ioc_fm_port_pcd_kg_params_t; ++ ++/**************************************************************************//** ++ @Description A structure for defining policer parameters ++ (Must match t_FmPortPcdPlcrParams defined in fm_port_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_port_pcd_plcr_params_t { ++ void *plcr_profile_id; /**< Selected profile handle; ++ relevant in one of the following cases: ++ e_IOC_FM_PORT_PCD_SUPPORT_PLCR_ONLY or ++ e_IOC_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR were selected, ++ or if any flow uses a KG scheme where policer ++ profile is not generated (bypass_plcr_profile_generation selected) */ ++} ioc_fm_port_pcd_plcr_params_t; ++ ++/**************************************************************************//** ++ @Description A structure for defining port PCD parameters ++ (Must match struct t_FmPortPcdParams defined in fm_port_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_port_pcd_params_t { ++ ioc_fm_port_pcd_support pcd_support; /**< Relevant for Rx and offline ports only. ++ Describes the active PCD engines for this port. */ ++ void *net_env_id; /**< HL Unused in PLCR only mode */ ++ ioc_fm_port_pcd_prs_params_t *p_prs_params; /**< Parser parameters for this port */ ++ ioc_fm_port_pcd_cc_params_t *p_cc_params; /**< Coarse classification parameters for this port */ ++ ioc_fm_port_pcd_kg_params_t *p_kg_params; /**< Keygen parameters for this port */ ++ ioc_fm_port_pcd_plcr_params_t *p_plcr_params; /**< Policer parameters for this port */ ++ void *p_ip_reassembly_manip;/**< IP Reassembly manipulation */ ++#if (DPAA_VERSION >= 11) ++ void *p_capwap_reassembly_manip;/**< CAPWAP Reassembly manipulation */ ++#endif /* (DPAA_VERSION >= 11) */ ++} ioc_fm_port_pcd_params_t; ++ ++/**************************************************************************//** ++ @Description A structure for defining the Parser starting point ++ (Must match struct t_FmPcdPrsStart defined in fm_port_ext.h) ++*//***************************************************************************/ ++typedef struct ioc_fm_pcd_prs_start_t { ++ uint8_t parsing_offset; /**< Number of bytes from begining of packet to ++ start parsing */ ++ ioc_net_header_type first_prs_hdr; /**< The type of the first header axpected at ++ 'parsing_offset' */ ++} ioc_fm_pcd_prs_start_t; ++ ++ ++/**************************************************************************//** ++ @Description FQID parameters structure ++*//***************************************************************************/ ++typedef struct ioc_fm_port_pcd_fqids_params_t { ++ uint32_t num_fqids; /**< Number of fqids to be allocated for the port */ ++ uint8_t alignment; /**< Alignment required for this port */ ++ uint32_t base_fqid; /**< output parameter - the base fqid */ ++} ioc_fm_port_pcd_fqids_params_t; ++ ++ ++/**************************************************************************//** ++ @Function FM_PORT_IOC_ALLOC_PCD_FQIDS ++ ++ @Description Allocates FQID's ++ ++ May be used for Rx and offline parsing ports only ++ ++ @Param[in,out] ioc_fm_port_pcd_fqids_params_t Parameters for allocating FQID's ++ ++ @Return 0 on success; error code otherwise. ++*//***************************************************************************/ ++#define FM_PORT_IOC_ALLOC_PCD_FQIDS _IOWR(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(19), ioc_fm_port_pcd_fqids_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PORT_IOC_FREE_PCD_FQIDS ++ ++ @Description Frees previously-allocated FQIDs ++ ++ May be used for Rx and offline parsing ports only ++ ++ @Param[in] uint32_t Base FQID of previously allocated range. ++ ++ @Return 0 on success; error code otherwise. ++*//***************************************************************************/ ++#define FM_PORT_IOC_FREE_PCD_FQIDS _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(19), uint32_t) ++ ++ ++/**************************************************************************//** ++ @Function FM_PORT_SetPCD ++ ++ @Description Calling this routine defines the port's PCD configuration. ++ It changes it from its default configuration which is PCD ++ disabled (BMI to BMI) and configures it according to the passed ++ parameters. ++ ++ May be used for Rx and offline parsing ports only ++ ++ @Param[in] ioc_fm_port_pcd_params_t A Structure of parameters defining the port's PCD ++ configuration. ++ ++ @Return 0 on success; error code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PORT_IOC_SET_PCD_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(20), ioc_compat_fm_port_pcd_params_t) ++#endif ++#define FM_PORT_IOC_SET_PCD _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(20), ioc_fm_port_pcd_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PORT_DeletePCD ++ ++ @Description Calling this routine releases the port's PCD configuration. ++ The port returns to its default configuration which is PCD ++ disabled (BMI to BMI) and all PCD configuration is removed. ++ ++ May be used for Rx and offline parsing ports which are ++ in PCD mode only ++ ++ @Return 0 on success; error code otherwise. ++*//***************************************************************************/ ++#define FM_PORT_IOC_DELETE_PCD _IO(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(21)) ++ ++/**************************************************************************//** ++ @Function FM_PORT_AttachPCD ++ ++ @Description This routine may be called after FM_PORT_DetachPCD was called, ++ to return to the originally configured PCD support flow. ++ The couple of routines are used to allow PCD configuration changes ++ that demand that PCD will not be used while changes take place. ++ ++ May be used for Rx and offline parsing ports which are ++ in PCD mode only ++ ++ @Return 0 on success; error code otherwise. ++*//***************************************************************************/ ++#define FM_PORT_IOC_ATTACH_PCD _IO(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(23)) ++ ++/**************************************************************************//** ++ @Function FM_PORT_DetachPCD ++ ++ @Description Calling this routine detaches the port from its PCD functionality. ++ The port returns to its default flow which is BMI to BMI. ++ ++ May be used for Rx and offline parsing ports which are ++ in PCD mode only ++ ++ @Return 0 on success; error code otherwise. ++*//***************************************************************************/ ++#define FM_PORT_IOC_DETACH_PCD _IO(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(22)) ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdPlcrAllocProfiles ++ ++ @Description This routine may be called only for ports that use the Policer in ++ order to allocate private policer profiles. ++ ++ @Param[in] uint16_t The number of required policer profiles ++ ++ @Return 0 on success; error code otherwise. ++ ++ @Cautions Allowed before FM_PORT_SetPCD() only. ++*//***************************************************************************/ ++#define FM_PORT_IOC_PCD_PLCR_ALLOC_PROFILES _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(24), uint16_t) ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdPlcrFreeProfiles ++ ++ @Description This routine should be called for freeing private policer profiles. ++ ++ @Return 0 on success; error code otherwise. ++ ++ @Cautions Allowed before FM_PORT_SetPCD() only. ++*//***************************************************************************/ ++#define FM_PORT_IOC_PCD_PLCR_FREE_PROFILES _IO(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(25)) ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdKgModifyInitialScheme ++ ++ @Description This routine may be called only for ports that use the keygen in ++ order to change the initial scheme frame should be routed to. ++ The change may be of a scheme id (in case of direct mode), ++ from direct to indirect, or from indirect to direct - specifying the scheme id. ++ ++ @Param[in] ioc_fm_pcd_kg_scheme_select_t A structure of parameters for defining whether ++ a scheme is direct/indirect, and if direct - scheme id. ++ ++ @Return 0 on success; error code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PORT_IOC_PCD_KG_MODIFY_INITIAL_SCHEME_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(26), ioc_compat_fm_pcd_kg_scheme_select_t) ++#endif ++#define FM_PORT_IOC_PCD_KG_MODIFY_INITIAL_SCHEME _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(26), ioc_fm_pcd_kg_scheme_select_t) ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdPlcrModifyInitialProfile ++ ++ @Description This routine may be called for ports with flows ++ e_IOC_FM_PCD_SUPPORT_PLCR_ONLY or e_IOC_FM_PCD_SUPPORT_PRS_AND_PLCR only, ++ to change the initial Policer profile frame should be routed to. ++ The change may be of a profile and/or absolute/direct mode selection. ++ ++ @Param[in] ioc_fm_obj_t Policer profile Id as returned from FM_PCD_PlcrSetProfile. ++ ++ @Return 0 on success; error code otherwise. ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PORT_IOC_PCD_PLCR_MODIFY_INITIAL_PROFILE_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(27), ioc_compat_fm_obj_t) ++#endif ++#define FM_PORT_IOC_PCD_PLCR_MODIFY_INITIAL_PROFILE _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(27), ioc_fm_obj_t) ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdCcModifyTree ++ ++ @Description This routine may be called to change this port connection to ++ a pre-initializes coarse classification Tree. ++ ++ @Param[in] ioc_fm_obj_t Id of new coarse classification tree selected for this port. ++ ++ @Return 0 on success; error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_SetPCD() and FM_PORT_DetachPCD() ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PORT_IOC_PCD_CC_MODIFY_TREE_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(28), ioc_compat_fm_obj_t) ++#endif ++#define FM_PORT_IOC_PCD_CC_MODIFY_TREE _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(28), ioc_fm_obj_t) ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdKgBindSchemes ++ ++ @Description These routines may be called for modifying the binding of ports ++ to schemes. The scheme itself is not added, ++ just this specific port starts using it. ++ ++ @Param[in] ioc_fm_pcd_port_schemes_params_t Schemes parameters structre ++ ++ @Return 0 on success; error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_SetPCD(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PORT_IOC_PCD_KG_BIND_SCHEMES_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(30), ioc_compat_fm_pcd_port_schemes_params_t) ++#endif ++#define FM_PORT_IOC_PCD_KG_BIND_SCHEMES _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(30), ioc_fm_pcd_port_schemes_params_t) ++ ++/**************************************************************************//** ++ @Function FM_PORT_PcdKgUnbindSchemes ++ ++ @Description These routines may be called for modifying the binding of ports ++ to schemes. The scheme itself is not removed or invalidated, ++ just this specific port stops using it. ++ ++ @Param[in] ioc_fm_pcd_port_schemes_params_t Schemes parameters structre ++ ++ @Return 0 on success; error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_SetPCD(). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PORT_IOC_PCD_KG_UNBIND_SCHEMES_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(31), ioc_compat_fm_pcd_port_schemes_params_t) ++#endif ++#define FM_PORT_IOC_PCD_KG_UNBIND_SCHEMES _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(31), ioc_fm_pcd_port_schemes_params_t) ++ ++typedef struct ioc_fm_port_mac_addr_params_t { ++ uint8_t addr[ENET_NUM_OCTETS_PER_ADDRESS]; ++} ioc_fm_port_mac_addr_params_t; ++ ++/**************************************************************************//** ++ @Function FM_MAC_AddHashMacAddr ++ ++ @Description Add an Address to the hash table. This is for filter purpose only. ++ ++ @Param[in] ioc_fm_port_mac_addr_params_t - Ethernet Mac address ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). It is a filter only address. ++ @Cautions Some address need to be filtered out in upper FM blocks. ++*//***************************************************************************/ ++#define FM_PORT_IOC_ADD_RX_HASH_MAC_ADDR _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(36), ioc_fm_port_mac_addr_params_t) ++ ++/**************************************************************************//** ++ @Function FM_MAC_RemoveHashMacAddr ++ ++ @Description Delete an Address to the hash table. This is for filter purpose only. ++ ++ @Param[in] ioc_fm_port_mac_addr_params_t - Ethernet Mac address ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++*//***************************************************************************/ ++#define FM_PORT_IOC_REMOVE_RX_HASH_MAC_ADDR _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(37), ioc_fm_port_mac_addr_params_t) ++ ++typedef struct ioc_fm_port_tx_pause_frames_params_t { ++ uint8_t priority; ++ uint16_t pause_time; ++ uint16_t thresh_time; ++} ioc_fm_port_tx_pause_frames_params_t; ++ ++/**************************************************************************//** ++ @Function FM_MAC_SetTxPauseFrames ++ ++ @Description Enable/Disable transmission of Pause-Frames. ++ The routine changes the default configuration: ++ pause-time - [0xf000] ++ threshold-time - [0] ++ ++ @Param[in] ioc_fm_port_tx_pause_frames_params_t A structure holding the required parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_MAC_Init(). ++ PFC is supported only on new mEMAC; i.e. in MACs that don't have ++ PFC support (10G-MAC and dTSEC), user should use 'FM_MAC_NO_PFC' ++ in the 'priority' field. ++*//***************************************************************************/ ++#define FM_PORT_IOC_SET_TX_PAUSE_FRAMES _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(40), ioc_fm_port_tx_pause_frames_params_t) ++ ++typedef struct ioc_fm_port_mac_statistics_t { ++ /* RMON */ ++ uint64_t e_stat_pkts_64; /**< r-10G tr-DT 64 byte frame counter */ ++ uint64_t e_stat_pkts_65_to_127; /**< r-10G 65 to 127 byte frame counter */ ++ uint64_t e_stat_pkts_128_to_255; /**< r-10G 128 to 255 byte frame counter */ ++ uint64_t e_stat_pkts_256_to_511; /**< r-10G 256 to 511 byte frame counter */ ++ uint64_t e_stat_pkts_512_to_1023; /**< r-10G 512 to 1023 byte frame counter */ ++ uint64_t e_stat_pkts_1024_to_1518; /**< r-10G 1024 to 1518 byte frame counter */ ++ uint64_t e_stat_pkts_1519_to_1522; /**< r-10G 1519 to 1522 byte good frame count */ ++ /* */ ++ uint64_t e_stat_fragments; /**< Total number of packets that were less than 64 octets long with a wrong CRC.*/ ++ uint64_t e_stat_jabbers; /**< Total number of packets longer than valid maximum length octets */ ++ uint64_t e_stat_drop_events; /**< number of dropped packets due to internal errors of the MAC Client (during recieve). */ ++ uint64_t e_stat_CRC_align_errors; /**< Incremented when frames of correct length but with CRC error are received.*/ ++ uint64_t e_stat_undersize_pkts; /**< Incremented for frames under 64 bytes with a valid FCS and otherwise well formed; ++ This count does not include range length errors */ ++ uint64_t e_stat_oversize_pkts; /**< Incremented for frames which exceed 1518 (non VLAN) or 1522 (VLAN) and contains ++ a valid FCS and otherwise well formed */ ++ /* Pause */ ++ uint64_t te_stat_pause; /**< Pause MAC Control received */ ++ uint64_t re_stat_pause; /**< Pause MAC Control sent */ ++ /* MIB II */ ++ uint64_t if_in_octets; /**< Total number of byte received. */ ++ uint64_t if_in_pkts; /**< Total number of packets received.*/ ++ uint64_t if_in_ucast_pkts; /**< Total number of unicast frame received; ++ NOTE: this counter is not supported on dTSEC MAC */ ++ uint64_t if_in_mcast_pkts; /**< Total number of multicast frame received*/ ++ uint64_t if_in_bcast_pkts; /**< Total number of broadcast frame received */ ++ uint64_t if_in_discards; /**< Frames received, but discarded due to problems within the MAC RX. */ ++ uint64_t if_in_errors; /**< Number of frames received with error: ++ - FIFO Overflow Error ++ - CRC Error ++ - Frame Too Long Error ++ - Alignment Error ++ - The dedicated Error Code (0xfe, not a code error) was received */ ++ uint64_t if_out_octets; /**< Total number of byte sent. */ ++ uint64_t if_out_pkts; /**< Total number of packets sent .*/ ++ uint64_t if_out_ucast_pkts; /**< Total number of unicast frame sent; ++ NOTE: this counter is not supported on dTSEC MAC */ ++ uint64_t if_out_mcast_pkts; /**< Total number of multicast frame sent */ ++ uint64_t if_out_bcast_pkts; /**< Total number of multicast frame sent */ ++ uint64_t if_out_discards; /**< Frames received, but discarded due to problems within the MAC TX N/A!.*/ ++ uint64_t if_out_errors; /**< Number of frames transmitted with error: ++ - FIFO Overflow Error ++ - FIFO Underflow Error ++ - Other */ ++} ioc_fm_port_mac_statistics_t; ++ ++/**************************************************************************//** ++ @Function FM_MAC_GetStatistics ++ ++ @Description get all MAC statistics counters ++ ++ @Param[out] ioc_fm_port_mac_statistics_t A structure holding the statistics ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_Init(). ++*//***************************************************************************/ ++#define FM_PORT_IOC_GET_MAC_STATISTICS _IOR(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(41), ioc_fm_port_mac_statistics_t) ++ ++/**************************************************************************//** ++ @Function FM_PORT_ConfigBufferPrefixContent ++ ++ @Description Defines the structure, size and content of the application buffer. ++ The prefix will ++ In Tx ports, if 'passPrsResult', the application ++ should set a value to their offsets in the prefix of ++ the FM will save the first 'privDataSize', than, ++ depending on 'passPrsResult' and 'passTimeStamp', copy parse result ++ and timeStamp, and the packet itself (in this order), to the ++ application buffer, and to offset. ++ Calling this routine changes the buffer margins definitions ++ in the internal driver data base from its default ++ configuration: Data size: [DEFAULT_FM_SP_bufferPrefixContent_privDataSize] ++ Pass Parser result: [DEFAULT_FM_SP_bufferPrefixContent_passPrsResult]. ++ Pass timestamp: [DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp]. ++ ++ May be used for all ports ++ ++ @Param[in] ioc_fm_buffer_prefix_content_t A structure holding the required parameters. ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init(). ++*//***************************************************************************/ ++#define FM_PORT_IOC_CONFIG_BUFFER_PREFIX_CONTENT _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(39), ioc_fm_buffer_prefix_content_t) ++ ++#if (DPAA_VERSION >= 11) ++typedef struct ioc_fm_port_vsp_alloc_params_t { ++ uint8_t num_of_profiles; /**< Number of Virtual Storage Profiles */ ++ uint8_t dflt_relative_id; /**< The default Virtual-Storage-Profile-id dedicated to Rx/OP port ++ The same default Virtual-Storage-Profile-id will be for coupled Tx port ++ if relevant function called for Rx port */ ++ void *p_fm_tx_port; /**< Handle to coupled Tx Port; not relevant for OP port. */ ++}ioc_fm_port_vsp_alloc_params_t; ++ ++/**************************************************************************//** ++ @Function FM_PORT_VSPAlloc ++ ++ @Description This routine allocated VSPs per port and forces the port to work ++ in VSP mode. Note that the port is initialized by default with the ++ physical-storage-profile only. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[in] p_Params A structure of parameters for allocation VSP's per port ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(), and before FM_PORT_SetPCD() ++ and also before FM_PORT_Enable() (i.e. the port should be disabled). ++*//***************************************************************************/ ++#if defined(CONFIG_COMPAT) ++#define FM_PORT_IOC_VSP_ALLOC_COMPAT _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(38), ioc_compat_fm_port_vsp_alloc_params_t) ++#endif ++#define FM_PORT_IOC_VSP_ALLOC _IOW(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(38), ioc_fm_port_vsp_alloc_params_t) ++#endif /* (DPAA_VERSION >= 11) */ ++ ++/**************************************************************************//** ++ @Function FM_PORT_GetBmiCounters ++ ++ @Description Read port's BMI stat counters and place them into ++ a designated structure of counters. ++ ++ @Param[in] h_FmPort A handle to a FM Port module. ++ @Param[out] p_BmiStats counters structure ++ ++ @Return E_OK on success; Error code otherwise. ++ ++ @Cautions Allowed only following FM_PORT_Init(). ++*//***************************************************************************/ ++ ++#define FM_PORT_IOC_GET_BMI_COUNTERS _IOR(FM_IOC_TYPE_BASE, FM_PORT_IOC_NUM(42), ioc_fm_port_bmi_stats_t) ++ ++ ++/** @} */ /* end of lnx_ioctl_FM_PORT_pcd_runtime_control_grp group */ ++/** @} */ /* end of lnx_ioctl_FM_PORT_runtime_control_grp group */ ++ ++/** @} */ /* end of lnx_ioctl_FM_PORT_grp group */ ++/** @} */ /* end of lnx_ioctl_FM_grp group */ ++#endif /* __FM_PORT_IOCTLS_H */ +diff --git a/include/uapi/linux/fmd/Peripherals/fm_test_ioctls.h b/include/uapi/linux/fmd/Peripherals/fm_test_ioctls.h +new file mode 100644 +index 0000000..207ed1e +--- /dev/null ++++ b/include/uapi/linux/fmd/Peripherals/fm_test_ioctls.h +@@ -0,0 +1,208 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++/**************************************************************************//** ++ @File fm_test_ioctls.h ++ ++ @Description FM Char device ioctls ++*//***************************************************************************/ ++#ifndef __FM_TEST_IOCTLS_H ++#define __FM_TEST_IOCTLS_H ++ ++#include "ioctls.h" ++ ++ ++/**************************************************************************//** ++ @Group lnx_ioctl_FMT_grp Frame Manager Test Linux IOCTL API ++ ++ @Description FM-Test Linux ioctls definitions and enums ++ ++ @{ ++*//***************************************************************************/ ++ ++#define IOC_FMT_MAX_NUM_OF_PORTS 26 ++ ++/**************************************************************************//** ++ @Collection TEST Parameters ++*//***************************************************************************/ ++/**************************************************************************//** ++ @Description: Name of the FM-Test chardev ++*//***************************************************************************/ ++#define DEV_FM_TEST_NAME "fm-test-port" ++ ++#define DEV_FM_TEST_PORTS_MINOR_BASE 0 ++#define DEV_FM_TEST_MAX_MINORS (DEV_FM_TEST_PORTS_MINOR_BASE + IOC_FMT_MAX_NUM_OF_PORTS) ++ ++#define FMT_PORT_IOC_NUM(n) n ++/* @} */ ++ ++/**************************************************************************//** ++ @Group lnx_ioctl_FMT_lib_grp FM-Test library ++ ++ @Description TODO ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description TODO ++*//***************************************************************************/ ++typedef uint8_t ioc_fmt_xxx_t; ++ ++#define FM_PRS_MAX 32 ++#define FM_TIME_STAMP_MAX 8 ++ ++/**************************************************************************//** ++ @Description FM Port buffer content description ++*//***************************************************************************/ ++typedef struct ioc_fmt_buff_context_t { ++ void *p_user_priv; ++ uint8_t fm_prs_res[FM_PRS_MAX]; ++ uint8_t fm_time_stamp[FM_TIME_STAMP_MAX]; ++} ioc_fmt_buff_context_t; ++ ++#if defined(__KERNEL__) && defined(CONFIG_COMPAT) ++typedef struct ioc_fmt_compat_buff_context_t { ++ compat_uptr_t p_user_priv; ++ uint8_t fm_prs_res[FM_PRS_MAX]; ++ uint8_t fm_time_stamp[FM_TIME_STAMP_MAX]; ++} ioc_fmt_compat_buff_context_t; ++#endif ++ ++/**************************************************************************//** ++ @Description Buffer descriptor ++*//***************************************************************************/ ++typedef struct ioc_fmt_buff_desc_t { ++ uint32_t qid; ++ void *p_data; ++ uint32_t size; ++ uint32_t status; ++ ioc_fmt_buff_context_t buff_context; ++} ioc_fmt_buff_desc_t; ++ ++#if defined(__KERNEL__) && defined(CONFIG_COMPAT) ++typedef struct ioc_fmt_compat_buff_desc_t { ++ uint32_t qid; ++ compat_uptr_t p_data; ++ uint32_t size; ++ uint32_t status; ++ ioc_fmt_compat_buff_context_t buff_context; ++} ioc_fmt_compat_buff_desc_t; ++#endif ++ ++/**************************************************************************//** ++ @Group lnx_ioctl_FMT_runtime_control_grp FM-Test Runtime Control Unit ++ ++ @Description TODO ++ @{ ++*//***************************************************************************/ ++ ++/** @} */ /* end of lnx_ioctl_FMT_runtime_control_grp group */ ++ ++ ++/**************************************************************************//** ++ @Group lnx_ioctl_FMTP_lib_grp FM-Port-Test library ++ ++ @Description TODO ++ ++ @{ ++*//***************************************************************************/ ++ ++/**************************************************************************//** ++ @Description FM-Test FM port type ++*//***************************************************************************/ ++typedef enum ioc_fmt_port_type { ++ e_IOC_FMT_PORT_T_RXTX, /**< Standard port */ ++ e_IOC_FMT_PORT_T_OP, /**< Offline-parsing port */ ++} ioc_fmt_port_type; ++ ++/**************************************************************************//** ++ @Description TODO ++*//***************************************************************************/ ++typedef struct ioc_fmt_port_param_t { ++ uint8_t fm_id; ++ ioc_fmt_port_type fm_port_type; ++ uint8_t fm_port_id; ++ uint32_t num_tx_queues; ++} ioc_fmt_port_param_t; ++ ++ ++/**************************************************************************//** ++ @Function FMT_PORT_IOC_INIT ++ ++ @Description TODO ++ ++ @Param[in] ioc_fmt_port_param_t TODO ++ ++ @Cautions Allowed only after the FM equivalent port is already initialized. ++*//***************************************************************************/ ++#define FMT_PORT_IOC_INIT _IOW(FMT_IOC_TYPE_BASE, FMT_PORT_IOC_NUM(0), ioc_fmt_port_param_t) ++ ++/**************************************************************************//** ++ @Function FMT_PORT_IOC_SET_DIAG_MODE ++ ++ @Description TODO ++ ++ @Param[in] ioc_diag_mode TODO ++ ++ @Cautions Allowed only following FMT_PORT_IOC_INIT(). ++*//***************************************************************************/ ++#define FMT_PORT_IOC_SET_DIAG_MODE _IOW(FMT_IOC_TYPE_BASE, FMT_PORT_IOC_NUM(1), ioc_diag_mode) ++ ++/**************************************************************************//** ++ @Function FMT_PORT_IOC_SET_IP_HEADER_MANIP ++ ++ @Description Set IP header manipulations for this port. ++ ++ @Param[in] int 1 to enable; 0 to disable ++ ++ @Cautions Allowed only following FMT_PORT_IOC_INIT(). ++*//***************************************************************************/ ++#define FMT_PORT_IOC_SET_IP_HEADER_MANIP _IOW(FMT_IOC_TYPE_BASE, FMT_PORT_IOC_NUM(2), int) ++ ++/**************************************************************************//** ++ @Function FMT_PORT_IOC_SET_DPAECHO_MODE ++ ++ @Description Set DPA in echo mode - all frame are sent back. ++ ++ @Param[in] int 1 to enable; 0 to disable ++ ++ @Cautions Allowed only following FMT_PORT_IOC_INIT(). ++*//***************************************************************************/ ++#define FMT_PORT_IOC_SET_DPAECHO_MODE _IOW(FMT_IOC_TYPE_BASE, FMT_PORT_IOC_NUM(3), int) ++ ++/** @} */ /* end of lnx_ioctl_FMTP_lib_grp group */ ++/** @} */ /* end of lnx_ioctl_FMT_lib_grp group */ ++/** @} */ /* end of lnx_ioctl_FMT_grp */ ++ ++ ++#endif /* __FM_TEST_IOCTLS_H */ +diff --git a/include/uapi/linux/fmd/integrations/Kbuild b/include/uapi/linux/fmd/integrations/Kbuild +new file mode 100644 +index 0000000..e548d67 +--- /dev/null ++++ b/include/uapi/linux/fmd/integrations/Kbuild +@@ -0,0 +1 @@ ++header-y += integration_ioctls.h +diff --git a/include/uapi/linux/fmd/integrations/integration_ioctls.h b/include/uapi/linux/fmd/integrations/integration_ioctls.h +new file mode 100644 +index 0000000..61d696e +--- /dev/null ++++ b/include/uapi/linux/fmd/integrations/integration_ioctls.h +@@ -0,0 +1,56 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++/**************************************************************************//** ++ @File integration_ioctls.h ++ ++ @Description External header file for Integration unit routines. ++*//***************************************************************************/ ++ ++#ifndef __INTG_IOCTLS_H ++#define __INTG_IOCTLS_H ++ ++ ++#define FM_IOC_TYPE_BASE (NCSW_IOC_TYPE_BASE+1) ++#define FMT_IOC_TYPE_BASE (NCSW_IOC_TYPE_BASE+3) ++ ++/*#define FM_IOCTL_DBG*/ ++ ++#if defined(FM_IOCTL_DBG) ++ #define _fm_ioctl_dbg(format, arg...) \ ++ printk("fm ioctl [%s:%u](cpu:%u) - " format, \ ++ __func__, __LINE__, smp_processor_id(), ##arg) ++#else ++# define _fm_ioctl_dbg(arg...) ++#endif ++ ++#endif /* __INTG_IOCTLS_H */ +diff --git a/include/uapi/linux/fmd/ioctls.h b/include/uapi/linux/fmd/ioctls.h +new file mode 100644 +index 0000000..4f36cb0 +--- /dev/null ++++ b/include/uapi/linux/fmd/ioctls.h +@@ -0,0 +1,96 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++/**************************************************************************//** ++ @File ioctls.h ++ ++ @Description Structures and definitions for Command Relay Ioctls ++*//***************************************************************************/ ++ ++#ifndef __IOCTLS_H__ ++#define __IOCTLS_H__ ++ ++#include ++ ++#include "integration_ioctls.h" ++ ++ ++/**************************************************************************//** ++ @Group lnx_ioctl_ncsw_grp NetCommSw Linux User-Space (IOCTL) API ++ @{ ++*//***************************************************************************/ ++ ++#define NCSW_IOC_TYPE_BASE 0xe0 /**< defines the IOCTL type for all ++ the NCSW Linux module commands */ ++ ++ ++/**************************************************************************//** ++ @Description IOCTL Memory allocation types. ++*//***************************************************************************/ ++typedef enum ioc_mem_type { ++ e_IOC_MEM_INVALID = 0x00000000, /**< Invalid memory type (error) */ ++ e_IOC_MEM_CACHABLE_SYS = 0x00000001, /**< Primary DDR, cacheable segment */ ++ e_IOC_MEM_NOCACHE_SYS = 0x00000004, /**< Primary DDR, non-cacheable segment */ ++ e_IOC_MEM_SECONDARY = 0x00000002, /**< Either secondary DDR or SDRAM */ ++ e_IOC_MEM_PRAM = 0x00000008 /**< Multi-user RAM identifier */ ++} ioc_mem_type; ++ ++/**************************************************************************//** ++ @Description Enumeration (bit flags) of communication modes (Transmit, ++ receive or both). ++*//***************************************************************************/ ++typedef enum ioc_comm_mode { ++ e_IOC_COMM_MODE_NONE = 0 /**< No transmit/receive communication */ ++ , e_IOC_COMM_MODE_RX = 1 /**< Only receive communication */ ++ , e_IOC_COMM_MODE_TX = 2 /**< Only transmit communication */ ++ , e_IOC_COMM_MODE_RX_AND_TX = 3 /**< Both transmit and receive communication */ ++} ioc_comm_mode; ++ ++/**************************************************************************//** ++ @Description General Diagnostic Mode ++*//***************************************************************************/ ++typedef enum ioc_diag_mode ++{ ++ e_IOC_DIAG_MODE_NONE = 0, ++ e_IOC_DIAG_MODE_CTRL_LOOPBACK, /**< loopback in the controller; E.g. MAC, TDM, etc. */ ++ e_IOC_DIAG_MODE_CHIP_LOOPBACK, /**< loopback in the chip but not in controller; ++ E.g. IO-pins, SerDes, etc. */ ++ e_IOC_DIAG_MODE_PHY_LOOPBACK, /**< loopback in the external PHY */ ++ e_IOC_DIAG_MODE_LINE_LOOPBACK, /**< loopback in the external line */ ++ e_IOC_DIAG_MODE_CTRL_ECHO, /**< */ ++ e_IOC_DIAG_MODE_PHY_ECHO /**< */ ++} ioc_diag_mode; ++ ++/** @} */ /* end of lnx_ioctl_ncsw_grp */ ++ ++ ++#endif /* __IOCTLS_H__ */ +diff --git a/include/uapi/linux/fmd/net_ioctls.h b/include/uapi/linux/fmd/net_ioctls.h +new file mode 100644 +index 0000000..c99d64c +--- /dev/null ++++ b/include/uapi/linux/fmd/net_ioctls.h +@@ -0,0 +1,430 @@ ++/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File net_ioctls.h ++ ++ @Description This file contains common and general netcomm headers definitions. ++*//***************************************************************************/ ++#ifndef __NET_IOCTLS_H ++#define __NET_IOCTLS_H ++ ++#include "ioctls.h" ++ ++ ++typedef uint8_t ioc_header_field_ppp_t; ++ ++#define IOC_NET_HEADER_FIELD_PPP_PID (1) ++#define IOC_NET_HEADER_FIELD_PPP_COMPRESSED (IOC_NET_HEADER_FIELD_PPP_PID << 1) ++#define IOC_NET_HEADER_FIELD_PPP_ALL_FIELDS ((IOC_NET_HEADER_FIELD_PPP_PID << 2) - 1) ++ ++ ++typedef uint8_t ioc_header_field_pppoe_t; ++ ++#define IOC_NET_HEADER_FIELD_PPPoE_VER (1) ++#define IOC_NET_HEADER_FIELD_PPPoE_TYPE (IOC_NET_HEADER_FIELD_PPPoE_VER << 1) ++#define IOC_NET_HEADER_FIELD_PPPoE_CODE (IOC_NET_HEADER_FIELD_PPPoE_VER << 2) ++#define IOC_NET_HEADER_FIELD_PPPoE_SID (IOC_NET_HEADER_FIELD_PPPoE_VER << 3) ++#define IOC_NET_HEADER_FIELD_PPPoE_LEN (IOC_NET_HEADER_FIELD_PPPoE_VER << 4) ++#define IOC_NET_HEADER_FIELD_PPPoE_SESSION (IOC_NET_HEADER_FIELD_PPPoE_VER << 5) ++#define IOC_NET_HEADER_FIELD_PPPoE_PID (IOC_NET_HEADER_FIELD_PPPoE_VER << 6) ++#define IOC_NET_HEADER_FIELD_PPPoE_ALL_FIELDS ((IOC_NET_HEADER_FIELD_PPPoE_VER << 7) - 1) ++ ++#define IOC_NET_HEADER_FIELD_PPPMUX_PID (1) ++#define IOC_NET_HEADER_FIELD_PPPMUX_CKSUM (IOC_NET_HEADER_FIELD_PPPMUX_PID << 1) ++#define IOC_NET_HEADER_FIELD_PPPMUX_COMPRESSED (IOC_NET_HEADER_FIELD_PPPMUX_PID << 2) ++#define IOC_NET_HEADER_FIELD_PPPMUX_ALL_FIELDS ((IOC_NET_HEADER_FIELD_PPPMUX_PID << 3) - 1) ++ ++#define IOC_NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF (1) ++#define IOC_NET_HEADER_FIELD_PPPMUX_SUBFRAME_LXT (IOC_NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 1) ++#define IOC_NET_HEADER_FIELD_PPPMUX_SUBFRAME_LEN (IOC_NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 2) ++#define IOC_NET_HEADER_FIELD_PPPMUX_SUBFRAME_PID (IOC_NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 3) ++#define IOC_NET_HEADER_FIELD_PPPMUX_SUBFRAME_USE_PID (IOC_NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 4) ++#define IOC_NET_HEADER_FIELD_PPPMUX_SUBFRAME_ALL_FIELDS ((IOC_NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 5) - 1) ++ ++ ++typedef uint8_t ioc_header_field_eth_t; ++ ++#define IOC_NET_HEADER_FIELD_ETH_DA (1) ++#define IOC_NET_HEADER_FIELD_ETH_SA (IOC_NET_HEADER_FIELD_ETH_DA << 1) ++#define IOC_NET_HEADER_FIELD_ETH_LENGTH (IOC_NET_HEADER_FIELD_ETH_DA << 2) ++#define IOC_NET_HEADER_FIELD_ETH_TYPE (IOC_NET_HEADER_FIELD_ETH_DA << 3) ++#define IOC_NET_HEADER_FIELD_ETH_FINAL_CKSUM (IOC_NET_HEADER_FIELD_ETH_DA << 4) ++#define IOC_NET_HEADER_FIELD_ETH_PADDING (IOC_NET_HEADER_FIELD_ETH_DA << 5) ++#define IOC_NET_HEADER_FIELD_ETH_ALL_FIELDS ((IOC_NET_HEADER_FIELD_ETH_DA << 6) - 1) ++ ++#define IOC_NET_HEADER_FIELD_ETH_ADDR_SIZE 6 ++ ++typedef uint16_t ioc_header_field_ip_t; ++ ++#define IOC_NET_HEADER_FIELD_IP_VER (1) ++#define IOC_NET_HEADER_FIELD_IP_DSCP (IOC_NET_HEADER_FIELD_IP_VER << 2) ++#define IOC_NET_HEADER_FIELD_IP_ECN (IOC_NET_HEADER_FIELD_IP_VER << 3) ++#define IOC_NET_HEADER_FIELD_IP_PROTO (IOC_NET_HEADER_FIELD_IP_VER << 4) ++ ++#define IOC_NET_HEADER_FIELD_IP_PROTO_SIZE 1 ++ ++typedef uint16_t ioc_header_field_ipv4_t; ++ ++#define IOC_NET_HEADER_FIELD_IPv4_VER (1) ++#define IOC_NET_HEADER_FIELD_IPv4_HDR_LEN (IOC_NET_HEADER_FIELD_IPv4_VER << 1) ++#define IOC_NET_HEADER_FIELD_IPv4_TOS (IOC_NET_HEADER_FIELD_IPv4_VER << 2) ++#define IOC_NET_HEADER_FIELD_IPv4_TOTAL_LEN (IOC_NET_HEADER_FIELD_IPv4_VER << 3) ++#define IOC_NET_HEADER_FIELD_IPv4_ID (IOC_NET_HEADER_FIELD_IPv4_VER << 4) ++#define IOC_NET_HEADER_FIELD_IPv4_FLAG_D (IOC_NET_HEADER_FIELD_IPv4_VER << 5) ++#define IOC_NET_HEADER_FIELD_IPv4_FLAG_M (IOC_NET_HEADER_FIELD_IPv4_VER << 6) ++#define IOC_NET_HEADER_FIELD_IPv4_OFFSET (IOC_NET_HEADER_FIELD_IPv4_VER << 7) ++#define IOC_NET_HEADER_FIELD_IPv4_TTL (IOC_NET_HEADER_FIELD_IPv4_VER << 8) ++#define IOC_NET_HEADER_FIELD_IPv4_PROTO (IOC_NET_HEADER_FIELD_IPv4_VER << 9) ++#define IOC_NET_HEADER_FIELD_IPv4_CKSUM (IOC_NET_HEADER_FIELD_IPv4_VER << 10) ++#define IOC_NET_HEADER_FIELD_IPv4_SRC_IP (IOC_NET_HEADER_FIELD_IPv4_VER << 11) ++#define IOC_NET_HEADER_FIELD_IPv4_DST_IP (IOC_NET_HEADER_FIELD_IPv4_VER << 12) ++#define IOC_NET_HEADER_FIELD_IPv4_OPTS (IOC_NET_HEADER_FIELD_IPv4_VER << 13) ++#define IOC_NET_HEADER_FIELD_IPv4_OPTS_COUNT (IOC_NET_HEADER_FIELD_IPv4_VER << 14) ++#define IOC_NET_HEADER_FIELD_IPv4_ALL_FIELDS ((IOC_NET_HEADER_FIELD_IPv4_VER << 15) - 1) ++ ++#define IOC_NET_HEADER_FIELD_IPv4_ADDR_SIZE 4 ++#define IOC_NET_HEADER_FIELD_IPv4_PROTO_SIZE 1 ++ ++ ++typedef uint8_t ioc_header_field_ipv6_t; ++ ++#define IOC_NET_HEADER_FIELD_IPv6_VER (1) ++#define IOC_NET_HEADER_FIELD_IPv6_TC (IOC_NET_HEADER_FIELD_IPv6_VER << 1) ++#define IOC_NET_HEADER_FIELD_IPv6_SRC_IP (IOC_NET_HEADER_FIELD_IPv6_VER << 2) ++#define IOC_NET_HEADER_FIELD_IPv6_DST_IP (IOC_NET_HEADER_FIELD_IPv6_VER << 3) ++#define IOC_NET_HEADER_FIELD_IPv6_NEXT_HDR (IOC_NET_HEADER_FIELD_IPv6_VER << 4) ++#define IOC_NET_HEADER_FIELD_IPv6_FL (IOC_NET_HEADER_FIELD_IPv6_VER << 5) ++#define IOC_NET_HEADER_FIELD_IPv6_HOP_LIMIT (IOC_NET_HEADER_FIELD_IPv6_VER << 6) ++#define IOC_NET_HEADER_FIELD_IPv6_ALL_FIELDS ((IOC_NET_HEADER_FIELD_IPv6_VER << 7) - 1) ++ ++#define IOC_NET_HEADER_FIELD_IPv6_ADDR_SIZE 16 ++#define IOC_NET_HEADER_FIELD_IPv6_NEXT_HDR_SIZE 1 ++ ++#define IOC_NET_HEADER_FIELD_ICMP_TYPE (1) ++#define IOC_NET_HEADER_FIELD_ICMP_CODE (IOC_NET_HEADER_FIELD_ICMP_TYPE << 1) ++#define IOC_NET_HEADER_FIELD_ICMP_CKSUM (IOC_NET_HEADER_FIELD_ICMP_TYPE << 2) ++#define IOC_NET_HEADER_FIELD_ICMP_ID (IOC_NET_HEADER_FIELD_ICMP_TYPE << 3) ++#define IOC_NET_HEADER_FIELD_ICMP_SQ_NUM (IOC_NET_HEADER_FIELD_ICMP_TYPE << 4) ++#define IOC_NET_HEADER_FIELD_ICMP_ALL_FIELDS ((IOC_NET_HEADER_FIELD_ICMP_TYPE << 5) - 1) ++ ++#define IOC_NET_HEADER_FIELD_ICMP_CODE_SIZE 1 ++#define IOC_NET_HEADER_FIELD_ICMP_TYPE_SIZE 1 ++ ++#define IOC_NET_HEADER_FIELD_IGMP_VERSION (1) ++#define IOC_NET_HEADER_FIELD_IGMP_TYPE (IOC_NET_HEADER_FIELD_IGMP_VERSION << 1) ++#define IOC_NET_HEADER_FIELD_IGMP_CKSUM (IOC_NET_HEADER_FIELD_IGMP_VERSION << 2) ++#define IOC_NET_HEADER_FIELD_IGMP_DATA (IOC_NET_HEADER_FIELD_IGMP_VERSION << 3) ++#define IOC_NET_HEADER_FIELD_IGMP_ALL_FIELDS ((IOC_NET_HEADER_FIELD_IGMP_VERSION << 4) - 1) ++ ++ ++typedef uint16_t ioc_header_field_tcp_t; ++ ++#define IOC_NET_HEADER_FIELD_TCP_PORT_SRC (1) ++#define IOC_NET_HEADER_FIELD_TCP_PORT_DST (IOC_NET_HEADER_FIELD_TCP_PORT_SRC << 1) ++#define IOC_NET_HEADER_FIELD_TCP_SEQ (IOC_NET_HEADER_FIELD_TCP_PORT_SRC << 2) ++#define IOC_NET_HEADER_FIELD_TCP_ACK (IOC_NET_HEADER_FIELD_TCP_PORT_SRC << 3) ++#define IOC_NET_HEADER_FIELD_TCP_OFFSET (IOC_NET_HEADER_FIELD_TCP_PORT_SRC << 4) ++#define IOC_NET_HEADER_FIELD_TCP_FLAGS (IOC_NET_HEADER_FIELD_TCP_PORT_SRC << 5) ++#define IOC_NET_HEADER_FIELD_TCP_WINDOW (IOC_NET_HEADER_FIELD_TCP_PORT_SRC << 6) ++#define IOC_NET_HEADER_FIELD_TCP_CKSUM (IOC_NET_HEADER_FIELD_TCP_PORT_SRC << 7) ++#define IOC_NET_HEADER_FIELD_TCP_URGPTR (IOC_NET_HEADER_FIELD_TCP_PORT_SRC << 8) ++#define IOC_NET_HEADER_FIELD_TCP_OPTS (IOC_NET_HEADER_FIELD_TCP_PORT_SRC << 9) ++#define IOC_NET_HEADER_FIELD_TCP_OPTS_COUNT (IOC_NET_HEADER_FIELD_TCP_PORT_SRC << 10) ++#define IOC_NET_HEADER_FIELD_TCP_ALL_FIELDS ((IOC_NET_HEADER_FIELD_TCP_PORT_SRC << 11) - 1) ++ ++#define IOC_NET_HEADER_FIELD_TCP_PORT_SIZE 2 ++ ++ ++typedef uint8_t ioc_header_field_sctp_t; ++ ++#define IOC_NET_HEADER_FIELD_SCTP_PORT_SRC (1) ++#define IOC_NET_HEADER_FIELD_SCTP_PORT_DST (IOC_NET_HEADER_FIELD_SCTP_PORT_SRC << 1) ++#define IOC_NET_HEADER_FIELD_SCTP_VER_TAG (IOC_NET_HEADER_FIELD_SCTP_PORT_SRC << 2) ++#define IOC_NET_HEADER_FIELD_SCTP_CKSUM (IOC_NET_HEADER_FIELD_SCTP_PORT_SRC << 3) ++#define IOC_NET_HEADER_FIELD_SCTP_ALL_FIELDS ((IOC_NET_HEADER_FIELD_SCTP_PORT_SRC << 4) - 1) ++ ++#define IOC_NET_HEADER_FIELD_SCTP_PORT_SIZE 2 ++ ++typedef uint8_t ioc_header_field_dccp_t; ++ ++#define IOC_NET_HEADER_FIELD_DCCP_PORT_SRC (1) ++#define IOC_NET_HEADER_FIELD_DCCP_PORT_DST (IOC_NET_HEADER_FIELD_DCCP_PORT_SRC << 1) ++#define IOC_NET_HEADER_FIELD_DCCP_ALL_FIELDS ((IOC_NET_HEADER_FIELD_DCCP_PORT_SRC << 2) - 1) ++ ++#define IOC_NET_HEADER_FIELD_DCCP_PORT_SIZE 2 ++ ++ ++typedef uint8_t ioc_header_field_udp_t; ++ ++#define IOC_NET_HEADER_FIELD_UDP_PORT_SRC (1) ++#define IOC_NET_HEADER_FIELD_UDP_PORT_DST (IOC_NET_HEADER_FIELD_UDP_PORT_SRC << 1) ++#define IOC_NET_HEADER_FIELD_UDP_LEN (IOC_NET_HEADER_FIELD_UDP_PORT_SRC << 2) ++#define IOC_NET_HEADER_FIELD_UDP_CKSUM (IOC_NET_HEADER_FIELD_UDP_PORT_SRC << 3) ++#define IOC_NET_HEADER_FIELD_UDP_ALL_FIELDS ((IOC_NET_HEADER_FIELD_UDP_PORT_SRC << 4) - 1) ++ ++#define IOC_NET_HEADER_FIELD_UDP_PORT_SIZE 2 ++ ++typedef uint8_t ioc_header_field_udp_lite_t; ++ ++#define IOC_NET_HEADER_FIELD_UDP_LITE_PORT_SRC (1) ++#define IOC_NET_HEADER_FIELD_UDP_LITE_PORT_DST (IOC_NET_HEADER_FIELD_UDP_LITE_PORT_SRC << 1) ++#define IOC_NET_HEADER_FIELD_UDP_LITE_ALL_FIELDS ((IOC_NET_HEADER_FIELD_UDP_LITE_PORT_SRC << 2) - 1) ++ ++#define IOC_NET_HEADER_FIELD_UDP_LITE_PORT_SIZE 2 ++ ++typedef uint8_t ioc_header_field_udp_encap_esp_t; ++ ++#define IOC_NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC (1) ++#define IOC_NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST (IOC_NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 1) ++#define IOC_NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN (IOC_NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 2) ++#define IOC_NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM (IOC_NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 3) ++#define IOC_NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI (IOC_NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 4) ++#define IOC_NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM (IOC_NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 5) ++#define IOC_NET_HEADER_FIELD_UDP_ENCAP_ESP_ALL_FIELDS ((IOC_NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 6) - 1) ++ ++#define IOC_NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SIZE 2 ++#define IOC_NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI_SIZE 4 ++ ++#define IOC_NET_HEADER_FIELD_IPHC_CID (1) ++#define IOC_NET_HEADER_FIELD_IPHC_CID_TYPE (IOC_NET_HEADER_FIELD_IPHC_CID << 1) ++#define IOC_NET_HEADER_FIELD_IPHC_HCINDEX (IOC_NET_HEADER_FIELD_IPHC_CID << 2) ++#define IOC_NET_HEADER_FIELD_IPHC_GEN (IOC_NET_HEADER_FIELD_IPHC_CID << 3) ++#define IOC_NET_HEADER_FIELD_IPHC_D_BIT (IOC_NET_HEADER_FIELD_IPHC_CID << 4) ++#define IOC_NET_HEADER_FIELD_IPHC_ALL_FIELDS ((IOC_NET_HEADER_FIELD_IPHC_CID << 5) - 1) ++ ++#define IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE (1) ++#define IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_FLAGS (IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 1) ++#define IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_LENGTH (IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 2) ++#define IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_TSN (IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 3) ++#define IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_STREAM_ID (IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 4) ++#define IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_STREAM_SQN (IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 5) ++#define IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_PAYLOAD_PID (IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 6) ++#define IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_UNORDERED (IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 7) ++#define IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_BEGGINING (IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 8) ++#define IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_END (IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 9) ++#define IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_ALL_FIELDS ((IOC_NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 10) - 1) ++ ++#define IOC_NET_HEADER_FIELD_L2TPv2_TYPE_BIT (1) ++#define IOC_NET_HEADER_FIELD_L2TPv2_LENGTH_BIT (IOC_NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 1) ++#define IOC_NET_HEADER_FIELD_L2TPv2_SEQUENCE_BIT (IOC_NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 2) ++#define IOC_NET_HEADER_FIELD_L2TPv2_OFFSET_BIT (IOC_NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 3) ++#define IOC_NET_HEADER_FIELD_L2TPv2_PRIORITY_BIT (IOC_NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 4) ++#define IOC_NET_HEADER_FIELD_L2TPv2_VERSION (IOC_NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 5) ++#define IOC_NET_HEADER_FIELD_L2TPv2_LEN (IOC_NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 6) ++#define IOC_NET_HEADER_FIELD_L2TPv2_TUNNEL_ID (IOC_NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 7) ++#define IOC_NET_HEADER_FIELD_L2TPv2_SESSION_ID (IOC_NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 8) ++#define IOC_NET_HEADER_FIELD_L2TPv2_NS (IOC_NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 9) ++#define IOC_NET_HEADER_FIELD_L2TPv2_NR (IOC_NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 10) ++#define IOC_NET_HEADER_FIELD_L2TPv2_OFFSET_SIZE (IOC_NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 11) ++#define IOC_NET_HEADER_FIELD_L2TPv2_FIRST_BYTE (IOC_NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 12) ++#define IOC_NET_HEADER_FIELD_L2TPv2_ALL_FIELDS ((IOC_NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 13) - 1) ++ ++#define IOC_NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT (1) ++#define IOC_NET_HEADER_FIELD_L2TPv3_CTRL_LENGTH_BIT (IOC_NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 1) ++#define IOC_NET_HEADER_FIELD_L2TPv3_CTRL_SEQUENCE_BIT (IOC_NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 2) ++#define IOC_NET_HEADER_FIELD_L2TPv3_CTRL_VERSION (IOC_NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 3) ++#define IOC_NET_HEADER_FIELD_L2TPv3_CTRL_LENGTH (IOC_NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 4) ++#define IOC_NET_HEADER_FIELD_L2TPv3_CTRL_CONTROL (IOC_NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 5) ++#define IOC_NET_HEADER_FIELD_L2TPv3_CTRL_SENT (IOC_NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 6) ++#define IOC_NET_HEADER_FIELD_L2TPv3_CTRL_RECV (IOC_NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 7) ++#define IOC_NET_HEADER_FIELD_L2TPv3_CTRL_FIRST_BYTE (IOC_NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 8) ++#define IOC_NET_HEADER_FIELD_L2TPv3_CTRL_ALL_FIELDS ((IOC_NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 9) - 1) ++ ++#define IOC_NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT (1) ++#define IOC_NET_HEADER_FIELD_L2TPv3_SESS_VERSION (IOC_NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT << 1) ++#define IOC_NET_HEADER_FIELD_L2TPv3_SESS_ID (IOC_NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT << 2) ++#define IOC_NET_HEADER_FIELD_L2TPv3_SESS_COOKIE (IOC_NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT << 3) ++#define IOC_NET_HEADER_FIELD_L2TPv3_SESS_ALL_FIELDS ((IOC_NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT << 4) - 1) ++ ++ ++typedef uint8_t ioc_header_field_vlan_t; ++ ++#define IOC_NET_HEADER_FIELD_VLAN_VPRI (1) ++#define IOC_NET_HEADER_FIELD_VLAN_CFI (IOC_NET_HEADER_FIELD_VLAN_VPRI << 1) ++#define IOC_NET_HEADER_FIELD_VLAN_VID (IOC_NET_HEADER_FIELD_VLAN_VPRI << 2) ++#define IOC_NET_HEADER_FIELD_VLAN_LENGTH (IOC_NET_HEADER_FIELD_VLAN_VPRI << 3) ++#define IOC_NET_HEADER_FIELD_VLAN_TYPE (IOC_NET_HEADER_FIELD_VLAN_VPRI << 4) ++#define IOC_NET_HEADER_FIELD_VLAN_ALL_FIELDS ((IOC_NET_HEADER_FIELD_VLAN_VPRI << 5) - 1) ++ ++#define IOC_NET_HEADER_FIELD_VLAN_TCI (IOC_NET_HEADER_FIELD_VLAN_VPRI | \ ++ IOC_NET_HEADER_FIELD_VLAN_CFI | \ ++ IOC_NET_HEADER_FIELD_VLAN_VID) ++ ++ ++typedef uint8_t ioc_header_field_llc_t; ++ ++#define IOC_NET_HEADER_FIELD_LLC_DSAP (1) ++#define IOC_NET_HEADER_FIELD_LLC_SSAP (IOC_NET_HEADER_FIELD_LLC_DSAP << 1) ++#define IOC_NET_HEADER_FIELD_LLC_CTRL (IOC_NET_HEADER_FIELD_LLC_DSAP << 2) ++#define IOC_NET_HEADER_FIELD_LLC_ALL_FIELDS ((IOC_NET_HEADER_FIELD_LLC_DSAP << 3) - 1) ++ ++#define IOC_NET_HEADER_FIELD_NLPID_NLPID (1) ++#define IOC_NET_HEADER_FIELD_NLPID_ALL_FIELDS ((IOC_NET_HEADER_FIELD_NLPID_NLPID << 1) - 1) ++ ++ ++typedef uint8_t ioc_header_field_snap_t; ++ ++#define IOC_NET_HEADER_FIELD_SNAP_OUI (1) ++#define IOC_NET_HEADER_FIELD_SNAP_PID (IOC_NET_HEADER_FIELD_SNAP_OUI << 1) ++#define IOC_NET_HEADER_FIELD_SNAP_ALL_FIELDS ((IOC_NET_HEADER_FIELD_SNAP_OUI << 2) - 1) ++ ++ ++typedef uint8_t ioc_header_field_llc_snap_t; ++ ++#define IOC_NET_HEADER_FIELD_LLC_SNAP_TYPE (1) ++#define IOC_NET_HEADER_FIELD_LLC_SNAP_ALL_FIELDS ((IOC_NET_HEADER_FIELD_LLC_SNAP_TYPE << 1) - 1) ++ ++#define IOC_NET_HEADER_FIELD_ARP_HTYPE (1) ++#define IOC_NET_HEADER_FIELD_ARP_PTYPE (IOC_NET_HEADER_FIELD_ARP_HTYPE << 1) ++#define IOC_NET_HEADER_FIELD_ARP_HLEN (IOC_NET_HEADER_FIELD_ARP_HTYPE << 2) ++#define IOC_NET_HEADER_FIELD_ARP_PLEN (IOC_NET_HEADER_FIELD_ARP_HTYPE << 3) ++#define IOC_NET_HEADER_FIELD_ARP_OPER (IOC_NET_HEADER_FIELD_ARP_HTYPE << 4) ++#define IOC_NET_HEADER_FIELD_ARP_SHA (IOC_NET_HEADER_FIELD_ARP_HTYPE << 5) ++#define IOC_NET_HEADER_FIELD_ARP_SPA (IOC_NET_HEADER_FIELD_ARP_HTYPE << 6) ++#define IOC_NET_HEADER_FIELD_ARP_THA (IOC_NET_HEADER_FIELD_ARP_HTYPE << 7) ++#define IOC_NET_HEADER_FIELD_ARP_TPA (IOC_NET_HEADER_FIELD_ARP_HTYPE << 8) ++#define IOC_NET_HEADER_FIELD_ARP_ALL_FIELDS ((IOC_NET_HEADER_FIELD_ARP_HTYPE << 9) - 1) ++ ++#define IOC_NET_HEADER_FIELD_RFC2684_LLC (1) ++#define IOC_NET_HEADER_FIELD_RFC2684_NLPID (IOC_NET_HEADER_FIELD_RFC2684_LLC << 1) ++#define IOC_NET_HEADER_FIELD_RFC2684_OUI (IOC_NET_HEADER_FIELD_RFC2684_LLC << 2) ++#define IOC_NET_HEADER_FIELD_RFC2684_PID (IOC_NET_HEADER_FIELD_RFC2684_LLC << 3) ++#define IOC_NET_HEADER_FIELD_RFC2684_VPN_OUI (IOC_NET_HEADER_FIELD_RFC2684_LLC << 4) ++#define IOC_NET_HEADER_FIELD_RFC2684_VPN_IDX (IOC_NET_HEADER_FIELD_RFC2684_LLC << 5) ++#define IOC_NET_HEADER_FIELD_RFC2684_ALL_FIELDS ((IOC_NET_HEADER_FIELD_RFC2684_LLC << 6) - 1) ++ ++#define IOC_NET_HEADER_FIELD_USER_DEFINED_SRCPORT (1) ++#define IOC_NET_HEADER_FIELD_USER_DEFINED_PCDID (IOC_NET_HEADER_FIELD_USER_DEFINED_SRCPORT << 1) ++#define IOC_NET_HEADER_FIELD_USER_DEFINED_ALL_FIELDS ((IOC_NET_HEADER_FIELD_USER_DEFINED_SRCPORT << 2) - 1) ++ ++#define IOC_NET_HEADER_FIELD_PAYLOAD_BUFFER (1) ++#define IOC_NET_HEADER_FIELD_PAYLOAD_SIZE (IOC_NET_HEADER_FIELD_PAYLOAD_BUFFER << 1) ++#define IOC_NET_HEADER_FIELD_MAX_FRM_SIZE (IOC_NET_HEADER_FIELD_PAYLOAD_BUFFER << 2) ++#define IOC_NET_HEADER_FIELD_MIN_FRM_SIZE (IOC_NET_HEADER_FIELD_PAYLOAD_BUFFER << 3) ++#define IOC_NET_HEADER_FIELD_PAYLOAD_TYPE (IOC_NET_HEADER_FIELD_PAYLOAD_BUFFER << 4) ++#define IOC_NET_HEADER_FIELD_FRAME_SIZE (IOC_NET_HEADER_FIELD_PAYLOAD_BUFFER << 5) ++#define IOC_NET_HEADER_FIELD_PAYLOAD_ALL_FIELDS ((IOC_NET_HEADER_FIELD_PAYLOAD_BUFFER << 6) - 1) ++ ++ ++typedef uint8_t ioc_header_field_gre_t; ++ ++#define IOC_NET_HEADER_FIELD_GRE_TYPE (1) ++#define IOC_NET_HEADER_FIELD_GRE_ALL_FIELDS ((IOC_NET_HEADER_FIELD_GRE_TYPE << 1) - 1) ++ ++ ++typedef uint8_t ioc_header_field_minencap_t; ++ ++#define IOC_NET_HEADER_FIELD_MINENCAP_SRC_IP (1) ++#define IOC_NET_HEADER_FIELD_MINENCAP_DST_IP (IOC_NET_HEADER_FIELD_MINENCAP_SRC_IP << 1) ++#define IOC_NET_HEADER_FIELD_MINENCAP_TYPE (IOC_NET_HEADER_FIELD_MINENCAP_SRC_IP << 2) ++#define IOC_NET_HEADER_FIELD_MINENCAP_ALL_FIELDS ((IOC_NET_HEADER_FIELD_MINENCAP_SRC_IP << 3) - 1) ++ ++ ++typedef uint8_t ioc_header_field_ipsec_ah_t; ++ ++#define IOC_NET_HEADER_FIELD_IPSEC_AH_SPI (1) ++#define IOC_NET_HEADER_FIELD_IPSEC_AH_NH (IOC_NET_HEADER_FIELD_IPSEC_AH_SPI << 1) ++#define IOC_NET_HEADER_FIELD_IPSEC_AH_ALL_FIELDS ((IOC_NET_HEADER_FIELD_IPSEC_AH_SPI << 2) - 1) ++ ++ ++typedef uint8_t ioc_header_field_ipsec_esp_t; ++ ++#define IOC_NET_HEADER_FIELD_IPSEC_ESP_SPI (1) ++#define IOC_NET_HEADER_FIELD_IPSEC_ESP_SEQUENCE_NUM (IOC_NET_HEADER_FIELD_IPSEC_ESP_SPI << 1) ++#define IOC_NET_HEADER_FIELD_IPSEC_ESP_ALL_FIELDS ((IOC_NET_HEADER_FIELD_IPSEC_ESP_SPI << 2) - 1) ++ ++#define IOC_NET_HEADER_FIELD_IPSEC_ESP_SPI_SIZE 4 ++ ++ ++typedef uint8_t ioc_header_field_mpls_t; ++ ++#define IOC_NET_HEADER_FIELD_MPLS_LABEL_STACK (1) ++#define IOC_NET_HEADER_FIELD_MPLS_LABEL_STACK_ALL_FIELDS ((IOC_NET_HEADER_FIELD_MPLS_LABEL_STACK << 1) - 1) ++ ++ ++typedef uint8_t ioc_header_field_macsec_t; ++ ++#define IOC_NET_HEADER_FIELD_MACSEC_SECTAG (1) ++#define IOC_NET_HEADER_FIELD_MACSEC_ALL_FIELDS ((IOC_NET_HEADER_FIELD_MACSEC_SECTAG << 1) - 1) ++ ++ ++typedef enum { ++ e_IOC_NET_HEADER_TYPE_NONE = 0, ++ e_IOC_NET_HEADER_TYPE_PAYLOAD, ++ e_IOC_NET_HEADER_TYPE_ETH, ++ e_IOC_NET_HEADER_TYPE_VLAN, ++ e_IOC_NET_HEADER_TYPE_IPv4, ++ e_IOC_NET_HEADER_TYPE_IPv6, ++ e_IOC_NET_HEADER_TYPE_IP, ++ e_IOC_NET_HEADER_TYPE_TCP, ++ e_IOC_NET_HEADER_TYPE_UDP, ++ e_IOC_NET_HEADER_TYPE_UDP_LITE, ++ e_IOC_NET_HEADER_TYPE_IPHC, ++ e_IOC_NET_HEADER_TYPE_SCTP, ++ e_IOC_NET_HEADER_TYPE_SCTP_CHUNK_DATA, ++ e_IOC_NET_HEADER_TYPE_PPPoE, ++ e_IOC_NET_HEADER_TYPE_PPP, ++ e_IOC_NET_HEADER_TYPE_PPPMUX, ++ e_IOC_NET_HEADER_TYPE_PPPMUX_SUBFRAME, ++ e_IOC_NET_HEADER_TYPE_L2TPv2, ++ e_IOC_NET_HEADER_TYPE_L2TPv3_CTRL, ++ e_IOC_NET_HEADER_TYPE_L2TPv3_SESS, ++ e_IOC_NET_HEADER_TYPE_LLC, ++ e_IOC_NET_HEADER_TYPE_LLC_SNAP, ++ e_IOC_NET_HEADER_TYPE_NLPID, ++ e_IOC_NET_HEADER_TYPE_SNAP, ++ e_IOC_NET_HEADER_TYPE_MPLS, ++ e_IOC_NET_HEADER_TYPE_IPSEC_AH, ++ e_IOC_NET_HEADER_TYPE_IPSEC_ESP, ++ e_IOC_NET_HEADER_TYPE_UDP_ENCAP_ESP, /* RFC 3948 */ ++ e_IOC_NET_HEADER_TYPE_MACSEC, ++ e_IOC_NET_HEADER_TYPE_GRE, ++ e_IOC_NET_HEADER_TYPE_MINENCAP, ++ e_IOC_NET_HEADER_TYPE_DCCP, ++ e_IOC_NET_HEADER_TYPE_ICMP, ++ e_IOC_NET_HEADER_TYPE_IGMP, ++ e_IOC_NET_HEADER_TYPE_ARP, ++ e_IOC_NET_HEADER_TYPE_CAPWAP, ++ e_IOC_NET_HEADER_TYPE_CAPWAP_DTLS, ++ e_IOC_NET_HEADER_TYPE_RFC2684, ++ e_IOC_NET_HEADER_TYPE_USER_DEFINED_L2, ++ e_IOC_NET_HEADER_TYPE_USER_DEFINED_L3, ++ e_IOC_NET_HEADER_TYPE_USER_DEFINED_L4, ++ e_IOC_NET_HEADER_TYPE_USER_DEFINED_SHIM1, ++ e_IOC_NET_HEADER_TYPE_USER_DEFINED_SHIM2, ++ e_IOC_NET_MAX_HEADER_TYPE_COUNT ++} ioc_net_header_type; ++ ++ ++#endif /* __NET_IOCTLS_H */ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0020-devres-add-devm_alloc_percpu.patch b/target/linux/layerscape-64b/patches-4.1/0020-devres-add-devm_alloc_percpu.patch new file mode 100644 index 0000000..169d28b --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0020-devres-add-devm_alloc_percpu.patch @@ -0,0 +1,147 @@ +From 19c7ed303955da04a0465c1c948f0d3d7883ae4a Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Wed, 19 Nov 2014 13:06:54 +0200 +Subject: [PATCH 020/151] devres: add devm_alloc_percpu() + +Introduce managed counterparts for alloc_percpu() and free_percpu(). +Add devm_alloc_percpu() and devm_free_percpu() into the managed +interfaces list. + +Signed-off-by: Madalin Bucur + +Change-Id: I93546348e7b0e1974fda8b6c7a3b3710ce45b724 +Reviewed-on: http://git.am.freescale.net:8181/24140 +Reviewed-by: Madalin-Cristian Bucur +Tested-by: Madalin-Cristian Bucur + +Conflicts: + Documentation/driver-model/devres.txt + drivers/base/devres.c + +Conflicts: + drivers/base/devres.c +--- + Documentation/driver-model/devres.txt | 4 +++ + drivers/base/devres.c | 63 +++++++++++++++++++++++++++++++++++ + include/linux/device.h | 19 +++++++++++ + 3 files changed, 86 insertions(+) + +diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt +index 831a536..fd4eae9 100644 +--- a/Documentation/driver-model/devres.txt ++++ b/Documentation/driver-model/devres.txt +@@ -320,6 +320,10 @@ PHY + devm_usb_get_phy() + devm_usb_put_phy() + ++PER-CPU MEM ++ devm_alloc_percpu() ++ devm_free_percpu() ++ + PINCTRL + devm_pinctrl_get() + devm_pinctrl_put() +diff --git a/drivers/base/devres.c b/drivers/base/devres.c +index 8754646..7fbf93d 100644 +--- a/drivers/base/devres.c ++++ b/drivers/base/devres.c +@@ -984,3 +984,66 @@ void devm_free_pages(struct device *dev, unsigned long addr) + &devres)); + } + EXPORT_SYMBOL_GPL(devm_free_pages); ++ ++static void devm_percpu_release(struct device *dev, void *pdata) ++{ ++ void __percpu *p; ++ ++ p = *(void __percpu **)pdata; ++ free_percpu(p); ++} ++ ++static int devm_percpu_match(struct device *dev, void *data, void *p) ++{ ++ struct devres *devr = container_of(data, struct devres, data); ++ ++ return *(void **)devr->data == p; ++} ++ ++/** ++ * __devm_alloc_percpu - Resource-managed alloc_percpu ++ * @dev: Device to allocate per-cpu memory for ++ * @size: Size of per-cpu memory to allocate ++ * @align: Alignement of per-cpu memory to allocate ++ * ++ * Managed alloc_percpu. Per-cpu memory allocated with this function is ++ * automatically freed on driver detach. ++ * ++ * RETURNS: ++ * Pointer to allocated memory on success, NULL on failure. ++ */ ++void __percpu *__devm_alloc_percpu(struct device *dev, size_t size, ++ size_t align) ++{ ++ void *p; ++ void __percpu *pcpu; ++ ++ pcpu = __alloc_percpu(size, align); ++ if (!pcpu) ++ return NULL; ++ ++ p = devres_alloc(devm_percpu_release, sizeof(void *), GFP_KERNEL); ++ if (!p) ++ return NULL; ++ ++ *(void __percpu **)p = pcpu; ++ ++ devres_add(dev, p); ++ ++ return pcpu; ++} ++EXPORT_SYMBOL_GPL(__devm_alloc_percpu); ++ ++/** ++ * devm_free_percpu - Resource-managed free_percpu ++ * @dev: Device this memory belongs to ++ * @pdata: Per-cpu memory to free ++ * ++ * Free memory allocated with devm_alloc_percpu(). ++ */ ++void devm_free_percpu(struct device *dev, void __percpu *pdata) ++{ ++ WARN_ON(devres_destroy(dev, devm_percpu_release, devm_percpu_match, ++ (void *)pdata)); ++} ++EXPORT_SYMBOL_GPL(devm_free_percpu); +diff --git a/include/linux/device.h b/include/linux/device.h +index 6558af9..e7f49af 100644 +--- a/include/linux/device.h ++++ b/include/linux/device.h +@@ -642,6 +642,25 @@ void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res); + int devm_add_action(struct device *dev, void (*action)(void *), void *data); + void devm_remove_action(struct device *dev, void (*action)(void *), void *data); + ++/** ++ * devm_alloc_percpu - Resource-managed alloc_percpu ++ * @dev: Device to allocate per-cpu memory for ++ * @type: Type to allocate per-cpu memory for ++ * ++ * Managed alloc_percpu. Per-cpu memory allocated with this function is ++ * automatically freed on driver detach. ++ * ++ * RETURNS: ++ * Pointer to allocated memory on success, NULL on failure. ++ */ ++#define devm_alloc_percpu(dev, type) \ ++ (typeof(type) __percpu *)__devm_alloc_percpu(dev, sizeof(type), \ ++ __alignof__(type)) ++ ++void __percpu *__devm_alloc_percpu(struct device *dev, size_t size, ++ size_t align); ++void devm_free_percpu(struct device *dev, void __percpu *pdata); ++ + struct device_dma_parameters { + /* + * a low level driver may set these to teach IOMMU code about +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0021-net-readd-skb_recycle.patch b/target/linux/layerscape-64b/patches-4.1/0021-net-readd-skb_recycle.patch new file mode 100644 index 0000000..22eed1a --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0021-net-readd-skb_recycle.patch @@ -0,0 +1,66 @@ +From 1331c3eea76c2462d4198178fbca829521085a19 Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Tue, 5 Jan 2016 12:12:07 +0200 +Subject: [PATCH 021/151] net: readd skb_recycle() + +Adding back skb_recycle() as it's used by the DPAA Ethernet driver. +This was removed from the upstream kernel because it was lacking users. + +Signed-off-by: Madalin Bucur +--- + include/linux/skbuff.h | 1 + + net/core/skbuff.c | 26 ++++++++++++++++++++++++++ + 2 files changed, 27 insertions(+) + +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 28e5555..ac47f2c 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -767,6 +767,7 @@ void kfree_skb(struct sk_buff *skb); + void kfree_skb_list(struct sk_buff *segs); + void skb_tx_error(struct sk_buff *skb); + void consume_skb(struct sk_buff *skb); ++void skb_recycle(struct sk_buff *skb); + void __kfree_skb(struct sk_buff *skb); + extern struct kmem_cache *skbuff_head_cache; + +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index fb0e890..b655c47 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -814,6 +814,32 @@ void consume_skb(struct sk_buff *skb) + } + EXPORT_SYMBOL(consume_skb); + ++/** ++ * skb_recycle - clean up an skb for reuse ++ * @skb: buffer ++ * ++ * Recycles the skb to be reused as a receive buffer. This ++ * function does any necessary reference count dropping, and ++ * cleans up the skbuff as if it just came from __alloc_skb(). ++ */ ++void skb_recycle(struct sk_buff *skb) ++{ ++ struct skb_shared_info *shinfo; ++ u8 head_frag = skb->head_frag; ++ ++ skb_release_head_state(skb); ++ ++ shinfo = skb_shinfo(skb); ++ memset(shinfo, 0, offsetof(struct skb_shared_info, dataref)); ++ atomic_set(&shinfo->dataref, 1); ++ ++ memset(skb, 0, offsetof(struct sk_buff, tail)); ++ skb->data = skb->head + NET_SKB_PAD; ++ skb->head_frag = head_frag; ++ skb_reset_tail_pointer(skb); ++} ++EXPORT_SYMBOL(skb_recycle); ++ + /* Make sure a field is enclosed inside headers_start/headers_end section */ + #define CHECK_SKB_FIELD(field) \ + BUILD_BUG_ON(offsetof(struct sk_buff, field) < \ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0022-net-add-custom-NETIF-flags.patch b/target/linux/layerscape-64b/patches-4.1/0022-net-add-custom-NETIF-flags.patch new file mode 100644 index 0000000..57eeb82 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0022-net-add-custom-NETIF-flags.patch @@ -0,0 +1,41 @@ +From a778ab2f8ddc8126361d6ee600624f3dc10e345f Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Tue, 5 Jan 2016 13:18:21 +0200 +Subject: [PATCH 022/151] net: add custom NETIF flags + +These flags are used by DPAA Ethernet to impose different behaviors +in the networking stack. + +Signed-off-by: Bogdan Hamciuc +Signed-off-by: Madalin Bucur +--- + include/linux/netdev_features.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h +index 7d59dc6..f511c3a 100644 +--- a/include/linux/netdev_features.h ++++ b/include/linux/netdev_features.h +@@ -67,6 +67,9 @@ enum { + NETIF_F_HW_L2FW_DOFFLOAD_BIT, /* Allow L2 Forwarding in Hardware */ + NETIF_F_BUSY_POLL_BIT, /* Busy poll */ + NETIF_F_HW_SWITCH_OFFLOAD_BIT, /* HW switch offload */ ++ /* Freescale DPA support */ ++ NETIF_F_HW_QDISC_BIT, /* Supports hardware Qdisc */ ++ NETIF_F_HW_ACCEL_MQ_BIT, /* Hardware-accelerated multiqueue */ + + /* + * Add your fresh new feature above and remember to update +@@ -126,6 +129,9 @@ enum { + #define NETIF_F_HW_L2FW_DOFFLOAD __NETIF_F(HW_L2FW_DOFFLOAD) + #define NETIF_F_BUSY_POLL __NETIF_F(BUSY_POLL) + #define NETIF_F_HW_SWITCH_OFFLOAD __NETIF_F(HW_SWITCH_OFFLOAD) ++/* Freescale DPA support */ ++#define NETIF_F_HW_QDISC __NETIF_F(HW_QDISC) ++#define NETIF_F_HW_ACCEL_MQ __NETIF_F(HW_ACCEL_MQ) + + /* Features valid for ethtool to change */ + /* = all defined minus driver/device-class-related */ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0023-net-Make-the-netdev-watchdog-aware-of-hardware-multi.patch b/target/linux/layerscape-64b/patches-4.1/0023-net-Make-the-netdev-watchdog-aware-of-hardware-multi.patch new file mode 100644 index 0000000..c4ebadd --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0023-net-Make-the-netdev-watchdog-aware-of-hardware-multi.patch @@ -0,0 +1,53 @@ +From 494a5a025c9146312b2b105e5cfe71ed6ec8699e Mon Sep 17 00:00:00 2001 +From: Bogdan Hamciuc +Date: Fri, 28 Sep 2012 17:04:33 +0300 +Subject: [PATCH 023/151] net: Make the netdev watchdog aware of hardware + multiqueue devices + +If the netdev declares the NETIF_F_HW_ACCEL_MQ (accelerated multiqueue) +capability, tell the watchdog to consider the per-netdev trans_start +field rather than any individual multiqueue's timestamp. That is +justified by the fact that queues only go in and out of congestion +in groups, not individually, as far as the net device is concerned. + +Change-Id: I07a6693bf1f0bb1e9396c5e232452223a511ecc1 +Signed-off-by: Bogdan Hamciuc +Reviewed-on: http://git.am.freescale.net:8181/1033 +Reviewed-by: Fleming Andrew-AFLEMING +Tested-by: Fleming Andrew-AFLEMING +--- + net/sched/sch_generic.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index 0a4fad8..c890957 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -287,8 +287,23 @@ static void dev_watchdog(unsigned long arg) + txq = netdev_get_tx_queue(dev, i); + /* + * old device drivers set dev->trans_start ++ * ++ * (Actually, not only "old" devices, but also ++ * those which perform queue management in a ++ * separate hw accelerator. So even though the ++ * net device itself is single-queued, it makes ++ * sense (and is safe, too) to use kernel's ++ * multiqueue interface, specifically to avoid ++ * unnecessary device locking in SMP systems. ++ * In this case, we ought to consider not an ++ * individual txq's timestamp as a congestion ++ * indicator, but the "old" per-netdev field.) + */ +- trans_start = txq->trans_start ? : dev->trans_start; ++ if (dev->features & NETIF_F_HW_ACCEL_MQ) ++ trans_start = dev->trans_start; ++ else ++ trans_start = txq->trans_start ? : ++ dev->trans_start; + if (netif_xmit_stopped(txq) && + time_after(jiffies, (trans_start + + dev->watchdog_timeo))) { +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0024-dpa-add-SDK1.9-codebase.patch b/target/linux/layerscape-64b/patches-4.1/0024-dpa-add-SDK1.9-codebase.patch new file mode 100644 index 0000000..2f4fc02 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0024-dpa-add-SDK1.9-codebase.patch @@ -0,0 +1,17026 @@ +From 2363409aed378dc4a9b272e745cd80ba2cbf69c4 Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Wed, 16 Dec 2015 22:00:36 +0200 +Subject: [PATCH 024/151] dpa: add SDK1.9 codebase + +Moved to sdk_dpaa and renamed Kconfig option to FSL_SDK_DPAA_ETH to +allow the addition of the upstreamable DPAA Ethernet driver in the +same tree. + +Signed-off-by: Madalin Bucur +--- + drivers/net/ethernet/freescale/Kconfig | 2 + + drivers/net/ethernet/freescale/Makefile | 1 + + drivers/net/ethernet/freescale/sdk_dpaa/Kconfig | 187 ++ + drivers/net/ethernet/freescale/sdk_dpaa/Makefile | 62 + + .../net/ethernet/freescale/sdk_dpaa/dpaa_1588.c | 580 ++++++ + .../net/ethernet/freescale/sdk_dpaa/dpaa_1588.h | 138 ++ + .../net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.c | 387 ++++ + .../net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.h | 43 + + .../freescale/sdk_dpaa/dpaa_debugfs_macsec.c | 193 ++ + .../freescale/sdk_dpaa/dpaa_debugfs_macsec.h | 45 + + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c | 1182 +++++++++++ + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h | 664 ++++++ + .../ethernet/freescale/sdk_dpaa/dpaa_eth_base.c | 250 +++ + .../ethernet/freescale/sdk_dpaa/dpaa_eth_base.h | 50 + + .../ethernet/freescale/sdk_dpaa/dpaa_eth_common.c | 1719 ++++++++++++++++ + .../ethernet/freescale/sdk_dpaa/dpaa_eth_common.h | 214 ++ + .../ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c | 1593 ++++++++++++++ + .../ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h | 94 + + .../freescale/sdk_dpaa/dpaa_eth_generic_sysfs.c | 201 ++ + .../ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c | 498 +++++ + .../ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.c | 2162 ++++++++++++++++++++ + .../ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.h | 287 +++ + .../ethernet/freescale/sdk_dpaa/dpaa_eth_proxy.c | 372 ++++ + .../net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 976 +++++++++ + .../ethernet/freescale/sdk_dpaa/dpaa_eth_shared.c | 910 ++++++++ + .../ethernet/freescale/sdk_dpaa/dpaa_eth_sysfs.c | 275 +++ + .../ethernet/freescale/sdk_dpaa/dpaa_eth_trace.h | 144 ++ + .../net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c | 333 +++ + .../freescale/sdk_dpaa/dpaa_generic_debugfs.c | 277 +++ + .../freescale/sdk_dpaa/dpaa_generic_debugfs.h | 41 + + .../freescale/sdk_dpaa/dpaa_generic_ethtool.c | 125 ++ + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ptp.c | 287 +++ + drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c | 909 ++++++++ + drivers/net/ethernet/freescale/sdk_dpaa/mac.c | 469 +++++ + drivers/net/ethernet/freescale/sdk_dpaa/mac.h | 134 ++ + .../net/ethernet/freescale/sdk_dpaa/offline_port.c | 848 ++++++++ + .../net/ethernet/freescale/sdk_dpaa/offline_port.h | 59 + + 37 files changed, 16711 insertions(+) + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/Kconfig + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/Makefile + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_1588.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_1588.h + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.h + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.h + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.h + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic_sysfs.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.h + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_proxy.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_shared.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sysfs.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_trace.h + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.h + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ptp.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/mac.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/mac.h + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/offline_port.c + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/offline_port.h + +diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig +index 536662c..d0c0ad7 100644 +--- a/drivers/net/ethernet/freescale/Kconfig ++++ b/drivers/net/ethernet/freescale/Kconfig +@@ -94,4 +94,6 @@ config GIANFAR + on the 8540. + + source "drivers/net/ethernet/freescale/sdk_fman/Kconfig" ++source "drivers/net/ethernet/freescale/sdk_dpaa/Kconfig" ++ + endif # NET_VENDOR_FREESCALE +diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile +index aa64c4e..62c532a 100644 +--- a/drivers/net/ethernet/freescale/Makefile ++++ b/drivers/net/ethernet/freescale/Makefile +@@ -18,3 +18,4 @@ gianfar_driver-objs := gianfar.o \ + obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o + ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o + obj-$(if $(CONFIG_FSL_SDK_FMAN),y) += sdk_fman/ ++obj-$(if $(CONFIG_FSL_SDK_DPAA_ETH),y) += sdk_dpaa/ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig b/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig +new file mode 100644 +index 0000000..760ac79 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig +@@ -0,0 +1,187 @@ ++menuconfig FSL_SDK_DPAA_ETH ++ tristate "DPAA Ethernet" ++ depends on FSL_SOC && FSL_BMAN && FSL_QMAN && FSL_SDK_FMAN ++ select PHYLIB ++ ---help--- ++ Data Path Acceleration Architecture Ethernet driver, ++ supporting the Freescale QorIQ chips. ++ Depends on Freescale Buffer Manager and Queue Manager ++ driver and Frame Manager Driver. ++ ++if FSL_SDK_DPAA_ETH ++ ++config FSL_DPAA_HOOKS ++ bool "DPAA Ethernet driver hooks" ++ ++config FSL_DPAA_MACSEC ++ tristate "DPAA MACSEC" ++ select FSL_DPAA_HOOKS ++ ---help--- ++ Enable MACSEC support in DPAA. ++ ++config FSL_DPAA_OFFLINE_PORTS ++ bool "Offline Ports support" ++ depends on FSL_SDK_DPAA_ETH ++ default y ++ ---help--- ++ The Offline Parsing / Host Command ports (short: OH ports, of Offline ports) provide ++ most of the functionality of the regular, online ports, except they receive their ++ frames from a core or an accelerator on the SoC, via QMan frame queues, ++ rather than directly from the network. ++ Offline ports are configured via PCD (Parse-Classify-Distribute) schemes, just like ++ any online FMan port. They deliver the processed frames to frame queues, according ++ to the applied PCD configurations. ++ ++ Choosing this feature will not impact the functionality and/or performance of the system, ++ so it is safe to have it. ++ ++config FSL_DPAA_ADVANCED_DRIVERS ++ bool "Advanced DPAA Ethernet drivers" ++ depends on FSL_SDK_DPAA_ETH ++ default y ++ ---help--- ++ Besides the standard DPAA Ethernet driver there are available other flavours ++ of DPAA drivers that support advanced scenarios: ++ - DPAA Shared MAC driver ++ - DPAA MAC-less driver ++ - DPAA Proxy initialization driver (for USDPAA) ++ Select this to also build the advanced drivers. ++ ++config FSL_DPAA_GENERIC_DRIVER ++ bool "Generic DPAA Ethernet driver" ++ depends on FSL_SDK_DPAA_ETH ++ default y ++ ---help--- ++ This enables the DPAA Generic driver (oNIC). ++ ++config FSL_DPAA_ETH_JUMBO_FRAME ++ bool "Optimize for jumbo frames" ++ default n ++ ---help--- ++ Optimize the DPAA Ethernet driver throughput for large frames ++ termination traffic (e.g. 4K and above). ++ NOTE: This option can only be used if FSL_FM_MAX_FRAME_SIZE ++ is set to 9600 bytes. ++ Using this option in combination with small frames increases ++ significantly the driver's memory footprint and may even deplete ++ the system memory. ++ ++config FSL_DPAA_TS ++ bool "Linux compliant timestamping" ++ depends on FSL_SDK_DPAA_ETH ++ default n ++ ---help--- ++ Enable Linux API compliant timestamping support. ++ ++config FSL_DPAA_1588 ++ bool "IEEE 1588-compliant timestamping" ++ depends on FSL_SDK_DPAA_ETH ++ select FSL_DPAA_TS ++ default n ++ ---help--- ++ Enable IEEE1588 support code. ++ ++config FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE ++ bool "Use driver's Tx queue selection mechanism" ++ default y ++ depends on FSL_SDK_DPAA_ETH ++ ---help--- ++ The DPAA-Ethernet driver defines a ndo_select_queue() callback for optimal selection ++ of the egress FQ. That will override the XPS support for this netdevice. ++ If for whatever reason you want to be in control of the egress FQ-to-CPU selection and mapping, ++ or simply don't want to use the driver's ndo_select_queue() callback, then unselect this ++ and use the standard XPS support instead. ++ ++config FSL_DPAA_ETH_MAX_BUF_COUNT ++ int "Maximum nuber of buffers in private bpool" ++ depends on FSL_SDK_DPAA_ETH ++ range 64 2048 ++ default "128" ++ ---help--- ++ The maximum number of buffers to be by default allocated in the DPAA-Ethernet private port's ++ buffer pool. One needn't normally modify this, as it has probably been tuned for performance ++ already. This cannot be lower than DPAA_ETH_REFILL_THRESHOLD. ++ ++config FSL_DPAA_ETH_REFILL_THRESHOLD ++ int "Private bpool refill threshold" ++ depends on FSL_SDK_DPAA_ETH ++ range 32 FSL_DPAA_ETH_MAX_BUF_COUNT ++ default "80" ++ ---help--- ++ The DPAA-Ethernet driver will start replenishing buffer pools whose count ++ falls below this threshold. This must be related to DPAA_ETH_MAX_BUF_COUNT. One needn't normally ++ modify this value unless one has very specific performance reasons. ++ ++config FSL_DPAA_CS_THRESHOLD_1G ++ hex "Egress congestion threshold on 1G ports" ++ depends on FSL_SDK_DPAA_ETH ++ range 0x1000 0x10000000 ++ default "0x06000000" ++ ---help--- ++ The size in bytes of the egress Congestion State notification threshold on 1G ports. ++ The 1G dTSECs can quite easily be flooded by cores doing Tx in a tight loop ++ (e.g. by sending UDP datagrams at "while(1) speed"), ++ and the larger the frame size, the more acute the problem. ++ So we have to find a balance between these factors: ++ - avoiding the device staying congested for a prolonged time (risking ++ the netdev watchdog to fire - see also the tx_timeout module param); ++ - affecting performance of protocols such as TCP, which otherwise ++ behave well under the congestion notification mechanism; ++ - preventing the Tx cores from tightly-looping (as if the congestion ++ threshold was too low to be effective); ++ - running out of memory if the CS threshold is set too high. ++ ++config FSL_DPAA_CS_THRESHOLD_10G ++ hex "Egress congestion threshold on 10G ports" ++ depends on FSL_SDK_DPAA_ETH ++ range 0x1000 0x20000000 ++ default "0x10000000" ++ ---help --- ++ The size in bytes of the egress Congestion State notification threshold on 10G ports. ++ ++config FSL_DPAA_INGRESS_CS_THRESHOLD ++ hex "Ingress congestion threshold on FMan ports" ++ depends on FSL_SDK_DPAA_ETH ++ default "0x10000000" ++ ---help--- ++ The size in bytes of the ingress tail-drop threshold on FMan ports. ++ Traffic piling up above this value will be rejected by QMan and discarded by FMan. ++ ++config FSL_DPAA_ETH_DEBUGFS ++ bool "DPAA Ethernet debugfs interface" ++ depends on DEBUG_FS && FSL_SDK_DPAA_ETH ++ default y ++ ---help--- ++ This option compiles debugfs code for the DPAA Ethernet driver. ++ ++config FSL_DPAA_MACSEC_DEBUGFS ++ bool "DPAA MACSEC debugfs interface" ++ default y ++ depends on DEBUG_FS && FSL_DPAA_MACSEC ++ ---help--- ++ This option compiles debugfs code for the DPAA Ethernet MACSEC driver. ++ ++config FSL_DPAA_ETH_DEBUG ++ bool "DPAA Ethernet Debug Support" ++ depends on FSL_SDK_DPAA_ETH ++ default n ++ ---help--- ++ This option compiles debug code for the DPAA Ethernet driver. ++ ++config FSL_DPAA_DBG_LOOP ++ bool "DPAA Ethernet Debug loopback" ++ depends on FSL_DPAA_ETH_DEBUGFS && FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE ++ default n ++ ---help--- ++ This option allows to divert all received traffic on a certain interface A towards a ++ selected interface B. This option is used to benchmark the HW + Ethernet driver in ++ isolation from the Linux networking stack. The loops are controlled by debugfs entries, ++ one for each interface. By default all loops are disabled (target value is -1). I.e. to ++ change the loop setting for interface 4 and divert all received traffic to interface 5 ++ write Tx interface number in the receive interface debugfs file: ++ # cat /sys/kernel/debug/powerpc/fsl_dpa/eth4_loop ++ 4->-1 ++ # echo 5 > /sys/kernel/debug/powerpc/fsl_dpa/eth4_loop ++ # cat /sys/kernel/debug/powerpc/fsl_dpa/eth4_loop ++ 4->5 ++endif # FSL_SDK_DPAA_ETH +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/Makefile b/drivers/net/ethernet/freescale/sdk_dpaa/Makefile +new file mode 100644 +index 0000000..7d11df6 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/Makefile +@@ -0,0 +1,62 @@ ++# ++# Makefile for the Freescale Ethernet controllers ++# ++ccflags-y += -DVERSION=\"\" ++# ++# Include netcomm SW specific definitions ++include $(srctree)/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk ++ ++ccflags-y += -I$(NET_DPA) ++ ++obj-$(CONFIG_FSL_SDK_DPAA_ETH) += fsl_mac.o fsl_dpa.o ++obj-$(CONFIG_PTP_1588_CLOCK_DPAA) += dpaa_ptp.o ++ ++fsl_dpa-objs += dpaa_ethtool.o dpaa_eth_sysfs.o dpaa_eth.o dpaa_eth_sg.o dpaa_eth_common.o ++ifeq ($(CONFIG_FSL_DPAA_ETH_DEBUGFS),y) ++fsl_dpa-objs += dpaa_debugfs.o ++endif ++ifeq ($(CONFIG_FSL_DPAA_1588),y) ++fsl_dpa-objs += dpaa_1588.o ++endif ++ ++fsl_mac-objs += mac.o mac-api.o ++ ++# Advanced drivers ++ifeq ($(CONFIG_FSL_DPAA_ADVANCED_DRIVERS),y) ++obj-$(CONFIG_FSL_SDK_DPAA_ETH) += fsl_advanced.o ++obj-$(CONFIG_FSL_SDK_DPAA_ETH) += fsl_proxy.o ++obj-$(CONFIG_FSL_SDK_DPAA_ETH) += fsl_dpa_shared.o ++obj-$(CONFIG_FSL_SDK_DPAA_ETH) += fsl_dpa_macless.o ++obj-$(CONFIG_FSL_DPAA_MACSEC) += fsl_dpa_macsec.o ++ ++fsl_advanced-objs += dpaa_eth_base.o ++# suport for multiple drivers per kernel module comes in kernel 3.14 ++# so we are forced to generate several modules for the advanced drivers ++fsl_proxy-objs += dpaa_eth_proxy.o ++fsl_dpa_shared-objs += dpaa_eth_shared.o ++fsl_dpa_macless-objs += dpaa_eth_macless.o ++fsl_dpa_macsec-objs += dpaa_eth_macsec.o ++ ++ifeq ($(CONFIG_FSL_DPAA_MACSEC_DEBUGFS),y) ++fsl_dpa_macsec-objs += dpaa_debugfs_macsec.o ++endif ++ ++ifeq ($(CONFIG_FSL_DPAA_OFFLINE_PORTS),y) ++obj-$(CONFIG_FSL_SDK_DPAA_ETH) += fsl_oh.o ++ ++fsl_oh-objs += offline_port.o ++endif ++endif ++ ++# Generic driver ++ifeq ($(CONFIG_FSL_DPAA_GENERIC_DRIVER),y) ++obj-$(CONFIG_FSL_SDK_DPAA_ETH) += fsl_generic.o ++ ++fsl_generic-objs += dpaa_eth_generic.o dpaa_eth_generic_sysfs.o dpaa_generic_ethtool.o ++ifeq ($(CONFIG_FSL_DPAA_ETH_DEBUGFS),y) ++fsl_generic-objs += dpaa_generic_debugfs.o ++endif ++endif ++ ++# Needed by the tracing framework ++CFLAGS_dpaa_eth.o := -I$(src) +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_1588.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_1588.c +new file mode 100644 +index 0000000..3bf8cbc +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_1588.c +@@ -0,0 +1,580 @@ ++/* Copyright (C) 2011 Freescale Semiconductor, Inc. ++ * Copyright (C) 2009 IXXAT Automation, GmbH ++ * ++ * DPAA Ethernet Driver -- IEEE 1588 interface functionality ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "dpaa_eth.h" ++#include "dpaa_eth_common.h" ++#include "dpaa_1588.h" ++#include "mac.h" ++ ++static int dpa_ptp_init_circ(struct dpa_ptp_circ_buf *ptp_buf, u32 size) ++{ ++ struct circ_buf *circ_buf = &ptp_buf->circ_buf; ++ ++ circ_buf->buf = vmalloc(sizeof(struct dpa_ptp_data) * size); ++ if (!circ_buf->buf) ++ return 1; ++ ++ circ_buf->head = 0; ++ circ_buf->tail = 0; ++ ptp_buf->size = size; ++ spin_lock_init(&ptp_buf->ptp_lock); ++ ++ return 0; ++} ++ ++static void dpa_ptp_reset_circ(struct dpa_ptp_circ_buf *ptp_buf, u32 size) ++{ ++ struct circ_buf *circ_buf = &ptp_buf->circ_buf; ++ ++ circ_buf->head = 0; ++ circ_buf->tail = 0; ++ ptp_buf->size = size; ++} ++ ++static int dpa_ptp_insert(struct dpa_ptp_circ_buf *ptp_buf, ++ struct dpa_ptp_data *data) ++{ ++ struct circ_buf *circ_buf = &ptp_buf->circ_buf; ++ int size = ptp_buf->size; ++ struct dpa_ptp_data *tmp; ++ unsigned long flags; ++ int head, tail; ++ ++ spin_lock_irqsave(&ptp_buf->ptp_lock, flags); ++ ++ head = circ_buf->head; ++ tail = circ_buf->tail; ++ ++ if (CIRC_SPACE(head, tail, size) <= 0) ++ circ_buf->tail = (tail + 1) & (size - 1); ++ ++ tmp = (struct dpa_ptp_data *)(circ_buf->buf) + head; ++ memcpy(tmp, data, sizeof(struct dpa_ptp_data)); ++ ++ circ_buf->head = (head + 1) & (size - 1); ++ ++ spin_unlock_irqrestore(&ptp_buf->ptp_lock, flags); ++ ++ return 0; ++} ++ ++static int dpa_ptp_is_ident_match(struct dpa_ptp_ident *dst, ++ struct dpa_ptp_ident *src) ++{ ++ int ret; ++ ++ if ((dst->version != src->version) || (dst->msg_type != src->msg_type)) ++ return 0; ++ ++ if ((dst->netw_prot == src->netw_prot) ++ || src->netw_prot == DPA_PTP_PROT_DONTCARE) { ++ if (dst->seq_id != src->seq_id) ++ return 0; ++ ++ ret = memcmp(dst->snd_port_id, src->snd_port_id, ++ DPA_PTP_SOURCE_PORT_LENGTH); ++ if (ret) ++ return 0; ++ else ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int dpa_ptp_find_and_remove(struct dpa_ptp_circ_buf *ptp_buf, ++ struct dpa_ptp_ident *ident, ++ struct dpa_ptp_time *ts) ++{ ++ struct circ_buf *circ_buf = &ptp_buf->circ_buf; ++ int size = ptp_buf->size; ++ int head, tail, idx; ++ unsigned long flags; ++ struct dpa_ptp_data *tmp, *tmp2; ++ struct dpa_ptp_ident *tmp_ident; ++ ++ spin_lock_irqsave(&ptp_buf->ptp_lock, flags); ++ ++ head = circ_buf->head; ++ tail = idx = circ_buf->tail; ++ ++ if (CIRC_CNT(head, tail, size) == 0) { ++ spin_unlock_irqrestore(&ptp_buf->ptp_lock, flags); ++ return 1; ++ } ++ ++ while (idx != head) { ++ tmp = (struct dpa_ptp_data *)(circ_buf->buf) + idx; ++ tmp_ident = &tmp->ident; ++ if (dpa_ptp_is_ident_match(tmp_ident, ident)) ++ break; ++ idx = (idx + 1) & (size - 1); ++ } ++ ++ if (idx == head) { ++ spin_unlock_irqrestore(&ptp_buf->ptp_lock, flags); ++ return 1; ++ } ++ ++ ts->sec = tmp->ts.sec; ++ ts->nsec = tmp->ts.nsec; ++ ++ if (idx != tail) { ++ if (CIRC_CNT(idx, tail, size) > TS_ACCUMULATION_THRESHOLD) { ++ tail = circ_buf->tail = ++ (idx - TS_ACCUMULATION_THRESHOLD) & (size - 1); ++ } ++ ++ while (CIRC_CNT(idx, tail, size) > 0) { ++ tmp = (struct dpa_ptp_data *)(circ_buf->buf) + idx; ++ idx = (idx - 1) & (size - 1); ++ tmp2 = (struct dpa_ptp_data *)(circ_buf->buf) + idx; ++ *tmp = *tmp2; ++ } ++ } ++ circ_buf->tail = (tail + 1) & (size - 1); ++ ++ spin_unlock_irqrestore(&ptp_buf->ptp_lock, flags); ++ ++ return 0; ++} ++ ++/* Parse the PTP packets ++ * ++ * The PTP header can be found in an IPv4 packet, IPv6 patcket or in ++ * an IEEE802.3 ethernet frame. This function returns the position of ++ * the PTP packet or NULL if no PTP found ++ */ ++static u8 *dpa_ptp_parse_packet(struct sk_buff *skb, u16 *eth_type) ++{ ++ u8 *pos = skb->data + ETH_ALEN + ETH_ALEN; ++ u8 *ptp_loc = NULL; ++ u8 msg_type; ++ u32 access_len = ETH_ALEN + ETH_ALEN + DPA_ETYPE_LEN; ++ struct iphdr *iph; ++ struct udphdr *udph; ++ struct ipv6hdr *ipv6h; ++ ++ /* when we can receive S/G frames we need to check the data we want to ++ * access is in the linear skb buffer ++ */ ++ if (!pskb_may_pull(skb, access_len)) ++ return NULL; ++ ++ *eth_type = *((u16 *)pos); ++ ++ /* Check if inner tag is here */ ++ if (*eth_type == ETH_P_8021Q) { ++ access_len += DPA_VLAN_TAG_LEN; ++ ++ if (!pskb_may_pull(skb, access_len)) ++ return NULL; ++ ++ pos += DPA_VLAN_TAG_LEN; ++ *eth_type = *((u16 *)pos); ++ } ++ ++ pos += DPA_ETYPE_LEN; ++ ++ switch (*eth_type) { ++ /* Transport of PTP over Ethernet */ ++ case ETH_P_1588: ++ ptp_loc = pos; ++ ++ if (!pskb_may_pull(skb, access_len + PTP_OFFS_MSG_TYPE + 1)) ++ return NULL; ++ ++ msg_type = *((u8 *)(ptp_loc + PTP_OFFS_MSG_TYPE)) & 0xf; ++ if ((msg_type == PTP_MSGTYPE_SYNC) ++ || (msg_type == PTP_MSGTYPE_DELREQ) ++ || (msg_type == PTP_MSGTYPE_PDELREQ) ++ || (msg_type == PTP_MSGTYPE_PDELRESP)) ++ return ptp_loc; ++ break; ++ /* Transport of PTP over IPv4 */ ++ case ETH_P_IP: ++ iph = (struct iphdr *)pos; ++ access_len += sizeof(struct iphdr); ++ ++ if (!pskb_may_pull(skb, access_len)) ++ return NULL; ++ ++ if (ntohs(iph->protocol) != IPPROTO_UDP) ++ return NULL; ++ ++ access_len += iph->ihl * 4 - sizeof(struct iphdr) + ++ sizeof(struct udphdr); ++ ++ if (!pskb_may_pull(skb, access_len)) ++ return NULL; ++ ++ pos += iph->ihl * 4; ++ udph = (struct udphdr *)pos; ++ if (ntohs(udph->dest) != 319) ++ return NULL; ++ ptp_loc = pos + sizeof(struct udphdr); ++ break; ++ /* Transport of PTP over IPv6 */ ++ case ETH_P_IPV6: ++ ipv6h = (struct ipv6hdr *)pos; ++ ++ access_len += sizeof(struct ipv6hdr) + sizeof(struct udphdr); ++ ++ if (ntohs(ipv6h->nexthdr) != IPPROTO_UDP) ++ return NULL; ++ ++ pos += sizeof(struct ipv6hdr); ++ udph = (struct udphdr *)pos; ++ if (ntohs(udph->dest) != 319) ++ return NULL; ++ ptp_loc = pos + sizeof(struct udphdr); ++ break; ++ default: ++ break; ++ } ++ ++ return ptp_loc; ++} ++ ++static int dpa_ptp_store_stamp(const struct dpa_priv_s *priv, ++ struct sk_buff *skb, void *data, enum port_type rx_tx, ++ struct dpa_ptp_data *ptp_data) ++{ ++ u64 nsec; ++ u32 mod; ++ u8 *ptp_loc; ++ u16 eth_type; ++ ++ ptp_loc = dpa_ptp_parse_packet(skb, ð_type); ++ if (!ptp_loc) ++ return -EINVAL; ++ ++ switch (eth_type) { ++ case ETH_P_IP: ++ ptp_data->ident.netw_prot = DPA_PTP_PROT_IPV4; ++ break; ++ case ETH_P_IPV6: ++ ptp_data->ident.netw_prot = DPA_PTP_PROT_IPV6; ++ break; ++ case ETH_P_1588: ++ ptp_data->ident.netw_prot = DPA_PTP_PROT_802_3; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (!pskb_may_pull(skb, ptp_loc - skb->data + PTP_OFFS_SEQ_ID + 2)) ++ return -EINVAL; ++ ++ ptp_data->ident.version = *(ptp_loc + PTP_OFFS_VER_PTP) & 0xf; ++ ptp_data->ident.msg_type = *(ptp_loc + PTP_OFFS_MSG_TYPE) & 0xf; ++ ptp_data->ident.seq_id = *((u16 *)(ptp_loc + PTP_OFFS_SEQ_ID)); ++ memcpy(ptp_data->ident.snd_port_id, ptp_loc + PTP_OFFS_SRCPRTID, ++ DPA_PTP_SOURCE_PORT_LENGTH); ++ ++ nsec = dpa_get_timestamp_ns(priv, rx_tx, data); ++ mod = do_div(nsec, NANOSEC_PER_SECOND); ++ ptp_data->ts.sec = nsec; ++ ptp_data->ts.nsec = mod; ++ ++ return 0; ++} ++ ++void dpa_ptp_store_txstamp(const struct dpa_priv_s *priv, ++ struct sk_buff *skb, void *data) ++{ ++ struct dpa_ptp_tsu *tsu = priv->tsu; ++ struct dpa_ptp_data ptp_tx_data; ++ ++ if (dpa_ptp_store_stamp(priv, skb, data, TX, &ptp_tx_data)) ++ return; ++ ++ dpa_ptp_insert(&tsu->tx_timestamps, &ptp_tx_data); ++} ++ ++void dpa_ptp_store_rxstamp(const struct dpa_priv_s *priv, ++ struct sk_buff *skb, void *data) ++{ ++ struct dpa_ptp_tsu *tsu = priv->tsu; ++ struct dpa_ptp_data ptp_rx_data; ++ ++ if (dpa_ptp_store_stamp(priv, skb, data, RX, &ptp_rx_data)) ++ return; ++ ++ dpa_ptp_insert(&tsu->rx_timestamps, &ptp_rx_data); ++} ++ ++static uint8_t dpa_get_tx_timestamp(struct dpa_ptp_tsu *ptp_tsu, ++ struct dpa_ptp_ident *ident, ++ struct dpa_ptp_time *ts) ++{ ++ struct dpa_ptp_tsu *tsu = ptp_tsu; ++ struct dpa_ptp_time tmp; ++ int flag; ++ ++ flag = dpa_ptp_find_and_remove(&tsu->tx_timestamps, ident, &tmp); ++ if (!flag) { ++ ts->sec = tmp.sec; ++ ts->nsec = tmp.nsec; ++ return 0; ++ } ++ ++ return -1; ++} ++ ++static uint8_t dpa_get_rx_timestamp(struct dpa_ptp_tsu *ptp_tsu, ++ struct dpa_ptp_ident *ident, ++ struct dpa_ptp_time *ts) ++{ ++ struct dpa_ptp_tsu *tsu = ptp_tsu; ++ struct dpa_ptp_time tmp; ++ int flag; ++ ++ flag = dpa_ptp_find_and_remove(&tsu->rx_timestamps, ident, &tmp); ++ if (!flag) { ++ ts->sec = tmp.sec; ++ ts->nsec = tmp.nsec; ++ return 0; ++ } ++ ++ return -1; ++} ++ ++static void dpa_set_fiper_alarm(struct dpa_ptp_tsu *tsu, ++ struct dpa_ptp_time *cnt_time) ++{ ++ struct mac_device *mac_dev = tsu->dpa_priv->mac_dev; ++ u64 tmp, fiper; ++ ++ if (mac_dev->fm_rtc_disable) ++ mac_dev->fm_rtc_disable(get_fm_handle(tsu->dpa_priv->net_dev)); ++ ++ /* TMR_FIPER1 will pulse every second after ALARM1 expired */ ++ tmp = (u64)cnt_time->sec * NANOSEC_PER_SECOND + (u64)cnt_time->nsec; ++ fiper = NANOSEC_PER_SECOND - DPA_PTP_NOMINAL_FREQ_PERIOD_NS; ++ if (mac_dev->fm_rtc_set_alarm) ++ mac_dev->fm_rtc_set_alarm(get_fm_handle(tsu->dpa_priv->net_dev), ++ 0, tmp); ++ if (mac_dev->fm_rtc_set_fiper) ++ mac_dev->fm_rtc_set_fiper(get_fm_handle(tsu->dpa_priv->net_dev), ++ 0, fiper); ++ ++ if (mac_dev->fm_rtc_enable) ++ mac_dev->fm_rtc_enable(get_fm_handle(tsu->dpa_priv->net_dev)); ++} ++ ++static void dpa_get_curr_cnt(struct dpa_ptp_tsu *tsu, ++ struct dpa_ptp_time *curr_time) ++{ ++ struct mac_device *mac_dev = tsu->dpa_priv->mac_dev; ++ u64 tmp; ++ u32 mod; ++ ++ if (mac_dev->fm_rtc_get_cnt) ++ mac_dev->fm_rtc_get_cnt(get_fm_handle(tsu->dpa_priv->net_dev), ++ &tmp); ++ ++ mod = do_div(tmp, NANOSEC_PER_SECOND); ++ curr_time->sec = (u32)tmp; ++ curr_time->nsec = mod; ++} ++ ++static void dpa_set_1588cnt(struct dpa_ptp_tsu *tsu, ++ struct dpa_ptp_time *cnt_time) ++{ ++ struct mac_device *mac_dev = tsu->dpa_priv->mac_dev; ++ u64 tmp; ++ ++ tmp = (u64)cnt_time->sec * NANOSEC_PER_SECOND + (u64)cnt_time->nsec; ++ ++ if (mac_dev->fm_rtc_set_cnt) ++ mac_dev->fm_rtc_set_cnt(get_fm_handle(tsu->dpa_priv->net_dev), ++ tmp); ++ ++ /* Restart fiper two seconds later */ ++ cnt_time->sec += 2; ++ cnt_time->nsec = 0; ++ dpa_set_fiper_alarm(tsu, cnt_time); ++} ++ ++static void dpa_get_drift(struct dpa_ptp_tsu *tsu, u32 *addend) ++{ ++ struct mac_device *mac_dev = tsu->dpa_priv->mac_dev; ++ u32 drift; ++ ++ if (mac_dev->fm_rtc_get_drift) ++ mac_dev->fm_rtc_get_drift(get_fm_handle(tsu->dpa_priv->net_dev), ++ &drift); ++ ++ *addend = drift; ++} ++ ++static void dpa_set_drift(struct dpa_ptp_tsu *tsu, u32 addend) ++{ ++ struct mac_device *mac_dev = tsu->dpa_priv->mac_dev; ++ ++ if (mac_dev->fm_rtc_set_drift) ++ mac_dev->fm_rtc_set_drift(get_fm_handle(tsu->dpa_priv->net_dev), ++ addend); ++} ++ ++static void dpa_flush_timestamp(struct dpa_ptp_tsu *tsu) ++{ ++ dpa_ptp_reset_circ(&tsu->rx_timestamps, DEFAULT_PTP_RX_BUF_SZ); ++ dpa_ptp_reset_circ(&tsu->tx_timestamps, DEFAULT_PTP_TX_BUF_SZ); ++} ++ ++int dpa_ioctl_1588(struct net_device *dev, struct ifreq *ifr, int cmd) ++{ ++ struct dpa_priv_s *priv = netdev_priv(dev); ++ struct dpa_ptp_tsu *tsu = priv->tsu; ++ struct mac_device *mac_dev = priv->mac_dev; ++ struct dpa_ptp_data ptp_data; ++ struct dpa_ptp_data *ptp_data_user; ++ struct dpa_ptp_time act_time; ++ u32 addend; ++ int retval = 0; ++ ++ if (!tsu || !tsu->valid) ++ return -ENODEV; ++ ++ switch (cmd) { ++ case PTP_ENBL_TXTS_IOCTL: ++ tsu->hwts_tx_en_ioctl = 1; ++ if (mac_dev->fm_rtc_enable) ++ mac_dev->fm_rtc_enable(get_fm_handle(dev)); ++ if (mac_dev->ptp_enable) ++ mac_dev->ptp_enable(mac_dev->get_mac_handle(mac_dev)); ++ break; ++ case PTP_DSBL_TXTS_IOCTL: ++ tsu->hwts_tx_en_ioctl = 0; ++ if (mac_dev->fm_rtc_disable) ++ mac_dev->fm_rtc_disable(get_fm_handle(dev)); ++ if (mac_dev->ptp_disable) ++ mac_dev->ptp_disable(mac_dev->get_mac_handle(mac_dev)); ++ break; ++ case PTP_ENBL_RXTS_IOCTL: ++ tsu->hwts_rx_en_ioctl = 1; ++ break; ++ case PTP_DSBL_RXTS_IOCTL: ++ tsu->hwts_rx_en_ioctl = 0; ++ break; ++ case PTP_GET_RX_TIMESTAMP: ++ ptp_data_user = (struct dpa_ptp_data *)ifr->ifr_data; ++ if (copy_from_user(&ptp_data.ident, ++ &ptp_data_user->ident, sizeof(ptp_data.ident))) ++ return -EINVAL; ++ ++ if (dpa_get_rx_timestamp(tsu, &ptp_data.ident, &ptp_data.ts)) ++ return -EAGAIN; ++ ++ if (copy_to_user((void __user *)&ptp_data_user->ts, ++ &ptp_data.ts, sizeof(ptp_data.ts))) ++ return -EFAULT; ++ break; ++ case PTP_GET_TX_TIMESTAMP: ++ ptp_data_user = (struct dpa_ptp_data *)ifr->ifr_data; ++ if (copy_from_user(&ptp_data.ident, ++ &ptp_data_user->ident, sizeof(ptp_data.ident))) ++ return -EINVAL; ++ ++ if (dpa_get_tx_timestamp(tsu, &ptp_data.ident, &ptp_data.ts)) ++ return -EAGAIN; ++ ++ if (copy_to_user((void __user *)&ptp_data_user->ts, ++ &ptp_data.ts, sizeof(ptp_data.ts))) ++ return -EFAULT; ++ break; ++ case PTP_GET_TIME: ++ dpa_get_curr_cnt(tsu, &act_time); ++ if (copy_to_user(ifr->ifr_data, &act_time, sizeof(act_time))) ++ return -EFAULT; ++ break; ++ case PTP_SET_TIME: ++ if (copy_from_user(&act_time, ifr->ifr_data, sizeof(act_time))) ++ return -EINVAL; ++ dpa_set_1588cnt(tsu, &act_time); ++ break; ++ case PTP_GET_ADJ: ++ dpa_get_drift(tsu, &addend); ++ if (copy_to_user(ifr->ifr_data, &addend, sizeof(addend))) ++ return -EFAULT; ++ break; ++ case PTP_SET_ADJ: ++ if (copy_from_user(&addend, ifr->ifr_data, sizeof(addend))) ++ return -EINVAL; ++ dpa_set_drift(tsu, addend); ++ break; ++ case PTP_SET_FIPER_ALARM: ++ if (copy_from_user(&act_time, ifr->ifr_data, sizeof(act_time))) ++ return -EINVAL; ++ dpa_set_fiper_alarm(tsu, &act_time); ++ break; ++ case PTP_CLEANUP_TS: ++ dpa_flush_timestamp(tsu); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return retval; ++} ++ ++int dpa_ptp_init(struct dpa_priv_s *priv) ++{ ++ struct dpa_ptp_tsu *tsu; ++ ++ /* Allocate memory for PTP structure */ ++ tsu = kzalloc(sizeof(struct dpa_ptp_tsu), GFP_KERNEL); ++ if (!tsu) ++ return -ENOMEM; ++ ++ tsu->valid = TRUE; ++ tsu->dpa_priv = priv; ++ ++ dpa_ptp_init_circ(&tsu->rx_timestamps, DEFAULT_PTP_RX_BUF_SZ); ++ dpa_ptp_init_circ(&tsu->tx_timestamps, DEFAULT_PTP_TX_BUF_SZ); ++ ++ priv->tsu = tsu; ++ ++ return 0; ++} ++EXPORT_SYMBOL(dpa_ptp_init); ++ ++void dpa_ptp_cleanup(struct dpa_priv_s *priv) ++{ ++ struct dpa_ptp_tsu *tsu = priv->tsu; ++ ++ tsu->valid = FALSE; ++ vfree(tsu->rx_timestamps.circ_buf.buf); ++ vfree(tsu->tx_timestamps.circ_buf.buf); ++ ++ kfree(tsu); ++} ++EXPORT_SYMBOL(dpa_ptp_cleanup); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_1588.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_1588.h +new file mode 100644 +index 0000000..7339016 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_1588.h +@@ -0,0 +1,138 @@ ++/* Copyright (C) 2011 Freescale Semiconductor, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ */ ++#ifndef __DPAA_1588_H__ ++#define __DPAA_1588_H__ ++ ++#include ++#include ++#include ++#include ++ ++#define DEFAULT_PTP_RX_BUF_SZ 256 ++#define DEFAULT_PTP_TX_BUF_SZ 256 ++ ++/* 1588 private ioctl calls */ ++#define PTP_ENBL_TXTS_IOCTL SIOCDEVPRIVATE ++#define PTP_DSBL_TXTS_IOCTL (SIOCDEVPRIVATE + 1) ++#define PTP_ENBL_RXTS_IOCTL (SIOCDEVPRIVATE + 2) ++#define PTP_DSBL_RXTS_IOCTL (SIOCDEVPRIVATE + 3) ++#define PTP_GET_TX_TIMESTAMP (SIOCDEVPRIVATE + 4) ++#define PTP_GET_RX_TIMESTAMP (SIOCDEVPRIVATE + 5) ++#define PTP_SET_TIME (SIOCDEVPRIVATE + 6) ++#define PTP_GET_TIME (SIOCDEVPRIVATE + 7) ++#define PTP_SET_FIPER_ALARM (SIOCDEVPRIVATE + 8) ++#define PTP_SET_ADJ (SIOCDEVPRIVATE + 9) ++#define PTP_GET_ADJ (SIOCDEVPRIVATE + 10) ++#define PTP_CLEANUP_TS (SIOCDEVPRIVATE + 11) ++ ++/* PTP V2 message type */ ++enum { ++ PTP_MSGTYPE_SYNC = 0x0, ++ PTP_MSGTYPE_DELREQ = 0x1, ++ PTP_MSGTYPE_PDELREQ = 0x2, ++ PTP_MSGTYPE_PDELRESP = 0x3, ++ PTP_MSGTYPE_FLWUP = 0x8, ++ PTP_MSGTYPE_DELRESP = 0x9, ++ PTP_MSGTYPE_PDELRES_FLWUP = 0xA, ++ PTP_MSGTYPE_ANNOUNCE = 0xB, ++ PTP_MSGTYPE_SGNLNG = 0xC, ++ PTP_MSGTYPE_MNGMNT = 0xD, ++}; ++ ++/* Byte offset of data in the PTP V2 headers */ ++#define PTP_OFFS_MSG_TYPE 0 ++#define PTP_OFFS_VER_PTP 1 ++#define PTP_OFFS_MSG_LEN 2 ++#define PTP_OFFS_DOM_NMB 4 ++#define PTP_OFFS_FLAGS 6 ++#define PTP_OFFS_CORFIELD 8 ++#define PTP_OFFS_SRCPRTID 20 ++#define PTP_OFFS_SEQ_ID 30 ++#define PTP_OFFS_CTRL 32 ++#define PTP_OFFS_LOGMEAN 33 ++ ++#define PTP_IP_OFFS 14 ++#define PTP_UDP_OFFS 34 ++#define PTP_HEADER_OFFS 42 ++#define PTP_MSG_TYPE_OFFS (PTP_HEADER_OFFS + PTP_OFFS_MSG_TYPE) ++#define PTP_SPORT_ID_OFFS (PTP_HEADER_OFFS + PTP_OFFS_SRCPRTID) ++#define PTP_SEQ_ID_OFFS (PTP_HEADER_OFFS + PTP_OFFS_SEQ_ID) ++#define PTP_CTRL_OFFS (PTP_HEADER_OFFS + PTP_OFFS_CTRL) ++ ++/* 1588-2008 network protocol enumeration values */ ++#define DPA_PTP_PROT_IPV4 1 ++#define DPA_PTP_PROT_IPV6 2 ++#define DPA_PTP_PROT_802_3 3 ++#define DPA_PTP_PROT_DONTCARE 0xFFFF ++ ++#define DPA_PTP_SOURCE_PORT_LENGTH 10 ++#define DPA_PTP_HEADER_SZE 34 ++#define DPA_ETYPE_LEN 2 ++#define DPA_VLAN_TAG_LEN 4 ++#define NANOSEC_PER_SECOND 1000000000 ++ ++/* The threshold between the current found one and the oldest one */ ++#define TS_ACCUMULATION_THRESHOLD 50 ++ ++/* Struct needed to identify a timestamp */ ++struct dpa_ptp_ident { ++ u8 version; ++ u8 msg_type; ++ u16 netw_prot; ++ u16 seq_id; ++ u8 snd_port_id[DPA_PTP_SOURCE_PORT_LENGTH]; ++}; ++ ++/* Timestamp format in 1588-2008 */ ++struct dpa_ptp_time { ++ u64 sec; /* just 48 bit used */ ++ u32 nsec; ++}; ++ ++/* needed for timestamp data over ioctl */ ++struct dpa_ptp_data { ++ struct dpa_ptp_ident ident; ++ struct dpa_ptp_time ts; ++}; ++ ++struct dpa_ptp_circ_buf { ++ struct circ_buf circ_buf; ++ u32 size; ++ spinlock_t ptp_lock; ++}; ++ ++/* PTP TSU control structure */ ++struct dpa_ptp_tsu { ++ struct dpa_priv_s *dpa_priv; ++ bool valid; ++ struct dpa_ptp_circ_buf rx_timestamps; ++ struct dpa_ptp_circ_buf tx_timestamps; ++ ++ /* HW timestamping over ioctl enabled flag */ ++ int hwts_tx_en_ioctl; ++ int hwts_rx_en_ioctl; ++}; ++ ++extern int dpa_ptp_init(struct dpa_priv_s *priv); ++extern void dpa_ptp_cleanup(struct dpa_priv_s *priv); ++extern void dpa_ptp_store_txstamp(const struct dpa_priv_s *priv, ++ struct sk_buff *skb, void *data); ++extern void dpa_ptp_store_rxstamp(const struct dpa_priv_s *priv, ++ struct sk_buff *skb, void *data); ++extern int dpa_ioctl_1588(struct net_device *dev, struct ifreq *ifr, int cmd); ++#endif +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.c +new file mode 100644 +index 0000000..59c7338 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.c +@@ -0,0 +1,387 @@ ++/* Copyright 2008-2013 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 ++#include /* struct qm_mcr_querycgr */ ++#include ++#include "dpaa_debugfs.h" ++#include "dpaa_eth.h" /* struct dpa_priv_s, dpa_percpu_priv_s, dpa_bp */ ++ ++#define DPA_DEBUGFS_DESCRIPTION "FSL DPAA Ethernet debugfs entries" ++#define DPA_ETH_DEBUGFS_ROOT "fsl_dpa" ++ ++static int __cold dpa_debugfs_open(struct inode *inode, struct file *file); ++ ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP ++static int __cold dpa_debugfs_loop_open(struct inode *inode, struct file *file); ++static ssize_t dpa_loop_write(struct file *f, ++ const char __user *buf, size_t count, loff_t *off); ++#endif ++ ++static struct dentry *dpa_debugfs_root; ++static const struct file_operations dpa_debugfs_fops = { ++ .open = dpa_debugfs_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP ++static const struct file_operations dpa_debugfs_lp_fops = { ++ .open = dpa_debugfs_loop_open, ++ .write = dpa_loop_write, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++#endif ++ ++static int dpa_debugfs_show(struct seq_file *file, void *offset) ++{ ++ int i; ++ struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv, total; ++ struct dpa_bp *dpa_bp; ++ unsigned int dpa_bp_count = 0; ++ unsigned int count_total = 0; ++ struct qm_mcr_querycgr query_cgr; ++ ++ BUG_ON(offset == NULL); ++ ++ priv = netdev_priv((struct net_device *)file->private); ++ ++ dpa_bp = priv->dpa_bp; ++ ++ memset(&total, 0, sizeof(total)); ++ ++ /* "Standard" counters */ ++ seq_printf(file, "\nDPA counters for %s:\n", priv->net_dev->name); ++ seq_puts(file, "CPU irqs rx tx recycle "); ++ seq_puts(file, "confirm tx sg tx err rx err bp count\n"); ++ ++ ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ if (dpa_bp->percpu_count) ++ dpa_bp_count = *(per_cpu_ptr(dpa_bp->percpu_count, i)); ++ ++ total.in_interrupt += percpu_priv->in_interrupt; ++ total.stats.rx_packets += percpu_priv->stats.rx_packets; ++ total.stats.tx_packets += percpu_priv->stats.tx_packets; ++ total.tx_returned += percpu_priv->tx_returned; ++ total.tx_confirm += percpu_priv->tx_confirm; ++ total.tx_frag_skbuffs += percpu_priv->tx_frag_skbuffs; ++ total.stats.tx_errors += percpu_priv->stats.tx_errors; ++ total.stats.rx_errors += percpu_priv->stats.rx_errors; ++ count_total += dpa_bp_count; ++ ++ seq_printf(file, " %hu %8llu %8llu %8llu %8llu ", ++ i, ++ percpu_priv->in_interrupt, ++ percpu_priv->stats.rx_packets, ++ percpu_priv->stats.tx_packets, ++ percpu_priv->tx_returned); ++ seq_printf(file, "%8llu %8llu %8llu %8llu %8d\n", ++ percpu_priv->tx_confirm, ++ percpu_priv->tx_frag_skbuffs, ++ percpu_priv->stats.tx_errors, ++ percpu_priv->stats.rx_errors, ++ dpa_bp_count); ++ } ++ seq_printf(file, "Total %8llu %8llu %8llu %8llu ", ++ total.in_interrupt, ++ total.stats.rx_packets, ++ total.stats.tx_packets, ++ total.tx_returned); ++ seq_printf(file, "%8llu %8llu %8llu %8llu %8d\n", ++ total.tx_confirm, ++ total.tx_frag_skbuffs, ++ total.stats.tx_errors, ++ total.stats.rx_errors, ++ count_total); ++ ++ /* Congestion stats */ ++ seq_puts(file, "\nDevice congestion stats:\n"); ++ seq_printf(file, "Device has been congested for %d ms.\n", ++ jiffies_to_msecs(priv->cgr_data.congested_jiffies)); ++ ++ if (qman_query_cgr(&priv->cgr_data.cgr, &query_cgr) != 0) { ++ seq_printf(file, "CGR id %d - failed to query values\n", ++ priv->cgr_data.cgr.cgrid); ++ } else { ++ seq_printf(file, "CGR id %d avg count: %llu\n", ++ priv->cgr_data.cgr.cgrid, ++ qm_mcr_querycgr_a_get64(&query_cgr)); ++ seq_printf(file, "Device entered congestion %u times. ", ++ priv->cgr_data.cgr_congested_count); ++ seq_printf(file, "Current congestion state is: %s.\n", ++ query_cgr.cgr.cs ? "congested" : "not congested"); ++ /* Reset congestion stats (like QMan CGR API does) */ ++ priv->cgr_data.congested_jiffies = 0; ++ priv->cgr_data.cgr_congested_count = 0; ++ } ++ ++ /* Rx Errors demultiplexing */ ++ seq_puts(file, "\nDPA RX Errors:\nCPU dma err phys err"); ++ seq_puts(file, " size err hdr err csum err\n"); ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ total.rx_errors.dme += percpu_priv->rx_errors.dme; ++ total.rx_errors.fpe += percpu_priv->rx_errors.fpe; ++ total.rx_errors.fse += percpu_priv->rx_errors.fse; ++ total.rx_errors.phe += percpu_priv->rx_errors.phe; ++ total.rx_errors.cse += percpu_priv->rx_errors.cse; ++ ++ seq_printf(file, " %hu %8llu %8llu ", ++ i, ++ percpu_priv->rx_errors.dme, ++ percpu_priv->rx_errors.fpe); ++ seq_printf(file, "%8llu %8llu %8llu\n", ++ percpu_priv->rx_errors.fse, ++ percpu_priv->rx_errors.phe, ++ percpu_priv->rx_errors.cse); ++ } ++ seq_printf(file, "Total %8llu %8llu %8llu %8llu %8llu\n", ++ total.rx_errors.dme, ++ total.rx_errors.fpe, ++ total.rx_errors.fse, ++ total.rx_errors.phe, ++ total.rx_errors.cse); ++ ++ /* ERN demultiplexing */ ++ seq_puts(file, "\nDPA ERN counters:\n CPU cg_td wred "); ++ seq_puts(file, "err_cond early_w late_w fq_td fq_ret"); ++ seq_puts(file, " orp_z\n"); ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ total.ern_cnt.cg_tdrop += percpu_priv->ern_cnt.cg_tdrop; ++ total.ern_cnt.wred += percpu_priv->ern_cnt.wred; ++ total.ern_cnt.err_cond += percpu_priv->ern_cnt.err_cond; ++ total.ern_cnt.early_window += percpu_priv->ern_cnt.early_window; ++ total.ern_cnt.late_window += percpu_priv->ern_cnt.late_window; ++ total.ern_cnt.fq_tdrop += percpu_priv->ern_cnt.fq_tdrop; ++ total.ern_cnt.fq_retired += percpu_priv->ern_cnt.fq_retired; ++ total.ern_cnt.orp_zero += percpu_priv->ern_cnt.orp_zero; ++ ++ seq_printf(file, " %hu %8llu %8llu %8llu %8llu ", ++ i, ++ percpu_priv->ern_cnt.cg_tdrop, ++ percpu_priv->ern_cnt.wred, ++ percpu_priv->ern_cnt.err_cond, ++ percpu_priv->ern_cnt.early_window); ++ seq_printf(file, "%8llu %8llu %8llu %8llu\n", ++ percpu_priv->ern_cnt.late_window, ++ percpu_priv->ern_cnt.fq_tdrop, ++ percpu_priv->ern_cnt.fq_retired, ++ percpu_priv->ern_cnt.orp_zero); ++ } ++ seq_printf(file, "Total %8llu %8llu %8llu %8llu ", ++ total.ern_cnt.cg_tdrop, ++ total.ern_cnt.wred, ++ total.ern_cnt.err_cond, ++ total.ern_cnt.early_window); ++ seq_printf(file, "%8llu %8llu %8llu %8llu\n", ++ total.ern_cnt.late_window, ++ total.ern_cnt.fq_tdrop, ++ total.ern_cnt.fq_retired, ++ total.ern_cnt.orp_zero); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP ++static int dpa_debugfs_loop_show(struct seq_file *file, void *offset) ++{ ++ struct dpa_priv_s *priv; ++ ++ BUG_ON(offset == NULL); ++ ++ priv = netdev_priv((struct net_device *)file->private); ++ seq_printf(file, "%d->%d\n", priv->loop_id, priv->loop_to); ++ ++ return 0; ++} ++ ++static int user_input_convert(const char __user *user_buf, size_t count, ++ long *val) ++{ ++ char buf[12]; ++ ++ if (count > sizeof(buf) - 1) ++ return -EINVAL; ++ if (copy_from_user(buf, user_buf, count)) ++ return -EFAULT; ++ buf[count] = '\0'; ++ if (kstrtol(buf, 0, val)) ++ return -EINVAL; ++ return 0; ++} ++ ++static ssize_t dpa_loop_write(struct file *f, ++ const char __user *buf, size_t count, loff_t *off) ++{ ++ struct dpa_priv_s *priv; ++ struct net_device *netdev; ++ struct seq_file *sf; ++ int ret; ++ long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ ++ sf = (struct seq_file *)f->private_data; ++ netdev = (struct net_device *)sf->private; ++ priv = netdev_priv(netdev); ++ ++ priv->loop_to = ((val < 0) || (val > 20)) ? -1 : val; ++ ++ return count; ++} ++ ++static int __cold dpa_debugfs_loop_open(struct inode *inode, struct file *file) ++{ ++ int _errno; ++ const struct net_device *net_dev; ++ ++ _errno = single_open(file, dpa_debugfs_loop_show, inode->i_private); ++ if (unlikely(_errno < 0)) { ++ net_dev = (struct net_device *)inode->i_private; ++ ++ if (netif_msg_drv((struct dpa_priv_s *)netdev_priv(net_dev))) ++ netdev_err(net_dev, "single_open() = %d\n", ++ _errno); ++ } ++ ++ return _errno; ++} ++#endif /* CONFIG_FSL_DPAA_DBG_LOOP */ ++ ++static int __cold dpa_debugfs_open(struct inode *inode, struct file *file) ++{ ++ int _errno; ++ const struct net_device *net_dev; ++ ++ _errno = single_open(file, dpa_debugfs_show, inode->i_private); ++ if (unlikely(_errno < 0)) { ++ net_dev = (struct net_device *)inode->i_private; ++ ++ if (netif_msg_drv((struct dpa_priv_s *)netdev_priv(net_dev))) ++ netdev_err(net_dev, "single_open() = %d\n", ++ _errno); ++ } ++ return _errno; ++} ++ ++int dpa_netdev_debugfs_create(struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ static int cnt; ++ char debugfs_file_name[100]; ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP ++ char loop_file_name[100]; ++#endif ++ ++ if (unlikely(dpa_debugfs_root == NULL)) { ++ pr_err(KBUILD_MODNAME ": %s:%hu:%s(): \t%s\n", ++ KBUILD_BASENAME".c", __LINE__, __func__, ++ "root debugfs missing, possible module ordering issue"); ++ return -ENOMEM; ++ } ++ ++ snprintf(debugfs_file_name, 100, "eth%d", ++cnt); ++ priv->debugfs_file = debugfs_create_file(debugfs_file_name, ++ S_IRUGO, ++ dpa_debugfs_root, ++ net_dev, ++ &dpa_debugfs_fops); ++ if (unlikely(priv->debugfs_file == NULL)) { ++ netdev_err(net_dev, "debugfs_create_file(%s/%s)", ++ dpa_debugfs_root->d_iname, ++ debugfs_file_name); ++ ++ return -ENOMEM; ++ } ++ ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP ++ sprintf(loop_file_name, "eth%d_loop", cnt); ++ priv->debugfs_loop_file = debugfs_create_file(loop_file_name, ++ S_IRUGO, ++ dpa_debugfs_root, ++ net_dev, ++ &dpa_debugfs_lp_fops); ++ if (unlikely(priv->debugfs_loop_file == NULL)) { ++ netdev_err(net_dev, "debugfs_create_file(%s/%s)", ++ dpa_debugfs_root->d_iname, ++ loop_file_name); ++ ++ return -ENOMEM; ++ } ++#endif ++ return 0; ++} ++ ++void dpa_netdev_debugfs_remove(struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ ++ debugfs_remove(priv->debugfs_file); ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP ++ debugfs_remove(priv->debugfs_loop_file); ++#endif ++} ++ ++int __init dpa_debugfs_module_init(void) ++{ ++ int _errno = 0; ++ ++ pr_info(KBUILD_MODNAME ": " DPA_DEBUGFS_DESCRIPTION " (" VERSION ")\n"); ++ ++ dpa_debugfs_root = debugfs_create_dir(DPA_ETH_DEBUGFS_ROOT, NULL); ++ ++ if (unlikely(dpa_debugfs_root == NULL)) { ++ _errno = -ENOMEM; ++ pr_err(KBUILD_MODNAME ": %s:%hu:%s():\n", ++ KBUILD_BASENAME".c", __LINE__, __func__); ++ pr_err("\tdebugfs_create_dir(%s/"KBUILD_MODNAME") = %d\n", ++ DPA_ETH_DEBUGFS_ROOT, _errno); ++ } ++ ++ return _errno; ++} ++ ++void __exit dpa_debugfs_module_exit(void) ++{ ++ debugfs_remove(dpa_debugfs_root); ++} +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.h +new file mode 100644 +index 0000000..63d3542 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.h +@@ -0,0 +1,43 @@ ++/* Copyright 2008-2013 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 DPAA_DEBUGFS_H_ ++#define DPAA_DEBUGFS_H_ ++ ++#include ++#include /* struct dentry needed in dpaa_eth.h */ ++ ++int dpa_netdev_debugfs_create(struct net_device *net_dev); ++void dpa_netdev_debugfs_remove(struct net_device *net_dev); ++int __init dpa_debugfs_module_init(void); ++void __exit dpa_debugfs_module_exit(void); ++ ++#endif /* DPAA_DEBUGFS_H_ */ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.c +new file mode 100644 +index 0000000..64e8a39 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.c +@@ -0,0 +1,193 @@ ++/* 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 ++#include ++#include ++#include "dpaa_eth_macsec.h" ++#include "dpaa_eth.h" ++ ++#define MACSEC_DEBUGFS_DESCRIPTION "FSL DPAA Ethernet MACsec debugfs entries" ++#define MACSEC_DEBUGFS_ROOT "fsl_macsec_dpa" ++ ++static int __cold macsec_debugfs_open(struct inode *inode, struct file *file); ++ ++static struct dentry *dpa_debugfs_root; ++static const struct file_operations macsec_debugfs_fops = { ++ .open = macsec_debugfs_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static struct macsec_priv_s *macsec_priv[FM_MAX_NUM_OF_MACS]; ++void set_macsec_priv(struct macsec_priv_s *macsec_priv_src, int index) ++{ ++ macsec_priv[index] = macsec_priv_src; ++} ++EXPORT_SYMBOL(set_macsec_priv); ++ ++void unset_macsec_priv(int index) ++{ ++ macsec_priv[index] = NULL; ++} ++EXPORT_SYMBOL(unset_macsec_priv); ++ ++static int dpa_debugfs_show(struct seq_file *file, void *offset) ++{ ++ int i; ++ struct macsec_percpu_priv_s *percpu_priv, total; ++ struct net_device *net_dev; ++ struct macsec_priv_s *selected_macsec_priv; ++ ++ BUG_ON(offset == NULL); ++ ++ memset(&total, 0, sizeof(total)); ++ ++ net_dev = (struct net_device *)file->private; ++ ++ selected_macsec_priv = macsec_priv[net_dev->ifindex - 1]; ++ if (unlikely(!selected_macsec_priv)) { ++ pr_err("selected macsec_priv is null\n"); ++ return -EFAULT; ++ } ++ ++ /* "Standard" counters */ ++ seq_printf(file, "\nMacsec counters for %s:\n", ++ selected_macsec_priv->net_dev->name); ++ seq_printf(file, "%s %8s %8s\n", "CPU", "tx", "rx"); ++ ++ ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(selected_macsec_priv->percpu_priv, i); ++ ++ total.tx_macsec += percpu_priv->tx_macsec; ++ total.rx_macsec += percpu_priv->rx_macsec; ++ ++ seq_printf(file, "%3hu %8llu %8llu\n", ++ i, ++ percpu_priv->tx_macsec, ++ percpu_priv->rx_macsec); ++ } ++ seq_printf(file, "Total: %5llu %8llu\n", ++ total.tx_macsec, ++ total.rx_macsec); ++ ++ return 0; ++} ++ ++static int __cold macsec_debugfs_open(struct inode *inode, struct file *file) ++{ ++ int _errno; ++ const struct net_device *net_dev; ++ ++ _errno = single_open(file, dpa_debugfs_show, inode->i_private); ++ if (unlikely(_errno < 0)) { ++ net_dev = (struct net_device *)inode->i_private; ++ ++ if (netif_msg_drv((struct macsec_priv_s *)netdev_priv(net_dev))) ++ netdev_err(net_dev, "single_open() = %d\n", ++ _errno); ++ } ++ return _errno; ++} ++ ++int macsec_netdev_debugfs_create(struct net_device *net_dev) ++{ ++ char buf[256]; ++ struct macsec_priv_s *selected_macsec_priv; ++ ++ if (unlikely(dpa_debugfs_root == NULL)) { ++ pr_err(KBUILD_MODNAME ": %s:%hu:%s(): \t%s\n", ++ KBUILD_BASENAME".c", __LINE__, __func__, ++ "root debugfs missing, possible module ordering issue"); ++ return -EINVAL; ++ } ++ ++ sprintf(buf, "%s_macsec", net_dev->name); ++ ++ selected_macsec_priv = macsec_priv[net_dev->ifindex - 1]; ++ ++ if (unlikely(!selected_macsec_priv)) { ++ pr_err("selected macsec_priv is null\n"); ++ return -EFAULT; ++ } ++ ++ selected_macsec_priv->debugfs_file = debugfs_create_file( ++ net_dev->name, ++ S_IRUGO, ++ dpa_debugfs_root, ++ net_dev, ++ &macsec_debugfs_fops); ++ if (unlikely(selected_macsec_priv->debugfs_file == NULL)) { ++ netdev_err(net_dev, "debugfs_create_file(%s/%s/%s)", ++ powerpc_debugfs_root->d_iname, ++ dpa_debugfs_root->d_iname, ++ buf); ++ ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(macsec_netdev_debugfs_create); ++ ++void macsec_netdev_debugfs_remove(struct net_device *net_dev) ++{ ++ struct macsec_priv_s *selected_macsec_priv; ++ ++ selected_macsec_priv = macsec_priv[net_dev->ifindex - 1]; ++ debugfs_remove(selected_macsec_priv->debugfs_file); ++} ++EXPORT_SYMBOL(macsec_netdev_debugfs_remove); ++ ++int __init macsec_debugfs_module_init(void) ++{ ++ int _errno = 0; ++ ++ dpa_debugfs_root = debugfs_create_dir(MACSEC_DEBUGFS_ROOT, ++ powerpc_debugfs_root); ++ if (unlikely(dpa_debugfs_root == NULL)) { ++ _errno = -ENOMEM; ++ pr_err(KBUILD_MODNAME ": %s:%hu:%s():\n", ++ KBUILD_BASENAME".c", __LINE__, __func__); ++ pr_err("\tdebugfs_create_dir(%s/"KBUILD_MODNAME") = %d\n", ++ powerpc_debugfs_root->d_iname, _errno); ++ } ++ ++ return _errno; ++} ++ ++void __exit macsec_debugfs_module_exit(void) ++{ ++ debugfs_remove(dpa_debugfs_root); ++} ++ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.h +new file mode 100644 +index 0000000..3090f8f +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.h +@@ -0,0 +1,45 @@ ++/* 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 DPAA_DEBUGFS_MACSEC_H_ ++#define DPAA_DEBUGFS_MACSEC_H_ ++ ++#include ++#include /* struct dentry needed in dpaa_eth.h */ ++ ++int macsec_netdev_debugfs_create(struct net_device *net_dev); ++void macsec_netdev_debugfs_remove(struct net_device *net_dev); ++int set_macsec_priv(struct macsec_priv_s *macsec_priv_src, int index); ++void unset_macsec_priv(int index); ++int __init macsec_debugfs_module_init(void); ++void __exit macsec_debugfs_module_exit(void); ++ ++#endif /* DPAA_DEBUGFS_MACSEC_H_ */ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c +new file mode 100644 +index 0000000..a5fb44f +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c +@@ -0,0 +1,1182 @@ ++/* Copyright 2008-2013 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. ++ */ ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUG ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++#else ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": " fmt ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* arp_hdr_len() */ ++#include /* VLAN_HLEN */ ++#include /* struct icmphdr */ ++#include /* struct iphdr */ ++#include /* struct ipv6hdr */ ++#include /* struct udphdr */ ++#include /* struct tcphdr */ ++#include /* net_ratelimit() */ ++#include /* ETH_P_IP and ETH_P_IPV6 */ ++#include ++#include ++#include ++#include ++ ++#include "fsl_fman.h" ++#include "fm_ext.h" ++#include "fm_port_ext.h" ++ ++#include "mac.h" ++#include "dpaa_eth.h" ++#include "dpaa_eth_common.h" ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++#include "dpaa_debugfs.h" ++#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++ ++/* CREATE_TRACE_POINTS only needs to be defined once. Other dpa files ++ * using trace events only need to #include ++ */ ++#define CREATE_TRACE_POINTS ++#include "dpaa_eth_trace.h" ++ ++#define DPA_NAPI_WEIGHT 64 ++ ++/* Valid checksum indication */ ++#define DPA_CSUM_VALID 0xFFFF ++ ++#define DPA_DESCRIPTION "FSL DPAA Ethernet driver" ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++MODULE_AUTHOR("Andy Fleming "); ++ ++MODULE_DESCRIPTION(DPA_DESCRIPTION); ++ ++static uint8_t debug = -1; ++module_param(debug, byte, S_IRUGO); ++MODULE_PARM_DESC(debug, "Module/Driver verbosity level"); ++ ++/* This has to work in tandem with the DPA_CS_THRESHOLD_xxx values. */ ++static uint16_t tx_timeout = 1000; ++module_param(tx_timeout, ushort, S_IRUGO); ++MODULE_PARM_DESC(tx_timeout, "The Tx timeout in ms"); ++ ++static const char rtx[][3] = { ++ [RX] = "RX", ++ [TX] = "TX" ++}; ++ ++/* BM */ ++ ++#define DPAA_ETH_MAX_PAD (L1_CACHE_BYTES * 8) ++ ++static uint8_t dpa_priv_common_bpid; ++ ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP ++struct net_device *dpa_loop_netdevs[20]; ++#endif ++ ++#ifdef CONFIG_PM ++ ++static int dpaa_suspend(struct device *dev) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct mac_device *mac_dev; ++ int err = 0; ++ ++ net_dev = dev_get_drvdata(dev); ++ ++ if (net_dev->flags & IFF_UP) { ++ priv = netdev_priv(net_dev); ++ mac_dev = priv->mac_dev; ++ ++ if (priv->wol & DPAA_WOL_MAGIC) { ++ err = priv->mac_dev->set_wol(mac_dev->port_dev[RX], ++ priv->mac_dev->get_mac_handle(mac_dev), true); ++ if (err) { ++ netdev_err(net_dev, "set_wol() = %d\n", err); ++ goto set_wol_failed; ++ } ++ } ++ ++ err = fm_port_suspend(mac_dev->port_dev[RX]); ++ if (err) { ++ netdev_err(net_dev, "fm_port_suspend(RX) = %d\n", err); ++ goto rx_port_suspend_failed; ++ } ++ ++ err = fm_port_suspend(mac_dev->port_dev[TX]); ++ if (err) { ++ netdev_err(net_dev, "fm_port_suspend(TX) = %d\n", err); ++ goto tx_port_suspend_failed; ++ } ++ } ++ ++ return 0; ++ ++tx_port_suspend_failed: ++ fm_port_resume(mac_dev->port_dev[RX]); ++rx_port_suspend_failed: ++ if (priv->wol & DPAA_WOL_MAGIC) { ++ priv->mac_dev->set_wol(mac_dev->port_dev[RX], ++ priv->mac_dev->get_mac_handle(mac_dev), false); ++ } ++set_wol_failed: ++ return err; ++} ++ ++static int dpaa_resume(struct device *dev) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct mac_device *mac_dev; ++ int err = 0; ++ ++ net_dev = dev_get_drvdata(dev); ++ ++ if (net_dev->flags & IFF_UP) { ++ priv = netdev_priv(net_dev); ++ mac_dev = priv->mac_dev; ++ ++ err = fm_port_resume(mac_dev->port_dev[TX]); ++ if (err) { ++ netdev_err(net_dev, "fm_port_resume(TX) = %d\n", err); ++ goto resume_failed; ++ } ++ ++ err = fm_port_resume(mac_dev->port_dev[RX]); ++ if (err) { ++ netdev_err(net_dev, "fm_port_resume(RX) = %d\n", err); ++ goto resume_failed; ++ } ++ ++ if (priv->wol & DPAA_WOL_MAGIC) { ++ err = priv->mac_dev->set_wol(mac_dev->port_dev[RX], ++ priv->mac_dev->get_mac_handle(mac_dev), false); ++ if (err) { ++ netdev_err(net_dev, "set_wol() = %d\n", err); ++ goto resume_failed; ++ } ++ } ++ } ++ ++ return 0; ++ ++resume_failed: ++ return err; ++} ++ ++static const struct dev_pm_ops dpaa_pm_ops = { ++ .suspend = dpaa_suspend, ++ .resume = dpaa_resume, ++}; ++ ++#define DPAA_PM_OPS (&dpaa_pm_ops) ++ ++#else /* CONFIG_PM */ ++ ++#define DPAA_PM_OPS NULL ++ ++#endif /* CONFIG_PM */ ++ ++/* Checks whether the checksum field in Parse Results array is valid ++ * (equals 0xFFFF) and increments the .cse counter otherwise ++ */ ++static inline void ++dpa_csum_validation(const struct dpa_priv_s *priv, ++ struct dpa_percpu_priv_s *percpu_priv, ++ const struct qm_fd *fd) ++{ ++ dma_addr_t addr = qm_fd_addr(fd); ++ struct dpa_bp *dpa_bp = priv->dpa_bp; ++ void *frm = phys_to_virt(addr); ++ fm_prs_result_t *parse_result; ++ ++ if (unlikely(!frm)) ++ return; ++ ++ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, DMA_BIDIRECTIONAL); ++ ++ parse_result = (fm_prs_result_t *)(frm + DPA_RX_PRIV_DATA_SIZE); ++ ++ if (parse_result->cksum != DPA_CSUM_VALID) ++ percpu_priv->rx_errors.cse++; ++} ++ ++static void _dpa_rx_error(struct net_device *net_dev, ++ const struct dpa_priv_s *priv, ++ struct dpa_percpu_priv_s *percpu_priv, ++ const struct qm_fd *fd, ++ u32 fqid) ++{ ++ /* limit common, possibly innocuous Rx FIFO Overflow errors' ++ * interference with zero-loss convergence benchmark results. ++ */ ++ if (likely(fd->status & FM_FD_STAT_ERR_PHYSICAL)) ++ pr_warn_once("fsl-dpa: non-zero error counters in fman statistics (sysfs)\n"); ++ else ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_err(net_dev, "Err FD status = 0x%08x\n", ++ fd->status & FM_FD_STAT_RX_ERRORS); ++#ifdef CONFIG_FSL_DPAA_HOOKS ++ if (dpaa_eth_hooks.rx_error && ++ dpaa_eth_hooks.rx_error(net_dev, fd, fqid) == DPAA_ETH_STOLEN) ++ /* it's up to the hook to perform resource cleanup */ ++ return; ++#endif ++ percpu_priv->stats.rx_errors++; ++ ++ if (fd->status & FM_PORT_FRM_ERR_DMA) ++ percpu_priv->rx_errors.dme++; ++ if (fd->status & FM_PORT_FRM_ERR_PHYSICAL) ++ percpu_priv->rx_errors.fpe++; ++ if (fd->status & FM_PORT_FRM_ERR_SIZE) ++ percpu_priv->rx_errors.fse++; ++ if (fd->status & FM_PORT_FRM_ERR_PRS_HDR_ERR) ++ percpu_priv->rx_errors.phe++; ++ if (fd->status & FM_FD_STAT_L4CV) ++ dpa_csum_validation(priv, percpu_priv, fd); ++ ++ dpa_fd_release(net_dev, fd); ++} ++ ++static void _dpa_tx_error(struct net_device *net_dev, ++ const struct dpa_priv_s *priv, ++ struct dpa_percpu_priv_s *percpu_priv, ++ const struct qm_fd *fd, ++ u32 fqid) ++{ ++ struct sk_buff *skb; ++ ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_warn(net_dev, "FD status = 0x%08x\n", ++ fd->status & FM_FD_STAT_TX_ERRORS); ++#ifdef CONFIG_FSL_DPAA_HOOKS ++ if (dpaa_eth_hooks.tx_error && ++ dpaa_eth_hooks.tx_error(net_dev, fd, fqid) == DPAA_ETH_STOLEN) ++ /* now the hook must ensure proper cleanup */ ++ return; ++#endif ++ percpu_priv->stats.tx_errors++; ++ ++ /* If we intended the buffers from this frame to go into the bpools ++ * when the FMan transmit was done, we need to put it in manually. ++ */ ++ if (fd->bpid != 0xff) { ++ dpa_fd_release(net_dev, fd); ++ return; ++ } ++ ++ skb = _dpa_cleanup_tx_fd(priv, fd); ++ dev_kfree_skb(skb); ++} ++ ++/* Helper function to factor out frame validation logic on all Rx paths. Its ++ * purpose is to extract from the Parse Results structure information about ++ * the integrity of the frame, its checksum, the length of the parsed headers ++ * and whether the frame is suitable for GRO. ++ * ++ * Assumes no parser errors, since any error frame is dropped before this ++ * function is called. ++ * ++ * @skb will have its ip_summed field overwritten; ++ * @use_gro will only be written with 0, if the frame is definitely not ++ * GRO-able; otherwise, it will be left unchanged; ++ * @hdr_size will be written with a safe value, at least the size of the ++ * headers' length. ++ */ ++void __hot _dpa_process_parse_results(const fm_prs_result_t *parse_results, ++ const struct qm_fd *fd, ++ struct sk_buff *skb, int *use_gro) ++{ ++ if (fd->status & FM_FD_STAT_L4CV) { ++ /* The parser has run and performed L4 checksum validation. ++ * We know there were no parser errors (and implicitly no ++ * L4 csum error), otherwise we wouldn't be here. ++ */ ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ ++ /* Don't go through GRO for certain types of traffic that ++ * we know are not GRO-able, such as dgram-based protocols. ++ * In the worst-case scenarios, such as small-pkt terminating ++ * UDP, the extra GRO processing would be overkill. ++ * ++ * The only protocol the Parser supports that is also GRO-able ++ * is currently TCP. ++ */ ++ if (!fm_l4_frame_is_tcp(parse_results)) ++ *use_gro = 0; ++ ++ return; ++ } ++ ++ /* We're here because either the parser didn't run or the L4 checksum ++ * was not verified. This may include the case of a UDP frame with ++ * checksum zero or an L4 proto other than TCP/UDP ++ */ ++ skb->ip_summed = CHECKSUM_NONE; ++ ++ /* Bypass GRO for unknown traffic or if no PCDs are applied */ ++ *use_gro = 0; ++} ++ ++int dpaa_eth_poll(struct napi_struct *napi, int budget) ++{ ++ struct dpa_napi_portal *np = ++ container_of(napi, struct dpa_napi_portal, napi); ++ ++ int cleaned = qman_p_poll_dqrr(np->p, budget); ++ ++ if (cleaned < budget) { ++ int tmp; ++ napi_complete(napi); ++ tmp = qman_p_irqsource_add(np->p, QM_PIRQ_DQRI); ++ DPA_BUG_ON(tmp); ++ } ++ ++ return cleaned; ++} ++EXPORT_SYMBOL(dpaa_eth_poll); ++ ++static void __hot _dpa_tx_conf(struct net_device *net_dev, ++ const struct dpa_priv_s *priv, ++ struct dpa_percpu_priv_s *percpu_priv, ++ const struct qm_fd *fd, ++ u32 fqid) ++{ ++ struct sk_buff *skb; ++ ++ /* do we need the timestamp for the error frames? */ ++ ++ if (unlikely(fd->status & FM_FD_STAT_TX_ERRORS) != 0) { ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_warn(net_dev, "FD status = 0x%08x\n", ++ fd->status & FM_FD_STAT_TX_ERRORS); ++ ++ percpu_priv->stats.tx_errors++; ++ } ++ ++ /* hopefully we need not get the timestamp before the hook */ ++#ifdef CONFIG_FSL_DPAA_HOOKS ++ if (dpaa_eth_hooks.tx_confirm && dpaa_eth_hooks.tx_confirm(net_dev, ++ fd, fqid) == DPAA_ETH_STOLEN) ++ /* it's the hook that must now perform cleanup */ ++ return; ++#endif ++ /* This might not perfectly reflect the reality, if the core dequeuing ++ * the Tx confirmation is different from the one that did the enqueue, ++ * but at least it'll show up in the total count. ++ */ ++ percpu_priv->tx_confirm++; ++ ++ skb = _dpa_cleanup_tx_fd(priv, fd); ++ ++ dev_kfree_skb(skb); ++} ++ ++enum qman_cb_dqrr_result ++priv_rx_error_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ int *count_ptr; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ count_ptr = raw_cpu_ptr(priv->dpa_bp->percpu_count); ++ ++ if (dpaa_eth_napi_schedule(percpu_priv, portal)) ++ return qman_cb_dqrr_stop; ++ ++ if (unlikely(dpaa_eth_refill_bpools(priv->dpa_bp, count_ptr))) ++ /* Unable to refill the buffer pool due to insufficient ++ * system memory. Just release the frame back into the pool, ++ * otherwise we'll soon end up with an empty buffer pool. ++ */ ++ dpa_fd_release(net_dev, &dq->fd); ++ else ++ _dpa_rx_error(net_dev, priv, percpu_priv, &dq->fd, fq->fqid); ++ ++ return qman_cb_dqrr_consume; ++} ++ ++ ++enum qman_cb_dqrr_result __hot ++priv_rx_default_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ int *count_ptr; ++ struct dpa_bp *dpa_bp; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ dpa_bp = priv->dpa_bp; ++ ++ /* Trace the Rx fd */ ++ trace_dpa_rx_fd(net_dev, fq, &dq->fd); ++ ++ /* IRQ handler, non-migratable; safe to use raw_cpu_ptr here */ ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ count_ptr = raw_cpu_ptr(dpa_bp->percpu_count); ++ ++ if (unlikely(dpaa_eth_napi_schedule(percpu_priv, portal))) ++ return qman_cb_dqrr_stop; ++ ++ /* Vale of plenty: make sure we didn't run out of buffers */ ++ ++ if (unlikely(dpaa_eth_refill_bpools(dpa_bp, count_ptr))) ++ /* Unable to refill the buffer pool due to insufficient ++ * system memory. Just release the frame back into the pool, ++ * otherwise we'll soon end up with an empty buffer pool. ++ */ ++ dpa_fd_release(net_dev, &dq->fd); ++ else ++ _dpa_rx(net_dev, portal, priv, percpu_priv, &dq->fd, fq->fqid, ++ count_ptr); ++ ++ return qman_cb_dqrr_consume; ++} ++ ++enum qman_cb_dqrr_result ++priv_tx_conf_error_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ ++ if (dpaa_eth_napi_schedule(percpu_priv, portal)) ++ return qman_cb_dqrr_stop; ++ ++ _dpa_tx_error(net_dev, priv, percpu_priv, &dq->fd, fq->fqid); ++ ++ return qman_cb_dqrr_consume; ++} ++ ++enum qman_cb_dqrr_result __hot ++priv_tx_conf_default_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ ++ /* Trace the fd */ ++ trace_dpa_tx_conf_fd(net_dev, fq, &dq->fd); ++ ++ /* Non-migratable context, safe to use raw_cpu_ptr */ ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ ++ if (dpaa_eth_napi_schedule(percpu_priv, portal)) ++ return qman_cb_dqrr_stop; ++ ++ _dpa_tx_conf(net_dev, priv, percpu_priv, &dq->fd, fq->fqid); ++ ++ return qman_cb_dqrr_consume; ++} ++ ++void priv_ern(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_mr_entry *msg) ++{ ++ struct net_device *net_dev; ++ const struct dpa_priv_s *priv; ++ struct sk_buff *skb; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct qm_fd fd = msg->ern.fd; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ /* Non-migratable context, safe to use raw_cpu_ptr */ ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ ++ percpu_priv->stats.tx_dropped++; ++ percpu_priv->stats.tx_fifo_errors++; ++ count_ern(percpu_priv, msg); ++ ++ /* If we intended this buffer to go into the pool ++ * when the FM was done, we need to put it in ++ * manually. ++ */ ++ if (msg->ern.fd.bpid != 0xff) { ++ dpa_fd_release(net_dev, &fd); ++ return; ++ } ++ ++ skb = _dpa_cleanup_tx_fd(priv, &fd); ++ dev_kfree_skb_any(skb); ++} ++ ++const struct dpa_fq_cbs_t private_fq_cbs = { ++ .rx_defq = { .cb = { .dqrr = priv_rx_default_dqrr } }, ++ .tx_defq = { .cb = { .dqrr = priv_tx_conf_default_dqrr } }, ++ .rx_errq = { .cb = { .dqrr = priv_rx_error_dqrr } }, ++ .tx_errq = { .cb = { .dqrr = priv_tx_conf_error_dqrr } }, ++ .egress_ern = { .cb = { .ern = priv_ern } } ++}; ++EXPORT_SYMBOL(private_fq_cbs); ++ ++static void dpaa_eth_napi_enable(struct dpa_priv_s *priv) ++{ ++ struct dpa_percpu_priv_s *percpu_priv; ++ int i, j; ++ ++ for_each_possible_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ for (j = 0; j < qman_portal_max; j++) ++ napi_enable(&percpu_priv->np[j].napi); ++ } ++} ++ ++static void dpaa_eth_napi_disable(struct dpa_priv_s *priv) ++{ ++ struct dpa_percpu_priv_s *percpu_priv; ++ int i, j; ++ ++ for_each_possible_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ for (j = 0; j < qman_portal_max; j++) ++ napi_disable(&percpu_priv->np[j].napi); ++ } ++} ++ ++static int __cold dpa_eth_priv_start(struct net_device *net_dev) ++{ ++ int err; ++ struct dpa_priv_s *priv; ++ ++ priv = netdev_priv(net_dev); ++ ++ dpaa_eth_napi_enable(priv); ++ ++ err = dpa_start(net_dev); ++ if (err < 0) ++ dpaa_eth_napi_disable(priv); ++ ++ return err; ++} ++ ++ ++ ++static int __cold dpa_eth_priv_stop(struct net_device *net_dev) ++{ ++ int _errno; ++ struct dpa_priv_s *priv; ++ ++ _errno = dpa_stop(net_dev); ++ /* Allow NAPI to consume any frame still in the Rx/TxConfirm ++ * ingress queues. This is to avoid a race between the current ++ * context and ksoftirqd which could leave NAPI disabled while ++ * in fact there's still Rx traffic to be processed. ++ */ ++ usleep_range(5000, 10000); ++ ++ priv = netdev_priv(net_dev); ++ dpaa_eth_napi_disable(priv); ++ ++ return _errno; ++} ++ ++#ifdef CONFIG_NET_POLL_CONTROLLER ++static void dpaa_eth_poll_controller(struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct dpa_percpu_priv_s *percpu_priv = ++ raw_cpu_ptr(priv->percpu_priv); ++ struct qman_portal *p; ++ const struct qman_portal_config *pc; ++ struct dpa_napi_portal *np; ++ ++ p = (struct qman_portal *)qman_get_affine_portal(smp_processor_id()); ++ pc = qman_p_get_portal_config(p); ++ np = &percpu_priv->np[pc->index]; ++ ++ qman_p_irqsource_remove(np->p, QM_PIRQ_DQRI); ++ qman_p_poll_dqrr(np->p, np->napi.weight); ++ qman_p_irqsource_add(np->p, QM_PIRQ_DQRI); ++} ++#endif ++ ++static const struct net_device_ops dpa_private_ops = { ++ .ndo_open = dpa_eth_priv_start, ++ .ndo_start_xmit = dpa_tx, ++ .ndo_stop = dpa_eth_priv_stop, ++ .ndo_tx_timeout = dpa_timeout, ++ .ndo_get_stats64 = dpa_get_stats64, ++ .ndo_set_mac_address = dpa_set_mac_address, ++ .ndo_validate_addr = eth_validate_addr, ++#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE ++ .ndo_select_queue = dpa_select_queue, ++#endif ++ .ndo_change_mtu = dpa_change_mtu, ++ .ndo_set_rx_mode = dpa_set_rx_mode, ++ .ndo_init = dpa_ndo_init, ++ .ndo_set_features = dpa_set_features, ++ .ndo_fix_features = dpa_fix_features, ++ .ndo_do_ioctl = dpa_ioctl, ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ .ndo_poll_controller = dpaa_eth_poll_controller, ++#endif ++}; ++ ++static int dpa_private_napi_add(struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct dpa_percpu_priv_s *percpu_priv; ++ int i, cpu; ++ ++ for_each_possible_cpu(cpu) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, cpu); ++ ++ percpu_priv->np = devm_kzalloc(net_dev->dev.parent, ++ qman_portal_max * sizeof(struct dpa_napi_portal), ++ GFP_KERNEL); ++ ++ if (unlikely(percpu_priv->np == NULL)) { ++ dev_err(net_dev->dev.parent, "devm_kzalloc() failed\n"); ++ return -ENOMEM; ++ } ++ ++ for (i = 0; i < qman_portal_max; i++) ++ netif_napi_add(net_dev, &percpu_priv->np[i].napi, ++ dpaa_eth_poll, DPA_NAPI_WEIGHT); ++ } ++ ++ return 0; ++} ++ ++void dpa_private_napi_del(struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct dpa_percpu_priv_s *percpu_priv; ++ int i, cpu; ++ ++ for_each_possible_cpu(cpu) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, cpu); ++ ++ if (percpu_priv->np) { ++ for (i = 0; i < qman_portal_max; i++) ++ netif_napi_del(&percpu_priv->np[i].napi); ++ ++ devm_kfree(net_dev->dev.parent, percpu_priv->np); ++ } ++ } ++} ++EXPORT_SYMBOL(dpa_private_napi_del); ++ ++static int dpa_private_netdev_init(struct net_device *net_dev) ++{ ++ int i; ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct dpa_percpu_priv_s *percpu_priv; ++ const uint8_t *mac_addr; ++ ++ /* Although we access another CPU's private data here ++ * we do it at initialization so it is safe ++ */ ++ for_each_possible_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ percpu_priv->net_dev = net_dev; ++ } ++ ++ net_dev->netdev_ops = &dpa_private_ops; ++ mac_addr = priv->mac_dev->addr; ++ ++ net_dev->mem_start = priv->mac_dev->res->start; ++ net_dev->mem_end = priv->mac_dev->res->end; ++ ++ net_dev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | ++ NETIF_F_LLTX); ++ ++ /* Advertise S/G and HIGHDMA support for private interfaces */ ++ net_dev->hw_features |= NETIF_F_SG | NETIF_F_HIGHDMA; ++ /* Recent kernels enable GSO automatically, if ++ * we declare NETIF_F_SG. For conformity, we'll ++ * still declare GSO explicitly. ++ */ ++ net_dev->features |= NETIF_F_GSO; ++ ++ /* Advertise GRO support */ ++ net_dev->features |= NETIF_F_GRO; ++ ++ return dpa_netdev_init(net_dev, mac_addr, tx_timeout); ++} ++ ++static struct dpa_bp * __cold ++dpa_priv_bp_probe(struct device *dev) ++{ ++ struct dpa_bp *dpa_bp; ++ ++ dpa_bp = devm_kzalloc(dev, sizeof(*dpa_bp), GFP_KERNEL); ++ if (unlikely(dpa_bp == NULL)) { ++ dev_err(dev, "devm_kzalloc() failed\n"); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ dpa_bp->percpu_count = devm_alloc_percpu(dev, *dpa_bp->percpu_count); ++ dpa_bp->target_count = CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT; ++ ++ dpa_bp->seed_cb = dpa_bp_priv_seed; ++ dpa_bp->free_buf_cb = _dpa_bp_free_pf; ++ ++ return dpa_bp; ++} ++ ++/* Place all ingress FQs (Rx Default, Rx Error, PCD FQs) in a dedicated CGR. ++ * We won't be sending congestion notifications to FMan; for now, we just use ++ * this CGR to generate enqueue rejections to FMan in order to drop the frames ++ * before they reach our ingress queues and eat up memory. ++ */ ++static int dpaa_eth_priv_ingress_cgr_init(struct dpa_priv_s *priv) ++{ ++ struct qm_mcc_initcgr initcgr; ++ u32 cs_th; ++ int err; ++ ++ err = qman_alloc_cgrid(&priv->ingress_cgr.cgrid); ++ if (err < 0) { ++ pr_err("Error %d allocating CGR ID\n", err); ++ goto out_error; ++ } ++ ++ /* Enable CS TD, but disable Congestion State Change Notifications. */ ++ initcgr.we_mask = QM_CGR_WE_CS_THRES; ++ initcgr.cgr.cscn_en = QM_CGR_EN; ++ cs_th = CONFIG_FSL_DPAA_INGRESS_CS_THRESHOLD; ++ qm_cgr_cs_thres_set64(&initcgr.cgr.cs_thres, cs_th, 1); ++ ++ initcgr.we_mask |= QM_CGR_WE_CSTD_EN; ++ initcgr.cgr.cstd_en = QM_CGR_EN; ++ ++ /* This is actually a hack, because this CGR will be associated with ++ * our affine SWP. However, we'll place our ingress FQs in it. ++ */ ++ err = qman_create_cgr(&priv->ingress_cgr, QMAN_CGR_FLAG_USE_INIT, ++ &initcgr); ++ if (err < 0) { ++ pr_err("Error %d creating ingress CGR with ID %d\n", err, ++ priv->ingress_cgr.cgrid); ++ qman_release_cgrid(priv->ingress_cgr.cgrid); ++ goto out_error; ++ } ++ pr_debug("Created ingress CGR %d for netdev with hwaddr %pM\n", ++ priv->ingress_cgr.cgrid, priv->mac_dev->addr); ++ ++ /* struct qman_cgr allows special cgrid values (i.e. outside the 0..255 ++ * range), but we have no common initialization path between the ++ * different variants of the DPAA Eth driver, so we do it here rather ++ * than modifying every other variant than "private Eth". ++ */ ++ priv->use_ingress_cgr = true; ++ ++out_error: ++ return err; ++} ++ ++static int dpa_priv_bp_create(struct net_device *net_dev, struct dpa_bp *dpa_bp, ++ size_t count) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ int i; ++ ++ if (netif_msg_probe(priv)) ++ dev_dbg(net_dev->dev.parent, ++ "Using private BM buffer pools\n"); ++ ++ priv->bp_count = count; ++ ++ for (i = 0; i < count; i++) { ++ int err; ++ err = dpa_bp_alloc(&dpa_bp[i]); ++ if (err < 0) { ++ dpa_bp_free(priv); ++ priv->dpa_bp = NULL; ++ return err; ++ } ++ ++ priv->dpa_bp = &dpa_bp[i]; ++ } ++ ++ dpa_priv_common_bpid = priv->dpa_bp->bpid; ++ return 0; ++} ++ ++static const struct of_device_id dpa_match[]; ++ ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP ++static int dpa_new_loop_id(void) ++{ ++ static int if_id; ++ ++ return if_id++; ++} ++#endif ++ ++static int ++dpaa_eth_priv_probe(struct platform_device *_of_dev) ++{ ++ int err = 0, i, channel; ++ struct device *dev; ++ struct device_node *dpa_node; ++ struct dpa_bp *dpa_bp; ++ struct dpa_fq *dpa_fq, *tmp; ++ size_t count = 1; ++ struct net_device *net_dev = NULL; ++ struct dpa_priv_s *priv = NULL; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct fm_port_fqs port_fqs; ++ struct dpa_buffer_layout_s *buf_layout = NULL; ++ struct mac_device *mac_dev; ++ struct task_struct *kth; ++ ++ dev = &_of_dev->dev; ++ ++ dpa_node = dev->of_node; ++ ++ if (!of_device_is_available(dpa_node)) ++ return -ENODEV; ++ ++ /* Get the buffer pools assigned to this interface; ++ * run only once the default pool probing code ++ */ ++ dpa_bp = (dpa_bpid2pool(dpa_priv_common_bpid)) ? : ++ dpa_priv_bp_probe(dev); ++ if (IS_ERR(dpa_bp)) ++ return PTR_ERR(dpa_bp); ++ ++ /* Allocate this early, so we can store relevant information in ++ * the private area (needed by 1588 code in dpa_mac_probe) ++ */ ++ net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA_ETH_TX_QUEUES); ++ if (!net_dev) { ++ dev_err(dev, "alloc_etherdev_mq() failed\n"); ++ goto alloc_etherdev_mq_failed; ++ } ++ ++ /* Do this here, so we can be verbose early */ ++ SET_NETDEV_DEV(net_dev, dev); ++ dev_set_drvdata(dev, net_dev); ++ ++ priv = netdev_priv(net_dev); ++ priv->net_dev = net_dev; ++ strcpy(priv->if_type, "private"); ++ ++ priv->msg_enable = netif_msg_init(debug, -1); ++ ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP ++ priv->loop_id = dpa_new_loop_id(); ++ priv->loop_to = -1; /* disabled by default */ ++ dpa_loop_netdevs[priv->loop_id] = net_dev; ++#endif ++ ++ mac_dev = dpa_mac_probe(_of_dev); ++ if (IS_ERR(mac_dev) || !mac_dev) { ++ err = PTR_ERR(mac_dev); ++ goto mac_probe_failed; ++ } ++ ++ /* We have physical ports, so we need to establish ++ * the buffer layout. ++ */ ++ buf_layout = devm_kzalloc(dev, 2 * sizeof(*buf_layout), ++ GFP_KERNEL); ++ if (!buf_layout) { ++ dev_err(dev, "devm_kzalloc() failed\n"); ++ goto alloc_failed; ++ } ++ dpa_set_buffers_layout(mac_dev, buf_layout); ++ ++ /* For private ports, need to compute the size of the default ++ * buffer pool, based on FMan port buffer layout;also update ++ * the maximum buffer size for private ports if necessary ++ */ ++ dpa_bp->size = dpa_bp_size(&buf_layout[RX]); ++ ++#ifdef CONFIG_FSL_DPAA_ETH_JUMBO_FRAME ++ /* We only want to use jumbo frame optimization if we actually have ++ * L2 MAX FRM set for jumbo frames as well. ++ */ ++ if (fm_get_max_frm() < 9600) ++ dev_warn(dev, ++ "Invalid configuration: if jumbo frames support is on, FSL_FM_MAX_FRAME_SIZE should be set to 9600\n"); ++#endif ++ ++ INIT_LIST_HEAD(&priv->dpa_fq_list); ++ ++ memset(&port_fqs, 0, sizeof(port_fqs)); ++ ++ err = dpa_fq_probe_mac(dev, &priv->dpa_fq_list, &port_fqs, true, RX); ++ if (!err) ++ err = dpa_fq_probe_mac(dev, &priv->dpa_fq_list, ++ &port_fqs, true, TX); ++ ++ if (err < 0) ++ goto fq_probe_failed; ++ ++ /* bp init */ ++ ++ err = dpa_priv_bp_create(net_dev, dpa_bp, count); ++ ++ if (err < 0) ++ goto bp_create_failed; ++ ++ priv->mac_dev = mac_dev; ++ ++ channel = dpa_get_channel(); ++ ++ if (channel < 0) { ++ err = channel; ++ goto get_channel_failed; ++ } ++ ++ priv->channel = (uint16_t)channel; ++ ++ /* Start a thread that will walk the cpus with affine portals ++ * and add this pool channel to each's dequeue mask. ++ */ ++ kth = kthread_run(dpaa_eth_add_channel, ++ (void *)(unsigned long)priv->channel, ++ "dpaa_%p:%d", net_dev, priv->channel); ++ if (!kth) { ++ err = -ENOMEM; ++ goto add_channel_failed; ++ } ++ ++ dpa_fq_setup(priv, &private_fq_cbs, priv->mac_dev->port_dev[TX]); ++ ++ /* Create a congestion group for this netdev, with ++ * dynamically-allocated CGR ID. ++ * Must be executed after probing the MAC, but before ++ * assigning the egress FQs to the CGRs. ++ */ ++ err = dpaa_eth_cgr_init(priv); ++ if (err < 0) { ++ dev_err(dev, "Error initializing CGR\n"); ++ goto tx_cgr_init_failed; ++ } ++ err = dpaa_eth_priv_ingress_cgr_init(priv); ++ if (err < 0) { ++ dev_err(dev, "Error initializing ingress CGR\n"); ++ goto rx_cgr_init_failed; ++ } ++ ++ /* Add the FQs to the interface, and make them active */ ++ list_for_each_entry_safe(dpa_fq, tmp, &priv->dpa_fq_list, list) { ++ err = dpa_fq_init(dpa_fq, false); ++ if (err < 0) ++ goto fq_alloc_failed; ++ } ++ ++ priv->buf_layout = buf_layout; ++ priv->tx_headroom = dpa_get_headroom(&priv->buf_layout[TX]); ++ priv->rx_headroom = dpa_get_headroom(&priv->buf_layout[RX]); ++ ++ /* All real interfaces need their ports initialized */ ++ dpaa_eth_init_ports(mac_dev, dpa_bp, count, &port_fqs, ++ buf_layout, dev); ++ ++#ifdef CONFIG_FMAN_PFC ++ for (i = 0; i < CONFIG_FMAN_PFC_COS_COUNT; i++) { ++ err = fm_port_set_pfc_priorities_mapping_to_qman_wq( ++ mac_dev->port_dev[TX], i, i); ++ if (unlikely(err != 0)) { ++ dev_err(dev, "Error maping PFC %u to WQ %u\n", i, i); ++ goto pfc_mapping_failed; ++ } ++ } ++#endif ++ ++ priv->percpu_priv = devm_alloc_percpu(dev, *priv->percpu_priv); ++ ++ if (priv->percpu_priv == NULL) { ++ dev_err(dev, "devm_alloc_percpu() failed\n"); ++ err = -ENOMEM; ++ goto alloc_percpu_failed; ++ } ++ for_each_possible_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ memset(percpu_priv, 0, sizeof(*percpu_priv)); ++ } ++ ++ /* Initialize NAPI */ ++ err = dpa_private_napi_add(net_dev); ++ ++ if (err < 0) ++ goto napi_add_failed; ++ ++ err = dpa_private_netdev_init(net_dev); ++ ++ if (err < 0) ++ goto netdev_init_failed; ++ ++ dpaa_eth_sysfs_init(&net_dev->dev); ++ ++#ifdef CONFIG_PM ++ device_set_wakeup_capable(dev, true); ++#endif ++ ++ pr_info("fsl_dpa: Probed interface %s\n", net_dev->name); ++ ++ return 0; ++ ++netdev_init_failed: ++napi_add_failed: ++ dpa_private_napi_del(net_dev); ++alloc_percpu_failed: ++#ifdef CONFIG_FMAN_PFC ++pfc_mapping_failed: ++#endif ++ dpa_fq_free(dev, &priv->dpa_fq_list); ++fq_alloc_failed: ++ qman_delete_cgr_safe(&priv->ingress_cgr); ++ qman_release_cgrid(priv->ingress_cgr.cgrid); ++rx_cgr_init_failed: ++ qman_delete_cgr_safe(&priv->cgr_data.cgr); ++ qman_release_cgrid(priv->cgr_data.cgr.cgrid); ++tx_cgr_init_failed: ++add_channel_failed: ++get_channel_failed: ++ dpa_bp_free(priv); ++bp_create_failed: ++fq_probe_failed: ++alloc_failed: ++mac_probe_failed: ++ dev_set_drvdata(dev, NULL); ++ free_netdev(net_dev); ++alloc_etherdev_mq_failed: ++ if (atomic_read(&dpa_bp->refs) == 0) ++ devm_kfree(dev, dpa_bp); ++ ++ return err; ++} ++ ++static const struct of_device_id dpa_match[] = { ++ { ++ .compatible = "fsl,dpa-ethernet" ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, dpa_match); ++ ++static struct platform_driver dpa_driver = { ++ .driver = { ++ .name = KBUILD_MODNAME, ++ .of_match_table = dpa_match, ++ .owner = THIS_MODULE, ++ .pm = DPAA_PM_OPS, ++ }, ++ .probe = dpaa_eth_priv_probe, ++ .remove = dpa_remove ++}; ++ ++static int __init __cold dpa_load(void) ++{ ++ int _errno; ++ ++ pr_info(DPA_DESCRIPTION " (" VERSION ")\n"); ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++ dpa_debugfs_module_init(); ++#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++ ++ /* initialise dpaa_eth mirror values */ ++ dpa_rx_extra_headroom = fm_get_rx_extra_headroom(); ++ dpa_max_frm = fm_get_max_frm(); ++ dpa_num_cpus = num_possible_cpus(); ++ ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP ++ memset(dpa_loop_netdevs, 0, sizeof(dpa_loop_netdevs)); ++#endif ++ ++ _errno = platform_driver_register(&dpa_driver); ++ if (unlikely(_errno < 0)) { ++ pr_err(KBUILD_MODNAME ++ ": %s:%hu:%s(): platform_driver_register() = %d\n", ++ KBUILD_BASENAME".c", __LINE__, __func__, _errno); ++ } ++ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ return _errno; ++} ++module_init(dpa_load); ++ ++static void __exit __cold dpa_unload(void) ++{ ++ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ platform_driver_unregister(&dpa_driver); ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++ dpa_debugfs_module_exit(); ++#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++ ++ /* Only one channel is used and needs to be relased after all ++ * interfaces are removed ++ */ ++ dpa_release_channel(); ++ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++} ++module_exit(dpa_unload); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +new file mode 100644 +index 0000000..b5c1bf8 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +@@ -0,0 +1,664 @@ ++/* Copyright 2008-2012 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 __DPA_H ++#define __DPA_H ++ ++#include ++#include /* struct qman_fq */ ++ ++#include "fm_ext.h" ++#include "dpaa_eth_trace.h" ++ ++extern int dpa_rx_extra_headroom; ++extern int dpa_max_frm; ++extern int dpa_num_cpus; ++ ++#define dpa_get_rx_extra_headroom() dpa_rx_extra_headroom ++#define dpa_get_max_frm() dpa_max_frm ++ ++#define dpa_get_max_mtu() \ ++ (dpa_get_max_frm() - (VLAN_ETH_HLEN + ETH_FCS_LEN)) ++ ++#define __hot ++ ++/* Simple enum of FQ types - used for array indexing */ ++enum port_type {RX, TX}; ++ ++/* TODO: This structure should be renamed & moved to the FMD wrapper */ ++struct dpa_buffer_layout_s { ++ uint16_t priv_data_size; ++ bool parse_results; ++ bool time_stamp; ++ bool hash_results; ++ uint8_t manip_extra_space; ++ uint16_t data_align; ++}; ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUG ++#define DPA_BUG_ON(cond) BUG_ON(cond) ++#else ++#define DPA_BUG_ON(cond) ++#endif ++ ++#define DPA_TX_PRIV_DATA_SIZE 16 ++#define DPA_PARSE_RESULTS_SIZE sizeof(fm_prs_result_t) ++#define DPA_TIME_STAMP_SIZE 8 ++#define DPA_HASH_RESULTS_SIZE 8 ++#define DPA_RX_PRIV_DATA_SIZE (DPA_TX_PRIV_DATA_SIZE + \ ++ dpa_get_rx_extra_headroom()) ++ ++#define FM_FD_STAT_RX_ERRORS \ ++ (FM_PORT_FRM_ERR_DMA | FM_PORT_FRM_ERR_PHYSICAL | \ ++ FM_PORT_FRM_ERR_SIZE | FM_PORT_FRM_ERR_CLS_DISCARD | \ ++ FM_PORT_FRM_ERR_EXTRACTION | FM_PORT_FRM_ERR_NO_SCHEME | \ ++ FM_PORT_FRM_ERR_ILL_PLCR | FM_PORT_FRM_ERR_PRS_TIMEOUT | \ ++ FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT | FM_PORT_FRM_ERR_PRS_HDR_ERR) ++ ++#define FM_FD_STAT_TX_ERRORS \ ++ (FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT | \ ++ FM_PORT_FRM_ERR_LENGTH | FM_PORT_FRM_ERR_DMA) ++ ++#ifndef CONFIG_FSL_DPAA_ETH_JUMBO_FRAME ++/* The raw buffer size must be cacheline aligned. ++ * Normally we use 2K buffers. ++ */ ++#define DPA_BP_RAW_SIZE 2048 ++#else ++/* For jumbo frame optimizations, use buffers large enough to accommodate ++ * 9.6K frames, FD maximum offset, skb sh_info overhead and some extra ++ * space to account for further alignments. ++ */ ++#define DPA_MAX_FRM_SIZE 9600 ++#define DPA_BP_RAW_SIZE \ ++ ((DPA_MAX_FRM_SIZE + DPA_MAX_FD_OFFSET + \ ++ sizeof(struct skb_shared_info) + 128) & ~(SMP_CACHE_BYTES - 1)) ++#endif ++ ++/* This is what FMan is ever allowed to use. ++ * FMan-DMA requires 16-byte alignment for Rx buffers, but SKB_DATA_ALIGN is ++ * even stronger (SMP_CACHE_BYTES-aligned), so we just get away with that, ++ * via SKB_WITH_OVERHEAD(). We can't rely on netdev_alloc_frag() giving us ++ * half-page-aligned buffers (can we?), so we reserve some more space ++ * for start-of-buffer alignment. ++ */ ++#define dpa_bp_size(buffer_layout) (SKB_WITH_OVERHEAD(DPA_BP_RAW_SIZE) - \ ++ SMP_CACHE_BYTES) ++/* We must ensure that skb_shinfo is always cacheline-aligned. */ ++#define DPA_SKB_SIZE(size) ((size) & ~(SMP_CACHE_BYTES - 1)) ++ ++/* Maximum size of a buffer for which recycling is allowed. ++ * We need an upper limit such that forwarded skbs that get reallocated on Tx ++ * aren't allowed to grow unboundedly. On the other hand, we need to make sure ++ * that skbs allocated by us will not fail to be recycled due to their size. ++ * ++ * For a requested size, the kernel allocator provides the next power of two ++ * sized block, which the stack will use as is, regardless of the actual size ++ * it required; since we must accommodate at most 9.6K buffers (L2 maximum ++ * supported frame size), set the recycling upper limit to 16K. ++ */ ++#define DPA_RECYCLE_MAX_SIZE 16384 ++ ++#if defined(CONFIG_FSL_SDK_FMAN_TEST) ++/*TODO: temporary for fman pcd testing */ ++#define FMAN_PCD_TESTS_MAX_NUM_RANGES 20 ++#endif ++ ++#define DPAA_ETH_PCD_FQ_BASE(device_addr) \ ++ (((device_addr) & 0x1fffff) >> 6) ++ ++/* Largest value that the FQD's OAL field can hold. ++ * This is DPAA-1.x specific. ++ * TODO: This rather belongs in fsl_qman.h ++ */ ++#define FSL_QMAN_MAX_OAL 127 ++ ++/* Maximum offset value for a contig or sg FD (represented on 9 bits) */ ++#define DPA_MAX_FD_OFFSET ((1 << 9) - 1) ++ ++/* Default alignment for start of data in an Rx FD */ ++#define DPA_FD_DATA_ALIGNMENT 16 ++ ++/* Values for the L3R field of the FM Parse Results ++ */ ++/* L3 Type field: First IP Present IPv4 */ ++#define FM_L3_PARSE_RESULT_IPV4 0x8000 ++/* L3 Type field: First IP Present IPv6 */ ++#define FM_L3_PARSE_RESULT_IPV6 0x4000 ++ ++/* Values for the L4R field of the FM Parse Results ++ * See $8.8.4.7.20 - L4 HXS - L4 Results from DPAA-Rev2 Reference Manual. ++ */ ++/* L4 Type field: UDP */ ++#define FM_L4_PARSE_RESULT_UDP 0x40 ++/* L4 Type field: TCP */ ++#define FM_L4_PARSE_RESULT_TCP 0x20 ++/* FD status field indicating whether the FM Parser has attempted to validate ++ * the L4 csum of the frame. ++ * Note that having this bit set doesn't necessarily imply that the checksum ++ * is valid. One would have to check the parse results to find that out. ++ */ ++#define FM_FD_STAT_L4CV 0x00000004 ++ ++ ++#define FM_FD_STAT_ERR_PHYSICAL FM_PORT_FRM_ERR_PHYSICAL ++ ++/* Check if the parsed frame was found to be a TCP segment. ++ * ++ * @parse_result_ptr must be of type (fm_prs_result_t *). ++ */ ++#define fm_l4_frame_is_tcp(parse_result_ptr) \ ++ ((parse_result_ptr)->l4r & FM_L4_PARSE_RESULT_TCP) ++ ++/* number of Tx queues to FMan */ ++#ifdef CONFIG_FMAN_PFC ++#define DPAA_ETH_TX_QUEUES (NR_CPUS * CONFIG_FMAN_PFC_COS_COUNT) ++#else ++#define DPAA_ETH_TX_QUEUES NR_CPUS ++#endif ++ ++#define DPAA_ETH_RX_QUEUES 128 ++ ++/* Convenience macros for storing/retrieving the skb back-pointers. They must ++ * accommodate both recycling and confirmation paths - i.e. cases when the buf ++ * was allocated by ourselves, respectively by the stack. In the former case, ++ * we could store the skb at negative offset; in the latter case, we can't, ++ * so we'll use 0 as offset. ++ * ++ * NB: @off is an offset from a (struct sk_buff **) pointer! ++ */ ++#define DPA_WRITE_SKB_PTR(skb, skbh, addr, off) \ ++{ \ ++ skbh = (struct sk_buff **)addr; \ ++ *(skbh + (off)) = skb; \ ++} ++#define DPA_READ_SKB_PTR(skb, skbh, addr, off) \ ++{ \ ++ skbh = (struct sk_buff **)addr; \ ++ skb = *(skbh + (off)); \ ++} ++ ++#ifdef CONFIG_PM ++/* Magic Packet wakeup */ ++#define DPAA_WOL_MAGIC 0x00000001 ++#endif ++ ++#if defined(CONFIG_FSL_SDK_FMAN_TEST) ++struct pcd_range { ++ uint32_t base; ++ uint32_t count; ++}; ++#endif ++ ++/* More detailed FQ types - used for fine-grained WQ assignments */ ++enum dpa_fq_type { ++ FQ_TYPE_RX_DEFAULT = 1, /* Rx Default FQs */ ++ FQ_TYPE_RX_ERROR, /* Rx Error FQs */ ++ FQ_TYPE_RX_PCD, /* User-defined PCDs */ ++ FQ_TYPE_TX, /* "Real" Tx FQs */ ++ FQ_TYPE_TX_CONFIRM, /* Tx default Conf FQ (actually an Rx FQ) */ ++ FQ_TYPE_TX_CONF_MQ, /* Tx conf FQs (one for each Tx FQ) */ ++ FQ_TYPE_TX_ERROR, /* Tx Error FQs (these are actually Rx FQs) */ ++}; ++ ++struct dpa_fq { ++ struct qman_fq fq_base; ++ struct list_head list; ++ struct net_device *net_dev; ++ bool init; ++ uint32_t fqid; ++ uint32_t flags; ++ uint16_t channel; ++ uint8_t wq; ++ enum dpa_fq_type fq_type; ++}; ++ ++struct dpa_fq_cbs_t { ++ struct qman_fq rx_defq; ++ struct qman_fq tx_defq; ++ struct qman_fq rx_errq; ++ struct qman_fq tx_errq; ++ struct qman_fq egress_ern; ++}; ++ ++struct fqid_cell { ++ uint32_t start; ++ uint32_t count; ++}; ++ ++struct dpa_bp { ++ struct bman_pool *pool; ++ uint8_t bpid; ++ struct device *dev; ++ union { ++ /* The buffer pools used for the private ports are initialized ++ * with target_count buffers for each CPU; at runtime the ++ * number of buffers per CPU is constantly brought back to this ++ * level ++ */ ++ int target_count; ++ /* The configured value for the number of buffers in the pool, ++ * used for shared port buffer pools ++ */ ++ int config_count; ++ }; ++ size_t size; ++ bool seed_pool; ++ /* physical address of the contiguous memory used by the pool to store ++ * the buffers ++ */ ++ dma_addr_t paddr; ++ /* virtual address of the contiguous memory used by the pool to store ++ * the buffers ++ */ ++ void __iomem *vaddr; ++ /* current number of buffers in the bpool alloted to this CPU */ ++ int __percpu *percpu_count; ++ atomic_t refs; ++ /* some bpools need to be seeded before use by this cb */ ++ int (*seed_cb)(struct dpa_bp *); ++ /* some bpools need to be emptied before freeing; this cb is used ++ * for freeing of individual buffers taken from the pool ++ */ ++ void (*free_buf_cb)(void *addr); ++}; ++ ++struct dpa_rx_errors { ++ u64 dme; /* DMA Error */ ++ u64 fpe; /* Frame Physical Error */ ++ u64 fse; /* Frame Size Error */ ++ u64 phe; /* Header Error */ ++ u64 cse; /* Checksum Validation Error */ ++}; ++ ++/* Counters for QMan ERN frames - one counter per rejection code */ ++struct dpa_ern_cnt { ++ u64 cg_tdrop; /* Congestion group taildrop */ ++ u64 wred; /* WRED congestion */ ++ u64 err_cond; /* Error condition */ ++ u64 early_window; /* Order restoration, frame too early */ ++ u64 late_window; /* Order restoration, frame too late */ ++ u64 fq_tdrop; /* FQ taildrop */ ++ u64 fq_retired; /* FQ is retired */ ++ u64 orp_zero; /* ORP disabled */ ++}; ++ ++struct dpa_napi_portal { ++ struct napi_struct napi; ++ struct qman_portal *p; ++}; ++ ++struct dpa_percpu_priv_s { ++ struct net_device *net_dev; ++ struct dpa_napi_portal *np; ++ u64 in_interrupt; ++ u64 tx_returned; ++ u64 tx_confirm; ++ /* fragmented (non-linear) skbuffs received from the stack */ ++ u64 tx_frag_skbuffs; ++ struct rtnl_link_stats64 stats; ++ struct dpa_rx_errors rx_errors; ++ struct dpa_ern_cnt ern_cnt; ++}; ++ ++struct dpa_priv_s { ++ struct dpa_percpu_priv_s __percpu *percpu_priv; ++ struct dpa_bp *dpa_bp; ++ /* Store here the needed Tx headroom for convenience and speed ++ * (even though it can be computed based on the fields of buf_layout) ++ */ ++ uint16_t tx_headroom; ++ struct net_device *net_dev; ++ struct mac_device *mac_dev; ++ struct qman_fq *egress_fqs[DPAA_ETH_TX_QUEUES]; ++ struct qman_fq *conf_fqs[DPAA_ETH_TX_QUEUES]; ++ ++ size_t bp_count; ++ ++ uint16_t channel; /* "fsl,qman-channel-id" */ ++ struct list_head dpa_fq_list; ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++ struct dentry *debugfs_file; ++#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP ++ struct dentry *debugfs_loop_file; ++#endif ++ ++ uint32_t msg_enable; /* net_device message level */ ++#ifdef CONFIG_FSL_DPAA_1588 ++ struct dpa_ptp_tsu *tsu; ++#endif ++ ++#if defined(CONFIG_FSL_SDK_FMAN_TEST) ++/* TODO: this is temporary until pcd support is implemented in dpaa */ ++ int priv_pcd_num_ranges; ++ struct pcd_range priv_pcd_ranges[FMAN_PCD_TESTS_MAX_NUM_RANGES]; ++#endif ++ ++ struct { ++ /** ++ * All egress queues to a given net device belong to one ++ * (and the same) congestion group. ++ */ ++ struct qman_cgr cgr; ++ /* If congested, when it began. Used for performance stats. */ ++ u32 congestion_start_jiffies; ++ /* Number of jiffies the Tx port was congested. */ ++ u32 congested_jiffies; ++ /** ++ * Counter for the number of times the CGR ++ * entered congestion state ++ */ ++ u32 cgr_congested_count; ++ } cgr_data; ++ /* Use a per-port CGR for ingress traffic. */ ++ bool use_ingress_cgr; ++ struct qman_cgr ingress_cgr; ++ ++#ifdef CONFIG_FSL_DPAA_TS ++ bool ts_tx_en; /* Tx timestamping enabled */ ++ bool ts_rx_en; /* Rx timestamping enabled */ ++#endif /* CONFIG_FSL_DPAA_TS */ ++ ++ struct dpa_buffer_layout_s *buf_layout; ++ uint16_t rx_headroom; ++ char if_type[30]; ++ ++ void *peer; ++#ifdef CONFIG_PM ++ u32 wol; ++#endif ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP ++ int loop_id; ++ int loop_to; ++#endif ++}; ++ ++struct fm_port_fqs { ++ struct dpa_fq *tx_defq; ++ struct dpa_fq *tx_errq; ++ struct dpa_fq *rx_defq; ++ struct dpa_fq *rx_errq; ++}; ++ ++ ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP ++extern struct net_device *dpa_loop_netdevs[20]; ++#endif ++ ++/* functions with different implementation for SG and non-SG: */ ++int dpa_bp_priv_seed(struct dpa_bp *dpa_bp); ++int dpaa_eth_refill_bpools(struct dpa_bp *dpa_bp, int *count_ptr); ++void __hot _dpa_rx(struct net_device *net_dev, ++ struct qman_portal *portal, ++ const struct dpa_priv_s *priv, ++ struct dpa_percpu_priv_s *percpu_priv, ++ const struct qm_fd *fd, ++ u32 fqid, ++ int *count_ptr); ++int __hot dpa_tx(struct sk_buff *skb, struct net_device *net_dev); ++int __hot dpa_tx_extended(struct sk_buff *skb, struct net_device *net_dev, ++ struct qman_fq *egress_fq, struct qman_fq *conf_fq); ++struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv, ++ const struct qm_fd *fd); ++void __hot _dpa_process_parse_results(const fm_prs_result_t *parse_results, ++ const struct qm_fd *fd, ++ struct sk_buff *skb, ++ int *use_gro); ++#ifndef CONFIG_FSL_DPAA_TS ++bool dpa_skb_is_recyclable(struct sk_buff *skb); ++bool dpa_buf_is_recyclable(struct sk_buff *skb, ++ uint32_t min_size, ++ uint16_t min_offset, ++ unsigned char **new_buf_start); ++#endif ++int __hot skb_to_contig_fd(struct dpa_priv_s *priv, ++ struct sk_buff *skb, struct qm_fd *fd, ++ int *count_ptr, int *offset); ++int __hot skb_to_sg_fd(struct dpa_priv_s *priv, ++ struct sk_buff *skb, struct qm_fd *fd); ++int __cold __attribute__((nonnull)) ++ _dpa_fq_free(struct device *dev, struct qman_fq *fq); ++ ++/* Turn on HW checksum computation for this outgoing frame. ++ * If the current protocol is not something we support in this regard ++ * (or if the stack has already computed the SW checksum), we do nothing. ++ * ++ * Returns 0 if all goes well (or HW csum doesn't apply), and a negative value ++ * otherwise. ++ * ++ * Note that this function may modify the fd->cmd field and the skb data buffer ++ * (the Parse Results area). ++ */ ++int dpa_enable_tx_csum(struct dpa_priv_s *priv, ++ struct sk_buff *skb, struct qm_fd *fd, char *parse_results); ++ ++static inline int dpaa_eth_napi_schedule(struct dpa_percpu_priv_s *percpu_priv, ++ struct qman_portal *portal) ++{ ++ /* In case of threaded ISR for RT enable kernel, ++ * in_irq() does not return appropriate value, so use ++ * in_serving_softirq to distinguish softirq or irq context. ++ */ ++ if (unlikely(in_irq() || !in_serving_softirq())) { ++ /* Disable QMan IRQ and invoke NAPI */ ++ int ret = qman_p_irqsource_remove(portal, QM_PIRQ_DQRI); ++ if (likely(!ret)) { ++ const struct qman_portal_config *pc = ++ qman_p_get_portal_config(portal); ++ struct dpa_napi_portal *np = ++ &percpu_priv->np[pc->index]; ++ ++ np->p = portal; ++ napi_schedule(&np->napi); ++ percpu_priv->in_interrupt++; ++ return 1; ++ } ++ } ++ return 0; ++} ++ ++static inline ssize_t __const __must_check __attribute__((nonnull)) ++dpa_fd_length(const struct qm_fd *fd) ++{ ++ return fd->length20; ++} ++ ++static inline ssize_t __const __must_check __attribute__((nonnull)) ++dpa_fd_offset(const struct qm_fd *fd) ++{ ++ return fd->offset; ++} ++ ++/* Verifies if the skb length is below the interface MTU */ ++static inline int dpa_check_rx_mtu(struct sk_buff *skb, int mtu) ++{ ++ if (unlikely(skb->len > mtu)) ++ if ((skb->protocol != htons(ETH_P_8021Q)) ++ || (skb->len > mtu + 4)) ++ return -1; ++ ++ return 0; ++} ++ ++static inline uint16_t dpa_get_headroom(struct dpa_buffer_layout_s *bl) ++{ ++ uint16_t headroom; ++ /* The frame headroom must accommodate: ++ * - the driver private data area ++ * - parse results, hash results, timestamp if selected ++ * - manip extra space ++ * If either hash results or time stamp are selected, both will ++ * be copied to/from the frame headroom, as TS is located between PR and ++ * HR in the IC and IC copy size has a granularity of 16bytes ++ * (see description of FMBM_RICP and FMBM_TICP registers in DPAARM) ++ * ++ * Also make sure the headroom is a multiple of data_align bytes ++ */ ++ headroom = (uint16_t)(bl->priv_data_size + ++ (bl->parse_results ? DPA_PARSE_RESULTS_SIZE : 0) + ++ (bl->hash_results || bl->time_stamp ? ++ DPA_TIME_STAMP_SIZE + DPA_HASH_RESULTS_SIZE : 0) + ++ bl->manip_extra_space); ++ ++ return bl->data_align ? ALIGN(headroom, bl->data_align) : headroom; ++} ++ ++int fm_mac_dump_regs(struct mac_device *h_dev, char *buf, int n); ++int fm_mac_dump_rx_stats(struct mac_device *h_dev, char *buf, int n); ++int fm_mac_dump_tx_stats(struct mac_device *h_dev, char *buf, int n); ++ ++void dpaa_eth_sysfs_remove(struct device *dev); ++void dpaa_eth_sysfs_init(struct device *dev); ++int dpaa_eth_poll(struct napi_struct *napi, int budget); ++ ++void dpa_private_napi_del(struct net_device *net_dev); ++ ++/* Equivalent to a memset(0), but works faster */ ++static inline void clear_fd(struct qm_fd *fd) ++{ ++ fd->opaque_addr = 0; ++ fd->opaque = 0; ++ fd->cmd = 0; ++} ++ ++static inline int _dpa_tx_fq_to_id(const struct dpa_priv_s *priv, ++ struct qman_fq *tx_fq) ++{ ++ int i; ++ ++ for (i = 0; i < DPAA_ETH_TX_QUEUES; i++) ++ if (priv->egress_fqs[i] == tx_fq) ++ return i; ++ ++ return -EINVAL; ++} ++ ++static inline int __hot dpa_xmit(struct dpa_priv_s *priv, ++ struct rtnl_link_stats64 *percpu_stats, ++ struct qm_fd *fd, struct qman_fq *egress_fq, ++ struct qman_fq *conf_fq) ++{ ++ int err, i; ++ ++ if (fd->bpid == 0xff) ++ fd->cmd |= qman_fq_fqid(conf_fq); ++ ++ /* Trace this Tx fd */ ++ trace_dpa_tx_fd(priv->net_dev, egress_fq, fd); ++ ++ for (i = 0; i < 100000; i++) { ++ err = qman_enqueue(egress_fq, fd, 0); ++ if (err != -EBUSY) ++ break; ++ } ++ ++ if (unlikely(err < 0)) { ++ /* TODO differentiate b/w -EBUSY (EQCR full) and other codes? */ ++ percpu_stats->tx_errors++; ++ percpu_stats->tx_fifo_errors++; ++ return err; ++ } ++ ++ percpu_stats->tx_packets++; ++ percpu_stats->tx_bytes += dpa_fd_length(fd); ++ ++ return 0; ++} ++ ++/* Use multiple WQs for FQ assignment: ++ * - Tx Confirmation queues go to WQ1. ++ * - Rx Default, Tx and PCD queues go to WQ3 (no differentiation between ++ * Rx and Tx traffic, or between Rx Default and Rx PCD frames). ++ * - Rx Error and Tx Error queues go to WQ2 (giving them a better chance ++ * to be scheduled, in case there are many more FQs in WQ3). ++ * This ensures that Tx-confirmed buffers are timely released. In particular, ++ * it avoids congestion on the Tx Confirm FQs, which can pile up PFDRs if they ++ * are greatly outnumbered by other FQs in the system (usually PCDs), while ++ * dequeue scheduling is round-robin. ++ */ ++static inline void _dpa_assign_wq(struct dpa_fq *fq) ++{ ++ switch (fq->fq_type) { ++ case FQ_TYPE_TX_CONFIRM: ++ case FQ_TYPE_TX_CONF_MQ: ++ fq->wq = 1; ++ break; ++ case FQ_TYPE_RX_DEFAULT: ++ case FQ_TYPE_TX: ++ case FQ_TYPE_RX_PCD: ++ fq->wq = 3; ++ break; ++ case FQ_TYPE_RX_ERROR: ++ case FQ_TYPE_TX_ERROR: ++ fq->wq = 2; ++ break; ++ default: ++ WARN(1, "Invalid FQ type %d for FQID %d!\n", ++ fq->fq_type, fq->fqid); ++ } ++} ++ ++#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE ++/* Use in lieu of skb_get_queue_mapping() */ ++#ifdef CONFIG_FMAN_PFC ++#define dpa_get_queue_mapping(skb) \ ++ (((skb)->priority < CONFIG_FMAN_PFC_COS_COUNT) ? \ ++ ((skb)->priority * dpa_num_cpus + smp_processor_id()) : \ ++ ((CONFIG_FMAN_PFC_COS_COUNT - 1) * \ ++ dpa_num_cpus + smp_processor_id())); ++ ++#else ++#define dpa_get_queue_mapping(skb) \ ++ smp_processor_id() ++#endif ++#else ++/* Use the queue selected by XPS */ ++#define dpa_get_queue_mapping(skb) \ ++ skb_get_queue_mapping(skb) ++#endif ++ ++#ifdef CONFIG_PTP_1588_CLOCK_DPAA ++struct ptp_priv_s { ++ struct device_node *node; ++ struct platform_device *of_dev; ++ struct mac_device *mac_dev; ++}; ++extern struct ptp_priv_s ptp_priv; ++#endif ++ ++static inline void _dpa_bp_free_pf(void *addr) ++{ ++ put_page(virt_to_head_page(addr)); ++} ++ ++#endif /* __DPA_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c +new file mode 100644 +index 0000000..9f55496 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c +@@ -0,0 +1,250 @@ ++/* Copyright 2008-2013 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. ++ */ ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUG ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++#else ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": " fmt ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "dpaa_eth.h" ++#include "dpaa_eth_common.h" ++#include "dpaa_eth_base.h" ++ ++#define DPA_DESCRIPTION "FSL DPAA Advanced drivers:" ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++uint8_t advanced_debug = -1; ++module_param(advanced_debug, byte, S_IRUGO); ++MODULE_PARM_DESC(advanced_debug, "Module/Driver verbosity level"); ++EXPORT_SYMBOL(advanced_debug); ++ ++static int dpa_bp_cmp(const void *dpa_bp0, const void *dpa_bp1) ++{ ++ return ((struct dpa_bp *)dpa_bp0)->size - ++ ((struct dpa_bp *)dpa_bp1)->size; ++} ++ ++struct dpa_bp * __cold __must_check /* __attribute__((nonnull)) */ ++dpa_bp_probe(struct platform_device *_of_dev, size_t *count) ++{ ++ int i, lenp, na, ns, err; ++ struct device *dev; ++ struct device_node *dev_node; ++ const __be32 *bpool_cfg; ++ struct dpa_bp *dpa_bp; ++ u32 bpid; ++ ++ dev = &_of_dev->dev; ++ ++ *count = of_count_phandle_with_args(dev->of_node, ++ "fsl,bman-buffer-pools", NULL); ++ if (*count < 1) { ++ dev_err(dev, "missing fsl,bman-buffer-pools device tree entry\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ dpa_bp = devm_kzalloc(dev, *count * sizeof(*dpa_bp), GFP_KERNEL); ++ if (dpa_bp == NULL) { ++ dev_err(dev, "devm_kzalloc() failed\n"); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ dev_node = of_find_node_by_path("/"); ++ if (unlikely(dev_node == NULL)) { ++ dev_err(dev, "of_find_node_by_path(/) failed\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ na = of_n_addr_cells(dev_node); ++ ns = of_n_size_cells(dev_node); ++ ++ for (i = 0; i < *count; i++) { ++ of_node_put(dev_node); ++ ++ dev_node = of_parse_phandle(dev->of_node, ++ "fsl,bman-buffer-pools", i); ++ if (dev_node == NULL) { ++ dev_err(dev, "of_find_node_by_phandle() failed\n"); ++ return ERR_PTR(-EFAULT); ++ } ++ ++ if (unlikely(!of_device_is_compatible(dev_node, "fsl,bpool"))) { ++ dev_err(dev, ++ "!of_device_is_compatible(%s, fsl,bpool)\n", ++ dev_node->full_name); ++ dpa_bp = ERR_PTR(-EINVAL); ++ goto _return_of_node_put; ++ } ++ ++ err = of_property_read_u32(dev_node, "fsl,bpid", &bpid); ++ if (err) { ++ dev_err(dev, "Cannot find buffer pool ID in the device tree\n"); ++ dpa_bp = ERR_PTR(-EINVAL); ++ goto _return_of_node_put; ++ } ++ dpa_bp[i].bpid = (uint8_t)bpid; ++ ++ bpool_cfg = of_get_property(dev_node, "fsl,bpool-ethernet-cfg", ++ &lenp); ++ if (bpool_cfg && (lenp == (2 * ns + na) * sizeof(*bpool_cfg))) { ++ const uint32_t *seed_pool; ++ ++ dpa_bp[i].config_count = ++ (int)of_read_number(bpool_cfg, ns); ++ dpa_bp[i].size = ++ (size_t)of_read_number(bpool_cfg + ns, ns); ++ dpa_bp[i].paddr = ++ of_read_number(bpool_cfg + 2 * ns, na); ++ ++ seed_pool = of_get_property(dev_node, ++ "fsl,bpool-ethernet-seeds", &lenp); ++ dpa_bp[i].seed_pool = !!seed_pool; ++ ++ } else { ++ dev_err(dev, ++ "Missing/invalid fsl,bpool-ethernet-cfg device tree entry for node %s\n", ++ dev_node->full_name); ++ dpa_bp = ERR_PTR(-EINVAL); ++ goto _return_of_node_put; ++ } ++ } ++ ++ sort(dpa_bp, *count, sizeof(*dpa_bp), dpa_bp_cmp, NULL); ++ ++ return dpa_bp; ++ ++_return_of_node_put: ++ if (dev_node) ++ of_node_put(dev_node); ++ ++ return dpa_bp; ++} ++EXPORT_SYMBOL(dpa_bp_probe); ++ ++int dpa_bp_shared_port_seed(struct dpa_bp *bp) ++{ ++ /* In MAC-less and Shared-MAC scenarios the physical ++ * address of the buffer pool in device tree is set ++ * to 0 to specify that another entity (USDPAA) will ++ * allocate and seed the buffers ++ */ ++ if (!bp->paddr) ++ return 0; ++ ++ /* allocate memory region for buffers */ ++ devm_request_mem_region(bp->dev, bp->paddr, ++ bp->size * bp->config_count, KBUILD_MODNAME); ++ bp->vaddr = devm_ioremap_prot(bp->dev, bp->paddr, ++ bp->size * bp->config_count, 0); ++ if (bp->vaddr == NULL) { ++ pr_err("Could not map memory for pool %d\n", bp->bpid); ++ return -EIO; ++ } ++ ++ /* seed pool with buffers from that memory region */ ++ if (bp->seed_pool) { ++ int count = bp->target_count; ++ dma_addr_t addr = bp->paddr; ++ ++ while (count) { ++ struct bm_buffer bufs[8]; ++ uint8_t num_bufs = 0; ++ ++ do { ++ BUG_ON(addr > 0xffffffffffffull); ++ bufs[num_bufs].bpid = bp->bpid; ++ bm_buffer_set64(&bufs[num_bufs++], addr); ++ addr += bp->size; ++ ++ } while (--count && (num_bufs < 8)); ++ ++ while (bman_release(bp->pool, bufs, num_bufs, 0)) ++ cpu_relax(); ++ } ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(dpa_bp_shared_port_seed); ++ ++int dpa_bp_create(struct net_device *net_dev, struct dpa_bp *dpa_bp, ++ size_t count) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ int i; ++ ++ priv->dpa_bp = dpa_bp; ++ priv->bp_count = count; ++ ++ for (i = 0; i < count; i++) { ++ int err; ++ err = dpa_bp_alloc(&dpa_bp[i]); ++ if (err < 0) { ++ dpa_bp_free(priv); ++ priv->dpa_bp = NULL; ++ return err; ++ } ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(dpa_bp_create); ++ ++static int __init __cold dpa_advanced_load(void) ++{ ++ pr_info(DPA_DESCRIPTION " (" VERSION ")\n"); ++ ++ return 0; ++} ++module_init(dpa_advanced_load); ++ ++static void __exit __cold dpa_advanced_unload(void) ++{ ++ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n", ++ KBUILD_BASENAME".c", __func__); ++ ++} ++module_exit(dpa_advanced_unload); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.h +new file mode 100644 +index 0000000..6f57041 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.h +@@ -0,0 +1,50 @@ ++/* Copyright 2008-2013 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 __DPAA_ETH_BASE_H ++#define __DPAA_ETH_BASE_H ++ ++#include /* struct net_device */ ++#include /* struct bm_buffer */ ++#include /* struct platform_device */ ++#include /* struct hwtstamp_config */ ++ ++extern uint8_t advanced_debug; ++extern const struct dpa_fq_cbs_t shared_fq_cbs; ++extern int __hot dpa_shared_tx(struct sk_buff *skb, struct net_device *net_dev); ++ ++struct dpa_bp * __cold __must_check /* __attribute__((nonnull)) */ ++dpa_bp_probe(struct platform_device *_of_dev, size_t *count); ++int dpa_bp_create(struct net_device *net_dev, struct dpa_bp *dpa_bp, ++ size_t count); ++int dpa_bp_shared_port_seed(struct dpa_bp *bp); ++ ++#endif /* __DPAA_ETH_BASE_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +new file mode 100644 +index 0000000..2015996 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +@@ -0,0 +1,1719 @@ ++/* Copyright 2008-2013 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include /* vlan_eth_hdr */ ++#include "dpaa_eth.h" ++#include "dpaa_eth_common.h" ++#ifdef CONFIG_FSL_DPAA_1588 ++#include "dpaa_1588.h" ++#endif ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++#include "dpaa_debugfs.h" ++#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++#include "mac.h" ++ ++/* DPAA platforms benefit from hardware-assisted queue management */ ++#ifdef CONFIG_AS_FASTPATH ++#define DPA_NETIF_FEATURES (NETIF_F_HW_QDISC | NETIF_F_HW_ACCEL_MQ) ++#else ++#define DPA_NETIF_FEATURES NETIF_F_HW_ACCEL_MQ ++#endif ++ ++/* Size in bytes of the FQ taildrop threshold */ ++#define DPA_FQ_TD 0x200000 ++ ++#ifdef CONFIG_PTP_1588_CLOCK_DPAA ++struct ptp_priv_s ptp_priv; ++#endif ++ ++static struct dpa_bp *dpa_bp_array[64]; ++ ++int dpa_max_frm; ++EXPORT_SYMBOL(dpa_max_frm); ++ ++int dpa_rx_extra_headroom; ++EXPORT_SYMBOL(dpa_rx_extra_headroom); ++ ++int dpa_num_cpus = NR_CPUS; ++ ++static const struct fqid_cell tx_confirm_fqids[] = { ++ {0, DPAA_ETH_TX_QUEUES} ++}; ++ ++static struct fqid_cell default_fqids[][3] = { ++ [RX] = { {0, 1}, {0, 1}, {0, DPAA_ETH_RX_QUEUES} }, ++ [TX] = { {0, 1}, {0, 1}, {0, DPAA_ETH_TX_QUEUES} } ++}; ++ ++static const char fsl_qman_frame_queues[][25] = { ++ [RX] = "fsl,qman-frame-queues-rx", ++ [TX] = "fsl,qman-frame-queues-tx" ++}; ++#ifdef CONFIG_FSL_DPAA_HOOKS ++/* A set of callbacks for hooking into the fastpath at different points. */ ++struct dpaa_eth_hooks_s dpaa_eth_hooks; ++EXPORT_SYMBOL(dpaa_eth_hooks); ++/* This function should only be called on the probe paths, since it makes no ++ * effort to guarantee consistency of the destination hooks structure. ++ */ ++void fsl_dpaa_eth_set_hooks(struct dpaa_eth_hooks_s *hooks) ++{ ++ if (hooks) ++ dpaa_eth_hooks = *hooks; ++ else ++ pr_err("NULL pointer to hooks!\n"); ++} ++EXPORT_SYMBOL(fsl_dpaa_eth_set_hooks); ++#endif ++ ++int dpa_netdev_init(struct net_device *net_dev, ++ const uint8_t *mac_addr, ++ uint16_t tx_timeout) ++{ ++ int err; ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct device *dev = net_dev->dev.parent; ++ ++ net_dev->hw_features |= DPA_NETIF_FEATURES; ++ ++ net_dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; ++ ++ net_dev->features |= net_dev->hw_features; ++ net_dev->vlan_features = net_dev->features; ++ ++ memcpy(net_dev->perm_addr, mac_addr, net_dev->addr_len); ++ memcpy(net_dev->dev_addr, mac_addr, net_dev->addr_len); ++ ++ net_dev->ethtool_ops = &dpa_ethtool_ops; ++ ++ net_dev->needed_headroom = priv->tx_headroom; ++ net_dev->watchdog_timeo = msecs_to_jiffies(tx_timeout); ++ ++ err = register_netdev(net_dev); ++ if (err < 0) { ++ dev_err(dev, "register_netdev() = %d\n", err); ++ return err; ++ } ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++ /* create debugfs entry for this net_device */ ++ err = dpa_netdev_debugfs_create(net_dev); ++ if (err) { ++ unregister_netdev(net_dev); ++ return err; ++ } ++#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++ ++ return 0; ++} ++EXPORT_SYMBOL(dpa_netdev_init); ++ ++int __cold dpa_start(struct net_device *net_dev) ++{ ++ int err, i; ++ struct dpa_priv_s *priv; ++ struct mac_device *mac_dev; ++ ++ priv = netdev_priv(net_dev); ++ mac_dev = priv->mac_dev; ++ ++ err = mac_dev->init_phy(net_dev, priv->mac_dev); ++ if (err < 0) { ++ if (netif_msg_ifup(priv)) ++ netdev_err(net_dev, "init_phy() = %d\n", err); ++ return err; ++ } ++ ++ for_each_port_device(i, mac_dev->port_dev) { ++ err = fm_port_enable(mac_dev->port_dev[i]); ++ if (err) ++ goto mac_start_failed; ++ } ++ ++ err = priv->mac_dev->start(mac_dev); ++ if (err < 0) { ++ if (netif_msg_ifup(priv)) ++ netdev_err(net_dev, "mac_dev->start() = %d\n", err); ++ goto mac_start_failed; ++ } ++ ++ netif_tx_start_all_queues(net_dev); ++ ++ return 0; ++ ++mac_start_failed: ++ for_each_port_device(i, mac_dev->port_dev) ++ fm_port_disable(mac_dev->port_dev[i]); ++ ++ return err; ++} ++EXPORT_SYMBOL(dpa_start); ++ ++int __cold dpa_stop(struct net_device *net_dev) ++{ ++ int _errno, i, err; ++ struct dpa_priv_s *priv; ++ struct mac_device *mac_dev; ++ ++ priv = netdev_priv(net_dev); ++ mac_dev = priv->mac_dev; ++ ++ netif_tx_stop_all_queues(net_dev); ++ /* Allow the Fman (Tx) port to process in-flight frames before we ++ * try switching it off. ++ */ ++ usleep_range(5000, 10000); ++ ++ _errno = mac_dev->stop(mac_dev); ++ if (unlikely(_errno < 0)) ++ if (netif_msg_ifdown(priv)) ++ netdev_err(net_dev, "mac_dev->stop() = %d\n", ++ _errno); ++ ++ for_each_port_device(i, mac_dev->port_dev) { ++ err = fm_port_disable(mac_dev->port_dev[i]); ++ _errno = err ? err : _errno; ++ } ++ ++ if (mac_dev->phy_dev) ++ phy_disconnect(mac_dev->phy_dev); ++ mac_dev->phy_dev = NULL; ++ ++ return _errno; ++} ++EXPORT_SYMBOL(dpa_stop); ++ ++void __cold dpa_timeout(struct net_device *net_dev) ++{ ++ const struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ ++ priv = netdev_priv(net_dev); ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ ++ if (netif_msg_timer(priv)) ++ netdev_crit(net_dev, "Transmit timeout latency: %u ms\n", ++ jiffies_to_msecs(jiffies - net_dev->trans_start)); ++ ++ percpu_priv->stats.tx_errors++; ++} ++EXPORT_SYMBOL(dpa_timeout); ++ ++/* net_device */ ++ ++/** ++ * @param net_dev the device for which statistics are calculated ++ * @param stats the function fills this structure with the device's statistics ++ * @return the address of the structure containing the statistics ++ * ++ * Calculates the statistics for the given device by adding the statistics ++ * collected by each CPU. ++ */ ++struct rtnl_link_stats64 * __cold ++dpa_get_stats64(struct net_device *net_dev, ++ struct rtnl_link_stats64 *stats) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ u64 *cpustats; ++ u64 *netstats = (u64 *)stats; ++ int i, j; ++ struct dpa_percpu_priv_s *percpu_priv; ++ int numstats = sizeof(struct rtnl_link_stats64) / sizeof(u64); ++ ++ for_each_possible_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ cpustats = (u64 *)&percpu_priv->stats; ++ ++ for (j = 0; j < numstats; j++) ++ netstats[j] += cpustats[j]; ++ } ++ ++ return stats; ++} ++EXPORT_SYMBOL(dpa_get_stats64); ++ ++int dpa_change_mtu(struct net_device *net_dev, int new_mtu) ++{ ++ const int max_mtu = dpa_get_max_mtu(); ++ ++ /* Make sure we don't exceed the Ethernet controller's MAXFRM */ ++ if (new_mtu < 68 || new_mtu > max_mtu) { ++ netdev_err(net_dev, "Invalid L3 mtu %d (must be between %d and %d).\n", ++ new_mtu, 68, max_mtu); ++ return -EINVAL; ++ } ++ net_dev->mtu = new_mtu; ++ ++ return 0; ++} ++EXPORT_SYMBOL(dpa_change_mtu); ++ ++/* .ndo_init callback */ ++int dpa_ndo_init(struct net_device *net_dev) ++{ ++ /* If fsl_fm_max_frm is set to a higher value than the all-common 1500, ++ * we choose conservatively and let the user explicitly set a higher ++ * MTU via ifconfig. Otherwise, the user may end up with different MTUs ++ * in the same LAN. ++ * If on the other hand fsl_fm_max_frm has been chosen below 1500, ++ * start with the maximum allowed. ++ */ ++ int init_mtu = min(dpa_get_max_mtu(), ETH_DATA_LEN); ++ ++ pr_debug("Setting initial MTU on net device: %d\n", init_mtu); ++ net_dev->mtu = init_mtu; ++ ++ return 0; ++} ++EXPORT_SYMBOL(dpa_ndo_init); ++ ++int dpa_set_features(struct net_device *dev, netdev_features_t features) ++{ ++ /* Not much to do here for now */ ++ dev->features = features; ++ return 0; ++} ++EXPORT_SYMBOL(dpa_set_features); ++ ++netdev_features_t dpa_fix_features(struct net_device *dev, ++ netdev_features_t features) ++{ ++ netdev_features_t unsupported_features = 0; ++ ++ /* In theory we should never be requested to enable features that ++ * we didn't set in netdev->features and netdev->hw_features at probe ++ * time, but double check just to be on the safe side. ++ * We don't support enabling Rx csum through ethtool yet ++ */ ++ unsupported_features |= NETIF_F_RXCSUM; ++ ++ features &= ~unsupported_features; ++ ++ return features; ++} ++EXPORT_SYMBOL(dpa_fix_features); ++ ++#ifdef CONFIG_FSL_DPAA_TS ++u64 dpa_get_timestamp_ns(const struct dpa_priv_s *priv, enum port_type rx_tx, ++ const void *data) ++{ ++ u64 *ts, ns; ++ ++ ts = fm_port_get_buffer_time_stamp(priv->mac_dev->port_dev[rx_tx], ++ data); ++ ++ if (!ts || *ts == 0) ++ return 0; ++ ++ /* multiple DPA_PTP_NOMINAL_FREQ_PERIOD_NS for case of non power of 2 */ ++ ns = *ts << DPA_PTP_NOMINAL_FREQ_PERIOD_SHIFT; ++ ++ return ns; ++} ++ ++int dpa_get_ts(const struct dpa_priv_s *priv, enum port_type rx_tx, ++ struct skb_shared_hwtstamps *shhwtstamps, const void *data) ++{ ++ u64 ns; ++ ++ ns = dpa_get_timestamp_ns(priv, rx_tx, data); ++ ++ if (ns == 0) ++ return -EINVAL; ++ ++ memset(shhwtstamps, 0, sizeof(*shhwtstamps)); ++ shhwtstamps->hwtstamp = ns_to_ktime(ns); ++ ++ return 0; ++} ++ ++static void dpa_ts_tx_enable(struct net_device *dev) ++{ ++ struct dpa_priv_s *priv = netdev_priv(dev); ++ struct mac_device *mac_dev = priv->mac_dev; ++ ++ if (mac_dev->fm_rtc_enable) ++ mac_dev->fm_rtc_enable(get_fm_handle(dev)); ++ if (mac_dev->ptp_enable) ++ mac_dev->ptp_enable(mac_dev->get_mac_handle(mac_dev)); ++ ++ priv->ts_tx_en = true; ++} ++ ++static void dpa_ts_tx_disable(struct net_device *dev) ++{ ++ struct dpa_priv_s *priv = netdev_priv(dev); ++ ++#if 0 ++/* the RTC might be needed by the Rx Ts, cannot disable here ++ * no separate ptp_disable API for Rx/Tx, cannot disable here ++ */ ++ struct mac_device *mac_dev = priv->mac_dev; ++ ++ if (mac_dev->fm_rtc_disable) ++ mac_dev->fm_rtc_disable(get_fm_handle(dev)); ++ ++ if (mac_dev->ptp_disable) ++ mac_dev->ptp_disable(mac_dev->get_mac_handle(mac_dev)); ++#endif ++ ++ priv->ts_tx_en = false; ++} ++ ++static void dpa_ts_rx_enable(struct net_device *dev) ++{ ++ struct dpa_priv_s *priv = netdev_priv(dev); ++ struct mac_device *mac_dev = priv->mac_dev; ++ ++ if (mac_dev->fm_rtc_enable) ++ mac_dev->fm_rtc_enable(get_fm_handle(dev)); ++ if (mac_dev->ptp_enable) ++ mac_dev->ptp_enable(mac_dev->get_mac_handle(mac_dev)); ++ ++ priv->ts_rx_en = true; ++} ++ ++static void dpa_ts_rx_disable(struct net_device *dev) ++{ ++ struct dpa_priv_s *priv = netdev_priv(dev); ++ ++#if 0 ++/* the RTC might be needed by the Tx Ts, cannot disable here ++ * no separate ptp_disable API for Rx/Tx, cannot disable here ++ */ ++ struct mac_device *mac_dev = priv->mac_dev; ++ ++ if (mac_dev->fm_rtc_disable) ++ mac_dev->fm_rtc_disable(get_fm_handle(dev)); ++ ++ if (mac_dev->ptp_disable) ++ mac_dev->ptp_disable(mac_dev->get_mac_handle(mac_dev)); ++#endif ++ ++ priv->ts_rx_en = false; ++} ++ ++static int dpa_ts_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ++{ ++ struct hwtstamp_config config; ++ ++ if (copy_from_user(&config, rq->ifr_data, sizeof(config))) ++ return -EFAULT; ++ ++ switch (config.tx_type) { ++ case HWTSTAMP_TX_OFF: ++ dpa_ts_tx_disable(dev); ++ break; ++ case HWTSTAMP_TX_ON: ++ dpa_ts_tx_enable(dev); ++ break; ++ default: ++ return -ERANGE; ++ } ++ ++ if (config.rx_filter == HWTSTAMP_FILTER_NONE) ++ dpa_ts_rx_disable(dev); ++ else { ++ dpa_ts_rx_enable(dev); ++ /* 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; ++} ++#endif /* CONFIG_FSL_DPAA_TS */ ++ ++int dpa_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ++{ ++#ifdef CONFIG_FSL_DPAA_1588 ++ struct dpa_priv_s *priv = netdev_priv(dev); ++#endif ++ int ret = 0; ++ ++ /* at least one timestamping feature must be enabled */ ++#ifdef CONFIG_FSL_DPAA_TS ++ if (!netif_running(dev)) ++#endif ++ return -EINVAL; ++ ++#ifdef CONFIG_FSL_DPAA_TS ++ if (cmd == SIOCSHWTSTAMP) ++ return dpa_ts_ioctl(dev, rq, cmd); ++#endif /* CONFIG_FSL_DPAA_TS */ ++ ++#ifdef CONFIG_FSL_DPAA_1588 ++ if ((cmd >= PTP_ENBL_TXTS_IOCTL) && (cmd <= PTP_CLEANUP_TS)) { ++ if (priv->tsu && priv->tsu->valid) ++ ret = dpa_ioctl_1588(dev, rq, cmd); ++ else ++ ret = -ENODEV; ++ } ++#endif ++ ++ return ret; ++} ++EXPORT_SYMBOL(dpa_ioctl); ++ ++int __cold dpa_remove(struct platform_device *of_dev) ++{ ++ int err; ++ struct device *dev; ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ ++ dev = &of_dev->dev; ++ net_dev = dev_get_drvdata(dev); ++ ++ priv = netdev_priv(net_dev); ++ ++ dpaa_eth_sysfs_remove(dev); ++ ++ dev_set_drvdata(dev, NULL); ++ unregister_netdev(net_dev); ++ ++ err = dpa_fq_free(dev, &priv->dpa_fq_list); ++ ++ qman_delete_cgr_safe(&priv->ingress_cgr); ++ qman_release_cgrid(priv->ingress_cgr.cgrid); ++ qman_delete_cgr_safe(&priv->cgr_data.cgr); ++ qman_release_cgrid(priv->cgr_data.cgr.cgrid); ++ ++ dpa_private_napi_del(net_dev); ++ ++ dpa_bp_free(priv); ++ ++ if (priv->buf_layout) ++ devm_kfree(dev, priv->buf_layout); ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++ /* remove debugfs entry for this net_device */ ++ dpa_netdev_debugfs_remove(net_dev); ++#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++ ++#ifdef CONFIG_FSL_DPAA_1588 ++ if (priv->tsu && priv->tsu->valid) ++ dpa_ptp_cleanup(priv); ++#endif ++ ++ free_netdev(net_dev); ++ ++ return err; ++} ++EXPORT_SYMBOL(dpa_remove); ++ ++struct mac_device * __cold __must_check ++__attribute__((nonnull)) ++dpa_mac_probe(struct platform_device *_of_dev) ++{ ++ struct device *dpa_dev, *dev; ++ struct device_node *mac_node; ++ struct platform_device *of_dev; ++ struct mac_device *mac_dev; ++#ifdef CONFIG_FSL_DPAA_1588 ++ int lenp; ++ const phandle *phandle_prop; ++ struct net_device *net_dev = NULL; ++ struct dpa_priv_s *priv = NULL; ++ struct device_node *timer_node; ++#endif ++#ifdef CONFIG_PTP_1588_CLOCK_DPAA ++ int lenp_ptp; ++ const phandle *phandle_ptp; ++#endif ++ ++ dpa_dev = &_of_dev->dev; ++ ++ mac_node = of_parse_phandle(_of_dev->dev.of_node, "fsl,fman-mac", 0); ++ if (unlikely(mac_node == NULL)) { ++ dev_err(dpa_dev, "Cannot find MAC device device tree node\n"); ++ return ERR_PTR(-EFAULT); ++ } ++ ++ of_dev = of_find_device_by_node(mac_node); ++ if (unlikely(of_dev == NULL)) { ++ dev_err(dpa_dev, "of_find_device_by_node(%s) failed\n", ++ mac_node->full_name); ++ of_node_put(mac_node); ++ return ERR_PTR(-EINVAL); ++ } ++ of_node_put(mac_node); ++ ++ dev = &of_dev->dev; ++ ++ mac_dev = dev_get_drvdata(dev); ++ if (unlikely(mac_dev == NULL)) { ++ dev_err(dpa_dev, "dev_get_drvdata(%s) failed\n", ++ dev_name(dev)); ++ return ERR_PTR(-EINVAL); ++ } ++ ++#ifdef CONFIG_FSL_DPAA_1588 ++ phandle_prop = of_get_property(mac_node, "ptimer-handle", &lenp); ++ if (phandle_prop && ((mac_dev->phy_if != PHY_INTERFACE_MODE_SGMII) || ++ ((mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII) && ++ (mac_dev->speed == SPEED_1000)))) { ++ timer_node = of_find_node_by_phandle(*phandle_prop); ++ if (timer_node) ++ net_dev = dev_get_drvdata(dpa_dev); ++ if (timer_node && net_dev) { ++ priv = netdev_priv(net_dev); ++ if (!dpa_ptp_init(priv)) ++ dev_info(dev, "%s: ptp 1588 is initialized.\n", ++ mac_node->full_name); ++ } ++ } ++#endif ++ ++#ifdef CONFIG_PTP_1588_CLOCK_DPAA ++ phandle_ptp = of_get_property(mac_node, "ptimer-handle", &lenp_ptp); ++ if (phandle_ptp && ((mac_dev->phy_if != PHY_INTERFACE_MODE_SGMII) || ++ ((mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII) && ++ (mac_dev->speed == SPEED_1000)))) { ++ ptp_priv.node = of_find_node_by_phandle(*phandle_ptp); ++ if (ptp_priv.node) { ++ ptp_priv.of_dev = of_find_device_by_node(ptp_priv.node); ++ if (unlikely(ptp_priv.of_dev == NULL)) { ++ dev_err(dpa_dev, ++ "Cannot find device represented by timer_node\n"); ++ of_node_put(ptp_priv.node); ++ return ERR_PTR(-EINVAL); ++ } ++ ptp_priv.mac_dev = mac_dev; ++ } ++ } ++#endif ++ return mac_dev; ++} ++EXPORT_SYMBOL(dpa_mac_probe); ++ ++int dpa_set_mac_address(struct net_device *net_dev, void *addr) ++{ ++ const struct dpa_priv_s *priv; ++ int _errno; ++ struct mac_device *mac_dev; ++ ++ priv = netdev_priv(net_dev); ++ ++ _errno = eth_mac_addr(net_dev, addr); ++ if (_errno < 0) { ++ if (netif_msg_drv(priv)) ++ netdev_err(net_dev, ++ "eth_mac_addr() = %d\n", ++ _errno); ++ return _errno; ++ } ++ ++ mac_dev = priv->mac_dev; ++ ++ _errno = mac_dev->change_addr(mac_dev->get_mac_handle(mac_dev), ++ net_dev->dev_addr); ++ if (_errno < 0) { ++ if (netif_msg_drv(priv)) ++ netdev_err(net_dev, ++ "mac_dev->change_addr() = %d\n", ++ _errno); ++ return _errno; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(dpa_set_mac_address); ++ ++void dpa_set_rx_mode(struct net_device *net_dev) ++{ ++ int _errno; ++ const struct dpa_priv_s *priv; ++ ++ priv = netdev_priv(net_dev); ++ ++ if (!!(net_dev->flags & IFF_PROMISC) != priv->mac_dev->promisc) { ++ priv->mac_dev->promisc = !priv->mac_dev->promisc; ++ _errno = priv->mac_dev->set_promisc( ++ priv->mac_dev->get_mac_handle(priv->mac_dev), ++ priv->mac_dev->promisc); ++ if (unlikely(_errno < 0) && netif_msg_drv(priv)) ++ netdev_err(net_dev, ++ "mac_dev->set_promisc() = %d\n", ++ _errno); ++ } ++ ++ _errno = priv->mac_dev->set_multi(net_dev, priv->mac_dev); ++ if (unlikely(_errno < 0) && netif_msg_drv(priv)) ++ netdev_err(net_dev, "mac_dev->set_multi() = %d\n", _errno); ++} ++EXPORT_SYMBOL(dpa_set_rx_mode); ++ ++void dpa_set_buffers_layout(struct mac_device *mac_dev, ++ struct dpa_buffer_layout_s *layout) ++{ ++ struct fm_port_params params; ++ ++ /* Rx */ ++ layout[RX].priv_data_size = (uint16_t)DPA_RX_PRIV_DATA_SIZE; ++ layout[RX].parse_results = true; ++ layout[RX].hash_results = true; ++#ifdef CONFIG_FSL_DPAA_TS ++ layout[RX].time_stamp = true; ++#endif ++ fm_port_get_buff_layout_ext_params(mac_dev->port_dev[RX], ¶ms); ++ layout[RX].manip_extra_space = params.manip_extra_space; ++ /* a value of zero for data alignment means "don't care", so align to ++ * a non-zero value to prevent FMD from using its own default ++ */ ++ layout[RX].data_align = params.data_align ? : DPA_FD_DATA_ALIGNMENT; ++ ++ /* Tx */ ++ layout[TX].priv_data_size = DPA_TX_PRIV_DATA_SIZE; ++ layout[TX].parse_results = true; ++ layout[TX].hash_results = true; ++#ifdef CONFIG_FSL_DPAA_TS ++ layout[TX].time_stamp = true; ++#endif ++ fm_port_get_buff_layout_ext_params(mac_dev->port_dev[TX], ¶ms); ++ layout[TX].manip_extra_space = params.manip_extra_space; ++ layout[TX].data_align = params.data_align ? : DPA_FD_DATA_ALIGNMENT; ++} ++EXPORT_SYMBOL(dpa_set_buffers_layout); ++ ++int __attribute__((nonnull)) ++dpa_bp_alloc(struct dpa_bp *dpa_bp) ++{ ++ int err; ++ struct bman_pool_params bp_params; ++ struct platform_device *pdev; ++ ++ if (dpa_bp->size == 0 || dpa_bp->config_count == 0) { ++ pr_err("Buffer pool is not properly initialized! Missing size or initial number of buffers"); ++ return -EINVAL; ++ } ++ ++ memset(&bp_params, 0, sizeof(struct bman_pool_params)); ++#ifdef CONFIG_FMAN_PFC ++ bp_params.flags = BMAN_POOL_FLAG_THRESH; ++ bp_params.thresholds[0] = bp_params.thresholds[2] = ++ CONFIG_FSL_DPAA_ETH_REFILL_THRESHOLD; ++ bp_params.thresholds[1] = bp_params.thresholds[3] = ++ CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT; ++#endif ++ ++ /* If the pool is already specified, we only create one per bpid */ ++ if (dpa_bpid2pool_use(dpa_bp->bpid)) ++ return 0; ++ ++ if (dpa_bp->bpid == 0) ++ bp_params.flags |= BMAN_POOL_FLAG_DYNAMIC_BPID; ++ else ++ bp_params.bpid = dpa_bp->bpid; ++ ++ dpa_bp->pool = bman_new_pool(&bp_params); ++ if (unlikely(dpa_bp->pool == NULL)) { ++ pr_err("bman_new_pool() failed\n"); ++ return -ENODEV; ++ } ++ ++ dpa_bp->bpid = (uint8_t)bman_get_params(dpa_bp->pool)->bpid; ++ ++ pdev = platform_device_register_simple("dpaa_eth_bpool", ++ dpa_bp->bpid, NULL, 0); ++ if (IS_ERR(pdev)) { ++ err = PTR_ERR(pdev); ++ goto pdev_register_failed; ++ } ++ ++ err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)); ++ if (err) ++ goto pdev_mask_failed; ++ ++ dpa_bp->dev = &pdev->dev; ++ ++ if (dpa_bp->seed_cb) { ++ err = dpa_bp->seed_cb(dpa_bp); ++ if (err) ++ goto pool_seed_failed; ++ } ++ ++ dpa_bpid2pool_map(dpa_bp->bpid, dpa_bp); ++ ++ return 0; ++ ++pool_seed_failed: ++pdev_mask_failed: ++ platform_device_unregister(pdev); ++pdev_register_failed: ++ bman_free_pool(dpa_bp->pool); ++ ++ return err; ++} ++EXPORT_SYMBOL(dpa_bp_alloc); ++ ++void dpa_bp_drain(struct dpa_bp *bp) ++{ ++ int ret, num = 8; ++ ++ do { ++ struct bm_buffer bmb[8]; ++ int i; ++ ++ ret = bman_acquire(bp->pool, bmb, num, 0); ++ if (ret < 0) { ++ if (num == 8) { ++ /* we have less than 8 buffers left; ++ * drain them one by one ++ */ ++ num = 1; ++ ret = 1; ++ continue; ++ } else { ++ /* Pool is fully drained */ ++ break; ++ } ++ } ++ ++ for (i = 0; i < num; i++) { ++ dma_addr_t addr = bm_buf_addr(&bmb[i]); ++ ++ dma_unmap_single(bp->dev, addr, bp->size, ++ DMA_BIDIRECTIONAL); ++ ++ bp->free_buf_cb(phys_to_virt(addr)); ++ } ++ } while (ret > 0); ++} ++EXPORT_SYMBOL(dpa_bp_drain); ++ ++static void __cold __attribute__((nonnull)) ++_dpa_bp_free(struct dpa_bp *dpa_bp) ++{ ++ struct dpa_bp *bp = dpa_bpid2pool(dpa_bp->bpid); ++ ++ /* the mapping between bpid and dpa_bp is done very late in the ++ * allocation procedure; if something failed before the mapping, the bp ++ * was not configured, therefore we don't need the below instructions ++ */ ++ if (!bp) ++ return; ++ ++ if (!atomic_dec_and_test(&bp->refs)) ++ return; ++ ++ if (bp->free_buf_cb) ++ dpa_bp_drain(bp); ++ ++ dpa_bp_array[bp->bpid] = NULL; ++ bman_free_pool(bp->pool); ++ ++ if (bp->dev) ++ platform_device_unregister(to_platform_device(bp->dev)); ++} ++ ++void __cold __attribute__((nonnull)) ++dpa_bp_free(struct dpa_priv_s *priv) ++{ ++ int i; ++ ++ for (i = 0; i < priv->bp_count; i++) ++ _dpa_bp_free(&priv->dpa_bp[i]); ++} ++EXPORT_SYMBOL(dpa_bp_free); ++ ++struct dpa_bp *dpa_bpid2pool(int bpid) ++{ ++ return dpa_bp_array[bpid]; ++} ++EXPORT_SYMBOL(dpa_bpid2pool); ++ ++void dpa_bpid2pool_map(int bpid, struct dpa_bp *dpa_bp) ++{ ++ dpa_bp_array[bpid] = dpa_bp; ++ atomic_set(&dpa_bp->refs, 1); ++} ++ ++bool dpa_bpid2pool_use(int bpid) ++{ ++ if (dpa_bpid2pool(bpid)) { ++ atomic_inc(&dpa_bp_array[bpid]->refs); ++ return true; ++ } ++ ++ return false; ++} ++ ++#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE ++u16 dpa_select_queue(struct net_device *net_dev, struct sk_buff *skb, ++ void *accel_priv, select_queue_fallback_t fallback) ++{ ++ return dpa_get_queue_mapping(skb); ++} ++EXPORT_SYMBOL(dpa_select_queue); ++#endif ++ ++struct dpa_fq *dpa_fq_alloc(struct device *dev, ++ const struct fqid_cell *fqids, ++ struct list_head *list, ++ enum dpa_fq_type fq_type) ++{ ++ int i; ++ struct dpa_fq *dpa_fq; ++ ++ dpa_fq = devm_kzalloc(dev, sizeof(*dpa_fq) * fqids->count, GFP_KERNEL); ++ if (dpa_fq == NULL) ++ return NULL; ++ ++ for (i = 0; i < fqids->count; i++) { ++ dpa_fq[i].fq_type = fq_type; ++ dpa_fq[i].fqid = fqids->start ? fqids->start + i : 0; ++ list_add_tail(&dpa_fq[i].list, list); ++ } ++ ++#ifdef CONFIG_FMAN_PFC ++ if (fq_type == FQ_TYPE_TX) ++ for (i = 0; i < fqids->count; i++) ++ dpa_fq[i].wq = i / dpa_num_cpus; ++ else ++#endif ++ for (i = 0; i < fqids->count; i++) ++ _dpa_assign_wq(dpa_fq + i); ++ ++ return dpa_fq; ++} ++EXPORT_SYMBOL(dpa_fq_alloc); ++ ++/* Probing of FQs for MACful ports */ ++int dpa_fq_probe_mac(struct device *dev, struct list_head *list, ++ struct fm_port_fqs *port_fqs, ++ bool alloc_tx_conf_fqs, ++ enum port_type ptype) ++{ ++ struct fqid_cell *fqids = NULL; ++ const void *fqids_off = NULL; ++ struct dpa_fq *dpa_fq = NULL; ++ struct device_node *np = dev->of_node; ++ int num_ranges; ++ int i, lenp; ++ ++ if (ptype == TX && alloc_tx_conf_fqs) { ++ if (!dpa_fq_alloc(dev, tx_confirm_fqids, list, ++ FQ_TYPE_TX_CONF_MQ)) ++ goto fq_alloc_failed; ++ } ++ ++ fqids_off = of_get_property(np, fsl_qman_frame_queues[ptype], &lenp); ++ if (fqids_off == NULL) { ++ /* No dts definition, so use the defaults. */ ++ fqids = default_fqids[ptype]; ++ num_ranges = 3; ++ } else { ++ num_ranges = lenp / sizeof(*fqids); ++ ++ fqids = devm_kzalloc(dev, sizeof(*fqids) * num_ranges, ++ GFP_KERNEL); ++ if (fqids == NULL) ++ goto fqids_alloc_failed; ++ ++ /* convert to CPU endianess */ ++ for (i = 0; i < num_ranges; i++) { ++ fqids[i].start = be32_to_cpup(fqids_off + ++ i * sizeof(*fqids)); ++ fqids[i].count = be32_to_cpup(fqids_off + ++ i * sizeof(*fqids) + sizeof(__be32)); ++ } ++ } ++ ++ for (i = 0; i < num_ranges; i++) { ++ switch (i) { ++ case 0: ++ /* The first queue is the error queue */ ++ if (fqids[i].count != 1) ++ goto invalid_error_queue; ++ ++ dpa_fq = dpa_fq_alloc(dev, &fqids[i], list, ++ ptype == RX ? ++ FQ_TYPE_RX_ERROR : ++ FQ_TYPE_TX_ERROR); ++ if (dpa_fq == NULL) ++ goto fq_alloc_failed; ++ ++ if (ptype == RX) ++ port_fqs->rx_errq = &dpa_fq[0]; ++ else ++ port_fqs->tx_errq = &dpa_fq[0]; ++ break; ++ case 1: ++ /* the second queue is the default queue */ ++ if (fqids[i].count != 1) ++ goto invalid_default_queue; ++ ++ dpa_fq = dpa_fq_alloc(dev, &fqids[i], list, ++ ptype == RX ? ++ FQ_TYPE_RX_DEFAULT : ++ FQ_TYPE_TX_CONFIRM); ++ if (dpa_fq == NULL) ++ goto fq_alloc_failed; ++ ++ if (ptype == RX) ++ port_fqs->rx_defq = &dpa_fq[0]; ++ else ++ port_fqs->tx_defq = &dpa_fq[0]; ++ break; ++ default: ++ /* all subsequent queues are either RX PCD or Tx */ ++ if (!dpa_fq_alloc(dev, &fqids[i], list, ptype == RX ? ++ FQ_TYPE_RX_PCD : FQ_TYPE_TX)) ++ goto fq_alloc_failed; ++ break; ++ } ++ } ++ ++ return 0; ++ ++fq_alloc_failed: ++fqids_alloc_failed: ++ dev_err(dev, "Cannot allocate memory for frame queues\n"); ++ return -ENOMEM; ++ ++invalid_default_queue: ++invalid_error_queue: ++ dev_err(dev, "Too many default or error queues\n"); ++ return -EINVAL; ++} ++EXPORT_SYMBOL(dpa_fq_probe_mac); ++ ++static u32 rx_pool_channel; ++static DEFINE_SPINLOCK(rx_pool_channel_init); ++ ++int dpa_get_channel(void) ++{ ++ spin_lock(&rx_pool_channel_init); ++ if (!rx_pool_channel) { ++ u32 pool; ++ int ret = qman_alloc_pool(&pool); ++ if (!ret) ++ rx_pool_channel = pool; ++ } ++ spin_unlock(&rx_pool_channel_init); ++ if (!rx_pool_channel) ++ return -ENOMEM; ++ return rx_pool_channel; ++} ++EXPORT_SYMBOL(dpa_get_channel); ++ ++void dpa_release_channel(void) ++{ ++ qman_release_pool(rx_pool_channel); ++} ++EXPORT_SYMBOL(dpa_release_channel); ++ ++int dpaa_eth_add_channel(void *__arg) ++{ ++ const cpumask_t *cpus = qman_affine_cpus(); ++ u32 pool = QM_SDQCR_CHANNELS_POOL_CONV((u16)(unsigned long)__arg); ++ int cpu; ++ struct qman_portal *portal; ++ ++ for_each_cpu(cpu, cpus) { ++ portal = (struct qman_portal *)qman_get_affine_portal(cpu); ++ qman_p_static_dequeue_add(portal, pool); ++ } ++ return 0; ++} ++EXPORT_SYMBOL(dpaa_eth_add_channel); ++ ++/** ++ * Congestion group state change notification callback. ++ * Stops the device's egress queues while they are congested and ++ * wakes them upon exiting congested state. ++ * Also updates some CGR-related stats. ++ */ ++static void dpaa_eth_cgscn(struct qman_portal *qm, struct qman_cgr *cgr, ++ ++ int congested) ++{ ++ struct dpa_priv_s *priv = (struct dpa_priv_s *)container_of(cgr, ++ struct dpa_priv_s, cgr_data.cgr); ++ ++ if (congested) { ++ priv->cgr_data.congestion_start_jiffies = jiffies; ++ netif_tx_stop_all_queues(priv->net_dev); ++ priv->cgr_data.cgr_congested_count++; ++ } else { ++ priv->cgr_data.congested_jiffies += ++ (jiffies - priv->cgr_data.congestion_start_jiffies); ++ netif_tx_wake_all_queues(priv->net_dev); ++ } ++} ++ ++int dpaa_eth_cgr_init(struct dpa_priv_s *priv) ++{ ++ struct qm_mcc_initcgr initcgr; ++ u32 cs_th; ++ int err; ++ ++ err = qman_alloc_cgrid(&priv->cgr_data.cgr.cgrid); ++ if (err < 0) { ++ pr_err("Error %d allocating CGR ID\n", err); ++ goto out_error; ++ } ++ priv->cgr_data.cgr.cb = dpaa_eth_cgscn; ++ ++ /* Enable Congestion State Change Notifications and CS taildrop */ ++ initcgr.we_mask = QM_CGR_WE_CSCN_EN | QM_CGR_WE_CS_THRES; ++ initcgr.cgr.cscn_en = QM_CGR_EN; ++ ++ /* Set different thresholds based on the MAC speed. ++ * TODO: this may turn suboptimal if the MAC is reconfigured at a speed ++ * lower than its max, e.g. if a dTSEC later negotiates a 100Mbps link. ++ * In such cases, we ought to reconfigure the threshold, too. ++ */ ++ if (priv->mac_dev->if_support & SUPPORTED_10000baseT_Full) ++ cs_th = CONFIG_FSL_DPAA_CS_THRESHOLD_10G; ++ else ++ cs_th = CONFIG_FSL_DPAA_CS_THRESHOLD_1G; ++ qm_cgr_cs_thres_set64(&initcgr.cgr.cs_thres, cs_th, 1); ++ ++ initcgr.we_mask |= QM_CGR_WE_CSTD_EN; ++ initcgr.cgr.cstd_en = QM_CGR_EN; ++ ++ err = qman_create_cgr(&priv->cgr_data.cgr, QMAN_CGR_FLAG_USE_INIT, ++ &initcgr); ++ if (err < 0) { ++ pr_err("Error %d creating CGR with ID %d\n", err, ++ priv->cgr_data.cgr.cgrid); ++ qman_release_cgrid(priv->cgr_data.cgr.cgrid); ++ goto out_error; ++ } ++ pr_debug("Created CGR %d for netdev with hwaddr %pM on QMan channel %d\n", ++ priv->cgr_data.cgr.cgrid, priv->mac_dev->addr, ++ priv->cgr_data.cgr.chan); ++ ++out_error: ++ return err; ++} ++EXPORT_SYMBOL(dpaa_eth_cgr_init); ++ ++static inline void dpa_setup_ingress(const struct dpa_priv_s *priv, ++ struct dpa_fq *fq, ++ const struct qman_fq *template) ++{ ++ fq->fq_base = *template; ++ fq->net_dev = priv->net_dev; ++ ++ fq->flags = QMAN_FQ_FLAG_NO_ENQUEUE; ++ fq->channel = priv->channel; ++} ++ ++static inline void dpa_setup_egress(const struct dpa_priv_s *priv, ++ struct dpa_fq *fq, ++ struct fm_port *port, ++ const struct qman_fq *template) ++{ ++ fq->fq_base = *template; ++ fq->net_dev = priv->net_dev; ++ ++ if (port) { ++ fq->flags = QMAN_FQ_FLAG_TO_DCPORTAL; ++ fq->channel = (uint16_t)fm_get_tx_port_channel(port); ++ } else { ++ fq->flags = QMAN_FQ_FLAG_NO_MODIFY; ++ } ++} ++ ++void dpa_fq_setup(struct dpa_priv_s *priv, const struct dpa_fq_cbs_t *fq_cbs, ++ struct fm_port *tx_port) ++{ ++ struct dpa_fq *fq; ++ uint16_t portals[NR_CPUS]; ++ int cpu, portal_cnt = 0, num_portals = 0; ++ uint32_t pcd_fqid; ++ const cpumask_t *affine_cpus = qman_affine_cpus(); ++ int egress_cnt = 0, conf_cnt = 0; ++ ++ /* Prepare for PCD FQs init */ ++ for_each_cpu(cpu, affine_cpus) ++ portals[num_portals++] = qman_affine_channel(cpu); ++ if (num_portals == 0) ++ dev_err(priv->net_dev->dev.parent, ++ "No Qman software (affine) channels found"); ++ ++ pcd_fqid = (priv->mac_dev) ? ++ DPAA_ETH_PCD_FQ_BASE(priv->mac_dev->res->start) : 0; ++ ++ /* Initialize each FQ in the list */ ++ list_for_each_entry(fq, &priv->dpa_fq_list, list) { ++ switch (fq->fq_type) { ++ case FQ_TYPE_RX_DEFAULT: ++ BUG_ON(!priv->mac_dev); ++ dpa_setup_ingress(priv, fq, &fq_cbs->rx_defq); ++ break; ++ case FQ_TYPE_RX_ERROR: ++ BUG_ON(!priv->mac_dev); ++ dpa_setup_ingress(priv, fq, &fq_cbs->rx_errq); ++ break; ++ case FQ_TYPE_RX_PCD: ++ /* For MACless we can't have dynamic Rx queues */ ++ BUG_ON(!priv->mac_dev && !fq->fqid); ++ dpa_setup_ingress(priv, fq, &fq_cbs->rx_defq); ++ if (!fq->fqid) ++ fq->fqid = pcd_fqid++; ++ fq->channel = portals[portal_cnt]; ++ portal_cnt = (portal_cnt + 1) % num_portals; ++ break; ++ case FQ_TYPE_TX: ++ dpa_setup_egress(priv, fq, tx_port, ++ &fq_cbs->egress_ern); ++ /* If we have more Tx queues than the number of cores, ++ * just ignore the extra ones. ++ */ ++ if (egress_cnt < DPAA_ETH_TX_QUEUES) ++ priv->egress_fqs[egress_cnt++] = &fq->fq_base; ++ break; ++ case FQ_TYPE_TX_CONFIRM: ++ BUG_ON(!priv->mac_dev); ++ dpa_setup_ingress(priv, fq, &fq_cbs->tx_defq); ++ break; ++ case FQ_TYPE_TX_CONF_MQ: ++ BUG_ON(!priv->mac_dev); ++ dpa_setup_ingress(priv, fq, &fq_cbs->tx_defq); ++ priv->conf_fqs[conf_cnt++] = &fq->fq_base; ++ break; ++ case FQ_TYPE_TX_ERROR: ++ BUG_ON(!priv->mac_dev); ++ dpa_setup_ingress(priv, fq, &fq_cbs->tx_errq); ++ break; ++ default: ++ dev_warn(priv->net_dev->dev.parent, ++ "Unknown FQ type detected!\n"); ++ break; ++ } ++ } ++ ++ /* The number of Tx queues may be smaller than the number of cores, if ++ * the Tx queue range is specified in the device tree instead of being ++ * dynamically allocated. ++ * Make sure all CPUs receive a corresponding Tx queue. ++ */ ++ while (egress_cnt < DPAA_ETH_TX_QUEUES) { ++ list_for_each_entry(fq, &priv->dpa_fq_list, list) { ++ if (fq->fq_type != FQ_TYPE_TX) ++ continue; ++ priv->egress_fqs[egress_cnt++] = &fq->fq_base; ++ if (egress_cnt == DPAA_ETH_TX_QUEUES) ++ break; ++ } ++ } ++} ++EXPORT_SYMBOL(dpa_fq_setup); ++ ++int dpa_fq_init(struct dpa_fq *dpa_fq, bool td_enable) ++{ ++ int _errno; ++ const struct dpa_priv_s *priv; ++ struct device *dev; ++ struct qman_fq *fq; ++ struct qm_mcc_initfq initfq; ++ struct qman_fq *confq; ++ int queue_id; ++ ++ priv = netdev_priv(dpa_fq->net_dev); ++ dev = dpa_fq->net_dev->dev.parent; ++ ++ if (dpa_fq->fqid == 0) ++ dpa_fq->flags |= QMAN_FQ_FLAG_DYNAMIC_FQID; ++ ++ dpa_fq->init = !(dpa_fq->flags & QMAN_FQ_FLAG_NO_MODIFY); ++ ++ _errno = qman_create_fq(dpa_fq->fqid, dpa_fq->flags, &dpa_fq->fq_base); ++ if (_errno) { ++ dev_err(dev, "qman_create_fq() failed\n"); ++ return _errno; ++ } ++ fq = &dpa_fq->fq_base; ++ ++ if (dpa_fq->init) { ++ memset(&initfq, 0, sizeof(initfq)); ++ ++ initfq.we_mask = QM_INITFQ_WE_FQCTRL; ++ /* FIXME: why would we want to keep an empty FQ in cache? */ ++ initfq.fqd.fq_ctrl = QM_FQCTRL_PREFERINCACHE; ++ ++ /* Try to reduce the number of portal interrupts for ++ * Tx Confirmation FQs. ++ */ ++ if (dpa_fq->fq_type == FQ_TYPE_TX_CONFIRM) ++ initfq.fqd.fq_ctrl |= QM_FQCTRL_HOLDACTIVE; ++ ++ /* FQ placement */ ++ initfq.we_mask |= QM_INITFQ_WE_DESTWQ; ++ ++ initfq.fqd.dest.channel = dpa_fq->channel; ++ initfq.fqd.dest.wq = dpa_fq->wq; ++ ++ /* Put all egress queues in a congestion group of their own. ++ * Sensu stricto, the Tx confirmation queues are Rx FQs, ++ * rather than Tx - but they nonetheless account for the ++ * memory footprint on behalf of egress traffic. We therefore ++ * place them in the netdev's CGR, along with the Tx FQs. ++ */ ++ if (dpa_fq->fq_type == FQ_TYPE_TX || ++ dpa_fq->fq_type == FQ_TYPE_TX_CONFIRM || ++ dpa_fq->fq_type == FQ_TYPE_TX_CONF_MQ) { ++ initfq.we_mask |= QM_INITFQ_WE_CGID; ++ initfq.fqd.fq_ctrl |= QM_FQCTRL_CGE; ++ initfq.fqd.cgid = (uint8_t)priv->cgr_data.cgr.cgrid; ++ /* Set a fixed overhead accounting, in an attempt to ++ * reduce the impact of fixed-size skb shells and the ++ * driver's needed headroom on system memory. This is ++ * especially the case when the egress traffic is ++ * composed of small datagrams. ++ * Unfortunately, QMan's OAL value is capped to an ++ * insufficient value, but even that is better than ++ * no overhead accounting at all. ++ */ ++ initfq.we_mask |= QM_INITFQ_WE_OAC; ++ initfq.fqd.oac_init.oac = QM_OAC_CG; ++ initfq.fqd.oac_init.oal = ++ (signed char)(min(sizeof(struct sk_buff) + ++ priv->tx_headroom, (size_t)FSL_QMAN_MAX_OAL)); ++ } ++ ++ if (td_enable) { ++ initfq.we_mask |= QM_INITFQ_WE_TDTHRESH; ++ qm_fqd_taildrop_set(&initfq.fqd.td, ++ DPA_FQ_TD, 1); ++ initfq.fqd.fq_ctrl = QM_FQCTRL_TDE; ++ } ++ ++ /* Configure the Tx confirmation queue, now that we know ++ * which Tx queue it pairs with. ++ */ ++ if (dpa_fq->fq_type == FQ_TYPE_TX) { ++ queue_id = _dpa_tx_fq_to_id(priv, &dpa_fq->fq_base); ++ if (queue_id >= 0) { ++ confq = priv->conf_fqs[queue_id]; ++ if (confq) { ++ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA; ++ /* ContextA: OVOM=1 (use contextA2 bits instead of ICAD) ++ * A2V=1 (contextA A2 field is valid) ++ * A0V=1 (contextA A0 field is valid) ++ * B0V=1 (contextB field is valid) ++ * ContextA A2: EBD=1 (deallocate buffers inside FMan) ++ * ContextB B0(ASPID): 0 (absolute Virtual Storage ID) ++ */ ++ initfq.fqd.context_a.hi = 0x1e000000; ++ initfq.fqd.context_a.lo = 0x80000000; ++ } ++ } ++ } ++ ++ /* Put all *private* ingress queues in our "ingress CGR". */ ++ if (priv->use_ingress_cgr && ++ (dpa_fq->fq_type == FQ_TYPE_RX_DEFAULT || ++ dpa_fq->fq_type == FQ_TYPE_RX_ERROR || ++ dpa_fq->fq_type == FQ_TYPE_RX_PCD)) { ++ initfq.we_mask |= QM_INITFQ_WE_CGID; ++ initfq.fqd.fq_ctrl |= QM_FQCTRL_CGE; ++ initfq.fqd.cgid = (uint8_t)priv->ingress_cgr.cgrid; ++ /* Set a fixed overhead accounting, just like for the ++ * egress CGR. ++ */ ++ initfq.we_mask |= QM_INITFQ_WE_OAC; ++ initfq.fqd.oac_init.oac = QM_OAC_CG; ++ initfq.fqd.oac_init.oal = ++ (signed char)(min(sizeof(struct sk_buff) + ++ priv->tx_headroom, (size_t)FSL_QMAN_MAX_OAL)); ++ } ++ ++ /* Initialization common to all ingress queues */ ++ if (dpa_fq->flags & QMAN_FQ_FLAG_NO_ENQUEUE) { ++ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA; ++ initfq.fqd.fq_ctrl |= ++ QM_FQCTRL_CTXASTASHING | QM_FQCTRL_AVOIDBLOCK; ++ initfq.fqd.context_a.stashing.exclusive = ++ QM_STASHING_EXCL_DATA | QM_STASHING_EXCL_CTX | ++ QM_STASHING_EXCL_ANNOTATION; ++ initfq.fqd.context_a.stashing.data_cl = 2; ++ initfq.fqd.context_a.stashing.annotation_cl = 1; ++ initfq.fqd.context_a.stashing.context_cl = ++ DIV_ROUND_UP(sizeof(struct qman_fq), 64); ++ } ++ ++ _errno = qman_init_fq(fq, QMAN_INITFQ_FLAG_SCHED, &initfq); ++ if (_errno < 0) { ++ dev_err(dev, "qman_init_fq(%u) = %d\n", ++ qman_fq_fqid(fq), _errno); ++ qman_destroy_fq(fq, 0); ++ return _errno; ++ } ++ } ++ ++ dpa_fq->fqid = qman_fq_fqid(fq); ++ ++ return 0; ++} ++EXPORT_SYMBOL(dpa_fq_init); ++ ++int __cold __attribute__((nonnull)) ++_dpa_fq_free(struct device *dev, struct qman_fq *fq) ++{ ++ int _errno, __errno; ++ struct dpa_fq *dpa_fq; ++ const struct dpa_priv_s *priv; ++ ++ _errno = 0; ++ ++ dpa_fq = container_of(fq, struct dpa_fq, fq_base); ++ priv = netdev_priv(dpa_fq->net_dev); ++ ++ if (dpa_fq->init) { ++ _errno = qman_retire_fq(fq, NULL); ++ if (unlikely(_errno < 0) && netif_msg_drv(priv)) ++ dev_err(dev, "qman_retire_fq(%u) = %d\n", ++ qman_fq_fqid(fq), _errno); ++ ++ __errno = qman_oos_fq(fq); ++ if (unlikely(__errno < 0) && netif_msg_drv(priv)) { ++ dev_err(dev, "qman_oos_fq(%u) = %d\n", ++ qman_fq_fqid(fq), __errno); ++ if (_errno >= 0) ++ _errno = __errno; ++ } ++ } ++ ++ qman_destroy_fq(fq, 0); ++ list_del(&dpa_fq->list); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(_dpa_fq_free); ++ ++int __cold __attribute__((nonnull)) ++dpa_fq_free(struct device *dev, struct list_head *list) ++{ ++ int _errno, __errno; ++ struct dpa_fq *dpa_fq, *tmp; ++ ++ _errno = 0; ++ list_for_each_entry_safe(dpa_fq, tmp, list, list) { ++ __errno = _dpa_fq_free(dev, (struct qman_fq *)dpa_fq); ++ if (unlikely(__errno < 0) && _errno >= 0) ++ _errno = __errno; ++ } ++ ++ return _errno; ++} ++EXPORT_SYMBOL(dpa_fq_free); ++ ++static void ++dpaa_eth_init_tx_port(struct fm_port *port, struct dpa_fq *errq, ++ struct dpa_fq *defq, struct dpa_buffer_layout_s *buf_layout) ++{ ++ struct fm_port_params tx_port_param; ++ bool frag_enabled = false; ++ ++ memset(&tx_port_param, 0, sizeof(tx_port_param)); ++ dpaa_eth_init_port(tx, port, tx_port_param, errq->fqid, defq->fqid, ++ buf_layout, frag_enabled); ++} ++ ++static void ++dpaa_eth_init_rx_port(struct fm_port *port, struct dpa_bp *bp, size_t count, ++ struct dpa_fq *errq, struct dpa_fq *defq, ++ struct dpa_buffer_layout_s *buf_layout) ++{ ++ struct fm_port_params rx_port_param; ++ int i; ++ bool frag_enabled = false; ++ ++ memset(&rx_port_param, 0, sizeof(rx_port_param)); ++ count = min(ARRAY_SIZE(rx_port_param.pool_param), count); ++ rx_port_param.num_pools = (uint8_t)count; ++ for (i = 0; i < count; i++) { ++ if (i >= rx_port_param.num_pools) ++ break; ++ rx_port_param.pool_param[i].id = bp[i].bpid; ++ rx_port_param.pool_param[i].size = (uint16_t)bp[i].size; ++ } ++ ++ dpaa_eth_init_port(rx, port, rx_port_param, errq->fqid, defq->fqid, ++ buf_layout, frag_enabled); ++} ++ ++#if defined(CONFIG_FSL_SDK_FMAN_TEST) ++/* Defined as weak, to be implemented by fman pcd tester. */ ++int dpa_alloc_pcd_fqids(struct device *, uint32_t, uint8_t, uint32_t *) ++__attribute__((weak)); ++ ++int dpa_free_pcd_fqids(struct device *, uint32_t) __attribute__((weak)); ++#else ++int dpa_alloc_pcd_fqids(struct device *, uint32_t, uint8_t, uint32_t *); ++ ++int dpa_free_pcd_fqids(struct device *, uint32_t); ++ ++#endif /* CONFIG_FSL_SDK_FMAN_TEST */ ++ ++ ++int dpa_alloc_pcd_fqids(struct device *dev, uint32_t num, ++ uint8_t alignment, uint32_t *base_fqid) ++{ ++ dev_crit(dev, "callback not implemented!\n"); ++ ++ return 0; ++} ++ ++int dpa_free_pcd_fqids(struct device *dev, uint32_t base_fqid) ++{ ++ ++ dev_crit(dev, "callback not implemented!\n"); ++ ++ return 0; ++} ++ ++void dpaa_eth_init_ports(struct mac_device *mac_dev, ++ struct dpa_bp *bp, size_t count, ++ struct fm_port_fqs *port_fqs, ++ struct dpa_buffer_layout_s *buf_layout, ++ struct device *dev) ++{ ++ struct fm_port_pcd_param rx_port_pcd_param; ++ struct fm_port *rxport = mac_dev->port_dev[RX]; ++ struct fm_port *txport = mac_dev->port_dev[TX]; ++ ++ dpaa_eth_init_tx_port(txport, port_fqs->tx_errq, ++ port_fqs->tx_defq, &buf_layout[TX]); ++ dpaa_eth_init_rx_port(rxport, bp, count, port_fqs->rx_errq, ++ port_fqs->rx_defq, &buf_layout[RX]); ++ ++ rx_port_pcd_param.cba = dpa_alloc_pcd_fqids; ++ rx_port_pcd_param.cbf = dpa_free_pcd_fqids; ++ rx_port_pcd_param.dev = dev; ++ fm_port_pcd_bind(rxport, &rx_port_pcd_param); ++} ++EXPORT_SYMBOL(dpaa_eth_init_ports); ++ ++void dpa_release_sgt(struct qm_sg_entry *sgt) ++{ ++ struct dpa_bp *dpa_bp; ++ struct bm_buffer bmb[DPA_BUFF_RELEASE_MAX]; ++ uint8_t i = 0, j; ++ ++ do { ++ dpa_bp = dpa_bpid2pool(sgt[i].bpid); ++ DPA_BUG_ON(!dpa_bp); ++ ++ j = 0; ++ do { ++ DPA_BUG_ON(sgt[i].extension); ++ ++ bmb[j].hi = sgt[i].addr_hi; ++ bmb[j].lo = be32_to_cpu(sgt[i].addr_lo); ++ ++ j++; i++; ++ } while (j < ARRAY_SIZE(bmb) && ++ !sgt[i-1].final && ++ sgt[i-1].bpid == sgt[i].bpid); ++ ++ while (bman_release(dpa_bp->pool, bmb, j, 0)) ++ cpu_relax(); ++ } while (!sgt[i-1].final); ++} ++EXPORT_SYMBOL(dpa_release_sgt); ++ ++void __attribute__((nonnull)) ++dpa_fd_release(const struct net_device *net_dev, const struct qm_fd *fd) ++{ ++ struct qm_sg_entry *sgt; ++ struct dpa_bp *_dpa_bp; ++ struct bm_buffer _bmb; ++ ++ _bmb.hi = fd->addr_hi; ++ _bmb.lo = fd->addr_lo; ++ ++ _dpa_bp = dpa_bpid2pool(fd->bpid); ++ DPA_BUG_ON(!_dpa_bp); ++ ++ if (fd->format == qm_fd_sg) { ++ sgt = (phys_to_virt(bm_buf_addr(&_bmb)) + dpa_fd_offset(fd)); ++ dpa_release_sgt(sgt); ++ } ++ ++ while (bman_release(_dpa_bp->pool, &_bmb, 1, 0)) ++ cpu_relax(); ++} ++EXPORT_SYMBOL(dpa_fd_release); ++ ++void count_ern(struct dpa_percpu_priv_s *percpu_priv, ++ const struct qm_mr_entry *msg) ++{ ++ switch (msg->ern.rc & QM_MR_RC_MASK) { ++ case QM_MR_RC_CGR_TAILDROP: ++ percpu_priv->ern_cnt.cg_tdrop++; ++ break; ++ case QM_MR_RC_WRED: ++ percpu_priv->ern_cnt.wred++; ++ break; ++ case QM_MR_RC_ERROR: ++ percpu_priv->ern_cnt.err_cond++; ++ break; ++ case QM_MR_RC_ORPWINDOW_EARLY: ++ percpu_priv->ern_cnt.early_window++; ++ break; ++ case QM_MR_RC_ORPWINDOW_LATE: ++ percpu_priv->ern_cnt.late_window++; ++ break; ++ case QM_MR_RC_FQ_TAILDROP: ++ percpu_priv->ern_cnt.fq_tdrop++; ++ break; ++ case QM_MR_RC_ORPWINDOW_RETIRED: ++ percpu_priv->ern_cnt.fq_retired++; ++ break; ++ case QM_MR_RC_ORP_ZERO: ++ percpu_priv->ern_cnt.orp_zero++; ++ break; ++ } ++} ++EXPORT_SYMBOL(count_ern); ++ ++/** ++ * Turn on HW checksum computation for this outgoing frame. ++ * If the current protocol is not something we support in this regard ++ * (or if the stack has already computed the SW checksum), we do nothing. ++ * ++ * Returns 0 if all goes well (or HW csum doesn't apply), and a negative value ++ * otherwise. ++ * ++ * Note that this function may modify the fd->cmd field and the skb data buffer ++ * (the Parse Results area). ++ */ ++int dpa_enable_tx_csum(struct dpa_priv_s *priv, ++ struct sk_buff *skb, struct qm_fd *fd, char *parse_results) ++{ ++ fm_prs_result_t *parse_result; ++ struct iphdr *iph; ++ struct ipv6hdr *ipv6h = NULL; ++ u8 l4_proto; ++ u16 ethertype = ntohs(skb->protocol); ++ int retval = 0; ++ ++ if (skb->ip_summed != CHECKSUM_PARTIAL) ++ return 0; ++ ++ /* Note: L3 csum seems to be already computed in sw, but we can't choose ++ * L4 alone from the FM configuration anyway. ++ */ ++ ++ /* Fill in some fields of the Parse Results array, so the FMan ++ * can find them as if they came from the FMan Parser. ++ */ ++ parse_result = (fm_prs_result_t *)parse_results; ++ ++ /* If we're dealing with VLAN, get the real Ethernet type */ ++ if (ethertype == ETH_P_8021Q) { ++ /* We can't always assume the MAC header is set correctly ++ * by the stack, so reset to beginning of skb->data ++ */ ++ skb_reset_mac_header(skb); ++ ethertype = ntohs(vlan_eth_hdr(skb)->h_vlan_encapsulated_proto); ++ } ++ ++ /* Fill in the relevant L3 parse result fields ++ * and read the L4 protocol type ++ */ ++ switch (ethertype) { ++ case ETH_P_IP: ++ parse_result->l3r = cpu_to_be16(FM_L3_PARSE_RESULT_IPV4); ++ iph = ip_hdr(skb); ++ DPA_BUG_ON(iph == NULL); ++ l4_proto = iph->protocol; ++ break; ++ case ETH_P_IPV6: ++ parse_result->l3r = cpu_to_be16(FM_L3_PARSE_RESULT_IPV6); ++ ipv6h = ipv6_hdr(skb); ++ DPA_BUG_ON(ipv6h == NULL); ++ l4_proto = ipv6h->nexthdr; ++ break; ++ default: ++ /* We shouldn't even be here */ ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_alert(priv->net_dev, ++ "Can't compute HW csum for L3 proto 0x%x\n", ++ ntohs(skb->protocol)); ++ retval = -EIO; ++ goto return_error; ++ } ++ ++ /* Fill in the relevant L4 parse result fields */ ++ switch (l4_proto) { ++ case IPPROTO_UDP: ++ parse_result->l4r = FM_L4_PARSE_RESULT_UDP; ++ break; ++ case IPPROTO_TCP: ++ parse_result->l4r = FM_L4_PARSE_RESULT_TCP; ++ break; ++ default: ++ /* This can as well be a BUG() */ ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_alert(priv->net_dev, ++ "Can't compute HW csum for L4 proto 0x%x\n", ++ l4_proto); ++ retval = -EIO; ++ goto return_error; ++ } ++ ++ /* At index 0 is IPOffset_1 as defined in the Parse Results */ ++ parse_result->ip_off[0] = (uint8_t)skb_network_offset(skb); ++ parse_result->l4_off = (uint8_t)skb_transport_offset(skb); ++ ++ /* Enable L3 (and L4, if TCP or UDP) HW checksum. */ ++ fd->cmd |= FM_FD_CMD_RPD | FM_FD_CMD_DTC; ++ ++ /* On P1023 and similar platforms fd->cmd interpretation could ++ * be disabled by setting CONTEXT_A bit ICMD; currently this bit ++ * is not set so we do not need to check; in the future, if/when ++ * using context_a we need to check this bit ++ */ ++ ++return_error: ++ return retval; ++} ++EXPORT_SYMBOL(dpa_enable_tx_csum); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h +new file mode 100644 +index 0000000..6ffae91 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h +@@ -0,0 +1,214 @@ ++/* Copyright 2008-2013 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 __DPAA_ETH_COMMON_H ++#define __DPAA_ETH_COMMON_H ++ ++#include /* struct net_device */ ++#include /* struct bm_buffer */ ++#include /* struct platform_device */ ++#include /* struct hwtstamp_config */ ++ ++#include "dpaa_eth.h" ++#include "lnxwrp_fsl_fman.h" ++ ++#define dpaa_eth_init_port(type, port, param, errq_id, defq_id, buf_layout,\ ++ frag_enabled) \ ++{ \ ++ param.errq = errq_id; \ ++ param.defq = defq_id; \ ++ param.priv_data_size = buf_layout->priv_data_size; \ ++ param.parse_results = buf_layout->parse_results; \ ++ param.hash_results = buf_layout->hash_results; \ ++ param.frag_enable = frag_enabled; \ ++ param.time_stamp = buf_layout->time_stamp; \ ++ param.manip_extra_space = buf_layout->manip_extra_space; \ ++ param.data_align = buf_layout->data_align; \ ++ fm_set_##type##_port_params(port, ¶m); \ ++} ++ ++#define DPA_SGT_MAX_ENTRIES 16 /* maximum number of entries in SG Table */ ++#define DPA_BUFF_RELEASE_MAX 8 /* maximum number of buffers released at once */ ++ ++/* return codes for the dpaa-eth hooks */ ++enum dpaa_eth_hook_result { ++ /* fd/skb was retained by the hook. ++ * ++ * On the Rx path, this means the Ethernet driver will _not_ ++ * deliver the skb to the stack. Instead, the hook implementation ++ * is expected to properly dispose of the skb. ++ * ++ * On the Tx path, the Ethernet driver's dpa_tx() function will ++ * immediately return NETDEV_TX_OK. The hook implementation is expected ++ * to free the skb. *DO*NOT* release it to BMan, or enqueue it to FMan, ++ * unless you know exactly what you're doing! ++ * ++ * On the confirmation/error paths, the Ethernet driver will _not_ ++ * perform any fd cleanup, nor update the interface statistics. ++ */ ++ DPAA_ETH_STOLEN, ++ /* fd/skb was returned to the Ethernet driver for regular processing. ++ * The hook is not allowed to, for instance, reallocate the skb (as if ++ * by linearizing, copying, cloning or reallocating the headroom). ++ */ ++ DPAA_ETH_CONTINUE ++}; ++ ++typedef enum dpaa_eth_hook_result (*dpaa_eth_ingress_hook_t)( ++ struct sk_buff *skb, struct net_device *net_dev, u32 fqid); ++typedef enum dpaa_eth_hook_result (*dpaa_eth_egress_hook_t)( ++ struct sk_buff *skb, struct net_device *net_dev); ++typedef enum dpaa_eth_hook_result (*dpaa_eth_confirm_hook_t)( ++ struct net_device *net_dev, const struct qm_fd *fd, u32 fqid); ++ ++/* used in napi related functions */ ++extern u16 qman_portal_max; ++ ++/* from dpa_ethtool.c */ ++extern const struct ethtool_ops dpa_ethtool_ops; ++ ++#ifdef CONFIG_FSL_DPAA_HOOKS ++/* Various hooks used for unit-testing and/or fastpath optimizations. ++ * Currently only one set of such hooks is supported. ++ */ ++struct dpaa_eth_hooks_s { ++ /* Invoked on the Tx private path, immediately after receiving the skb ++ * from the stack. ++ */ ++ dpaa_eth_egress_hook_t tx; ++ ++ /* Invoked on the Rx private path, right before passing the skb ++ * up the stack. At that point, the packet's protocol id has already ++ * been set. The skb's data pointer is now at the L3 header, and ++ * skb->mac_header points to the L2 header. skb->len has been adjusted ++ * to be the length of L3+payload (i.e., the length of the ++ * original frame minus the L2 header len). ++ * For more details on what the skb looks like, see eth_type_trans(). ++ */ ++ dpaa_eth_ingress_hook_t rx_default; ++ ++ /* Driver hook for the Rx error private path. */ ++ dpaa_eth_confirm_hook_t rx_error; ++ /* Driver hook for the Tx confirmation private path. */ ++ dpaa_eth_confirm_hook_t tx_confirm; ++ /* Driver hook for the Tx error private path. */ ++ dpaa_eth_confirm_hook_t tx_error; ++}; ++ ++void fsl_dpaa_eth_set_hooks(struct dpaa_eth_hooks_s *hooks); ++ ++extern struct dpaa_eth_hooks_s dpaa_eth_hooks; ++#endif ++ ++int dpa_netdev_init(struct net_device *net_dev, ++ const uint8_t *mac_addr, ++ uint16_t tx_timeout); ++int __cold dpa_start(struct net_device *net_dev); ++int __cold dpa_stop(struct net_device *net_dev); ++void __cold dpa_timeout(struct net_device *net_dev); ++struct rtnl_link_stats64 * __cold ++dpa_get_stats64(struct net_device *net_dev, ++ struct rtnl_link_stats64 *stats); ++int dpa_change_mtu(struct net_device *net_dev, int new_mtu); ++int dpa_ndo_init(struct net_device *net_dev); ++int dpa_set_features(struct net_device *dev, netdev_features_t features); ++netdev_features_t dpa_fix_features(struct net_device *dev, ++ netdev_features_t features); ++#ifdef CONFIG_FSL_DPAA_TS ++u64 dpa_get_timestamp_ns(const struct dpa_priv_s *priv, ++ enum port_type rx_tx, const void *data); ++/* Updates the skb shared hw timestamp from the hardware timestamp */ ++int dpa_get_ts(const struct dpa_priv_s *priv, enum port_type rx_tx, ++ struct skb_shared_hwtstamps *shhwtstamps, const void *data); ++#endif /* CONFIG_FSL_DPAA_TS */ ++int dpa_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); ++int __cold dpa_remove(struct platform_device *of_dev); ++struct mac_device * __cold __must_check ++__attribute__((nonnull)) dpa_mac_probe(struct platform_device *_of_dev); ++int dpa_set_mac_address(struct net_device *net_dev, void *addr); ++void dpa_set_rx_mode(struct net_device *net_dev); ++void dpa_set_buffers_layout(struct mac_device *mac_dev, ++ struct dpa_buffer_layout_s *layout); ++int __attribute__((nonnull)) ++dpa_bp_alloc(struct dpa_bp *dpa_bp); ++void __cold __attribute__((nonnull)) ++dpa_bp_free(struct dpa_priv_s *priv); ++struct dpa_bp *dpa_bpid2pool(int bpid); ++void dpa_bpid2pool_map(int bpid, struct dpa_bp *dpa_bp); ++bool dpa_bpid2pool_use(int bpid); ++void dpa_bp_drain(struct dpa_bp *bp); ++#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE ++u16 dpa_select_queue(struct net_device *net_dev, struct sk_buff *skb, ++ void *accel_priv, select_queue_fallback_t fallback); ++#endif ++struct dpa_fq *dpa_fq_alloc(struct device *dev, ++ const struct fqid_cell *fqids, ++ struct list_head *list, ++ enum dpa_fq_type fq_type); ++int dpa_fq_probe_mac(struct device *dev, struct list_head *list, ++ struct fm_port_fqs *port_fqs, ++ bool tx_conf_fqs_per_core, ++ enum port_type ptype); ++int dpa_get_channel(void); ++void dpa_release_channel(void); ++int dpaa_eth_add_channel(void *__arg); ++int dpaa_eth_cgr_init(struct dpa_priv_s *priv); ++void dpa_fq_setup(struct dpa_priv_s *priv, const struct dpa_fq_cbs_t *fq_cbs, ++ struct fm_port *tx_port); ++int dpa_fq_init(struct dpa_fq *dpa_fq, bool td_enable); ++int __cold __attribute__((nonnull)) ++dpa_fq_free(struct device *dev, struct list_head *list); ++void dpaa_eth_init_ports(struct mac_device *mac_dev, ++ struct dpa_bp *bp, size_t count, ++ struct fm_port_fqs *port_fqs, ++ struct dpa_buffer_layout_s *buf_layout, ++ struct device *dev); ++void dpa_release_sgt(struct qm_sg_entry *sgt); ++void __attribute__((nonnull)) ++dpa_fd_release(const struct net_device *net_dev, const struct qm_fd *fd); ++void count_ern(struct dpa_percpu_priv_s *percpu_priv, ++ const struct qm_mr_entry *msg); ++int dpa_enable_tx_csum(struct dpa_priv_s *priv, ++ struct sk_buff *skb, struct qm_fd *fd, char *parse_results); ++ ++struct proxy_device { ++ struct mac_device *mac_dev; ++}; ++ ++/* mac device control functions exposed by proxy interface*/ ++int dpa_proxy_start(struct net_device *net_dev); ++int dpa_proxy_stop(struct proxy_device *proxy_dev, struct net_device *net_dev); ++int dpa_proxy_set_mac_address(struct proxy_device *proxy_dev, ++ struct net_device *net_dev); ++int dpa_proxy_set_rx_mode(struct proxy_device *proxy_dev, ++ struct net_device *net_dev); ++ ++#endif /* __DPAA_ETH_COMMON_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +new file mode 100644 +index 0000000..37effc1 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +@@ -0,0 +1,1593 @@ ++/* Copyright 2013 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. ++ */ ++ ++/* "generic" flavour of DPAA Ethernet driver, called oNIC ++ * ++ * TODO: ++ * 1. This file should be conditionally compiled. For the moment it is ++ * compiled by default. ++ * 2. Tx multiqueues (ndo_select queue, alloc_etherdev_mq) ++ * 3. Fetch the buffer layouts from OH ports. ++ * 4. Make the drive generic (can connect with multiple OH ports, ++ * remove '2' hardcode from oh_ports, buffer_layout, etc.). ++ * 5. Multiple buffer pools for RX (up to 4 supported on HW) ++ * 6. Different queue initializations (enable taildrop) ++ * 7. ethtool ++ * 8. Recycling (draining buffer pool = default buffer pool) ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dpaa_eth.h" ++#include "dpaa_eth_common.h" ++#include "dpaa_eth_base.h" ++#include "dpaa_eth_generic.h" ++#include "dpaa_generic_debugfs.h" ++ ++#define DPA_DEFAULT_TX_HEADROOM 64 ++#define DPA_GENERIC_SKB_COPY_MAX_SIZE 256 ++#define DPA_GENERIC_NAPI_WEIGHT 64 ++#define DPA_GENERIC_DESCRIPTION "FSL DPAA Generic Ethernet driver" ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION(DPA_GENERIC_DESCRIPTION); ++ ++static uint8_t generic_debug = -1; ++module_param(generic_debug, byte, S_IRUGO); ++MODULE_PARM_DESC(generic_debug, "Module/Driver verbosity level"); ++ ++/* This has to work in tandem with the DPA_CS_THRESHOLD_xxx values. */ ++static uint16_t tx_timeout = 1000; ++module_param(tx_timeout, ushort, S_IRUGO); ++MODULE_PARM_DESC(tx_timeout, "The Tx timeout in ms"); ++ ++struct rtnl_link_stats64 *__cold ++dpa_generic_get_stats64(struct net_device *netdev, ++ struct rtnl_link_stats64 *stats); ++static int dpa_generic_set_mac_address(struct net_device *net_dev, ++ void *addr); ++static int __cold dpa_generic_start(struct net_device *netdev); ++static int __cold dpa_generic_stop(struct net_device *netdev); ++static int dpa_generic_eth_probe(struct platform_device *_of_dev); ++static int dpa_generic_remove(struct platform_device *of_dev); ++static void dpa_generic_ern(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_mr_entry *msg); ++static int __hot dpa_generic_tx(struct sk_buff *skb, ++ struct net_device *netdev); ++static void dpa_generic_drain_bp(struct dpa_bp *bp, u8 nbuf); ++ ++static const struct net_device_ops dpa_generic_ops = { ++ .ndo_open = dpa_generic_start, ++ .ndo_start_xmit = dpa_generic_tx, ++ .ndo_stop = dpa_generic_stop, ++ .ndo_set_mac_address = dpa_generic_set_mac_address, ++ .ndo_tx_timeout = dpa_timeout, ++ .ndo_get_stats64 = dpa_generic_get_stats64, ++ .ndo_init = dpa_ndo_init, ++ .ndo_set_features = dpa_set_features, ++ .ndo_fix_features = dpa_fix_features, ++ .ndo_change_mtu = dpa_change_mtu, ++}; ++ ++static void dpa_generic_draining_timer(unsigned long arg) ++{ ++ struct dpa_generic_priv_s *priv = (struct dpa_generic_priv_s *)arg; ++ ++ /* drain in pairs of 4 buffers */ ++ dpa_generic_drain_bp(priv->draining_tx_bp, 4); ++ ++ if (atomic_read(&priv->ifup)) ++ mod_timer(&(priv->timer), jiffies + 1); ++} ++ ++struct rtnl_link_stats64 *__cold ++dpa_generic_get_stats64(struct net_device *netdev, ++ struct rtnl_link_stats64 *stats) ++{ ++ struct dpa_generic_priv_s *priv = netdev_priv(netdev); ++ u64 *cpustats; ++ u64 *netstats = (u64 *)stats; ++ int i, j; ++ struct dpa_percpu_priv_s *percpu_priv; ++ int numstats = sizeof(struct rtnl_link_stats64) / sizeof(u64); ++ ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ cpustats = (u64 *)&percpu_priv->stats; ++ ++ for (j = 0; j < numstats; j++) ++ netstats[j] += cpustats[j]; ++ } ++ ++ return stats; ++} ++ ++static int dpa_generic_set_mac_address(struct net_device *net_dev, ++ void *addr) ++{ ++ const struct dpa_generic_priv_s *priv = netdev_priv(net_dev); ++ int _errno; ++ ++ _errno = eth_mac_addr(net_dev, addr); ++ if (_errno < 0) { ++ if (netif_msg_drv(priv)) ++ netdev_err(net_dev, "eth_mac_addr() = %d\n", _errno); ++ return _errno; ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id dpa_generic_match[] = { ++ { ++ .compatible = "fsl,dpa-ethernet-generic" ++ }, ++ {} ++}; ++ ++MODULE_DEVICE_TABLE(of, dpa_generic_match); ++ ++static struct platform_driver dpa_generic_driver = { ++ .driver = { ++ .name = KBUILD_MODNAME, ++ .of_match_table = dpa_generic_match, ++ .owner = THIS_MODULE, ++ }, ++ .probe = dpa_generic_eth_probe, ++ .remove = dpa_generic_remove ++}; ++ ++static int get_port_ref(struct device_node *dev_node, ++ struct fm_port **port) ++{ ++ struct platform_device *port_of_dev = NULL; ++ struct device *op_dev = NULL; ++ struct device_node *port_node = NULL; ++ ++ port_node = of_parse_phandle(dev_node, "fsl,fman-oh-port", 0); ++ if (port_node == NULL) ++ return -EINVAL; ++ ++ port_of_dev = of_find_device_by_node(port_node); ++ of_node_put(port_node); ++ ++ if (port_of_dev == NULL) ++ return -EINVAL; ++ ++ /* get the reference to oh port from FMD */ ++ op_dev = &port_of_dev->dev; ++ *port = fm_port_bind(op_dev); ++ ++ if (*port == NULL) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static void dpaa_generic_napi_enable(struct dpa_generic_priv_s *priv) ++{ ++ struct dpa_percpu_priv_s *percpu_priv; ++ int i, j; ++ ++ for_each_possible_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ for (j = 0; j < qman_portal_max; j++) ++ napi_enable(&percpu_priv->np[j].napi); ++ } ++} ++ ++static void dpaa_generic_napi_disable(struct dpa_generic_priv_s *priv) ++{ ++ struct dpa_percpu_priv_s *percpu_priv; ++ int i, j; ++ ++ for_each_possible_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ for (j = 0; j < qman_portal_max; j++) ++ napi_disable(&percpu_priv->np[j].napi); ++ } ++} ++ ++static struct device_node *get_rx_op_port_node(struct platform_device *_of_dev) ++{ ++ struct device *dev = &_of_dev->dev; ++ struct device_node *port_node = NULL; ++ struct device_node *onic_node = NULL; ++ int num_ports = 0; ++ ++ onic_node = dev->of_node; ++ ++ num_ports = of_count_phandle_with_args(onic_node, "fsl,oh-ports", NULL); ++ if (num_ports != 2) { ++ dev_err(dev, "There should be two O/H port handles in the device tree\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ port_node = of_parse_phandle(onic_node, "fsl,oh-ports", 0); ++ if (port_node == NULL) { ++ dev_err(dev, "Cannot find O/H port node in the device tree\n"); ++ return ERR_PTR(-EFAULT); ++ } ++ ++ return port_node; ++} ++ ++static int __cold dpa_generic_start(struct net_device *netdev) ++{ ++ struct dpa_generic_priv_s *priv = netdev_priv(netdev); ++ ++ /* seed default buffer pool */ ++ dpa_bp_priv_seed(priv->rx_bp); ++ ++ dpaa_generic_napi_enable(priv); ++ netif_tx_start_all_queues(netdev); ++ ++ mod_timer(&priv->timer, jiffies + 100); ++ atomic_dec(&priv->ifup); ++ ++ return 0; ++} ++ ++static int __cold dpa_generic_stop(struct net_device *netdev) ++{ ++ struct dpa_generic_priv_s *priv = netdev_priv(netdev); ++ ++ netif_tx_stop_all_queues(netdev); ++ dpaa_generic_napi_disable(priv); ++ ++ atomic_inc_not_zero(&priv->ifup); ++ ++ return 0; ++} ++ ++static enum qman_cb_dqrr_result __hot ++dpa_generic_rx_err_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *netdev; ++ struct dpa_generic_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ const struct qm_fd *fd; ++ int *countptr; ++ ++ netdev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(netdev); ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ countptr = raw_cpu_ptr(priv->rx_bp->percpu_count); ++ fd = &dq->fd; ++ ++ /* TODO: extract bpid from the fd; when multiple bps are supported ++ * there won't be a default bp ++ */ ++ ++ if (dpaa_eth_napi_schedule(percpu_priv, portal)) ++ return qman_cb_dqrr_stop; ++ ++ if (unlikely(dpaa_eth_refill_bpools(priv->rx_bp, countptr))) { ++ /* Unable to refill the buffer pool due to insufficient ++ * system memory. Just release the frame back into the pool, ++ * otherwise we'll soon end up with an empty buffer pool. ++ */ ++ dpa_fd_release(netdev, fd); ++ goto qman_consume; ++ } ++ ++ /* limit common, possibly innocuous Rx FIFO Overflow errors' ++ * interference with zero-loss convergence benchmark results. ++ */ ++ if (likely(fd->status & FM_FD_STAT_ERR_PHYSICAL)) ++ pr_warn_once("fsl-dpa: non-zero error counters in fman statistics (sysfs)\n"); ++ else ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_err(netdev, "Err FD status 2 = 0x%08x\n", ++ fd->status & FM_FD_STAT_RX_ERRORS); ++ ++ ++ percpu_priv->stats.rx_errors++; ++ ++ if (fd->status & FM_PORT_FRM_ERR_DMA) ++ percpu_priv->rx_errors.dme++; ++ if (fd->status & FM_PORT_FRM_ERR_PHYSICAL) ++ percpu_priv->rx_errors.fpe++; ++ if (fd->status & FM_PORT_FRM_ERR_SIZE) ++ percpu_priv->rx_errors.fse++; ++ if (fd->status & FM_PORT_FRM_ERR_PRS_HDR_ERR) ++ percpu_priv->rx_errors.phe++; ++ ++ /* TODO dpa_csum_validation */ ++ ++ dpa_fd_release(netdev, fd); ++ ++qman_consume: ++ return qman_cb_dqrr_consume; ++} ++ ++ ++static enum qman_cb_dqrr_result __hot ++dpa_generic_rx_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *netdev; ++ struct dpa_generic_priv_s *priv; ++ struct dpa_bp *bp; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct sk_buff **skbh; ++ struct sk_buff *skb; ++ const struct qm_fd *fd = &dq->fd; ++ unsigned int skb_len; ++ u32 fd_status = fd->status; ++ u64 pad; ++ dma_addr_t addr = qm_fd_addr(fd); ++ unsigned int data_start; ++ unsigned long skb_addr; ++ int *countptr; ++ ++ netdev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(netdev); ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ countptr = raw_cpu_ptr(priv->rx_bp->percpu_count); ++ ++ /* This is needed for TCP traffic as draining only on TX is not ++ * enough ++ */ ++ dpa_generic_drain_bp(priv->draining_tx_bp, 1); ++ ++ if (unlikely(dpaa_eth_napi_schedule(percpu_priv, portal))) ++ return qman_cb_dqrr_stop; ++ ++ if (unlikely(dpaa_eth_refill_bpools(priv->rx_bp, countptr))) { ++ /* Unable to refill the buffer pool due to insufficient ++ * system memory. Just release the frame back into the pool, ++ * otherwise we'll soon end up with an empty buffer pool. ++ */ ++ dpa_fd_release(netdev, fd); ++ goto qman_consume; ++ } ++ ++ skbh = (struct sk_buff **)phys_to_virt(addr); ++ /* according to the last common code (bp refill) the skb pointer is set ++ * to another address shifted by sizeof(struct sk_buff) to the left ++ */ ++ skb = *(skbh - 1); ++ ++ if (unlikely(fd_status & FM_FD_STAT_RX_ERRORS) != 0) { ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_warn(netdev, "FD status = 0x%08x\n", ++ fd->status & FM_FD_STAT_RX_ERRORS); ++ ++ percpu_priv->stats.rx_errors++; ++ dpa_fd_release(netdev, fd); ++ goto qman_consume; ++ } ++ if (unlikely(fd->format != qm_fd_contig)) { ++ percpu_priv->stats.rx_dropped++; ++ if (netif_msg_rx_status(priv) && net_ratelimit()) ++ netdev_warn(netdev, "Dropping a SG frame\n"); ++ dpa_fd_release(netdev, fd); ++ goto qman_consume; ++ } ++ ++ bp = dpa_bpid2pool(fd->bpid); ++ /* TODO add bp check on hot path? */ ++ ++ /* find out the pad */ ++ skb_addr = virt_to_phys(skb->head); ++ pad = addr - skb_addr; ++ ++ dma_unmap_single(bp->dev, addr, bp->size, DMA_BIDIRECTIONAL); ++ ++ countptr = raw_cpu_ptr(bp->percpu_count); ++ (*countptr)--; ++ ++ /* The skb is currently pointed at head + headroom. The packet ++ * starts at skb->head + pad + fd offset. ++ */ ++ data_start = (unsigned int)(pad + dpa_fd_offset(fd) - ++ skb_headroom(skb)); ++ skb_put(skb, dpa_fd_length(fd) + data_start); ++ skb_pull(skb, data_start); ++ skb->protocol = eth_type_trans(skb, netdev); ++ if (unlikely(dpa_check_rx_mtu(skb, netdev->mtu))) { ++ percpu_priv->stats.rx_dropped++; ++ dev_kfree_skb(skb); ++ goto qman_consume; ++ } ++ ++ skb_len = skb->len; ++ ++ if (fd->status & FM_FD_STAT_L4CV) ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ else ++ skb->ip_summed = CHECKSUM_NONE; ++ ++ if (unlikely(netif_receive_skb(skb) == NET_RX_DROP)) ++ goto qman_consume; ++ ++ percpu_priv->stats.rx_packets++; ++ percpu_priv->stats.rx_bytes += skb_len; ++ ++qman_consume: ++ return qman_cb_dqrr_consume; ++} ++ ++static void dpa_generic_drain_bp(struct dpa_bp *bp, u8 nbuf) ++{ ++ int ret, i; ++ struct bm_buffer bmb[8]; ++ dma_addr_t addr; ++ int *countptr = raw_cpu_ptr(bp->percpu_count); ++ int count = *countptr; ++ struct sk_buff **skbh; ++ ++ do { ++ /* bman_acquire will fail if nbuf > 8 */ ++ ret = bman_acquire(bp->pool, bmb, nbuf, 0); ++ if (ret > 0) { ++ for (i = 0; i < nbuf; i++) { ++ addr = bm_buf_addr(&bmb[i]); ++ skbh = (struct sk_buff **)phys_to_virt(addr); ++ dma_unmap_single(bp->dev, addr, bp->size, ++ DMA_TO_DEVICE); ++ dev_kfree_skb_any(*skbh); ++ } ++ count -= i; ++ } ++ } while (ret > 0); ++ ++ *countptr = count; ++} ++ ++/** ++ * Turn on HW checksum computation for this outgoing frame. ++ * If the current protocol is not something we support in this regard ++ * (or if the stack has already computed the SW checksum), we do nothing. ++ * ++ * Returns 0 if all goes well (or HW csum doesn't apply), and a negative value ++ * otherwise. ++ * ++ * Note that this function may modify the fd->cmd field and the skb data buffer ++ * (the Parse Results area). ++ */ ++static int dpa_generic_tx_csum(struct dpa_generic_priv_s *priv, ++ struct sk_buff *skb, ++ struct qm_fd *fd, ++ char *parse_results) ++{ ++ fm_prs_result_t *parse_result; ++ struct iphdr *iph; ++ struct ipv6hdr *ipv6h = NULL; ++ int l4_proto; ++ int ethertype = ntohs(skb->protocol); ++ int retval = 0; ++ ++ if (skb->ip_summed != CHECKSUM_PARTIAL) ++ return 0; ++ ++ /* Note: L3 csum seems to be already computed in sw, but we can't choose ++ * L4 alone from the FM configuration anyway. ++ */ ++ ++ /* Fill in some fields of the Parse Results array, so the FMan ++ * can find them as if they came from the FMan Parser. ++ */ ++ parse_result = (fm_prs_result_t *)parse_results; ++ ++ /* If we're dealing with VLAN, get the real Ethernet type */ ++ if (ethertype == ETH_P_8021Q) { ++ /* We can't always assume the MAC header is set correctly ++ * by the stack, so reset to beginning of skb->data ++ */ ++ skb_reset_mac_header(skb); ++ ethertype = ntohs(vlan_eth_hdr(skb)->h_vlan_encapsulated_proto); ++ } ++ ++ /* Fill in the relevant L3 parse result fields ++ * and read the L4 protocol type ++ */ ++ switch (ethertype) { ++ case ETH_P_IP: ++ parse_result->l3r = FM_L3_PARSE_RESULT_IPV4; ++ iph = ip_hdr(skb); ++ BUG_ON(iph == NULL); ++ l4_proto = iph->protocol; ++ break; ++ case ETH_P_IPV6: ++ parse_result->l3r = FM_L3_PARSE_RESULT_IPV6; ++ ipv6h = ipv6_hdr(skb); ++ BUG_ON(ipv6h == NULL); ++ l4_proto = ipv6h->nexthdr; ++ break; ++ default: ++ /* We shouldn't even be here */ ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_alert(priv->net_dev, ++ "Can't compute HW csum for L3 proto 0x%x\n", ++ ntohs(skb->protocol)); ++ retval = -EIO; ++ goto return_error; ++ } ++ ++ /* Fill in the relevant L4 parse result fields */ ++ switch (l4_proto) { ++ case IPPROTO_UDP: ++ parse_result->l4r = FM_L4_PARSE_RESULT_UDP; ++ break; ++ case IPPROTO_TCP: ++ parse_result->l4r = FM_L4_PARSE_RESULT_TCP; ++ break; ++ default: ++ /* This can as well be a BUG() */ ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_alert(priv->net_dev, ++ "Can't compute HW csum for L4 proto 0x%x\n", ++ l4_proto); ++ retval = -EIO; ++ goto return_error; ++ } ++ ++ /* At index 0 is IPOffset_1 as defined in the Parse Results */ ++ parse_result->ip_off[0] = (uint8_t)skb_network_offset(skb); ++ parse_result->l4_off = (uint8_t)skb_transport_offset(skb); ++ ++ /* Enable L3 (and L4, if TCP or UDP) HW checksum. */ ++ fd->cmd |= FM_FD_CMD_RPD | FM_FD_CMD_DTC; ++ ++ /* On P1023 and similar platforms fd->cmd interpretation could ++ * be disabled by setting CONTEXT_A bit ICMD; currently this bit ++ * is not set so we do not need to check; in the future, if/when ++ * using context_a we need to check this bit ++ */ ++ ++return_error: ++ return retval; ++} ++ ++static int __hot dpa_generic_tx(struct sk_buff *skb, struct net_device *netdev) ++{ ++ struct dpa_generic_priv_s *priv = netdev_priv(netdev); ++ struct dpa_percpu_priv_s *percpu_priv = ++ raw_cpu_ptr(priv->percpu_priv); ++ struct rtnl_link_stats64 *percpu_stats = &percpu_priv->stats; ++ struct dpa_bp *bp = priv->draining_tx_bp; ++ struct sk_buff **skbh = NULL; ++ dma_addr_t addr; ++ struct qm_fd fd; ++ int queue_mapping; ++ struct qman_fq *egress_fq; ++ int i = 0, err = 0; ++ int *countptr; ++ ++ if (unlikely(skb_headroom(skb) < priv->tx_headroom)) { ++ struct sk_buff *skb_new; ++ ++ skb_new = skb_realloc_headroom(skb, priv->tx_headroom); ++ if (unlikely(!skb_new)) { ++ percpu_stats->tx_errors++; ++ kfree_skb(skb); ++ goto done; ++ } ++ kfree_skb(skb); ++ skb = skb_new; ++ } ++ ++ clear_fd(&fd); ++ ++ /* store skb backpointer to release the skb later */ ++ skbh = (struct sk_buff **)(skb->data - priv->tx_headroom); ++ *skbh = skb; ++ ++ /* TODO check if skb->len + priv->tx_headroom < bp->size */ ++ ++ /* Enable L3/L4 hardware checksum computation. ++ * ++ * We must do this before dma_map_single(), because we may ++ * need to write into the skb. ++ */ ++ err = dpa_generic_tx_csum(priv, skb, &fd, ++ ((char *)skbh) + DPA_TX_PRIV_DATA_SIZE); ++ if (unlikely(err < 0)) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(netdev, "HW csum error: %d\n", err); ++ return err; ++ } ++ ++ addr = dma_map_single(bp->dev, skbh, ++ skb->len + priv->tx_headroom, DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(bp->dev, addr))) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(netdev, "dma_map_single() failed\n"); ++ goto dma_mapping_failed; ++ } ++ ++ fd.format = qm_fd_contig; ++ fd.length20 = skb->len; ++ fd.offset = priv->tx_headroom; ++ fd.addr_hi = (uint8_t)upper_32_bits(addr); ++ fd.addr_lo = lower_32_bits(addr); ++ /* fd.cmd |= FM_FD_CMD_FCO; */ ++ fd.bpid = bp->bpid; ++ ++ dpa_generic_drain_bp(bp, 1); ++ ++ queue_mapping = dpa_get_queue_mapping(skb); ++ egress_fq = priv->egress_fqs[queue_mapping]; ++ ++ for (i = 0; i < 100000; i++) { ++ err = qman_enqueue(egress_fq, &fd, 0); ++ if (err != -EBUSY) ++ break; ++ } ++ ++ if (unlikely(err < 0)) { ++ percpu_stats->tx_fifo_errors++; ++ goto xmit_failed; ++ } ++ ++ countptr = raw_cpu_ptr(bp->percpu_count); ++ (*countptr)++; ++ ++ percpu_stats->tx_packets++; ++ percpu_stats->tx_bytes += fd.length20; ++ netdev->trans_start = jiffies; ++ ++ goto done; ++ ++xmit_failed: ++ dma_unmap_single(bp->dev, addr, fd.offset + fd.length20, DMA_TO_DEVICE); ++dma_mapping_failed: ++ percpu_stats->tx_errors++; ++ dev_kfree_skb(skb); ++done: ++ return NETDEV_TX_OK; ++} ++ ++static int dpa_generic_napi_add(struct net_device *net_dev) ++{ ++ struct dpa_generic_priv_s *priv = netdev_priv(net_dev); ++ struct dpa_percpu_priv_s *percpu_priv; ++ int i, cpu; ++ ++ for_each_possible_cpu(cpu) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, cpu); ++ ++ percpu_priv->np = devm_kzalloc(net_dev->dev.parent, ++ qman_portal_max * sizeof(struct dpa_napi_portal), ++ GFP_KERNEL); ++ ++ if (unlikely(percpu_priv->np == NULL)) { ++ dev_err(net_dev->dev.parent, "devm_kzalloc() failed\n"); ++ return -ENOMEM; ++ } ++ ++ for (i = 0; i < qman_portal_max; i++) ++ netif_napi_add(net_dev, &percpu_priv->np[i].napi, ++ dpaa_eth_poll, DPA_GENERIC_NAPI_WEIGHT); ++ } ++ ++ return 0; ++} ++ ++static void dpa_generic_napi_del(struct net_device *net_dev) ++{ ++ struct dpa_generic_priv_s *priv = netdev_priv(net_dev); ++ struct dpa_percpu_priv_s *percpu_priv; ++ int i, cpu; ++ ++ for_each_possible_cpu(cpu) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, cpu); ++ ++ if (percpu_priv->np) { ++ for (i = 0; i < qman_portal_max; i++) ++ netif_napi_del(&percpu_priv->np[i].napi); ++ ++ devm_kfree(net_dev->dev.parent, percpu_priv->np); ++ } ++ } ++} ++ ++ ++static int dpa_generic_netdev_init(struct device_node *dpa_node, ++ struct net_device *netdev) ++{ ++ struct dpa_generic_priv_s *priv = netdev_priv(netdev); ++ struct device *dev = netdev->dev.parent; ++ const uint8_t *mac_addr; ++ int err; ++ ++ netdev->netdev_ops = &dpa_generic_ops; ++ ++ mac_addr = of_get_mac_address(dpa_node); ++ if (mac_addr == NULL) { ++ if (netif_msg_probe(priv)) ++ dev_err(dev, "No virtual MAC address found!\n"); ++ return -EINVAL; ++ } ++ ++ netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; ++ netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE; ++ netdev->features |= netdev->hw_features; ++ netdev->vlan_features = netdev->features; ++ ++ memcpy(netdev->perm_addr, mac_addr, netdev->addr_len); ++ memcpy(netdev->dev_addr, mac_addr, netdev->addr_len); ++ ++ netdev->ethtool_ops = &dpa_generic_ethtool_ops; ++ ++ netdev->needed_headroom = priv->tx_headroom; ++ netdev->watchdog_timeo = msecs_to_jiffies(tx_timeout); ++ ++ err = register_netdev(netdev); ++ if (err < 0) { ++ dev_err(dev, "register_netdev() = %d\n", err); ++ return err; ++ } ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++ /* create debugfs entry for this net_device */ ++ err = dpa_generic_debugfs_create(netdev); ++ if (err) { ++ unregister_netdev(netdev); ++ return err; ++ } ++#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++ ++ return 0; ++} ++ ++static struct dpa_fq_cbs_t generic_fq_cbs = { ++ .rx_defq = { .cb = { .dqrr = dpa_generic_rx_dqrr } }, ++ .rx_errq = { .cb = { .dqrr = dpa_generic_rx_err_dqrr } }, ++ .egress_ern = { .cb = { .ern = dpa_generic_ern } } ++}; ++ ++static struct fqid_cell *__fq_alloc(struct device *dev, ++ int num_ranges, ++ const void *fqids_off) ++{ ++ struct fqid_cell *fqids; ++ int i; ++ ++ fqids = kzalloc(sizeof(*fqids) * num_ranges, GFP_KERNEL); ++ if (fqids == NULL) ++ return NULL; ++ ++ /* convert to CPU endianess */ ++ for (i = 0; i < num_ranges; i++) { ++ fqids[i].start = be32_to_cpup(fqids_off + ++ i * sizeof(*fqids)); ++ fqids[i].count = be32_to_cpup(fqids_off + ++ i * sizeof(*fqids) + sizeof(__be32)); ++ } ++ ++ return fqids; ++} ++ ++static struct list_head *dpa_generic_fq_probe(struct platform_device *_of_dev, ++ struct fm_port *tx_port) ++{ ++ struct device *dev = &_of_dev->dev; ++ struct device_node *oh_node = NULL; ++ struct device_node *onic_node = NULL; ++ struct fqid_cell *fqids; ++ const void *fqids_off; ++ struct dpa_fq *fq, *tmp; ++ struct list_head *list; ++ int num_ranges; ++ int i, lenp; ++ ++ onic_node = dev->of_node; ++ ++ list = devm_kzalloc(dev, sizeof(*list), GFP_KERNEL); ++ if (!list) { ++ dev_err(dev, "Cannot allocate space for frame queues list\n"); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ INIT_LIST_HEAD(list); ++ ++ /* RX queues (RX error, RX default) are specified in Rx O/H port node */ ++ oh_node = get_rx_op_port_node(_of_dev); ++ fqids_off = of_get_property(oh_node, "fsl,qman-frame-queues-oh", &lenp); ++ if (fqids_off == NULL) { ++ dev_err(dev, "Need Rx FQ definition in dts for generic devices\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ of_node_put(oh_node); ++ ++ num_ranges = lenp / sizeof(*fqids); ++ if (num_ranges != 2) { ++ dev_err(dev, "Need 2 Rx FQ definitions in dts for generic devices\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ fqids = __fq_alloc(dev, num_ranges, fqids_off); ++ if (!dpa_fq_alloc(dev, &fqids[0], list, FQ_TYPE_RX_ERROR) || ++ !dpa_fq_alloc(dev, &fqids[1], list, ++ FQ_TYPE_RX_DEFAULT)) { ++ dev_err(dev, "Cannot allocate space for default frame queues\n"); ++ return ERR_PTR(-ENOMEM); ++ } ++ kfree(fqids); ++ ++ /* TX queues */ ++ fqids_off = of_get_property(onic_node, "fsl,qman-frame-queues-tx", ++ &lenp); ++ if (fqids_off == NULL) { ++ dev_err(dev, "Need Tx FQ definition in dts for generic devices\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ num_ranges = lenp / sizeof(*fqids); ++ fqids = __fq_alloc(dev, num_ranges, fqids_off); ++ for (i = 0; i < num_ranges; i++) { ++ if (!dpa_fq_alloc(dev, &fqids[i], list, FQ_TYPE_TX)) { ++ dev_err(dev, "_dpa_fq_alloc() failed\n"); ++ return ERR_PTR(-ENOMEM); ++ } ++ } ++ kfree(fqids); ++ ++ /* optional RX PCD queues */ ++ lenp = 0; ++ fqids_off = of_get_property(onic_node, ++ "fsl,qman-frame-queues-rx", &lenp); ++ num_ranges = lenp / sizeof(*fqids); ++ fqids = __fq_alloc(dev, num_ranges, fqids_off); ++ for (i = 0; i < num_ranges; i++) { ++ if (!dpa_fq_alloc(dev, &fqids[i], list, FQ_TYPE_RX_PCD)) { ++ dev_err(dev, "_dpa_fq_alloc() failed\n"); ++ return ERR_PTR(-ENOMEM); ++ } ++ } ++ kfree(fqids); ++ ++ list_for_each_entry_safe(fq, tmp, list, list) { ++ if (fq->fq_type == FQ_TYPE_TX) ++ fq->channel = fm_get_tx_port_channel(tx_port); ++ } ++ ++ return list; ++} ++ ++static void dpa_generic_ern(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_mr_entry *msg) ++{ ++ struct net_device *netdev; ++ const struct dpa_generic_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct qm_fd fd = msg->ern.fd; ++ ++ netdev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(netdev); ++ /* Non-migratable context, safe to use raw_cpu_ptr */ ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ percpu_priv->stats.tx_dropped++; ++ percpu_priv->stats.tx_fifo_errors++; ++ count_ern(percpu_priv, msg); ++ ++ /* release this buffer into the draining buffer pool */ ++ dpa_fd_release(netdev, &fd); ++} ++ ++static int dpa_generic_rx_bp_probe(struct platform_device *_of_dev, ++ struct fm_port *rx_port, ++ int *rx_bp_count, ++ struct dpa_bp **rx_bp, ++ struct dpa_buffer_layout_s **rx_buf_layout) ++{ ++ struct device *dev = &_of_dev->dev; ++ struct fm_port_params params; ++ struct dpa_bp *bp = NULL; ++ int bp_count = 0; ++ int bpid; ++ const __be32 *bpool_cfg = NULL; ++ struct device_node *dev_node = NULL; ++ struct device_node *oh_node = NULL; ++ struct dpa_buffer_layout_s *buf_layout = NULL; ++ int lenp = 0; ++ int na = 0, ns = 0; ++ int err = 0, i = 0; ++ ++ oh_node = get_rx_op_port_node(_of_dev); ++ ++ bp_count = of_count_phandle_with_args(oh_node, ++ "fsl,bman-buffer-pools", NULL); ++ if (bp_count <= 0) { ++ dev_err(dev, "Missing buffer pool handles from onic node from device tree\n"); ++ return -EINVAL; ++ } ++ ++ bp = devm_kzalloc(dev, bp_count * sizeof(*bp), GFP_KERNEL); ++ if (unlikely(bp == NULL)) { ++ dev_err(dev, "devm_kzalloc() failed\n"); ++ return -ENOMEM; ++ } ++ ++ dev_node = of_find_node_by_path("/"); ++ if (unlikely(dev_node == NULL)) { ++ dev_err(dev, "of_find_node_by_path(/) failed\n"); ++ return -EINVAL; ++ } ++ ++ na = of_n_addr_cells(dev_node); ++ ns = of_n_size_cells(dev_node); ++ ++ of_node_put(dev_node); ++ ++ for (i = 0; i < bp_count; i++) { ++ dev_node = of_parse_phandle(oh_node, ++ "fsl,bman-buffer-pools", i); ++ if (dev_node == NULL) { ++ dev_err(dev, "Cannot find buffer pool node in the device tree\n"); ++ return -EFAULT; ++ } ++ ++ err = of_property_read_u32(dev_node, "fsl,bpid", &bpid); ++ if (err) { ++ dev_err(dev, "Cannot find buffer pool ID in the buffer pool node in the device tree\n"); ++ goto _return_of_node_put; ++ } ++ ++ bp[i].bpid = (uint8_t)bpid; ++ ++ bpool_cfg = of_get_property(dev_node, "fsl,bpool-ethernet-cfg", ++ &lenp); ++ if (bpool_cfg && (lenp == (2 * ns + na) * sizeof(*bpool_cfg))) { ++ bp[i].config_count = (int)of_read_number(bpool_cfg, ns); ++ bp[i].size = of_read_number(bpool_cfg + ns, ns); ++ bp[i].paddr = 0; ++ bp[i].seed_pool = false; ++ } else { ++ dev_err(dev, "Missing/invalid fsl,bpool-ethernet-cfg device tree entry for node %s\n", ++ dev_node->full_name); ++ err = -EINVAL; ++ goto _return_of_node_put; ++ } ++ ++ bp[i].percpu_count = devm_alloc_percpu(dev, ++ *bp[i].percpu_count); ++ } ++ ++ of_node_put(oh_node); ++ ++ buf_layout = devm_kzalloc(dev, sizeof(*buf_layout), GFP_KERNEL); ++ if (!buf_layout) { ++ dev_err(dev, "devm_kzalloc() failed\n"); ++ err = -ENOMEM; ++ goto _return_of_node_put; ++ } ++ ++ buf_layout->priv_data_size = DPA_TX_PRIV_DATA_SIZE; ++ buf_layout->parse_results = false; ++ buf_layout->hash_results = false; ++ buf_layout->time_stamp = false; ++ fm_port_get_buff_layout_ext_params(rx_port, ¶ms); ++ buf_layout->manip_extra_space = params.manip_extra_space; ++ /* a value of zero for data alignment means "don't care", so align to ++ * a non-zero value to prevent FMD from using its own default ++ */ ++ buf_layout->data_align = params.data_align ? : DPA_FD_DATA_ALIGNMENT; ++ ++ *rx_buf_layout = buf_layout; ++ *rx_bp = bp; ++ *rx_bp_count = bp_count; ++ ++ return 0; ++ ++_return_of_node_put: ++ if (dev_node) ++ of_node_put(dev_node); ++ ++ return err; ++} ++ ++static int dpa_generic_tx_bp_probe(struct platform_device *_of_dev, ++ struct fm_port *tx_port, ++ struct dpa_bp **draining_tx_bp, ++ struct dpa_buffer_layout_s **tx_buf_layout) ++{ ++ struct device *dev = &_of_dev->dev; ++ struct fm_port_params params; ++ struct dpa_bp *bp = NULL; ++ struct dpa_buffer_layout_s *buf_layout = NULL; ++ ++ buf_layout = devm_kzalloc(dev, sizeof(*buf_layout), GFP_KERNEL); ++ if (!buf_layout) { ++ dev_err(dev, "devm_kzalloc() failed\n"); ++ return -ENOMEM; ++ } ++ ++ buf_layout->priv_data_size = DPA_TX_PRIV_DATA_SIZE; ++ buf_layout->parse_results = true; ++ buf_layout->hash_results = true; ++ buf_layout->time_stamp = false; ++ ++ fm_port_get_buff_layout_ext_params(tx_port, ¶ms); ++ buf_layout->manip_extra_space = params.manip_extra_space; ++ buf_layout->data_align = params.data_align ? : DPA_FD_DATA_ALIGNMENT; ++ ++ bp = devm_kzalloc(dev, sizeof(*bp), GFP_KERNEL); ++ if (unlikely(bp == NULL)) { ++ dev_err(dev, "devm_kzalloc() failed\n"); ++ return -ENOMEM; ++ } ++ ++ bp->size = dpa_bp_size(buf_layout); ++ bp->percpu_count = devm_alloc_percpu(dev, *bp->percpu_count); ++ bp->target_count = CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT; ++ ++ *draining_tx_bp = bp; ++ *tx_buf_layout = buf_layout; ++ ++ return 0; ++} ++ ++static int dpa_generic_buff_dealloc_probe(struct platform_device *_of_dev, ++ int *disable_buff_dealloc) ++{ ++ struct device *dev = &_of_dev->dev; ++ const phandle *disable_handle = NULL; ++ int lenp = 0; ++ int err = 0; ++ ++ disable_handle = of_get_property(dev->of_node, ++ "fsl,disable_buff_dealloc", &lenp); ++ if (disable_handle != NULL) ++ *disable_buff_dealloc = 1; ++ ++ return err; ++} ++ ++static int dpa_generic_port_probe(struct platform_device *_of_dev, ++ struct fm_port **rx_port, ++ struct fm_port **tx_port) ++{ ++ struct device *dev = &_of_dev->dev; ++ struct device_node *dev_node = NULL; ++ struct device_node *onic_node = NULL; ++ int num_ports = 0; ++ int err = 0; ++ ++ onic_node = dev->of_node; ++ ++ num_ports = of_count_phandle_with_args(onic_node, "fsl,oh-ports", NULL); ++ if (num_ports != 2) { ++ dev_err(dev, "There should be two OH ports in device tree (one for RX, one for TX\n"); ++ return -EINVAL; ++ } ++ ++ dev_node = of_parse_phandle(onic_node, "fsl,oh-ports", RX); ++ if (dev_node == NULL) { ++ dev_err(dev, "Cannot find Rx OH port node in device tree\n"); ++ return err; ++ } ++ ++ err = get_port_ref(dev_node, rx_port); ++ if (err) { ++ dev_err(dev, "Cannot read Rx OH port node in device tree\n"); ++ return err; ++ } ++ ++ dev_node = of_parse_phandle(onic_node, "fsl,oh-ports", TX); ++ if (dev_node == NULL) { ++ dev_err(dev, "Cannot find Tx OH port node in device tree\n"); ++ return -EFAULT; ++ } ++ ++ err = get_port_ref(dev_node, tx_port); ++ if (err) { ++ dev_err(dev, "Cannot read Tx OH port node in device tree\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static inline void dpa_generic_setup_ingress( ++ const struct dpa_generic_priv_s *priv, ++ struct dpa_fq *fq, ++ const struct qman_fq *template) ++{ ++ fq->fq_base = *template; ++ fq->net_dev = priv->net_dev; ++ ++ fq->flags = QMAN_FQ_FLAG_NO_ENQUEUE; ++ fq->channel = priv->channel; ++} ++ ++static inline void dpa_generic_setup_egress( ++ const struct dpa_generic_priv_s *priv, ++ struct dpa_fq *fq, ++ struct fm_port *port, ++ const struct qman_fq *template) ++{ ++ fq->fq_base = *template; ++ fq->net_dev = priv->net_dev; ++ ++ if (port) { ++ fq->flags = QMAN_FQ_FLAG_TO_DCPORTAL; ++ fq->channel = fm_get_tx_port_channel(port); ++ } else { ++ fq->flags = QMAN_FQ_FLAG_NO_MODIFY; ++ } ++} ++ ++static void dpa_generic_fq_setup(struct dpa_generic_priv_s *priv, ++ const struct dpa_fq_cbs_t *fq_cbs, ++ struct fm_port *tx_port) ++{ ++ struct dpa_fq *fq; ++ int egress_cnt = 0; ++ ++ /* Initialize each FQ in the list */ ++ list_for_each_entry(fq, &priv->dpa_fq_list, list) { ++ switch (fq->fq_type) { ++ case FQ_TYPE_RX_DEFAULT: ++ dpa_generic_setup_ingress(priv, fq, &fq_cbs->rx_defq); ++ break; ++ case FQ_TYPE_RX_ERROR: ++ dpa_generic_setup_ingress(priv, fq, &fq_cbs->rx_errq); ++ break; ++ case FQ_TYPE_RX_PCD: ++ dpa_generic_setup_ingress(priv, fq, &fq_cbs->rx_defq); ++ break; ++ case FQ_TYPE_TX: ++ dpa_generic_setup_egress(priv, fq, ++ tx_port, &fq_cbs->egress_ern); ++ /* If we have more Tx queues than the number of cores, ++ * just ignore the extra ones. ++ */ ++ if (egress_cnt < DPAA_ETH_TX_QUEUES) ++ priv->egress_fqs[egress_cnt++] = &fq->fq_base; ++ break; ++ default: ++ dev_warn(priv->net_dev->dev.parent, ++ "Unknown FQ type detected!\n"); ++ break; ++ } ++ } ++ ++ /* The number of Tx queues may be smaller than the number of cores, if ++ * the Tx queue range is specified in the device tree instead of being ++ * dynamically allocated. ++ * Make sure all CPUs receive a corresponding Tx queue. ++ */ ++ while (egress_cnt < DPAA_ETH_TX_QUEUES) { ++ list_for_each_entry(fq, &priv->dpa_fq_list, list) { ++ if (fq->fq_type != FQ_TYPE_TX) ++ continue; ++ priv->egress_fqs[egress_cnt++] = &fq->fq_base; ++ if (egress_cnt == DPAA_ETH_TX_QUEUES) ++ break; ++ } ++ } ++} ++ ++static int dpa_generic_fq_init(struct dpa_fq *dpa_fq, int disable_buff_dealloc) ++{ ++ int _errno; ++ struct device *dev; ++ struct qman_fq *fq; ++ struct qm_mcc_initfq initfq; ++ ++ dev = dpa_fq->net_dev->dev.parent; ++ ++ if (dpa_fq->fqid == 0) ++ dpa_fq->flags |= QMAN_FQ_FLAG_DYNAMIC_FQID; ++ ++ dpa_fq->init = !(dpa_fq->flags & QMAN_FQ_FLAG_NO_MODIFY); ++ ++ _errno = qman_create_fq(dpa_fq->fqid, dpa_fq->flags, &dpa_fq->fq_base); ++ if (_errno) { ++ dev_err(dev, "qman_create_fq() failed\n"); ++ return _errno; ++ } ++ fq = &dpa_fq->fq_base; ++ ++ if (dpa_fq->init) { ++ initfq.we_mask = QM_INITFQ_WE_FQCTRL; ++ /* FIXME: why would we want to keep an empty FQ in cache? */ ++ initfq.fqd.fq_ctrl = QM_FQCTRL_PREFERINCACHE; ++ ++ /* FQ placement */ ++ initfq.we_mask |= QM_INITFQ_WE_DESTWQ; ++ ++ initfq.fqd.dest.channel = dpa_fq->channel; ++ initfq.fqd.dest.wq = dpa_fq->wq; ++ ++ if (dpa_fq->fq_type == FQ_TYPE_TX && !disable_buff_dealloc) { ++ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA; ++ /* ContextA: A2V=1 (contextA A2 field is valid) ++ * ContextA A2: EBD=1 (deallocate buffers inside FMan) ++ */ ++ initfq.fqd.context_a.hi = 0x10000000; ++ initfq.fqd.context_a.lo = 0x80000000; ++ } ++ ++ /* Initialization common to all ingress queues */ ++ if (dpa_fq->flags & QMAN_FQ_FLAG_NO_ENQUEUE) { ++ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA; ++ initfq.fqd.fq_ctrl |= ++ QM_FQCTRL_CTXASTASHING | QM_FQCTRL_AVOIDBLOCK; ++ initfq.fqd.context_a.stashing.exclusive = ++ QM_STASHING_EXCL_DATA | QM_STASHING_EXCL_CTX | ++ QM_STASHING_EXCL_ANNOTATION; ++ initfq.fqd.context_a.stashing.data_cl = 2; ++ initfq.fqd.context_a.stashing.annotation_cl = 1; ++ initfq.fqd.context_a.stashing.context_cl = ++ DIV_ROUND_UP(sizeof(struct qman_fq), 64); ++ } ++ ++ _errno = qman_init_fq(fq, QMAN_INITFQ_FLAG_SCHED, &initfq); ++ if (_errno < 0) { ++ dev_err(dev, "qman_init_fq(%u) = %d\n", ++ qman_fq_fqid(fq), _errno); ++ qman_destroy_fq(fq, 0); ++ return _errno; ++ } ++ } ++ ++ dpa_fq->fqid = qman_fq_fqid(fq); ++ ++ return 0; ++} ++ ++static int dpa_generic_fq_create(struct net_device *netdev, ++ struct list_head *dpa_fq_list, ++ struct fm_port *tx_port) ++{ ++ struct dpa_generic_priv_s *priv = netdev_priv(netdev); ++ struct dpa_fq *fqs = NULL, *tmp = NULL; ++ struct task_struct *kth; ++ int err = 0; ++ int channel; ++ ++ INIT_LIST_HEAD(&priv->dpa_fq_list); ++ ++ list_replace_init(dpa_fq_list, &priv->dpa_fq_list); ++ ++ channel = dpa_get_channel(); ++ if (channel < 0) ++ return channel; ++ priv->channel = (uint16_t)channel; ++ ++ /* Start a thread that will walk the cpus with affine portals ++ * and add this pool channel to each's dequeue mask. ++ */ ++ kth = kthread_run(dpaa_eth_add_channel, ++ (void *)(unsigned long)priv->channel, ++ "dpaa_%p:%d", netdev, priv->channel); ++ if (!kth) ++ return -ENOMEM; ++ ++ dpa_generic_fq_setup(priv, &generic_fq_cbs, tx_port); ++ ++ /* Add the FQs to the interface, and make them active */ ++ list_for_each_entry_safe(fqs, tmp, &priv->dpa_fq_list, list) { ++ err = dpa_generic_fq_init(fqs, priv->disable_buff_dealloc); ++ if (err) ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int dpa_generic_bp_create(struct net_device *net_dev, ++ int rx_bp_count, ++ struct dpa_bp *rx_bp, ++ struct dpa_buffer_layout_s *rx_buf_layout, ++ struct dpa_bp *draining_tx_bp, ++ struct dpa_buffer_layout_s *tx_buf_layout) ++{ ++ struct dpa_generic_priv_s *priv = netdev_priv(net_dev); ++ int err = 0; ++ ++ /* TODO: multiple Rx bps */ ++ priv->rx_bp_count = rx_bp_count; ++ priv->rx_bp = rx_bp; ++ priv->rx_buf_layout = rx_buf_layout; ++ priv->draining_tx_bp = draining_tx_bp; ++ priv->tx_buf_layout = tx_buf_layout; ++ ++ err = dpa_bp_alloc(priv->rx_bp); ++ if (err < 0) { ++ /* _dpa_bp_free(priv->rx_bp); */ ++ priv->rx_bp = NULL; ++ return err; ++ } ++ ++ err = dpa_bp_alloc(priv->draining_tx_bp); ++ if (err < 0) { ++ /* _dpa_bp_free(priv->draining_tx_bp); */ ++ priv->draining_tx_bp = NULL; ++ return err; ++ } ++ ++ return 0; ++} ++ ++static void dpa_generic_bp_free(struct dpa_generic_priv_s *priv) ++{ ++ struct dpa_bp *bp = NULL; ++ int i = 0; ++ ++ /* release the rx bpools */ ++ for (i = 0; i < priv->rx_bp_count; i++) { ++ bp = &priv->rx_bp[i]; ++ if (!bp) ++ continue; ++ ++ if (!atomic_dec_and_test(&bp->refs)) ++ continue; ++ ++ if (bp->free_buf_cb) ++ dpa_bp_drain(bp); ++ ++ bman_free_pool(bp->pool); ++ ++ if (bp->dev) ++ platform_device_unregister(to_platform_device(bp->dev)); ++ } ++ ++ /* release the tx draining bpool */ ++ bp = priv->draining_tx_bp; ++ if (!bp) ++ return; ++ ++ if (!atomic_dec_and_test(&bp->refs)) ++ return; ++ ++ if (bp->free_buf_cb) ++ dpa_bp_drain(bp); ++ ++ bman_free_pool(bp->pool); ++ ++ if (bp->dev) ++ platform_device_unregister(to_platform_device(bp->dev)); ++} ++ ++static int dpa_generic_remove(struct platform_device *of_dev) ++{ ++ int err; ++ struct device *dev; ++ struct net_device *net_dev; ++ struct dpa_generic_priv_s *priv; ++ ++ dev = &of_dev->dev; ++ net_dev = dev_get_drvdata(dev); ++ priv = netdev_priv(net_dev); ++ ++ dpaa_eth_generic_sysfs_remove(dev); ++ ++ dev_set_drvdata(dev, NULL); ++ unregister_netdev(net_dev); ++ ++ err = dpa_fq_free(dev, &priv->dpa_fq_list); ++ ++ dpa_generic_napi_del(net_dev); ++ ++ dpa_generic_bp_free(priv); ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++ dpa_generic_debugfs_remove(net_dev); ++#endif ++ free_netdev(net_dev); ++ ++ return err; ++} ++ ++static int dpa_generic_eth_probe(struct platform_device *_of_dev) ++{ ++ struct device *dev = &_of_dev->dev; ++ struct device_node *dpa_node = dev->of_node; ++ struct net_device *netdev = NULL; ++ struct dpa_generic_priv_s *priv; ++ struct fm_port *rx_port = NULL; ++ struct fm_port *tx_port = NULL; ++ struct dpa_percpu_priv_s *percpu_priv; ++ int rx_bp_count = 0; ++ int disable_buff_dealloc = 0; ++ struct dpa_bp *rx_bp = NULL, *draining_tx_bp = NULL; ++ struct dpa_buffer_layout_s *rx_buf_layout = NULL, *tx_buf_layout = NULL; ++ struct list_head *dpa_fq_list; ++ static u8 generic_idx; ++ int err = 0; ++ int i = 0; ++ ++ if (!of_device_is_available(dpa_node)) ++ return -ENODEV; ++ ++ err = dpa_generic_port_probe(_of_dev, &tx_port, &rx_port); ++ if (err < 0) ++ return err; ++ ++ err = dpa_generic_rx_bp_probe(_of_dev, rx_port, &rx_bp_count, ++ &rx_bp, &rx_buf_layout); ++ if (err < 0) ++ return err; ++ ++ err = dpa_generic_tx_bp_probe(_of_dev, tx_port, &draining_tx_bp, ++ &tx_buf_layout); ++ if (err < 0) ++ return err; ++ ++ dpa_fq_list = dpa_generic_fq_probe(_of_dev, tx_port); ++ if (IS_ERR(dpa_fq_list)) ++ return PTR_ERR(dpa_fq_list); ++ ++ err = dpa_generic_buff_dealloc_probe(_of_dev, &disable_buff_dealloc); ++ if (err < 0) ++ return err; ++ ++ /* just one queue for now */ ++ netdev = alloc_etherdev_mq(sizeof(*priv), 1); ++ if (!netdev) { ++ dev_err(dev, "alloc_etherdev_mq() failed\n"); ++ return -ENOMEM; ++ } ++ ++ SET_NETDEV_DEV(netdev, dev); ++ dev_set_drvdata(dev, netdev); ++ priv = netdev_priv(netdev); ++ priv->net_dev = netdev; ++ sprintf(priv->if_type, "generic%d", generic_idx++); ++ priv->msg_enable = netif_msg_init(generic_debug, -1); ++ priv->tx_headroom = DPA_DEFAULT_TX_HEADROOM; ++ ++ init_timer(&priv->timer); ++ atomic_set(&priv->ifup, 0); ++ priv->timer.data = (unsigned long)priv; ++ priv->timer.function = dpa_generic_draining_timer; ++ ++ err = dpa_generic_bp_create(netdev, rx_bp_count, rx_bp, rx_buf_layout, ++ draining_tx_bp, tx_buf_layout); ++ if (err < 0) ++ goto bp_create_failed; ++ ++ priv->disable_buff_dealloc = disable_buff_dealloc; ++ ++ err = dpa_generic_fq_create(netdev, dpa_fq_list, rx_port); ++ if (err < 0) ++ goto fq_create_failed; ++ ++ priv->tx_headroom = dpa_get_headroom(tx_buf_layout); ++ priv->rx_headroom = dpa_get_headroom(rx_buf_layout); ++ priv->rx_port = rx_port; ++ priv->tx_port = tx_port; ++ priv->mac_dev = NULL; ++ ++ ++ priv->percpu_priv = devm_alloc_percpu(dev, *priv->percpu_priv); ++ if (priv->percpu_priv == NULL) { ++ dev_err(dev, "devm_alloc_percpu() failed\n"); ++ err = -ENOMEM; ++ goto alloc_percpu_failed; ++ } ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ memset(percpu_priv, 0, sizeof(*percpu_priv)); ++ } ++ ++ /* Initialize NAPI */ ++ err = dpa_generic_napi_add(netdev); ++ if (err < 0) ++ goto napi_add_failed; ++ ++ err = dpa_generic_netdev_init(dpa_node, netdev); ++ if (err < 0) ++ goto netdev_init_failed; ++ ++ dpaa_eth_generic_sysfs_init(&netdev->dev); ++ ++ pr_info("fsl_dpa_generic: Probed %s interface as %s\n", ++ priv->if_type, netdev->name); ++ ++ return 0; ++ ++netdev_init_failed: ++napi_add_failed: ++ dpa_generic_napi_del(netdev); ++alloc_percpu_failed: ++ if (netdev) ++ dpa_fq_free(dev, &priv->dpa_fq_list); ++fq_create_failed: ++ if (netdev) { ++ /* _dpa_bp_free(priv->rx_bp); */ ++ /* _dpa_bp_free(priv->draining_tx_bp); */ ++ } ++bp_create_failed: ++ dev_set_drvdata(dev, NULL); ++ if (netdev) ++ free_netdev(netdev); ++ ++ return err; ++} ++ ++static int __init __cold dpa_generic_load(void) ++{ ++ int _errno; ++ ++ pr_info(KBUILD_MODNAME ": " DPA_GENERIC_DESCRIPTION " (" VERSION ")\n"); ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++ dpa_generic_debugfs_module_init(); ++#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++ ++ /* initialise dpaa_eth mirror values */ ++ dpa_rx_extra_headroom = fm_get_rx_extra_headroom(); ++ dpa_max_frm = fm_get_max_frm(); ++ ++ _errno = platform_driver_register(&dpa_generic_driver); ++ if (unlikely(_errno < 0)) { ++ pr_err(KBUILD_MODNAME ++ ": %s:%hu:%s(): platform_driver_register() = %d\n", ++ KBUILD_BASENAME".c", __LINE__, __func__, _errno); ++ } ++ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ return _errno; ++} ++ ++/* waiting for all referenced ports to be initialized ++ * by other kernel modules (proxy ethernet, offline_port) ++ */ ++late_initcall(dpa_generic_load); ++ ++static void __exit __cold dpa_generic_unload(void) ++{ ++ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ platform_driver_unregister(&dpa_generic_driver); ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++ dpa_generic_debugfs_module_exit(); ++#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++} ++module_exit(dpa_generic_unload); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h +new file mode 100644 +index 0000000..aa74edf +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h +@@ -0,0 +1,94 @@ ++/* Copyright 2013 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 __DPA_ETH_GENERIC_H ++#define __DPA_ETH_GENERIC_H ++ ++#include "lnxwrp_fsl_fman.h" ++#include "dpaa_eth.h" ++ ++struct dpa_generic_priv_s { ++ struct net_device *net_dev; ++ /* use the same percpu_priv as other DPAA Ethernet drivers */ ++ struct dpa_percpu_priv_s __percpu *percpu_priv; ++ ++ /* up to 4 bps supported for RX */ ++ int rx_bp_count; ++ struct dpa_bp *rx_bp; ++ struct dpa_buffer_layout_s *rx_buf_layout; ++ ++ struct dpa_bp *draining_tx_bp; ++ struct dpa_buffer_layout_s *tx_buf_layout; ++ ++ /* Store here the needed Tx headroom for convenience and speed ++ * (even though it can be computed based on the fields of buf_layout) ++ */ ++ uint16_t tx_headroom; ++ uint16_t rx_headroom; ++ ++ /* In some scenarios, when VSP are not enabled on the Tx O/H port, ++ * the buffers will be released by other hardware modules ++ */ ++ int disable_buff_dealloc; ++ ++ struct qman_fq *egress_fqs[DPAA_ETH_TX_QUEUES]; ++ ++ struct fm_port *rx_port; ++ struct fm_port *tx_port; ++ ++ /* oNIC can have limited control capabilities over a MAC device */ ++ struct mac_device *mac_dev; ++ ++ uint16_t channel; /* "fsl,qman-channel-id" */ ++ struct list_head dpa_fq_list; ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++ struct dentry *debugfs_file; ++#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++ ++ uint32_t msg_enable; /* net_device message level */ ++ ++ struct dpa_buffer_layout_s *buf_layout; ++ char if_type[30]; ++ ++ /* periodic drain */ ++ atomic_t ifup; ++ struct timer_list timer; ++}; ++ ++extern const struct ethtool_ops dpa_generic_ethtool_ops; ++ ++void dpaa_eth_generic_sysfs_init(struct device *dev); ++void dpaa_eth_generic_sysfs_remove(struct device *dev); ++int __init dpa_generic_debugfs_module_init(void); ++void __exit dpa_generic_debugfs_module_exit(void); ++ ++#endif /* __DPA_ETH_GENERIC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic_sysfs.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic_sysfs.c +new file mode 100644 +index 0000000..912f615 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic_sysfs.c +@@ -0,0 +1,201 @@ ++/* Copyright 2014 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 ++#include ++#include ++#include ++#include ++ ++#include "dpaa_eth_generic.h" ++#include "mac.h" /* struct mac_device */ ++ ++static ssize_t dpaa_eth_generic_show_addr(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dpa_generic_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ struct mac_device *mac_dev = priv->mac_dev; ++ ++ if (mac_dev) ++ return sprintf(buf, "%llx\n", ++ (unsigned long long)mac_dev->res->start); ++ else ++ return sprintf(buf, "none\n"); ++} ++ ++static ssize_t dpaa_eth_generic_show_type(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ssize_t res = 0; ++ res = sprintf(buf, "generic\n"); ++ ++ return res; ++} ++ ++static ssize_t dpaa_eth_generic_show_fqids(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dpa_generic_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ ssize_t bytes = 0; ++ int i = 0; ++ char *str; ++ struct dpa_fq *fq; ++ struct dpa_fq *tmp; ++ struct dpa_fq *prev = NULL; ++ u32 first_fqid = 0; ++ u32 last_fqid = 0; ++ char *prevstr = NULL; ++ ++ list_for_each_entry_safe(fq, tmp, &priv->dpa_fq_list, list) { ++ switch (fq->fq_type) { ++ case FQ_TYPE_RX_DEFAULT: ++ str = "Rx default"; ++ break; ++ case FQ_TYPE_RX_ERROR: ++ str = "Rx error"; ++ break; ++ case FQ_TYPE_RX_PCD: ++ str = "Rx PCD"; ++ break; ++ case FQ_TYPE_TX_CONFIRM: ++ str = "Tx default confirmation"; ++ break; ++ case FQ_TYPE_TX_CONF_MQ: ++ str = "Tx confirmation (mq)"; ++ break; ++ case FQ_TYPE_TX_ERROR: ++ str = "Tx error"; ++ break; ++ case FQ_TYPE_TX: ++ str = "Tx"; ++ break; ++ default: ++ str = "Unknown"; ++ } ++ ++ if (prev && (abs(fq->fqid - prev->fqid) != 1 || ++ str != prevstr)) { ++ if (last_fqid == first_fqid) ++ bytes += sprintf(buf + bytes, ++ "%s: %d\n", prevstr, prev->fqid); ++ else ++ bytes += sprintf(buf + bytes, ++ "%s: %d - %d\n", prevstr, ++ first_fqid, last_fqid); ++ } ++ ++ if (prev && abs(fq->fqid - prev->fqid) == 1 && str == prevstr) ++ last_fqid = fq->fqid; ++ else ++ first_fqid = last_fqid = fq->fqid; ++ ++ prev = fq; ++ prevstr = str; ++ i++; ++ } ++ ++ if (prev) { ++ if (last_fqid == first_fqid) ++ bytes += sprintf(buf + bytes, "%s: %d\n", prevstr, ++ prev->fqid); ++ else ++ bytes += sprintf(buf + bytes, "%s: %d - %d\n", prevstr, ++ first_fqid, last_fqid); ++ } ++ ++ return bytes; ++} ++ ++static ssize_t dpaa_eth_generic_show_bpids(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ssize_t bytes = 0; ++ struct dpa_generic_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ struct dpa_bp *rx_bp = priv->rx_bp; ++ struct dpa_bp *draining_tx_bp = priv->draining_tx_bp; ++ int i = 0; ++ ++ bytes += snprintf(buf + bytes, PAGE_SIZE, "Rx buffer pools:\n"); ++ for (i = 0; i < priv->rx_bp_count; i++) ++ bytes += snprintf(buf + bytes, PAGE_SIZE, "%u ", ++ rx_bp[i].bpid); ++ ++ bytes += snprintf(buf + bytes, PAGE_SIZE, "\n"); ++ bytes += snprintf(buf + bytes, PAGE_SIZE, "Draining buffer pool:\n"); ++ bytes += snprintf(buf + bytes, PAGE_SIZE, "%u\n", draining_tx_bp->bpid); ++ ++ return bytes; ++} ++ ++static ssize_t dpaa_eth_generic_show_mac_regs(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dpa_generic_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ struct mac_device *mac_dev = priv->mac_dev; ++ int n = 0; ++ ++ if (mac_dev) ++ n = fm_mac_dump_regs(mac_dev, buf, n); ++ else ++ return sprintf(buf, "no mac control\n"); ++ ++ return n; ++} ++ ++static struct device_attribute dpaa_eth_generic_attrs[] = { ++ __ATTR(device_addr, S_IRUGO, dpaa_eth_generic_show_addr, NULL), ++ __ATTR(device_type, S_IRUGO, dpaa_eth_generic_show_type, NULL), ++ __ATTR(fqids, S_IRUGO, dpaa_eth_generic_show_fqids, NULL), ++ __ATTR(bpids, S_IRUGO, dpaa_eth_generic_show_bpids, NULL), ++ __ATTR(mac_regs, S_IRUGO, dpaa_eth_generic_show_mac_regs, NULL), ++}; ++ ++void dpaa_eth_generic_sysfs_init(struct device *dev) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(dpaa_eth_generic_attrs); i++) ++ if (device_create_file(dev, &dpaa_eth_generic_attrs[i])) { ++ dev_err(dev, "Error creating sysfs file\n"); ++ while (i > 0) ++ device_remove_file(dev, ++ &dpaa_eth_generic_attrs[--i]); ++ return; ++ } ++} ++ ++void dpaa_eth_generic_sysfs_remove(struct device *dev) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(dpaa_eth_generic_attrs); i++) ++ device_remove_file(dev, &dpaa_eth_generic_attrs[i]); ++} +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c +new file mode 100644 +index 0000000..bd97536 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c +@@ -0,0 +1,498 @@ ++/* Copyright 2008-2013 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. ++ */ ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUG ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++#else ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": " fmt ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "dpaa_eth.h" ++#include "dpaa_eth_common.h" ++#include "dpaa_eth_base.h" ++#include "lnxwrp_fsl_fman.h" /* fm_get_rx_extra_headroom(), fm_get_max_frm() */ ++#include "mac.h" ++ ++/* For MAC-based interfaces, we compute the tx needed headroom from the ++ * associated Tx port's buffer layout settings. ++ * For MACless interfaces just use a default value. ++ */ ++#define DPA_DEFAULT_TX_HEADROOM 64 ++ ++#define DPA_DESCRIPTION "FSL DPAA MACless Ethernet driver" ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++MODULE_DESCRIPTION(DPA_DESCRIPTION); ++ ++/* This has to work in tandem with the DPA_CS_THRESHOLD_xxx values. */ ++static uint16_t macless_tx_timeout = 1000; ++module_param(macless_tx_timeout, ushort, S_IRUGO); ++MODULE_PARM_DESC(macless_tx_timeout, "The MACless Tx timeout in ms"); ++ ++/* forward declarations */ ++static int __cold dpa_macless_start(struct net_device *net_dev); ++static int __cold dpa_macless_stop(struct net_device *net_dev); ++static int __cold dpa_macless_set_address(struct net_device *net_dev, ++ void *addr); ++static void __cold dpa_macless_set_rx_mode(struct net_device *net_dev); ++ ++static int dpaa_eth_macless_probe(struct platform_device *_of_dev); ++static netdev_features_t ++dpa_macless_fix_features(struct net_device *dev, netdev_features_t features); ++ ++static const struct net_device_ops dpa_macless_ops = { ++ .ndo_open = dpa_macless_start, ++ .ndo_start_xmit = dpa_shared_tx, ++ .ndo_stop = dpa_macless_stop, ++ .ndo_tx_timeout = dpa_timeout, ++ .ndo_get_stats64 = dpa_get_stats64, ++ .ndo_set_mac_address = dpa_macless_set_address, ++ .ndo_set_rx_mode = dpa_macless_set_rx_mode, ++ .ndo_validate_addr = eth_validate_addr, ++#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE ++ .ndo_select_queue = dpa_select_queue, ++#endif ++ .ndo_change_mtu = dpa_change_mtu, ++ .ndo_init = dpa_ndo_init, ++ .ndo_set_features = dpa_set_features, ++ .ndo_fix_features = dpa_macless_fix_features, ++}; ++ ++static const struct of_device_id dpa_macless_match[] = { ++ { ++ .compatible = "fsl,dpa-ethernet-macless" ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, dpa_macless_match); ++ ++static struct platform_driver dpa_macless_driver = { ++ .driver = { ++ .name = KBUILD_MODNAME "-macless", ++ .of_match_table = dpa_macless_match, ++ .owner = THIS_MODULE, ++ }, ++ .probe = dpaa_eth_macless_probe, ++ .remove = dpa_remove ++}; ++ ++static const char macless_frame_queues[][25] = { ++ [RX] = "fsl,qman-frame-queues-rx", ++ [TX] = "fsl,qman-frame-queues-tx" ++}; ++ ++static int __cold dpa_macless_start(struct net_device *net_dev) ++{ ++ const struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer; ++ ++ netif_tx_start_all_queues(net_dev); ++ ++ if (proxy_dev) ++ dpa_proxy_start(net_dev); ++ ++ ++ return 0; ++} ++ ++static int __cold dpa_macless_stop(struct net_device *net_dev) ++{ ++ const struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer; ++ ++ netif_tx_stop_all_queues(net_dev); ++ ++ if (proxy_dev) ++ dpa_proxy_stop(proxy_dev, net_dev); ++ ++ return 0; ++} ++ ++static int dpa_macless_set_address(struct net_device *net_dev, void *addr) ++{ ++ const struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer; ++ int _errno; ++ ++ _errno = eth_mac_addr(net_dev, addr); ++ if (_errno < 0) { ++ if (netif_msg_drv(priv)) ++ netdev_err(net_dev, "eth_mac_addr() = %d\n", _errno); ++ return _errno; ++ } ++ ++ if (proxy_dev) { ++ _errno = dpa_proxy_set_mac_address(proxy_dev, net_dev); ++ if (_errno < 0) { ++ if (netif_msg_drv(priv)) ++ netdev_err(net_dev, "proxy_set_mac_address() = %d\n", ++ _errno); ++ return _errno; ++ } ++ } ++ ++ return 0; ++} ++ ++static void __cold dpa_macless_set_rx_mode(struct net_device *net_dev) ++{ ++ const struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer; ++ ++ if (proxy_dev) ++ dpa_proxy_set_rx_mode(proxy_dev, net_dev); ++} ++ ++static netdev_features_t ++dpa_macless_fix_features(struct net_device *dev, netdev_features_t features) ++{ ++ netdev_features_t unsupported_features = 0; ++ ++ /* In theory we should never be requested to enable features that ++ * we didn't set in netdev->features and netdev->hw_features at probe ++ * time, but double check just to be on the safe side. ++ */ ++ unsupported_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; ++ /* We don't support enabling Rx csum through ethtool yet */ ++ unsupported_features |= NETIF_F_RXCSUM; ++ ++ features &= ~unsupported_features; ++ ++ return features; ++} ++ ++static int dpa_macless_netdev_init(struct device_node *dpa_node, ++ struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer; ++ struct device *dev = net_dev->dev.parent; ++ const uint8_t *mac_addr; ++ ++ net_dev->netdev_ops = &dpa_macless_ops; ++ ++ if (proxy_dev) { ++ struct mac_device *mac_dev = proxy_dev->mac_dev; ++ net_dev->mem_start = mac_dev->res->start; ++ net_dev->mem_end = mac_dev->res->end; ++ ++ return dpa_netdev_init(net_dev, mac_dev->addr, ++ macless_tx_timeout); ++ } else { ++ /* Get the MAC address from device tree */ ++ mac_addr = of_get_mac_address(dpa_node); ++ ++ if (mac_addr == NULL) { ++ if (netif_msg_probe(priv)) ++ dev_err(dev, "No MAC address found!\n"); ++ return -EINVAL; ++ } ++ ++ return dpa_netdev_init(net_dev, mac_addr, ++ macless_tx_timeout); ++ } ++} ++ ++/* Probing of FQs for MACless ports */ ++static int dpa_fq_probe_macless(struct device *dev, struct list_head *list, ++ enum port_type ptype) ++{ ++ struct device_node *np = dev->of_node; ++ const struct fqid_cell *fqids; ++ int num_ranges; ++ int i, lenp; ++ ++ fqids = of_get_property(np, macless_frame_queues[ptype], &lenp); ++ if (fqids == NULL) { ++ dev_err(dev, "Need FQ definition in dts for MACless devices\n"); ++ return -EINVAL; ++ } ++ ++ num_ranges = lenp / sizeof(*fqids); ++ ++ /* All ranges defined in the device tree are used as Rx/Tx queues */ ++ for (i = 0; i < num_ranges; i++) { ++ if (!dpa_fq_alloc(dev, &fqids[i], list, ptype == RX ? ++ FQ_TYPE_RX_PCD : FQ_TYPE_TX)) { ++ dev_err(dev, "_dpa_fq_alloc() failed\n"); ++ return -ENOMEM; ++ } ++ } ++ ++ return 0; ++} ++ ++ static struct proxy_device * ++dpa_macless_proxy_probe(struct platform_device *_of_dev) ++{ ++ struct device *dev; ++ const phandle *proxy_prop; ++ struct proxy_device *proxy_dev; ++ struct device_node *proxy_node; ++ struct platform_device *proxy_pdev; ++ int lenp; ++ ++ dev = &_of_dev->dev; ++ ++ proxy_prop = of_get_property(dev->of_node, "proxy", &lenp); ++ if (!proxy_prop) ++ return NULL; ++ ++ proxy_node = of_find_node_by_phandle(*proxy_prop); ++ if (!proxy_node) { ++ dev_err(dev, "Cannot find proxy node\n"); ++ return NULL; ++ } ++ ++ proxy_pdev = of_find_device_by_node(proxy_node); ++ if (!proxy_pdev) { ++ of_node_put(proxy_node); ++ dev_err(dev, "Cannot find device represented by proxy node\n"); ++ return NULL; ++ } ++ ++ proxy_dev = dev_get_drvdata(&proxy_pdev->dev); ++ ++ of_node_put(proxy_node); ++ ++ return proxy_dev; ++} ++ ++static int dpaa_eth_macless_probe(struct platform_device *_of_dev) ++{ ++ int err = 0, i, channel; ++ struct device *dev; ++ struct device_node *dpa_node; ++ struct dpa_bp *dpa_bp; ++ struct dpa_fq *dpa_fq, *tmp; ++ size_t count; ++ struct net_device *net_dev = NULL; ++ struct dpa_priv_s *priv = NULL; ++ struct dpa_percpu_priv_s *percpu_priv; ++ static struct proxy_device *proxy_dev; ++ struct task_struct *kth; ++ static u8 macless_idx; ++ ++ dev = &_of_dev->dev; ++ ++ dpa_node = dev->of_node; ++ ++ if (!of_device_is_available(dpa_node)) ++ return -ENODEV; ++ ++ /* Get the buffer pools assigned to this interface */ ++ dpa_bp = dpa_bp_probe(_of_dev, &count); ++ if (IS_ERR(dpa_bp)) ++ return PTR_ERR(dpa_bp); ++ ++ for (i = 0; i < count; i++) ++ dpa_bp[i].seed_cb = dpa_bp_shared_port_seed; ++ ++ proxy_dev = dpa_macless_proxy_probe(_of_dev); ++ ++ ++ /* Allocate this early, so we can store relevant information in ++ * the private area (needed by 1588 code in dpa_mac_probe) ++ */ ++ net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA_ETH_TX_QUEUES); ++ if (!net_dev) { ++ dev_err(dev, "alloc_etherdev_mq() failed\n"); ++ return -ENOMEM; ++ } ++ ++ /* Do this here, so we can be verbose early */ ++ SET_NETDEV_DEV(net_dev, dev); ++ dev_set_drvdata(dev, net_dev); ++ ++ priv = netdev_priv(net_dev); ++ priv->net_dev = net_dev; ++ sprintf(priv->if_type, "macless%d", macless_idx++); ++ ++ priv->msg_enable = netif_msg_init(advanced_debug, -1); ++ ++ priv->peer = NULL; ++ priv->mac_dev = NULL; ++ if (proxy_dev) { ++ /* This is a temporary solution for the need of ++ * having main driver upstreamability: adjust_link ++ * is a general function that should work for both ++ * private driver and macless driver with MAC device ++ * control capabilities even if the last will not be ++ * upstreamable. ++ * TODO: find a convenient solution (wrapper over ++ * main priv structure, etc.) ++ */ ++ priv->mac_dev = proxy_dev->mac_dev; ++ ++ /* control over proxy's mac device */ ++ priv->peer = (void *)proxy_dev; ++ } ++ ++ INIT_LIST_HEAD(&priv->dpa_fq_list); ++ ++ err = dpa_fq_probe_macless(dev, &priv->dpa_fq_list, RX); ++ if (!err) ++ err = dpa_fq_probe_macless(dev, &priv->dpa_fq_list, ++ TX); ++ if (err < 0) ++ goto fq_probe_failed; ++ ++ /* bp init */ ++ priv->bp_count = count; ++ err = dpa_bp_create(net_dev, dpa_bp, count); ++ if (err < 0) ++ goto bp_create_failed; ++ ++ channel = dpa_get_channel(); ++ ++ if (channel < 0) { ++ err = channel; ++ goto get_channel_failed; ++ } ++ ++ priv->channel = (uint16_t)channel; ++ ++ /* Start a thread that will walk the cpus with affine portals ++ * and add this pool channel to each's dequeue mask. ++ */ ++ kth = kthread_run(dpaa_eth_add_channel, ++ (void *)(unsigned long)priv->channel, ++ "dpaa_%p:%d", net_dev, priv->channel); ++ if (!kth) { ++ err = -ENOMEM; ++ goto add_channel_failed; ++ } ++ ++ dpa_fq_setup(priv, &shared_fq_cbs, NULL); ++ ++ /* Add the FQs to the interface, and make them active */ ++ list_for_each_entry_safe(dpa_fq, tmp, &priv->dpa_fq_list, list) { ++ /* For MAC-less devices we only get here for RX frame queues ++ * initialization, which are the TX queues of the other ++ * partition. ++ * It is safe to rely on one partition to set the FQ taildrop ++ * threshold for the TX queues of the other partition ++ * because the ERN notifications will be received by the ++ * partition doing qman_enqueue. ++ */ ++ err = dpa_fq_init(dpa_fq, true); ++ if (err < 0) ++ goto fq_alloc_failed; ++ } ++ ++ priv->tx_headroom = DPA_DEFAULT_TX_HEADROOM; ++ ++ priv->percpu_priv = devm_alloc_percpu(dev, *priv->percpu_priv); ++ ++ if (priv->percpu_priv == NULL) { ++ dev_err(dev, "devm_alloc_percpu() failed\n"); ++ err = -ENOMEM; ++ goto alloc_percpu_failed; ++ } ++ for_each_possible_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ memset(percpu_priv, 0, sizeof(*percpu_priv)); ++ } ++ ++ err = dpa_macless_netdev_init(dpa_node, net_dev); ++ if (err < 0) ++ goto netdev_init_failed; ++ ++ dpaa_eth_sysfs_init(&net_dev->dev); ++ ++ pr_info("fsl_dpa_macless: Probed %s interface as %s\n", ++ priv->if_type, net_dev->name); ++ ++ return 0; ++ ++netdev_init_failed: ++alloc_percpu_failed: ++fq_alloc_failed: ++ if (net_dev) ++ dpa_fq_free(dev, &priv->dpa_fq_list); ++add_channel_failed: ++get_channel_failed: ++ if (net_dev) ++ dpa_bp_free(priv); ++bp_create_failed: ++fq_probe_failed: ++ dev_set_drvdata(dev, NULL); ++ if (net_dev) ++ free_netdev(net_dev); ++ ++ return err; ++} ++ ++static int __init __cold dpa_macless_load(void) ++{ ++ int _errno; ++ ++ pr_info(DPA_DESCRIPTION " (" VERSION ")\n"); ++ ++ /* Initialize dpaa_eth mirror values */ ++ dpa_rx_extra_headroom = fm_get_rx_extra_headroom(); ++ dpa_max_frm = fm_get_max_frm(); ++ ++ _errno = platform_driver_register(&dpa_macless_driver); ++ if (unlikely(_errno < 0)) { ++ pr_err(KBUILD_MODNAME ++ ": %s:%hu:%s(): platform_driver_register() = %d\n", ++ KBUILD_BASENAME".c", __LINE__, __func__, _errno); ++ } ++ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ return _errno; ++} ++module_init(dpa_macless_load); ++ ++static void __exit __cold dpa_macless_unload(void) ++{ ++ platform_driver_unregister(&dpa_macless_driver); ++ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++} ++module_exit(dpa_macless_unload); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.c +new file mode 100644 +index 0000000..6275648 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.c +@@ -0,0 +1,2162 @@ ++/* 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 ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "dpaa_eth_macsec.h" ++#include "dpaa_eth_common.h" ++ ++#ifdef CONFIG_FSL_DPAA_1588 ++#include "dpaa_1588.h" ++#endif ++ ++#ifdef CONFIG_FSL_DPAA_MACSEC_DEBUGFS ++#include "dpaa_debugfs_macsec.h" ++#endif /* CONFIG_FSL_DPAA_MACSEC_DEBUGFS */ ++ ++static struct sock *nl_sk; ++static struct macsec_priv_s *macsec_priv[FM_MAX_NUM_OF_MACS]; ++static char *macsec_ifs[FM_MAX_NUM_OF_MACS]; ++static int macsec_ifs_cnt; ++ ++static char ifs[MAX_LEN]; ++module_param_string(ifs, ifs, MAX_LEN, 0000); ++MODULE_PARM_DESC(ifs, "Comma separated interface list"); ++ ++#ifdef CONFIG_FSL_DPAA_MACSEC_DEBUGFS ++static void remove_debugfs(int index) ++{ ++ struct net_device *net_dev; ++ net_dev = first_net_device(&init_net); ++ while (net_dev) { ++ if (strcmp(net_dev->name, macsec_ifs[index]) == 0) { ++ macsec_netdev_debugfs_remove(net_dev); ++ unset_macsec_priv(index); ++ break; ++ } ++ net_dev = next_net_device(net_dev); ++ } ++} ++#endif /* CONFIG_FSL_DPAA_MACSEC_DEBUGFS */ ++ ++static int ifname_to_id(char *ifname) ++{ ++ int i; ++ ++ for (i = 0; i < FM_MAX_NUM_OF_MACS; i++) { ++ if (macsec_priv[i]->net_dev && ++ (strcmp(ifname, macsec_priv[i]->net_dev->name) == 0)) { ++ return i; ++ } ++ } ++ ++ return -1; ++} ++ ++static void deinit_macsec(int macsec_id) ++{ ++ struct macsec_priv_s *selected_macsec_priv; ++ int i; ++ ++ selected_macsec_priv = macsec_priv[macsec_id]; ++ ++ if (selected_macsec_priv->en_state == SECY_ENABLED) { ++ for (i = 0; i < NUM_OF_RX_SC; i++) { ++ if (!selected_macsec_priv->rx_sc_dev[i]) ++ continue; ++ fm_macsec_secy_rxsa_disable_receive( ++ selected_macsec_priv->fm_ms_secy, ++ selected_macsec_priv->rx_sc_dev[i], ++ selected_macsec_priv->an); ++ pr_debug("disable rx_sa done\n"); ++ ++ fm_macsec_secy_delete_rx_sa( ++ selected_macsec_priv->fm_ms_secy, ++ selected_macsec_priv->rx_sc_dev[i], ++ selected_macsec_priv->an); ++ pr_debug("delete rx_sa done\n"); ++ ++ fm_macsec_secy_delete_rxsc( ++ selected_macsec_priv->fm_ms_secy, ++ selected_macsec_priv->rx_sc_dev[i]); ++ pr_debug("delete rx_sc done\n"); ++ } ++ ++ fm_macsec_secy_delete_tx_sa(selected_macsec_priv->fm_ms_secy, ++ selected_macsec_priv->an); ++ pr_debug("delete tx_sa done\n"); ++ ++ fm_macsec_secy_free(selected_macsec_priv->fm_ms_secy); ++ selected_macsec_priv->fm_ms_secy = NULL; ++ pr_debug("secy free done\n"); ++ } ++ ++ if (selected_macsec_priv->en_state != MACSEC_DISABLED) { ++ fm_macsec_disable(selected_macsec_priv->fm_macsec); ++ fm_macsec_free(selected_macsec_priv->fm_macsec); ++ selected_macsec_priv->fm_macsec = NULL; ++ pr_debug("macsec disable and free done\n"); ++ } ++} ++ ++static void parse_ifs(void) ++{ ++ char *token, *strpos = ifs; ++ ++ while ((token = strsep(&strpos, ","))) { ++ if (strlen(token) == 0) ++ return; ++ else ++ macsec_ifs[macsec_ifs_cnt] = token; ++ macsec_ifs_cnt++; ++ } ++} ++ ++static void macsec_exception(handle_t _macsec_priv_s, ++ fm_macsec_exception exception) ++{ ++ struct macsec_priv_s *priv; ++ priv = (struct macsec_priv_s *)_macsec_priv_s; ++ ++ switch (exception) { ++ case (SINGLE_BIT_ECC): ++ dev_warn(priv->mac_dev->dev, "%s:%s SINGLE_BIT_ECC exception\n", ++ KBUILD_BASENAME".c", __func__); ++ break; ++ case (MULTI_BIT_ECC): ++ dev_warn(priv->mac_dev->dev, "%s:%s MULTI_BIT_ECC exception\n", ++ KBUILD_BASENAME".c", __func__); ++ break; ++ default: ++ dev_warn(priv->mac_dev->dev, "%s:%s exception %d\n", ++ KBUILD_BASENAME".c", __func__, exception); ++ break; ++ } ++} ++ ++ ++static void macsec_secy_exception(handle_t _macsec_priv_s, ++ fm_macsec_secy_exception exception) ++{ ++ struct macsec_priv_s *priv; ++ priv = (struct macsec_priv_s *)_macsec_priv_s; ++ ++ switch (exception) { ++ case (SECY_EX_FRAME_DISCARDED): ++ dev_warn(priv->mac_dev->dev, ++ "%s:%s SECY_EX_FRAME_DISCARDED exception\n", ++ KBUILD_BASENAME".c", __func__); ++ break; ++ default: ++ dev_warn(priv->mac_dev->dev, "%s:%s exception %d\n", ++ KBUILD_BASENAME".c", __func__, exception); ++ break; ++ } ++} ++ ++static void macsec_secy_events(handle_t _macsec_priv_s, ++ fm_macsec_secy_event event) ++{ ++ struct macsec_priv_s *priv; ++ priv = (struct macsec_priv_s *)_macsec_priv_s; ++ ++ switch (event) { ++ case (SECY_EV_NEXT_PN): ++ dev_dbg(priv->mac_dev->dev, "%s:%s SECY_EV_NEXT_PN event\n", ++ KBUILD_BASENAME".c", __func__); ++ break; ++ default: ++ dev_dbg(priv->mac_dev->dev, "%s:%s event %d\n", ++ KBUILD_BASENAME".c", __func__, event); ++ break; ++ } ++} ++ ++static struct qman_fq *macsec_get_tx_conf_queue( ++ const struct macsec_priv_s *macsec_priv, ++ struct qman_fq *tx_fq) ++{ ++ int i; ++ ++ for (i = 0; i < MACSEC_ETH_TX_QUEUES; i++) ++ if (macsec_priv->egress_fqs[i] == tx_fq) ++ return macsec_priv->conf_fqs[i]; ++ return NULL; ++} ++ ++/* Initialize qman fqs. Still need to set context_a, specifically the bits ++ * that identify the secure channel. ++ */ ++static int macsec_fq_init(struct dpa_fq *dpa_fq) ++{ ++ struct qman_fq *fq; ++ struct device *dev; ++ struct qm_mcc_initfq initfq; ++ uint32_t sc_phys_id; ++ int _errno, macsec_id; ++ ++ dev = dpa_fq->net_dev->dev.parent; ++ macsec_id = dpa_fq->net_dev->ifindex - 1; ++ ++ if (dpa_fq->fqid == 0) ++ dpa_fq->flags |= QMAN_FQ_FLAG_DYNAMIC_FQID; ++ ++ dpa_fq->init = !(dpa_fq->flags & QMAN_FQ_FLAG_NO_MODIFY); ++ _errno = qman_create_fq(dpa_fq->fqid, dpa_fq->flags, &dpa_fq->fq_base); ++ ++ if (_errno) { ++ dev_err(dev, "qman_create_fq() failed\n"); ++ return _errno; ++ } ++ ++ fq = &dpa_fq->fq_base; ++ ++ if (dpa_fq->init) { ++ initfq.we_mask = QM_INITFQ_WE_FQCTRL; ++ initfq.fqd.fq_ctrl = QM_FQCTRL_PREFERINCACHE; ++ ++ if (dpa_fq->fq_type == FQ_TYPE_TX_CONFIRM) ++ initfq.fqd.fq_ctrl |= QM_FQCTRL_HOLDACTIVE; ++ ++ initfq.we_mask |= QM_INITFQ_WE_DESTWQ; ++ ++ initfq.fqd.dest.channel = dpa_fq->channel; ++ initfq.fqd.dest.wq = dpa_fq->wq; ++ ++ if (dpa_fq->fq_type == FQ_TYPE_TX) { ++ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA; ++ ++ /* Obtain the TX scId from fman */ ++ _errno = fm_macsec_secy_get_txsc_phys_id( ++ macsec_priv[macsec_id]->fm_ms_secy, ++ &sc_phys_id); ++ if (unlikely(_errno < 0)) { ++ dev_err(dev, "fm_macsec_secy_get_txsc_phys_id = %d\n", ++ _errno); ++ return _errno; ++ } ++ ++ /* Write the TX SC-ID in the context of the FQ. ++ * A2V=1 (use the A2 field) ++ * A0V=1 (use the A0 field) ++ * OVOM=1 ++ * MCV=1 (MACsec controlled frames) ++ * MACCMD=the TX scId ++ */ ++ initfq.fqd.context_a.hi = 0x1a100000 | ++ sc_phys_id << 16; ++ initfq.fqd.context_a.lo = 0x80000000; ++ } ++ ++ _errno = qman_init_fq(fq, QMAN_INITFQ_FLAG_SCHED, &initfq); ++ if (_errno < 0) { ++ dev_err(dev, "qman_init_fq(%u) = %d\n", ++ qman_fq_fqid(fq), _errno); ++ qman_destroy_fq(fq, 0); ++ return _errno; ++ } ++ } ++ ++ dpa_fq->fqid = qman_fq_fqid(fq); ++ ++ return 0; ++} ++ ++/* Configure and enable secy. */ ++static int enable_secy(struct generic_msg *gen, int *macsec_id) ++{ ++ struct enable_secy *sec; ++ int _errno; ++ struct fm_macsec_secy_params secy_params; ++ struct dpa_fq *dpa_fq, *tmp; ++ struct macsec_priv_s *selected_macsec_priv; ++ ++ sec = &gen->payload.secy; ++ ++ if (sec->macsec_id < 0 || sec->macsec_id >= FM_MAX_NUM_OF_MACS) { ++ _errno = -EINVAL; ++ goto _return; ++ } ++ *macsec_id = sec->macsec_id; ++ selected_macsec_priv = macsec_priv[sec->macsec_id]; ++ ++ if (selected_macsec_priv->fm_ms_secy) { ++ pr_err("Secy has already been enabled\n"); ++ return -EINVAL; ++ } ++ ++ memset(&secy_params, 0, sizeof(secy_params)); ++ secy_params.fm_macsec_h = selected_macsec_priv->fm_macsec; ++ secy_params.num_receive_channels = NUM_OF_RX_SC; ++ secy_params.tx_sc_params.sci = sec->sci; ++ ++ /* Set encryption method */ ++ secy_params.tx_sc_params.cipher_suite = SECY_GCM_AES_128; ++#if (DPAA_VERSION >= 11) ++ secy_params.tx_sc_params.cipher_suite = SECY_GCM_AES_256; ++#endif /* (DPAA_VERSION >= 11) */ ++ secy_params.exception_f = macsec_secy_exception; ++ secy_params.event_f = macsec_secy_events; ++ secy_params.app_h = selected_macsec_priv; ++ ++ selected_macsec_priv->fm_ms_secy = ++ fm_macsec_secy_config(&secy_params); ++ ++ if (unlikely(selected_macsec_priv->fm_ms_secy == NULL)) { ++ _errno = -EINVAL; ++ goto _return; ++ } ++ ++ /* Configure the insertion mode */ ++ if (sec->config_insertion_mode) { ++ _errno = fm_macsec_secy_config_sci_insertion_mode( ++ selected_macsec_priv->fm_ms_secy, ++ sec->sci_insertion_mode); ++ if (unlikely(_errno < 0)) ++ goto _return; ++ } ++ ++ /* Configure the frame protection */ ++ if (sec->config_protect_frames) { ++ _errno = fm_macsec_secy_config_protect_frames( ++ selected_macsec_priv->fm_ms_secy, ++ sec->protect_frames); ++ if (unlikely(_errno < 0)) ++ goto _return; ++ } ++ ++ /* Configure the replay window */ ++ if (sec->config_replay_window) { ++ _errno = fm_macsec_secy_config_replay_window( ++ selected_macsec_priv->fm_ms_secy, ++ sec->replay_protect, ++ sec->replay_window); ++ if (unlikely(_errno < 0)) ++ goto _return; ++ } ++ ++ /* Configure the validation mode */ ++ if (sec->config_validation_mode) { ++ _errno = fm_macsec_secy_config_validation_mode( ++ selected_macsec_priv->fm_ms_secy, ++ sec->validate_frames); ++ if (unlikely(_errno < 0)) ++ goto _return; ++ } ++ ++ /* Select the exceptions that will be signaled */ ++ if (sec->config_exception) { ++ _errno = fm_macsec_secy_config_exception( ++ selected_macsec_priv->fm_ms_secy, ++ sec->exception, ++ sec->enable_exception); ++ if (unlikely(_errno < 0)) ++ goto _return; ++ } ++ ++ /* Select the events that will be signaled */ ++ if (sec->config_event) { ++ _errno = fm_macsec_secy_config_event( ++ selected_macsec_priv->fm_ms_secy, ++ sec->event, ++ sec->enable_event); ++ if (unlikely(_errno < 0)) ++ goto _return; ++ } ++ ++ /* Configure a point-to-point connection */ ++ if (sec->config_point_to_point) { ++ _errno = fm_macsec_secy_config_point_to_point( ++ selected_macsec_priv->fm_ms_secy); ++ if (unlikely(_errno < 0)) ++ goto _return; ++ } ++ ++ /* Configure the connection's confidentiality state */ ++ if (sec->config_confidentiality) { ++ _errno = fm_macsec_secy_config_confidentiality( ++ selected_macsec_priv->fm_ms_secy, ++ sec->confidentiality_enable, ++ sec->confidentiality_offset); ++ if (unlikely(_errno < 0)) ++ goto _return; ++ } ++ ++ _errno = fm_macsec_secy_init(selected_macsec_priv->fm_ms_secy); ++ if (unlikely(_errno < 0)) ++ goto _return_fm_macsec_secy_free; ++ ++ list_for_each_entry_safe(dpa_fq, ++ tmp, ++ &selected_macsec_priv->dpa_fq_list, ++ list) { ++ _errno = macsec_fq_init(dpa_fq); ++ if (_errno < 0) ++ goto _return; ++ } ++ ++ return 0; ++ ++_return_fm_macsec_secy_free: ++ fm_macsec_secy_free(selected_macsec_priv->fm_ms_secy); ++ selected_macsec_priv->fm_ms_secy = NULL; ++_return: ++ return _errno; ++} ++ ++static int set_macsec_exception(struct generic_msg *gen) ++{ ++ struct set_exception *set_ex; ++ struct macsec_priv_s *selected_macsec_priv; ++ int rv; ++ ++ set_ex = &(gen->payload.set_ex); ++ ++ selected_macsec_priv = macsec_priv[set_ex->macsec_id]; ++ ++ rv = fm_macsec_set_exception(selected_macsec_priv->fm_macsec, ++ set_ex->exception, ++ set_ex->enable_exception); ++ if (unlikely(rv < 0)) ++ pr_err("error when setting the macsec exception mask\n"); ++ ++ return rv; ++} ++ ++static int create_tx_sa(struct generic_msg *gen) ++{ ++ struct create_tx_sa *c_tx_sa; ++ macsec_sa_key_t sa_key; ++ int rv; ++ struct macsec_priv_s *selected_macsec_priv; ++ ++ c_tx_sa = &(gen->payload.c_tx_sa); ++ ++ if (c_tx_sa->macsec_id < 0 || ++ c_tx_sa->macsec_id >= FM_MAX_NUM_OF_MACS) { ++ kfree(c_tx_sa); ++ return -EINVAL; ++ } ++ selected_macsec_priv = macsec_priv[c_tx_sa->macsec_id]; ++ ++ /* set macsec_priv field */ ++ selected_macsec_priv->an = c_tx_sa->an; ++ ++ /* because of the algorithms used */ ++ if (unlikely(c_tx_sa->sak_len > 32)) { ++ pr_warn("size of secure key is greater than 32 bytes!\n"); ++ kfree(c_tx_sa); ++ return -EINVAL; ++ } ++ ++ rv = copy_from_user(&sa_key, ++ c_tx_sa->sak, ++ c_tx_sa->sak_len); ++ if (unlikely(rv != 0)) { ++ pr_err("copy_from_user could not copy %i bytes\n", rv); ++ return -EFAULT; ++ } ++ ++ rv = fm_macsec_secy_create_tx_sa(selected_macsec_priv->fm_ms_secy, ++ c_tx_sa->an, ++ sa_key); ++ if (unlikely(rv < 0)) ++ pr_err("error when creating tx sa\n"); ++ ++ return rv; ++} ++ ++static int modify_tx_sa_key(struct generic_msg *gen) ++{ ++ struct modify_tx_sa_key *tx_sa_key; ++ struct macsec_priv_s *selected_macsec_priv; ++ macsec_sa_key_t sa_key; ++ int rv; ++ ++ tx_sa_key = &(gen->payload.modify_tx_sa_key); ++ ++ if (tx_sa_key->macsec_id < 0 || ++ tx_sa_key->macsec_id >= FM_MAX_NUM_OF_MACS) ++ return -EINVAL; ++ selected_macsec_priv = macsec_priv[tx_sa_key->macsec_id]; ++ ++ /* set macsec_priv field */ ++ selected_macsec_priv->an = tx_sa_key->an; ++ ++ if (unlikely(tx_sa_key->sak_len > 32)) { ++ pr_warn("size of secure key is greater than 32 bytes!\n"); ++ kfree(tx_sa_key); ++ return -EINVAL; ++ } ++ ++ rv = copy_from_user(&sa_key, ++ tx_sa_key->sak, ++ tx_sa_key->sak_len); ++ if (unlikely(rv != 0)) { ++ pr_err("copy_from_user could not copy %i bytes\n", rv); ++ return -EFAULT; ++ } ++ ++ rv = fm_macsec_secy_txsa_modify_key(selected_macsec_priv->fm_ms_secy, ++ tx_sa_key->an, ++ sa_key); ++ if (unlikely(rv < 0)) ++ pr_err("error while modifying the tx sa key\n"); ++ ++ return rv; ++} ++ ++static int activate_tx_sa(struct generic_msg *gen) ++{ ++ struct activate_tx_sa *a_tx_sa; ++ struct macsec_priv_s *selected_macsec_priv; ++ int rv; ++ ++ a_tx_sa = &(gen->payload.a_tx_sa); ++ ++ if (a_tx_sa->macsec_id < 0 || ++ a_tx_sa->macsec_id >= FM_MAX_NUM_OF_MACS) { ++ kfree(a_tx_sa); ++ return -EINVAL; ++ } ++ selected_macsec_priv = macsec_priv[a_tx_sa->macsec_id]; ++ ++ rv = fm_macsec_secy_txsa_set_active(selected_macsec_priv->fm_ms_secy, ++ a_tx_sa->an); ++ if (unlikely(rv < 0)) ++ pr_err("error when creating tx sa\n"); ++ ++ return rv; ++} ++ ++static int get_tx_sa_an(struct generic_msg *gen, macsec_an_t *an) ++{ ++ struct macsec_priv_s *selected_macsec_priv; ++ ++ if (gen->payload.macsec_id < 0 || ++ gen->payload.macsec_id >= FM_MAX_NUM_OF_MACS) ++ return -EINVAL; ++ ++ selected_macsec_priv = macsec_priv[gen->payload.macsec_id]; ++ ++ fm_macsec_secy_txsa_get_active(selected_macsec_priv->fm_ms_secy, an); ++ ++ return 0; ++} ++ ++static int create_rx_sc(struct generic_msg *gen) ++{ ++ struct fm_macsec_secy_sc_params params; ++ struct macsec_priv_s *selected_macsec_priv; ++ struct rx_sc_dev *rx_sc_dev; ++ uint32_t sc_phys_id; ++ int i; ++ ++ if (gen->payload.c_rx_sc.macsec_id < 0 || ++ gen->payload.c_rx_sc.macsec_id >= FM_MAX_NUM_OF_MACS) ++ return -EINVAL; ++ selected_macsec_priv = macsec_priv[gen->payload.c_rx_sc.macsec_id]; ++ ++ for (i = 0; i < NUM_OF_RX_SC; i++) ++ if (!selected_macsec_priv->rx_sc_dev[i]) ++ break; ++ if (i == NUM_OF_RX_SC) { ++ pr_err("number of maximum RX_SC's has been reached\n"); ++ return -EINVAL; ++ } ++ ++ params.sci = gen->payload.c_rx_sc.sci; ++ params.cipher_suite = SECY_GCM_AES_128; ++#if (DPAA_VERSION >= 11) ++ params.cipher_suite = SECY_GCM_AES_256; ++#endif /* (DPAA_VERSION >= 11) */ ++ ++ rx_sc_dev = fm_macsec_secy_create_rxsc(selected_macsec_priv->fm_ms_secy, ++ ¶ms); ++ ++ fm_macsec_secy_get_rxsc_phys_id(selected_macsec_priv->fm_ms_secy, ++ rx_sc_dev, ++ &sc_phys_id); ++ ++ selected_macsec_priv->rx_sc_dev[sc_phys_id] = rx_sc_dev; ++ ++ return sc_phys_id; ++} ++ ++static int create_rx_sa(struct generic_msg *gen) ++{ ++ struct create_rx_sa *c_rx_sa; ++ struct macsec_priv_s *selected_macsec_priv; ++ struct rx_sc_dev *selected_rx_sc_dev; ++ macsec_sa_key_t sak; ++ int rv; ++ ++ c_rx_sa = &(gen->payload.c_rx_sa); ++ ++ if (unlikely(c_rx_sa->sak_len > 32)) { ++ pr_warn("size of secure key is greater than 32 bytes!\n"); ++ return -EINVAL; ++ } ++ rv = copy_from_user(&sak, ++ c_rx_sa->sak, ++ c_rx_sa->sak_len); ++ if (unlikely(rv != 0)) { ++ pr_err("copy_from_user could not copy %i bytes\n", rv); ++ return -EFAULT; ++ } ++ ++ if (c_rx_sa->macsec_id < 0 || ++ c_rx_sa->macsec_id >= FM_MAX_NUM_OF_MACS) ++ return -EINVAL; ++ ++ selected_macsec_priv = macsec_priv[c_rx_sa->macsec_id]; ++ ++ if (c_rx_sa->rx_sc_id < 0 || c_rx_sa->rx_sc_id >= NUM_OF_RX_SC) ++ return -EINVAL; ++ ++ selected_rx_sc_dev = selected_macsec_priv->rx_sc_dev[c_rx_sa->rx_sc_id]; ++ ++ rv = fm_macsec_secy_create_rx_sa(selected_macsec_priv->fm_ms_secy, ++ selected_rx_sc_dev, ++ c_rx_sa->an, ++ c_rx_sa->lpn, ++ sak); ++ if (unlikely(rv < 0)) { ++ pr_err("fm_macsec_secy_create_rx_sa failed\n"); ++ return -EBUSY; ++ } ++ ++ return 0; ++} ++ ++static int modify_rx_sa_key(struct generic_msg *gen) ++{ ++ struct modify_rx_sa_key *rx_sa_key; ++ struct macsec_priv_s *selected_macsec_priv; ++ struct rx_sc_dev *selected_rx_sc; ++ macsec_sa_key_t sa_key; ++ int rv; ++ ++ rx_sa_key = &(gen->payload.modify_rx_sa_key); ++ ++ if (rx_sa_key->macsec_id < 0 || ++ rx_sa_key->macsec_id >= FM_MAX_NUM_OF_MACS) ++ return -EINVAL; ++ selected_macsec_priv = macsec_priv[rx_sa_key->macsec_id]; ++ ++ if (rx_sa_key->rx_sc_id < 0 || rx_sa_key->rx_sc_id >= NUM_OF_RX_SC) ++ return -EINVAL; ++ selected_rx_sc = selected_macsec_priv->rx_sc_dev[rx_sa_key->rx_sc_id]; ++ ++ /* set macsec_priv field */ ++ selected_macsec_priv->an = rx_sa_key->an; ++ ++ if (unlikely(rx_sa_key->sak_len > 32)) { ++ pr_warn("size of secure key is greater than 32 bytes!\n"); ++ kfree(rx_sa_key); ++ return -EINVAL; ++ } ++ ++ rv = copy_from_user(&sa_key, ++ rx_sa_key->sak, ++ rx_sa_key->sak_len); ++ if (unlikely(rv != 0)) { ++ pr_err("copy_from_user could not copy %i bytes\n", rv); ++ return -EFAULT; ++ } ++ ++ rv = fm_macsec_secy_rxsa_modify_key(selected_macsec_priv->fm_ms_secy, ++ selected_rx_sc, ++ rx_sa_key->an, ++ sa_key); ++ if (unlikely(rv < 0)) ++ pr_err("error while modifying the rx sa key\n"); ++ ++ return rv; ++} ++ ++static int update_npn(struct generic_msg *gen) ++{ ++ struct update_npn *update_npn; ++ struct macsec_priv_s *selected_macsec_priv; ++ struct rx_sc_dev *selected_rx_sc_dev; ++ int err; ++ ++ update_npn = &(gen->payload.update_npn); ++ ++ if (update_npn->macsec_id < 0 || ++ update_npn->macsec_id >= FM_MAX_NUM_OF_MACS) ++ return -EINVAL; ++ selected_macsec_priv = macsec_priv[update_npn->macsec_id]; ++ ++ if (update_npn->rx_sc_id < 0 || update_npn->rx_sc_id >= NUM_OF_RX_SC) ++ return -EINVAL; ++ ++ selected_rx_sc_dev = ++ selected_macsec_priv->rx_sc_dev[update_npn->rx_sc_id]; ++ ++ err = fm_macsec_secy_rxsa_update_next_pn( ++ selected_macsec_priv->fm_ms_secy, ++ selected_rx_sc_dev, ++ update_npn->an, ++ update_npn->pn); ++ if (unlikely(err < 0)) { ++ pr_err("fm_macsec_secy_rxsa_update_next_pn failed\n"); ++ return -EBUSY; ++ } ++ ++ return 0; ++} ++ ++static int update_lpn(struct generic_msg *gen) ++{ ++ struct update_lpn *update_lpn; ++ struct macsec_priv_s *selected_macsec_priv; ++ struct rx_sc_dev *selected_rx_sc_dev; ++ int err; ++ ++ update_lpn = &(gen->payload.update_lpn); ++ ++ if (update_lpn->macsec_id < 0 || ++ update_lpn->macsec_id >= FM_MAX_NUM_OF_MACS) ++ return -EINVAL; ++ selected_macsec_priv = macsec_priv[update_lpn->macsec_id]; ++ ++ if (update_lpn->rx_sc_id < 0 || update_lpn->rx_sc_id >= NUM_OF_RX_SC) ++ return -EINVAL; ++ selected_rx_sc_dev = ++ selected_macsec_priv->rx_sc_dev[update_lpn->rx_sc_id]; ++ ++ err = fm_macsec_secy_rxsa_update_lowest_pn( ++ selected_macsec_priv->fm_ms_secy, ++ selected_rx_sc_dev, ++ update_lpn->an, ++ update_lpn->pn); ++ if (unlikely(err < 0)) { ++ pr_err("fm_macsec_secy_rxsa_update_lowest_pn failed\n"); ++ return -EBUSY; ++ } ++ ++ return 0; ++} ++ ++static int activate_rx_sa(struct generic_msg *gen) ++{ ++ struct activate_rx_sa *a_rx_sa; ++ struct macsec_priv_s *selected_macsec_priv; ++ struct rx_sc_dev *selected_rx_sc_dev; ++ int err; ++ ++ a_rx_sa = &(gen->payload.a_rx_sa); ++ ++ if (a_rx_sa->macsec_id < 0 || ++ a_rx_sa->macsec_id >= FM_MAX_NUM_OF_MACS) { ++ return -EINVAL; ++ } ++ selected_macsec_priv = macsec_priv[a_rx_sa->macsec_id]; ++ ++ if (a_rx_sa->rx_sc_id < 0 || a_rx_sa->rx_sc_id >= NUM_OF_RX_SC) ++ return -EINVAL; ++ selected_rx_sc_dev = selected_macsec_priv->rx_sc_dev[a_rx_sa->rx_sc_id]; ++ ++ err = fm_macsec_secy_rxsa_enable_receive( ++ selected_macsec_priv->fm_ms_secy, ++ selected_rx_sc_dev, ++ a_rx_sa->an); ++ if (unlikely(err < 0)) { ++ pr_err("fm_macsec_secy_rxsa_enable_receive failed\n"); ++ return -EBUSY; ++ } ++ ++ return 0; ++} ++ ++static int get_tx_sc_phys_id(struct generic_msg *gen, uint32_t *sc_id) ++{ ++ struct macsec_priv_s *selected_macsec_priv; ++ int err; ++ ++ if (gen->payload.macsec_id < 0 || ++ gen->payload.macsec_id >= FM_MAX_NUM_OF_MACS) { ++ return -EINVAL; ++ } ++ selected_macsec_priv = macsec_priv[gen->payload.macsec_id]; ++ ++ err = fm_macsec_secy_get_txsc_phys_id(selected_macsec_priv->fm_ms_secy, ++ sc_id); ++ ++ if (unlikely(err < 0)) { ++ pr_err("fm_macsec_secy_get_txsc_phys_id failed\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int get_rx_sc_phys_id(struct generic_msg *gen, uint32_t *sc_id) ++{ ++ struct get_rx_sc_id *get_rx_sc_id; ++ struct macsec_priv_s *selected_macsec_priv; ++ struct rx_sc_dev *selected_rx_sc_dev; ++ int err; ++ ++ get_rx_sc_id = &(gen->payload.get_rx_sc_id); ++ ++ if (get_rx_sc_id->macsec_id < 0 || ++ get_rx_sc_id->macsec_id >= FM_MAX_NUM_OF_MACS) { ++ return -EINVAL; ++ } ++ selected_macsec_priv = macsec_priv[get_rx_sc_id->macsec_id]; ++ ++ if (get_rx_sc_id->rx_sc_id < 0 || ++ get_rx_sc_id->rx_sc_id >= NUM_OF_RX_SC) ++ return -EINVAL; ++ selected_rx_sc_dev = ++ selected_macsec_priv->rx_sc_dev[get_rx_sc_id->rx_sc_id]; ++ ++ err = fm_macsec_secy_get_rxsc_phys_id(selected_macsec_priv->fm_ms_secy, ++ selected_rx_sc_dev, ++ sc_id); ++ if (unlikely(err < 0)) { ++ pr_err("fm_macsec_secy_get_rxsc_phys_id failed\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int get_macsec_revision(struct generic_msg *gen, int *macsec_revision) ++{ ++ struct macsec_priv_s *selected_macsec_priv; ++ int err; ++ ++ if (gen->payload.macsec_id < 0 || ++ gen->payload.macsec_id >= FM_MAX_NUM_OF_MACS) { ++ return -EINVAL; ++ } ++ selected_macsec_priv = macsec_priv[gen->payload.macsec_id]; ++ ++ err = fm_macsec_get_revision(selected_macsec_priv->fm_macsec, ++ macsec_revision); ++ if (unlikely(err < 0)) { ++ pr_err("fm_macsec_get_revision failed\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int rx_sa_disable(struct generic_msg *gen) ++{ ++ struct disable_rx_sa *disable_rx_sa; ++ struct macsec_priv_s *selected_macsec_priv; ++ struct rx_sc_dev *selected_rx_sc_dev; ++ int err; ++ ++ disable_rx_sa = &(gen->payload.d_rx_sa); ++ ++ if (disable_rx_sa->macsec_id < 0 || ++ disable_rx_sa->macsec_id >= FM_MAX_NUM_OF_MACS) { ++ return -EINVAL; ++ } ++ selected_macsec_priv = macsec_priv[disable_rx_sa->macsec_id]; ++ ++ if (disable_rx_sa->rx_sc_id < 0 || ++ disable_rx_sa->rx_sc_id >= NUM_OF_RX_SC) ++ return -EINVAL; ++ selected_rx_sc_dev = ++ selected_macsec_priv->rx_sc_dev[disable_rx_sa->rx_sc_id]; ++ ++ err = fm_macsec_secy_rxsa_disable_receive( ++ selected_macsec_priv->fm_ms_secy, ++ selected_rx_sc_dev, ++ selected_macsec_priv->an); ++ ++ if (unlikely(err < 0)) { ++ pr_err("fm_macsec_secy_rxsa_disable_receive failed\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int rx_sa_delete(struct generic_msg *gen) ++{ ++ struct delete_rx_sa *delete_rx_sa; ++ struct macsec_priv_s *selected_macsec_priv; ++ struct rx_sc_dev *selected_rx_sc_dev; ++ int err; ++ ++ delete_rx_sa = &(gen->payload.del_rx_sa); ++ ++ if (delete_rx_sa->macsec_id < 0 || ++ delete_rx_sa->macsec_id >= FM_MAX_NUM_OF_MACS) { ++ return -EINVAL; ++ } ++ selected_macsec_priv = macsec_priv[delete_rx_sa->macsec_id]; ++ ++ if (delete_rx_sa->rx_sc_id < 0 || ++ delete_rx_sa->rx_sc_id >= NUM_OF_RX_SC) ++ return -EINVAL; ++ selected_rx_sc_dev = ++ selected_macsec_priv->rx_sc_dev[delete_rx_sa->rx_sc_id]; ++ ++ err = fm_macsec_secy_delete_rx_sa(selected_macsec_priv->fm_ms_secy, ++ selected_rx_sc_dev, ++ selected_macsec_priv->an); ++ ++ if (unlikely(err < 0)) { ++ pr_err("fm_macsec_secy_delete_rx_sa failed\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int rx_sc_delete(struct generic_msg *gen) ++{ ++ struct delete_rx_sc *delete_rx_sc; ++ struct macsec_priv_s *selected_macsec_priv; ++ struct rx_sc_dev *selected_rx_sc_dev; ++ int err; ++ ++ delete_rx_sc = &(gen->payload.del_rx_sc); ++ ++ if (delete_rx_sc->macsec_id < 0 || ++ delete_rx_sc->macsec_id >= FM_MAX_NUM_OF_MACS) { ++ return -EINVAL; ++ } ++ selected_macsec_priv = macsec_priv[delete_rx_sc->macsec_id]; ++ ++ if (delete_rx_sc->rx_sc_id < 0 || ++ delete_rx_sc->rx_sc_id >= NUM_OF_RX_SC) ++ return -EINVAL; ++ selected_rx_sc_dev = ++ selected_macsec_priv->rx_sc_dev[delete_rx_sc->rx_sc_id]; ++ ++ err = fm_macsec_secy_delete_rxsc(selected_macsec_priv->fm_ms_secy, ++ selected_rx_sc_dev); ++ ++ if (unlikely(err < 0)) { ++ pr_err("fm_macsec_secy_delete_rxsc failed\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int tx_sa_delete(struct generic_msg *gen) ++{ ++ struct macsec_priv_s *selected_macsec_priv; ++ int err; ++ ++ if (gen->payload.del_tx_sa.macsec_id < 0 || ++ gen->payload.del_tx_sa.macsec_id >= FM_MAX_NUM_OF_MACS) { ++ return -EINVAL; ++ } ++ selected_macsec_priv = macsec_priv[gen->payload.del_tx_sa.macsec_id]; ++ ++ err = fm_macsec_secy_delete_tx_sa(selected_macsec_priv->fm_ms_secy, ++ selected_macsec_priv->an); ++ ++ if (unlikely(err < 0)) { ++ pr_err("fm_macsec_secy_delete_tx_sa failed\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int disable_secy(struct generic_msg *gen, int *macsec_id) ++{ ++ struct macsec_priv_s *selected_macsec_priv; ++ int err; ++ ++ if (gen->payload.macsec_id < 0 || ++ gen->payload.macsec_id >= FM_MAX_NUM_OF_MACS) { ++ return -EINVAL; ++ } ++ selected_macsec_priv = macsec_priv[gen->payload.macsec_id]; ++ *macsec_id = gen->payload.macsec_id; ++ ++ err = fm_macsec_secy_free(selected_macsec_priv->fm_ms_secy); ++ selected_macsec_priv->fm_ms_secy = NULL; ++ ++ if (unlikely(err < 0)) { ++ pr_err("fm_macsec_secy_free failed\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static int disable_macsec(struct generic_msg *gen, int *macsec_id) ++{ ++ struct macsec_priv_s *selected_macsec_priv; ++ int err; ++ ++ if (gen->payload.macsec_id < 0 || ++ gen->payload.macsec_id >= FM_MAX_NUM_OF_MACS) { ++ return -EINVAL; ++ } ++ ++ selected_macsec_priv = ++ macsec_priv[gen->payload.macsec_id]; ++ *macsec_id = gen->payload.macsec_id; ++ ++ err = fm_macsec_disable(selected_macsec_priv->fm_macsec); ++ err += fm_macsec_free(selected_macsec_priv->fm_macsec); ++ selected_macsec_priv->fm_macsec = NULL; ++ ++ if (unlikely(err < 0)) { ++ pr_err("macsec disable failed\n"); ++ return err; ++ } ++ ++ return 0; ++ ++} ++ ++static int disable_all(struct generic_msg *gen, int *macsec_id) ++{ ++ struct macsec_priv_s *selected_macsec_priv; ++ struct rx_sc_dev *selected_rx_sc_dev; ++ int err = 0, i; ++ ++ if (gen->payload.macsec_id < 0 || ++ gen->payload.macsec_id >= FM_MAX_NUM_OF_MACS) { ++ return -EINVAL; ++ } ++ ++ selected_macsec_priv = macsec_priv[gen->payload.macsec_id]; ++ *macsec_id = gen->payload.macsec_id; ++ ++ for (i = 0; i < NUM_OF_RX_SC; i++) { ++ selected_rx_sc_dev = selected_macsec_priv->rx_sc_dev[i]; ++ ++ if (!selected_rx_sc_dev) ++ continue; ++ ++ err += fm_macsec_secy_rxsa_disable_receive( ++ selected_macsec_priv->fm_ms_secy, ++ selected_rx_sc_dev, ++ selected_macsec_priv->an); ++ ++ err += fm_macsec_secy_delete_rx_sa( ++ selected_macsec_priv->fm_ms_secy, ++ selected_rx_sc_dev, ++ selected_macsec_priv->an); ++ ++ err += fm_macsec_secy_delete_rxsc( ++ selected_macsec_priv->fm_ms_secy, ++ selected_rx_sc_dev); ++ } ++ ++ err += fm_macsec_secy_delete_tx_sa( ++ selected_macsec_priv->fm_ms_secy, ++ selected_macsec_priv->an); ++ ++ err += fm_macsec_secy_free(selected_macsec_priv->fm_ms_secy); ++ selected_macsec_priv->fm_ms_secy = NULL; ++ ++ err += fm_macsec_disable(selected_macsec_priv->fm_macsec); ++ ++ err += fm_macsec_free(selected_macsec_priv->fm_macsec); ++ selected_macsec_priv->fm_macsec = NULL; ++ ++ if (unlikely(err < 0)) { ++ pr_err("macsec disable failed\n"); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static inline void macsec_setup_ingress(struct macsec_priv_s *macsec_priv, ++ struct dpa_fq *fq, ++ const struct qman_fq *template) ++{ ++ fq->fq_base = *template; ++ fq->net_dev = macsec_priv->net_dev; ++ ++ fq->flags = QMAN_FQ_FLAG_NO_ENQUEUE; ++ fq->channel = macsec_priv->channel; ++} ++ ++static inline void macsec_setup_egress(struct macsec_priv_s *macsec_priv, ++ struct dpa_fq *fq, ++ struct fm_port *port, ++ const struct qman_fq *template) ++{ ++ fq->fq_base = *template; ++ fq->net_dev = macsec_priv->net_dev; ++ ++ if (port) { ++ fq->flags = QMAN_FQ_FLAG_TO_DCPORTAL; ++ fq->channel = (uint16_t)fm_get_tx_port_channel(port); ++ } else { ++ fq->flags = QMAN_FQ_FLAG_NO_MODIFY; ++ } ++} ++ ++/* At the moment, we don't create recycle queues. */ ++static void macsec_fq_setup(struct macsec_priv_s *macsec_priv, ++ const struct dpa_fq_cbs_t *fq_cbs, ++ struct fm_port *tx_port) ++{ ++ struct dpa_fq *fq; ++ int egress_cnt = 0, conf_cnt = 0; ++ ++ /* Initialize each FQ in the list */ ++ list_for_each_entry(fq, &macsec_priv->dpa_fq_list, list) { ++ switch (fq->fq_type) { ++ /* Normal TX queues */ ++ case FQ_TYPE_TX: ++ macsec_setup_egress(macsec_priv, fq, tx_port, ++ &fq_cbs->egress_ern); ++ /* If we have more Tx queues than the number of cores, ++ * just ignore the extra ones. ++ */ ++ if (egress_cnt < MACSEC_ETH_TX_QUEUES) ++ macsec_priv->egress_fqs[egress_cnt++] = ++ &fq->fq_base; ++ break; ++ case FQ_TYPE_TX_CONFIRM: ++ BUG_ON(!macsec_priv->mac_dev); ++ macsec_setup_ingress(macsec_priv, fq, &fq_cbs->tx_defq); ++ break; ++ /* TX confirm multiple queues */ ++ case FQ_TYPE_TX_CONF_MQ: ++ BUG_ON(!macsec_priv->mac_dev); ++ macsec_setup_ingress(macsec_priv, fq, &fq_cbs->tx_defq); ++ macsec_priv->conf_fqs[conf_cnt++] = &fq->fq_base; ++ break; ++ case FQ_TYPE_TX_ERROR: ++ BUG_ON(!macsec_priv->mac_dev); ++ macsec_setup_ingress(macsec_priv, fq, &fq_cbs->tx_errq); ++ break; ++ default: ++ dev_warn(macsec_priv->net_dev->dev.parent, ++ "Unknown FQ type detected!\n"); ++ break; ++ } ++ } ++ ++ /* The number of Tx queues may be smaller than the number of cores, if ++ * the Tx queue range is specified in the device tree instead of being ++ * dynamically allocated. ++ * Make sure all CPUs receive a corresponding Tx queue. ++ */ ++ while (egress_cnt < MACSEC_ETH_TX_QUEUES) { ++ list_for_each_entry(fq, &macsec_priv->dpa_fq_list, list) { ++ if (fq->fq_type != FQ_TYPE_TX) ++ continue; ++ macsec_priv->egress_fqs[egress_cnt++] = &fq->fq_base; ++ if (egress_cnt == MACSEC_ETH_TX_QUEUES) ++ break; ++ } ++ } ++ ++} ++ ++static const struct fqid_cell tx_fqids[] = { ++ {0, MACSEC_ETH_TX_QUEUES} ++}; ++ ++static const struct fqid_cell tx_confirm_fqids[] = { ++ {0, MACSEC_ETH_TX_QUEUES} ++}; ++ ++/* Allocate percpu priv. This is used to keep track of rx and tx packets on ++ * each cpu (take into consideration that the number of queues is equal to the ++ * number of cpus, so there is one queue/cpu). ++ */ ++static void alloc_priv(struct macsec_percpu_priv_s *percpu_priv, ++ struct macsec_priv_s *macsec_priv, struct device *dev) ++{ ++ int i, err; ++ ++ macsec_priv->percpu_priv = alloc_percpu(*macsec_priv->percpu_priv); ++ ++ if (unlikely(macsec_priv->percpu_priv == NULL)) { ++ dev_err(dev, "alloc_percpu() failed\n"); ++ err = -ENOMEM; ++ dpa_fq_free(dev, &macsec_priv->dpa_fq_list); ++ } ++ ++ for_each_possible_cpu(i) { ++ percpu_priv = per_cpu_ptr(macsec_priv->percpu_priv, i); ++ memset(percpu_priv, 0, sizeof(*percpu_priv)); ++ } ++ ++} ++ ++/* On RX, we only need to retain the information about frames, if they were ++ * encrypted or not. Statistics regarding this will be printed in a log file. ++ */ ++static int macsec_rx_hook(void *ptr, struct net_device *net_dev, u32 fqid) ++{ ++ ++ struct qm_fd *rx_fd = (struct qm_fd *)ptr; ++ struct macsec_percpu_priv_s *percpu_priv_m; ++ struct macsec_priv_s *selected_macsec_priv; ++ ++ selected_macsec_priv = macsec_priv[net_dev->ifindex - 1]; ++ ++ percpu_priv_m = raw_cpu_ptr(selected_macsec_priv->percpu_priv); ++ ++ if ((rx_fd->status & FM_FD_STAT_RX_MACSEC) != 0) { ++ if (netif_msg_hw(selected_macsec_priv) && net_ratelimit()) ++ netdev_warn(net_dev, "FD status = 0x%u\n", ++ rx_fd->status & FM_FD_STAT_RX_MACSEC); ++ percpu_priv_m->rx_macsec++; ++ } ++ ++ return DPAA_ETH_CONTINUE; ++} ++ ++/* Split TX traffic. If encryption enabled, send packets on specific QMAN frame ++ * queues. Other way, let them be handled by dpa eth. Also, keep track of the ++ * number of packets that are walking away through "macsec" queues. ++ */ ++static enum dpaa_eth_hook_result macsec_tx_hook(struct sk_buff *skb, ++ struct net_device *net_dev) ++{ ++ struct dpa_priv_s *dpa_priv; ++ struct qm_fd fd; ++ struct macsec_percpu_priv_s *macsec_percpu_priv; ++ struct dpa_percpu_priv_s *dpa_percpu_priv; ++ int i, err = 0; ++ int *countptr, offset = 0; ++ const bool nonlinear = skb_is_nonlinear(skb); ++ struct qman_fq *egress_fq; ++ struct macsec_priv_s *selected_macsec_priv; ++ ++ selected_macsec_priv = macsec_priv[net_dev->ifindex - 1]; ++ ++ if (!selected_macsec_priv->net_dev || ++ (selected_macsec_priv->en_state != SECY_ENABLED) || ++ (ntohs(skb->protocol) == ETH_P_PAE)) ++ return DPAA_ETH_CONTINUE; ++ ++ dpa_priv = netdev_priv(net_dev); ++ /* Non-migratable context, safe to use raw_cpu_ptr */ ++ macsec_percpu_priv = raw_cpu_ptr(selected_macsec_priv->percpu_priv); ++ dpa_percpu_priv = raw_cpu_ptr(dpa_priv->percpu_priv); ++ ++ countptr = raw_cpu_ptr(dpa_priv->dpa_bp->percpu_count); ++ ++ clear_fd(&fd); ++ ++#ifdef CONFIG_FSL_DPAA_1588 ++ if (dpa_priv->tsu && dpa_priv->tsu->valid && ++ dpa_priv->tsu->hwts_tx_en_ioctl) ++ fd.cmd |= FM_FD_CMD_UPD; ++#endif ++#ifdef CONFIG_FSL_DPAA_TS ++ if (unlikely(dpa_priv->ts_tx_en && ++ skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) ++ fd.cmd |= FM_FD_CMD_UPD; ++ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; ++#endif /* CONFIG_FSL_DPAA_TS */ ++ ++ /* MAX_SKB_FRAGS is larger than our DPA_SGT_MAX_ENTRIES; make sure ++ * we don't feed FMan with more fragments than it supports. ++ * Btw, we're using the first sgt entry to store the linear part of ++ * the skb, so we're one extra frag short. ++ */ ++ if (nonlinear && ++ likely(skb_shinfo(skb)->nr_frags < DPA_SGT_MAX_ENTRIES)) { ++ /* Just create a S/G fd based on the skb */ ++ err = skb_to_sg_fd(dpa_priv, skb, &fd); ++ dpa_percpu_priv->tx_frag_skbuffs++; ++ } else { ++ /* Make sure we have enough headroom to accommodate private ++ * data, parse results, etc. Normally this shouldn't happen if ++ * we're here via the standard kernel stack. ++ */ ++ if (unlikely(skb_headroom(skb) < dpa_priv->tx_headroom)) { ++ struct sk_buff *skb_new; ++ ++ skb_new = skb_realloc_headroom(skb, ++ dpa_priv->tx_headroom); ++ if (unlikely(!skb_new)) { ++ dev_kfree_skb(skb); ++ dpa_percpu_priv->stats.tx_errors++; ++ return DPAA_ETH_STOLEN; ++ } ++ dev_kfree_skb(skb); ++ skb = skb_new; ++ } ++ ++ /* We're going to store the skb backpointer at the beginning ++ * of the data buffer, so we need a privately owned skb ++ */ ++ ++ /* Code borrowed from skb_unshare(). */ ++ if (skb_cloned(skb)) { ++ struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC); ++ kfree_skb(skb); ++ skb = nskb; ++ /* skb_copy() has now linearized the skbuff. */ ++ } else if (unlikely(nonlinear)) { ++ /* We are here because the egress skb contains ++ * more fragments than we support. In this case, ++ * we have no choice but to linearize it ourselves. ++ */ ++ err = __skb_linearize(skb); ++ } ++ if (unlikely(!skb || err < 0)) { ++ /* Common out-of-memory error path */ ++ goto enomem; ++ } ++ ++ /* Finally, create a contig FD from this skb */ ++ err = skb_to_contig_fd(dpa_priv, skb, &fd, countptr, &offset); ++ } ++ if (unlikely(err < 0)) ++ goto skb_to_fd_failed; ++ ++ if (fd.bpid != 0xff) { ++ skb_recycle(skb); ++ /* skb_recycle() reserves NET_SKB_PAD as skb headroom, ++ * but we need the skb to look as if returned by build_skb(). ++ * We need to manually adjust the tailptr as well. ++ */ ++ skb->data = skb->head + offset; ++ skb_reset_tail_pointer(skb); ++ ++ (*countptr)++; ++ dpa_percpu_priv->tx_returned++; ++ } ++ ++ egress_fq = selected_macsec_priv->egress_fqs[smp_processor_id()]; ++ if (fd.bpid == 0xff) ++ fd.cmd |= qman_fq_fqid(macsec_get_tx_conf_queue( ++ selected_macsec_priv, ++ egress_fq)); ++ ++ for (i = 0; i < 100000; i++) { ++ err = qman_enqueue(egress_fq, &fd, 0); ++ if (err != -EBUSY) ++ break; ++ } ++ ++ if (unlikely(err < 0)) { ++ dpa_percpu_priv->stats.tx_errors++; ++ dpa_percpu_priv->stats.tx_fifo_errors++; ++ goto xmit_failed; ++ } ++ ++ macsec_percpu_priv->tx_macsec++; ++ dpa_percpu_priv->stats.tx_packets++; ++ dpa_percpu_priv->stats.tx_bytes += dpa_fd_length(&fd); ++ ++ net_dev->trans_start = jiffies; ++ return DPAA_ETH_STOLEN; ++ ++xmit_failed: ++ if (fd.bpid != 0xff) { ++ (*countptr)--; ++ dpa_percpu_priv->tx_returned--; ++ dpa_fd_release(net_dev, &fd); ++ dpa_percpu_priv->stats.tx_errors++; ++ return DPAA_ETH_STOLEN; ++ } ++ _dpa_cleanup_tx_fd(dpa_priv, &fd); ++skb_to_fd_failed: ++enomem: ++ dpa_percpu_priv->stats.tx_errors++; ++ dev_kfree_skb(skb); ++ return DPAA_ETH_STOLEN; ++} ++ ++/* Allocate and initialize macsec priv and fqs. Also, create debugfs entry for ++ * a spcific interface. Iterate thourgh existing devices in order to find the ++ * one we want to have macsec for. ++ */ ++static int macsec_setup(void) ++{ ++ struct net_device *net_dev; ++ struct macsec_percpu_priv_s *percpu_priv = NULL; ++ struct dpa_priv_s *dpa_priv = NULL; ++ struct dpa_fq *dpa_fq; ++ struct device *dev = NULL; ++ int err, i, j, macsec_id; ++ ++ pr_debug("Entering: %s\n", __func__); ++ ++ for (i = 0; i < FM_MAX_NUM_OF_MACS; i++) { ++ macsec_priv[i] = kzalloc(sizeof(*(macsec_priv[i])), GFP_KERNEL); ++ ++ if (unlikely(macsec_priv[i] == NULL)) { ++ int j; ++ for (j = 0; j < i; j++) ++ kfree(macsec_priv[j]); ++ pr_err("could not allocate\n"); ++ return -ENOMEM; ++ } ++ } ++ ++ for (i = 0; i < macsec_ifs_cnt; i++) { ++ net_dev = first_net_device(&init_net); ++ macsec_id = net_dev->ifindex - 1; ++ while (net_dev) { ++ macsec_id = net_dev->ifindex - 1; ++ ++ /* to maintain code readability and less than ++ * 80 characters per line ++ */ ++ if (strcmp(net_dev->name, macsec_ifs[i]) != 0) { ++ net_dev = next_net_device(net_dev); ++ continue; ++ } ++ ++ /* strcmp(net_dev->name, macsec_ifs[i]) == 0 */ ++ macsec_priv[macsec_id]->en_state = MACSEC_DISABLED; ++ macsec_priv[macsec_id]->net_dev = net_dev; ++ dpa_priv = netdev_priv(net_dev); ++ macsec_priv[macsec_id]->mac_dev = dpa_priv->mac_dev; ++ macsec_priv[macsec_id]->channel = dpa_priv->channel; ++ dev = net_dev->dev.parent; ++ ++ INIT_LIST_HEAD(&macsec_priv[macsec_id]->dpa_fq_list); ++ ++ dpa_fq = dpa_fq_alloc(dev, ++ tx_fqids, ++ &macsec_priv[macsec_id]->dpa_fq_list, ++ FQ_TYPE_TX); ++ if (unlikely(dpa_fq == NULL)) { ++ dev_err(dev, "dpa_fq_alloc() failed\n"); ++ return -ENOMEM; ++ } ++ ++ dpa_fq = dpa_fq_alloc(dev, ++ tx_confirm_fqids, ++ &macsec_priv[macsec_id]->dpa_fq_list, ++ FQ_TYPE_TX_CONF_MQ); ++ if (unlikely(dpa_fq == NULL)) { ++ dev_err(dev, "dpa_fq_alloc() failed\n"); ++ return -ENOMEM; ++ } ++ ++ macsec_fq_setup(macsec_priv[macsec_id], &private_fq_cbs, ++ macsec_priv[macsec_id]->mac_dev->port_dev[TX]); ++ ++ alloc_priv(percpu_priv, macsec_priv[macsec_id], dev); ++ ++#ifdef CONFIG_FSL_DPAA_MACSEC_DEBUGFS ++ /* copy macsec_priv to dpaa_debugfs_macsec */ ++ set_macsec_priv(macsec_priv[macsec_id], macsec_id); ++ ++ /* create debugfs entry for this net_device */ ++ err = macsec_netdev_debugfs_create(net_dev); ++ if (unlikely(err)) ++ goto _err_debugfs_create; ++#endif /* CONFIG_FSL_DPAA_MACSEC_DEBUGFS */ ++ break; ++ } ++ if (macsec_priv[macsec_id]->net_dev == NULL) { ++ pr_err("Interface unknown\n"); ++ err = -EINVAL; ++ goto _error; ++ } ++ } ++ return 0; ++#ifdef CONFIG_FSL_DPAA_MACSEC_DEBUGFS ++_err_debugfs_create: ++ for (i = 0; i < macsec_ifs_cnt; i++) ++ remove_debugfs(i); ++#endif /* CONFIG_FSL_DPAA_MACSEC_DEBUGFS */ ++_error: ++ for (j = 0; j < i; i++) { ++ net_dev = first_net_device(&init_net); ++ while (net_dev) { ++ macsec_id = net_dev->ifindex - 1; ++ if (strcmp(net_dev->name, macsec_ifs[j]) != 0) { ++ net_dev = next_net_device(net_dev); ++ continue; ++ } ++ dpa_fq_free(net_dev->dev.parent, ++ &macsec_priv[macsec_id]->dpa_fq_list); ++ break; ++ } ++ kfree(macsec_priv[j]); ++ } ++ for (j = i; j < FM_MAX_NUM_OF_MACS; j++) ++ kfree(macsec_priv[j]); ++ return err; ++} ++ ++static int enable_macsec(struct generic_msg *gen) ++{ ++ struct fm_macsec_params macsec_params; ++ int rv, macsec_id; ++ void __iomem *mac_dev_base_addr; ++ uintptr_t macsec_reg_addr; ++ struct macsec_data *mdata; ++ char if_name[IFNAMSIZ]; ++ struct macsec_priv_s *selected_macsec_priv; ++ ++ mdata = &gen->payload.en_macsec; ++ ++ if (unlikely(mdata->if_name_length > IFNAMSIZ)) { ++ pr_err("interface name too long\n"); ++ return -EINVAL; ++ } ++ ++ rv = copy_from_user(if_name, mdata->if_name, mdata->if_name_length); ++ if (unlikely(rv != 0)) { ++ pr_err("copy_from_user could not copy %i bytes\n", rv); ++ return -EFAULT; ++ } ++ ++ macsec_id = ifname_to_id(if_name); ++ if (macsec_id < 0 || macsec_id >= FM_MAX_NUM_OF_MACS) { ++ pr_err("error on converting to macsec_id\n"); ++ return -ENXIO; ++ } ++ ++ selected_macsec_priv = macsec_priv[macsec_id]; ++ ++ if (selected_macsec_priv->fm_macsec) { ++ pr_err("macsec has already been configured\n"); ++ return -EINVAL; ++ } ++ ++ mac_dev_base_addr = selected_macsec_priv->mac_dev->vaddr; ++ ++ macsec_reg_addr = (uintptr_t)(mac_dev_base_addr + MACSEC_REG_OFFSET); ++ ++ memset(&macsec_params, 0, sizeof(macsec_params)); ++ macsec_params.fm_h = (handle_t)selected_macsec_priv->mac_dev->fm; ++ macsec_params.guest_mode = FALSE; ++ /* The MACsec offset relative to the memory mapped MAC device */ ++ macsec_params.non_guest_params.base_addr = macsec_reg_addr; ++ macsec_params.non_guest_params.fm_mac_h = ++ (handle_t)selected_macsec_priv->mac_dev->get_mac_handle( ++ selected_macsec_priv->mac_dev); ++ macsec_params.non_guest_params.exception_f = macsec_exception; ++ macsec_params.non_guest_params.app_h = selected_macsec_priv->mac_dev; ++ ++ selected_macsec_priv->fm_macsec = fm_macsec_config(&macsec_params); ++ if (unlikely(selected_macsec_priv->fm_macsec == NULL)) ++ return -EINVAL; ++ ++ if (mdata->config_unknown_sci_treatment) { ++ rv = fm_macsec_config_unknown_sci_frame_treatment( ++ selected_macsec_priv->fm_macsec, ++ mdata->unknown_sci_treatment); ++ if (unlikely(rv < 0)) ++ goto _return_fm_macsec_free; ++ } ++ ++ if (mdata->config_invalid_tag_treatment) { ++ rv = fm_macsec_config_invalid_tags_frame_treatment( ++ selected_macsec_priv->fm_macsec, ++ mdata->deliver_uncontrolled); ++ if (unlikely(rv < 0)) ++ goto _return_fm_macsec_free; ++ } ++ ++ if (mdata->config_kay_frame_treatment) { ++ rv = fm_macsec_config_kay_frame_treatment( ++ selected_macsec_priv->fm_macsec, ++ mdata->discard_uncontrolled); ++ if (unlikely(rv < 0)) ++ goto _return_fm_macsec_free; ++ } ++ ++ if (mdata->config_untag_treatment) { ++ rv = fm_macsec_config_untag_frame_treatment( ++ selected_macsec_priv->fm_macsec, ++ mdata->untag_treatment); ++ if (unlikely(rv < 0)) ++ goto _return_fm_macsec_free; ++ } ++ ++ if (mdata->config_pn_exhaustion_threshold) { ++ rv = fm_macsec_config_pn_exhaustion_threshold( ++ selected_macsec_priv->fm_macsec, ++ mdata->pn_threshold); ++ if (unlikely(rv < 0)) ++ goto _return_fm_macsec_free; ++ } ++ ++ if (mdata->config_keys_unreadable) { ++ rv = fm_macsec_config_keys_unreadable( ++ selected_macsec_priv->fm_macsec); ++ if (unlikely(rv < 0)) ++ goto _return_fm_macsec_free; ++ } ++ ++ if (mdata->config_sectag_without_sci) { ++ rv = fm_macsec_config_sectag_without_sci( ++ selected_macsec_priv->fm_macsec); ++ if (unlikely(rv < 0)) ++ goto _return_fm_macsec_free; ++ } ++ ++ if (mdata->config_exception) { ++ rv = fm_macsec_config_exception(selected_macsec_priv->fm_macsec, ++ mdata->exception, ++ mdata->enable_exception); ++ if (unlikely(rv < 0)) ++ goto _return_fm_macsec_free; ++ } ++ ++ rv = fm_macsec_init(selected_macsec_priv->fm_macsec); ++ if (unlikely(rv < 0)) ++ goto _return_fm_macsec_free; ++ ++ rv = fm_macsec_enable(selected_macsec_priv->fm_macsec); ++ if (unlikely(rv < 0)) ++ goto _return_fm_macsec_free; ++ ++ return macsec_id; ++ ++_return_fm_macsec_free: ++ fm_macsec_free(selected_macsec_priv->fm_macsec); ++ selected_macsec_priv->fm_macsec = NULL; ++ return rv; ++} ++ ++static int send_result(struct nlmsghdr *nlh, int pid, int result) ++{ ++ int res; ++ struct sk_buff *skb_out; ++ size_t msg_size = sizeof(result); ++ ++ skb_out = nlmsg_new(msg_size, 0); ++ if (unlikely(!skb_out)) { ++ pr_err("Failed to allocate new skb\n"); ++ goto _ret_err; ++ } ++ ++ nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, msg_size, 0); ++ if (unlikely(!nlh)) { ++ pr_err("Failed to send\n"); ++ goto _ret_err; ++ } ++ ++ NETLINK_CB(skb_out).dst_group = 0; /* not in mcast group */ ++ memcpy(nlmsg_data(nlh), &result, msg_size); ++ ++ res = nlmsg_unicast(nl_sk, skb_out, pid); ++ if (unlikely(res < 0)) { ++ pr_err("Error while sending back to user\n"); ++ goto _ret_err; ++ } ++ ++ return 0; ++ ++_ret_err: ++ return -1; ++} ++ ++/* Kernel communicates with user space through netlink sockets. This function ++ * implements the responses of the kernel. The generic struct is used for ++ * easier handling of the code, which otherwise would have been duplicated. ++ */ ++static void switch_messages(struct sk_buff *skb) ++{ ++ struct nlmsghdr *nlh; ++ int pid, rv; ++ enum msg_type cmd; ++ ++ struct dpa_fq *dpa_fq, *tmp; ++ struct device *dev; ++ ++ struct dpaa_eth_hooks_s macsec_dpaa_eth_hooks; ++ ++ struct generic_msg *check; ++ int macsec_id = 0; ++ uint32_t sc_id, macsec_revision; ++ macsec_an_t ret_an; ++ int i; ++ ++ pr_debug("Entering: %s\n", __func__); ++ ++ if (unlikely(!skb)) { ++ pr_err("skb null\n"); ++ return; ++ } ++ ++ nlh = (struct nlmsghdr *)skb->data; ++ check = kmalloc(sizeof(*check), GFP_KERNEL); ++ memcpy(check, nlmsg_data(nlh), sizeof(*check)); ++ pid = nlh->nlmsg_pid; /*pid of sending process */ ++ cmd = check->chf; ++ ++ switch (cmd) { ++ case ENABLE_MACSEC: ++ pr_debug("ENABLE_MACSEC\n"); ++ ++ macsec_id = enable_macsec(check); ++ ++ if (macsec_id >= 0) ++ macsec_priv[macsec_id]->en_state = MACSEC_ENABLED; ++ ++ rv = send_result(nlh, pid, (macsec_id < 0) ? NACK : macsec_id); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case SET_EXCEPTION: ++ pr_debug("SET_EXCEPTION\n"); ++ ++ rv = set_macsec_exception(check); ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case ENABLE_SECY: ++ pr_debug("ENABLE_SECY\n"); ++ ++ rv = enable_secy(check, &macsec_id); ++ ++ if (rv == 0) ++ macsec_priv[macsec_id]->en_state = SECY_ENABLED; ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case GET_REVISION: ++ pr_debug("GET_REVISION\n"); ++ ++ rv = get_macsec_revision(check, &macsec_revision); ++ ++ rv = send_result(nlh, pid, ++ (rv < 0) ? NACK : (int)macsec_revision); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case GET_TXSC_PHYS_ID: ++ pr_debug("GET_TXSC_PHYS_ID\n"); ++ ++ rv = get_tx_sc_phys_id(check, &sc_id); ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : (int)sc_id); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case TX_SA_CREATE: ++ pr_debug("TX_SA_CREATE\n"); ++ ++ rv = create_tx_sa(check); ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case MODIFY_TXSA_KEY: ++ pr_debug("MODIFY_TXSA_KEY\n"); ++ ++ rv = modify_tx_sa_key(check); ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case TX_SA_ACTIVATE: ++ pr_debug("TX_SA_ACTIVATE\n"); ++ ++ rv = activate_tx_sa(check); ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case GET_TXSA_AN: ++ pr_debug("GET_TXSA_AN\n"); ++ ++ rv = get_tx_sa_an(check, &ret_an); ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : (int)ret_an); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case RX_SC_CREATE: ++ pr_debug("RX_SC_CREATE\n"); ++ ++ sc_id = create_rx_sc(check); ++ ++ rv = send_result(nlh, pid, (sc_id < 0) ? NACK : (int)sc_id); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case GET_RXSC_PHYS_ID: ++ pr_debug("GET_RXSC_PHYS_ID\n"); ++ ++ rv = get_rx_sc_phys_id(check, &sc_id); ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : (int)sc_id); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case RX_SA_CREATE: ++ pr_debug("RX_SA_CREATE\n"); ++ ++ rv = create_rx_sa(check); ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case MODIFY_RXSA_KEY: ++ pr_debug("MODIFY_RXSA_KEY\n"); ++ ++ rv = modify_rx_sa_key(check); ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case UPDATE_NPN: ++ pr_debug("UPDATE_NPN\n"); ++ ++ rv = update_npn(check); ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case UPDATE_LPN: ++ pr_debug("UPDATE_LPN\n"); ++ ++ rv = update_lpn(check); ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case RX_SA_ACTIVATE: ++ pr_debug("RX_SA_ACTIVATE\n"); ++ ++ rv = activate_rx_sa(check); ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case RX_SA_DISABLE: ++ pr_debug("RX_SA_DISABLE\n"); ++ ++ rv = rx_sa_disable(check); ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case RX_SA_DELETE: ++ pr_debug("RX_SA_DELETE\n"); ++ ++ rv = rx_sa_delete(check); ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case RX_SC_DELETE: ++ pr_debug("RX_SC_DELETE\n"); ++ ++ rv = rx_sc_delete(check); ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case TX_SA_DELETE: ++ pr_debug("TX_SA_DELETE\n"); ++ ++ rv = tx_sa_delete(check); ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case DISABLE_SECY: ++ pr_debug("DISABLE_SECY\n"); ++ ++ rv = disable_secy(check, &macsec_id); ++ ++ if (unlikely(rv < 0)) ++ macsec_priv[macsec_id]->en_state = SECY_ENABLED; ++ else ++ macsec_priv[macsec_id]->en_state = MACSEC_ENABLED; ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case DISABLE_MACSEC: ++ pr_debug("DISABLE_MACSEC\n"); ++ ++ rv = disable_macsec(check, &macsec_id); ++ ++ macsec_priv[macsec_id]->en_state = MACSEC_DISABLED; ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ ++ break; ++ ++ case DISABLE_ALL: ++ pr_debug("DISABLE_ALL\n"); ++ ++ rv = disable_all(check, &macsec_id); ++ ++ macsec_priv[macsec_id]->en_state = MACSEC_DISABLED; ++ ++ rv = send_result(nlh, pid, (rv < 0) ? NACK : ACK); ++ if (unlikely(rv < 0)) ++ goto _release; ++ break; ++ ++ default: ++ /* should never get here */ ++ pr_err("not a state\n"); ++ break; ++ } ++ ++ return; ++ ++_release: ++ for (i = 0; i < FM_MAX_NUM_OF_MACS; i++) ++ deinit_macsec(i); ++ ++ /* Reset the TX hooks */ ++ memset(&macsec_dpaa_eth_hooks, 0, sizeof(macsec_dpaa_eth_hooks)); ++ fsl_dpaa_eth_set_hooks(&macsec_dpaa_eth_hooks); ++ ++#ifdef CONFIG_FSL_DPAA_MACSEC_DEBUGFS ++ for (i = 0; i < macsec_ifs_cnt; i++) ++ remove_debugfs(i); ++#endif /* CONFIG_FSL_DPAA_MACSEC_DEBUGFS */ ++ for (i = 0; i < FM_MAX_NUM_OF_MACS; i++) { ++ ++ if (!macsec_priv[i]->net_dev) ++ continue; ++ ++ free_percpu(macsec_priv[i]->percpu_priv); ++ ++ /* Delete the fman queues */ ++ list_for_each_entry_safe(dpa_fq, ++ tmp, ++ &macsec_priv[i]->dpa_fq_list, ++ list) { ++ dev = dpa_fq->net_dev->dev.parent; ++ rv = _dpa_fq_free(dev, (struct qman_fq *)dpa_fq); ++ if (unlikely(rv < 0)) ++ pr_err("_dpa_fq_fre=%d\n", rv); ++ } ++ ++ kfree(macsec_priv[i]); ++ macsec_priv[i] = NULL; ++ } ++ ++ kfree(check); ++ ++ netlink_kernel_release(nl_sk); ++} ++ ++struct netlink_kernel_cfg ms_cfg = { ++ .groups = 1, ++ .input = switch_messages, ++}; ++ ++static int __init macsec_init(void) ++{ ++ struct dpaa_eth_hooks_s macsec_dpaa_eth_hooks; ++ int ret, i; ++ ++ pr_debug("Entering: %s\n", __func__); ++ ++ /* If there is no interface we want macsec on, just exit. */ ++ parse_ifs(); ++ for (i = 0; i < macsec_ifs_cnt; i++) { ++ if (!macsec_ifs[i]) { ++ pr_err("Interface unknown\n"); ++ return -EINVAL; ++ } ++ } ++ ++#ifdef CONFIG_FSL_DPAA_MACSEC_DEBUGFS ++ macsec_debugfs_module_init(); ++#endif /* CONFIG_FSL_DPAA_MACSEC_DEBUGFS */ ++ ++ /* Actually send the info to the user through a given socket. */ ++ nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, &ms_cfg); ++ if (unlikely(!nl_sk)) { ++ pr_err("Error creating socket.\n"); ++ ret = -ENOMEM; ++ goto _release; ++ } ++ ++ ret = macsec_setup(); ++ if (unlikely(ret != 0)) { ++ pr_err("Setup of macsec failed\n"); ++ goto _release; ++ } ++ ++ /* set dpaa hooks for default queues */ ++ memset(&macsec_dpaa_eth_hooks, 0, sizeof(macsec_dpaa_eth_hooks)); ++ macsec_dpaa_eth_hooks.tx = (dpaa_eth_egress_hook_t)(macsec_tx_hook); ++ macsec_dpaa_eth_hooks.rx_default = ++ (dpaa_eth_ingress_hook_t)(macsec_rx_hook); ++ ++ fsl_dpaa_eth_set_hooks(&macsec_dpaa_eth_hooks); ++ ++ return 0; ++ ++_release: ++ memset(&macsec_dpaa_eth_hooks, 0, sizeof(macsec_dpaa_eth_hooks)); ++ fsl_dpaa_eth_set_hooks(&macsec_dpaa_eth_hooks); ++ netlink_kernel_release(nl_sk); ++ return ret; ++} ++ ++static void __exit macsec_exit(void) ++{ ++ int _errno; ++ struct dpa_fq *dpa_fq, *tmp; ++ struct device *dev; ++ struct dpaa_eth_hooks_s macsec_dpaa_eth_hooks; ++ int i; ++ ++ pr_debug("exiting macsec module\n"); ++ ++ for (i = 0; i < FM_MAX_NUM_OF_MACS; i++) { ++ /* release has already been done, due to errors, ++ * in switch_messages we will return to exit the module properly ++ */ ++ if (!macsec_priv[i]->net_dev) { ++ pr_debug("no release needed\n"); ++ continue; ++ } ++ deinit_macsec(i); ++ } ++ ++ /* Reset the TX hooks before exiting */ ++ memset(&macsec_dpaa_eth_hooks, 0, sizeof(macsec_dpaa_eth_hooks)); ++ fsl_dpaa_eth_set_hooks(&macsec_dpaa_eth_hooks); ++ ++#ifdef CONFIG_FSL_DPAA_MACSEC_DEBUGFS ++ for (i = 0; i < macsec_ifs_cnt; i++) ++ remove_debugfs(i); ++ ++ macsec_debugfs_module_exit(); ++#endif /* CONFIG_FSL_DPAA_MACSEC_DEBUGFS */ ++ ++ for (i = 0; i < FM_MAX_NUM_OF_MACS; i++) { ++ ++ if (!macsec_priv[i]->net_dev) { ++ pr_debug("no release needed\n"); ++ continue; ++ } ++ ++ free_percpu(macsec_priv[i]->percpu_priv); ++ ++ /* Delete the fman queues */ ++ list_for_each_entry_safe(dpa_fq, tmp, ++ &macsec_priv[i]->dpa_fq_list, list) { ++ if (dpa_fq) { ++ dev = dpa_fq->net_dev->dev.parent; ++ _errno = _dpa_fq_free(dev, ++ (struct qman_fq *)dpa_fq); ++ if (unlikely(_errno < 0)) ++ pr_err("_dpa_fq_fre=%d\n", _errno); ++ } ++ } ++ ++ kfree(macsec_priv[i]); ++ } ++ ++ netlink_kernel_release(nl_sk); ++ ++ pr_debug("exited macsec module\n"); ++} ++ ++module_init(macsec_init); ++module_exit(macsec_exit); ++ ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.h +new file mode 100644 +index 0000000..b7a8795 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.h +@@ -0,0 +1,287 @@ ++/* 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 __DPAA_ETH_MACSEC_H ++#define __DPAA_ETH_MACSEC_H ++ ++#include "mac.h" ++ ++#define NETLINK_USER 31 ++#define MAX_NUM_OF_SECY 1 ++#define MAX_LEN 100 ++#define FM_FD_STAT_RX_MACSEC 0x00800000 ++#define MACSEC_ETH_TX_QUEUES NR_CPUS ++#define MACSEC_REG_OFFSET 0x800 ++#define ACK 0 ++#define NACK -1 ++ ++extern const struct dpa_fq_cbs_t private_fq_cbs; ++ ++enum msg_type {ENABLE_MACSEC, ++ SET_EXCEPTION, ++ ENABLE_SECY, ++ TX_SA_CREATE, ++ TX_SA_ACTIVATE, ++ RX_SC_CREATE, ++ RX_SA_CREATE, ++ RX_SA_ACTIVATE, ++ RX_SA_DISABLE, ++ RX_SA_DELETE, ++ RX_SC_DELETE, ++ TX_SA_DELETE, ++ DISABLE_MACSEC, ++ DISABLE_SECY, ++ DISABLE_ALL, ++ GET_REVISION, ++ UPDATE_NPN, ++ UPDATE_LPN, ++ GET_TXSC_PHYS_ID, ++ GET_RXSC_PHYS_ID, ++ GET_TXSA_AN, ++ MODIFY_TXSA_KEY, ++ MODIFY_RXSA_KEY, ++}; ++ ++enum macsec_enablement {MACSEC_DISABLED, MACSEC_ENABLED, SECY_ENABLED}; ++ ++struct enable_secy { ++ int macsec_id; ++ ++ u64 sci; /* MAC address(48b) + port_id(16b) */ ++ ++ bool config_insertion_mode; ++ fm_macsec_sci_insertion_mode sci_insertion_mode; ++ ++ bool config_protect_frames; ++ bool protect_frames; ++ ++ bool config_replay_window; ++ bool replay_protect; ++ uint32_t replay_window; ++ ++ bool config_validation_mode; ++ fm_macsec_valid_frame_behavior validate_frames; ++ ++ bool config_confidentiality; ++ bool confidentiality_enable; ++ uint32_t confidentiality_offset; ++ ++ bool config_point_to_point; ++ ++ bool config_exception; ++ bool enable_exception; ++ fm_macsec_secy_exception exception; ++ ++ bool config_event; ++ bool enable_event; ++ fm_macsec_secy_event event; ++}; ++ ++struct macsec_data { ++ char *if_name; ++ size_t if_name_length; /* including string terminator */ ++ ++ bool config_unknown_sci_treatment; ++ fm_macsec_unknown_sci_frame_treatment unknown_sci_treatment; ++ ++ bool config_invalid_tag_treatment; ++ bool deliver_uncontrolled; ++ ++ bool config_kay_frame_treatment; ++ bool discard_uncontrolled; ++ ++ bool config_untag_treatment; ++ fm_macsec_untag_frame_treatment untag_treatment; ++ ++ bool config_pn_exhaustion_threshold; ++ uint32_t pn_threshold; ++ ++ bool config_keys_unreadable; ++ ++ bool config_sectag_without_sci; ++ ++ bool config_exception; ++ bool enable_exception; ++ fm_macsec_exception exception; ++}; ++ ++struct set_exception { ++ int macsec_id; ++ bool enable_exception; ++ fm_macsec_exception exception; ++}; ++ ++struct create_tx_sa { ++ int macsec_id; ++ u8 an; /* association number */ ++ u8 *sak; /* secure assoc key */ ++ u32 sak_len; /* assoc key length */ ++}; ++ ++struct modify_tx_sa_key { ++ int macsec_id; ++ u8 an; /* association number */ ++ u8 *sak; /* secure assoc key */ ++ u32 sak_len; /* assoc key length */ ++}; ++ ++struct activate_tx_sa { ++ int macsec_id; ++ u8 an; /* association number */ ++}; ++ ++struct create_rx_sc { ++ int macsec_id; ++ u64 sci; ++}; ++ ++struct delete_rx_sc { ++ int macsec_id; ++ u32 rx_sc_id; ++}; ++ ++struct get_rx_sc_id { ++ int macsec_id; ++ u32 rx_sc_id; ++}; ++ ++struct create_rx_sa { ++ int macsec_id; ++ u32 rx_sc_id; ++ u8 an; ++ u32 lpn; ++ u8 *sak; ++ u32 sak_len; ++}; ++ ++struct activate_rx_sa { ++ int macsec_id; ++ u32 rx_sc_id; ++ u8 an; ++}; ++ ++struct disable_rx_sa { ++ int macsec_id; ++ u32 rx_sc_id; ++ u8 an; ++}; ++ ++struct delete_rx_sa { ++ int macsec_id; ++ u32 rx_sc_id; ++ u8 an; ++}; ++ ++struct delete_tx_sa { ++ int macsec_id; ++ u32 rx_sc_id; ++ u8 an; ++}; ++ ++struct update_npn { ++ int macsec_id; ++ u32 rx_sc_id; ++ u8 an; ++ u32 pn; ++}; ++ ++struct update_lpn { ++ int macsec_id; ++ u32 rx_sc_id; ++ u8 an; ++ u32 pn; ++}; ++ ++struct modify_rx_sa_key { ++ int macsec_id; ++ u32 rx_sc_id; ++ u8 an; ++ u8 *sak; ++ u32 sak_len; ++}; ++ ++struct generic_msg { ++ enum msg_type chf; ++ union { ++ int macsec_id; ++ struct macsec_data en_macsec; ++ struct enable_secy secy; ++ struct create_tx_sa c_tx_sa; ++ struct activate_tx_sa a_tx_sa; ++ struct create_rx_sc c_rx_sc; ++ struct get_rx_sc_id get_rx_sc_id; ++ struct create_rx_sa c_rx_sa; ++ struct activate_rx_sa a_rx_sa; ++ struct disable_rx_sa d_rx_sa; ++ struct delete_rx_sa del_rx_sa; ++ struct delete_rx_sc del_rx_sc; ++ struct delete_tx_sa del_tx_sa; ++ struct update_npn update_npn; ++ struct update_lpn update_lpn; ++ struct modify_tx_sa_key modify_tx_sa_key; ++ struct modify_rx_sa_key modify_rx_sa_key; ++ struct set_exception set_ex; ++ } payload; ++}; ++ ++struct macsec_percpu_priv_s { ++ u64 rx_macsec; ++ u64 tx_macsec; ++}; ++ ++struct macsec_priv_s { ++ struct macsec_percpu_priv_s __percpu *percpu_priv; ++ ++ struct net_device *net_dev; ++ struct mac_device *mac_dev; ++ ++ struct qman_fq *egress_fqs[MACSEC_ETH_TX_QUEUES]; ++ struct qman_fq *conf_fqs[MACSEC_ETH_TX_QUEUES]; ++ struct list_head dpa_fq_list; ++#ifdef CONFIG_FSL_DPAA_MACSEC_DEBUGFS ++ struct dentry *debugfs_file; ++#endif /* CONFIG_FSL_DPAA_MACSEC_DEBUGFS */ ++ uint32_t msg_enable; /* net_device message level */ ++ uint16_t channel; ++ struct fm_macsec_dev *fm_macsec; ++ ++ struct fm_macsec_secy_dev *fm_ms_secy; ++ uint8_t an; ++ ++ struct rx_sc_dev *rx_sc_dev[NUM_OF_RX_SC]; ++ uint8_t *sa_key; ++ enum macsec_enablement en_state; ++ ++ uintptr_t vaddr; ++ struct resource *fman_resource; ++}; ++ ++#endif /* __DPAA_ETH_MACSEC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_proxy.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_proxy.c +new file mode 100644 +index 0000000..bc8f5f7 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_proxy.c +@@ -0,0 +1,372 @@ ++/* Copyright 2008-2013 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. ++ */ ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUG ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++#else ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": " fmt ++#endif ++ ++#include ++#include ++#include ++#include "dpaa_eth.h" ++#include "dpaa_eth_common.h" ++#include "dpaa_eth_base.h" ++#include "lnxwrp_fsl_fman.h" /* fm_get_rx_extra_headroom(), fm_get_max_frm() */ ++#include "mac.h" ++ ++#define DPA_DESCRIPTION "FSL DPAA Proxy initialization driver" ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++MODULE_DESCRIPTION(DPA_DESCRIPTION); ++ ++static int __cold dpa_eth_proxy_remove(struct platform_device *of_dev); ++#ifdef CONFIG_PM ++ ++static int proxy_suspend(struct device *dev) ++{ ++ struct proxy_device *proxy_dev = dev_get_drvdata(dev); ++ struct mac_device *mac_dev = proxy_dev->mac_dev; ++ int err = 0; ++ ++ err = fm_port_suspend(mac_dev->port_dev[RX]); ++ if (err) ++ goto port_suspend_failed; ++ ++ err = fm_port_suspend(mac_dev->port_dev[TX]); ++ if (err) ++ err = fm_port_resume(mac_dev->port_dev[RX]); ++ ++port_suspend_failed: ++ return err; ++} ++ ++static int proxy_resume(struct device *dev) ++{ ++ struct proxy_device *proxy_dev = dev_get_drvdata(dev); ++ struct mac_device *mac_dev = proxy_dev->mac_dev; ++ int err = 0; ++ ++ err = fm_port_resume(mac_dev->port_dev[TX]); ++ if (err) ++ goto port_resume_failed; ++ ++ err = fm_port_resume(mac_dev->port_dev[RX]); ++ if (err) ++ err = fm_port_suspend(mac_dev->port_dev[TX]); ++ ++port_resume_failed: ++ return err; ++} ++ ++static const struct dev_pm_ops proxy_pm_ops = { ++ .suspend = proxy_suspend, ++ .resume = proxy_resume, ++}; ++ ++#define PROXY_PM_OPS (&proxy_pm_ops) ++ ++#else /* CONFIG_PM */ ++ ++#define PROXY_PM_OPS NULL ++ ++#endif /* CONFIG_PM */ ++ ++static int dpaa_eth_proxy_probe(struct platform_device *_of_dev) ++{ ++ int err = 0, i; ++ struct device *dev; ++ struct device_node *dpa_node; ++ struct dpa_bp *dpa_bp; ++ struct list_head proxy_fq_list; ++ size_t count; ++ struct fm_port_fqs port_fqs; ++ struct dpa_buffer_layout_s *buf_layout = NULL; ++ struct mac_device *mac_dev; ++ struct proxy_device *proxy_dev; ++ ++ dev = &_of_dev->dev; ++ ++ dpa_node = dev->of_node; ++ ++ if (!of_device_is_available(dpa_node)) ++ return -ENODEV; ++ ++ /* Get the buffer pools assigned to this interface */ ++ dpa_bp = dpa_bp_probe(_of_dev, &count); ++ if (IS_ERR(dpa_bp)) ++ return PTR_ERR(dpa_bp); ++ ++ mac_dev = dpa_mac_probe(_of_dev); ++ if (IS_ERR(mac_dev)) ++ return PTR_ERR(mac_dev); ++ ++ proxy_dev = devm_kzalloc(dev, sizeof(*proxy_dev), GFP_KERNEL); ++ if (!proxy_dev) { ++ dev_err(dev, "devm_kzalloc() failed\n"); ++ return -ENOMEM; ++ } ++ ++ proxy_dev->mac_dev = mac_dev; ++ dev_set_drvdata(dev, proxy_dev); ++ ++ /* We have physical ports, so we need to establish ++ * the buffer layout. ++ */ ++ buf_layout = devm_kzalloc(dev, 2 * sizeof(*buf_layout), ++ GFP_KERNEL); ++ if (!buf_layout) { ++ dev_err(dev, "devm_kzalloc() failed\n"); ++ return -ENOMEM; ++ } ++ dpa_set_buffers_layout(mac_dev, buf_layout); ++ ++ INIT_LIST_HEAD(&proxy_fq_list); ++ ++ memset(&port_fqs, 0, sizeof(port_fqs)); ++ ++ err = dpa_fq_probe_mac(dev, &proxy_fq_list, &port_fqs, true, RX); ++ if (!err) ++ err = dpa_fq_probe_mac(dev, &proxy_fq_list, &port_fqs, true, ++ TX); ++ if (err < 0) { ++ devm_kfree(dev, buf_layout); ++ return err; ++ } ++ ++ /* Proxy initializer - Just configures the MAC on behalf of ++ * another partition. ++ */ ++ dpaa_eth_init_ports(mac_dev, dpa_bp, count, &port_fqs, ++ buf_layout, dev); ++ ++ /* Proxy interfaces need to be started, and the allocated ++ * memory freed ++ */ ++ devm_kfree(dev, buf_layout); ++ devm_kfree(dev, dpa_bp); ++ ++ /* Free FQ structures */ ++ devm_kfree(dev, port_fqs.rx_defq); ++ devm_kfree(dev, port_fqs.rx_errq); ++ devm_kfree(dev, port_fqs.tx_defq); ++ devm_kfree(dev, port_fqs.tx_errq); ++ ++ for_each_port_device(i, mac_dev->port_dev) { ++ err = fm_port_enable(mac_dev->port_dev[i]); ++ if (err) ++ goto port_enable_fail; ++ } ++ ++ dev_info(dev, "probed MAC device with MAC address: %02hx:%02hx:%02hx:%02hx:%02hx:%02hx\n", ++ mac_dev->addr[0], mac_dev->addr[1], mac_dev->addr[2], ++ mac_dev->addr[3], mac_dev->addr[4], mac_dev->addr[5]); ++ ++ return 0; /* Proxy interface initialization ended */ ++ ++port_enable_fail: ++ for_each_port_device(i, mac_dev->port_dev) ++ fm_port_disable(mac_dev->port_dev[i]); ++ dpa_eth_proxy_remove(_of_dev); ++ ++ return err; ++} ++ ++int dpa_proxy_set_mac_address(struct proxy_device *proxy_dev, ++ struct net_device *net_dev) ++{ ++ struct mac_device *mac_dev; ++ int _errno; ++ ++ mac_dev = proxy_dev->mac_dev; ++ ++ _errno = mac_dev->change_addr(mac_dev->get_mac_handle(mac_dev), ++ net_dev->dev_addr); ++ if (_errno < 0) ++ return _errno; ++ ++ return 0; ++} ++EXPORT_SYMBOL(dpa_proxy_set_mac_address); ++ ++int dpa_proxy_set_rx_mode(struct proxy_device *proxy_dev, ++ struct net_device *net_dev) ++{ ++ struct mac_device *mac_dev = proxy_dev->mac_dev; ++ int _errno; ++ ++ _errno = mac_dev->set_multi(net_dev, mac_dev); ++ if (unlikely(_errno < 0)) ++ return _errno; ++ ++ return 0; ++} ++EXPORT_SYMBOL(dpa_proxy_set_rx_mode); ++ ++int dpa_proxy_start(struct net_device *net_dev) ++{ ++ struct mac_device *mac_dev; ++ const struct dpa_priv_s *priv; ++ struct proxy_device *proxy_dev; ++ int _errno; ++ int i; ++ ++ priv = netdev_priv(net_dev); ++ proxy_dev = (struct proxy_device *)priv->peer; ++ mac_dev = proxy_dev->mac_dev; ++ ++ _errno = mac_dev->init_phy(net_dev, mac_dev); ++ if (_errno < 0) { ++ if (netif_msg_drv(priv)) ++ netdev_err(net_dev, "init_phy() = %d\n", ++ _errno); ++ return _errno; ++ } ++ ++ for_each_port_device(i, mac_dev->port_dev) { ++ _errno = fm_port_enable(mac_dev->port_dev[i]); ++ if (_errno) ++ goto port_enable_fail; ++ } ++ ++ _errno = mac_dev->start(mac_dev); ++ if (_errno < 0) { ++ if (netif_msg_drv(priv)) ++ netdev_err(net_dev, "mac_dev->start() = %d\n", ++ _errno); ++ goto port_enable_fail; ++ } ++ ++ return _errno; ++ ++port_enable_fail: ++ for_each_port_device(i, mac_dev->port_dev) ++ fm_port_disable(mac_dev->port_dev[i]); ++ ++ return _errno; ++} ++EXPORT_SYMBOL(dpa_proxy_start); ++ ++int dpa_proxy_stop(struct proxy_device *proxy_dev, struct net_device *net_dev) ++{ ++ struct mac_device *mac_dev = proxy_dev->mac_dev; ++ const struct dpa_priv_s *priv = netdev_priv(net_dev); ++ int _errno, i, err; ++ ++ _errno = mac_dev->stop(mac_dev); ++ if (_errno < 0) { ++ if (netif_msg_drv(priv)) ++ netdev_err(net_dev, "mac_dev->stop() = %d\n", ++ _errno); ++ return _errno; ++ } ++ ++ for_each_port_device(i, mac_dev->port_dev) { ++ err = fm_port_disable(mac_dev->port_dev[i]); ++ _errno = err ? err : _errno; ++ } ++ ++ if (mac_dev->phy_dev) ++ phy_disconnect(mac_dev->phy_dev); ++ mac_dev->phy_dev = NULL; ++ ++ return _errno; ++} ++EXPORT_SYMBOL(dpa_proxy_stop); ++ ++static int __cold dpa_eth_proxy_remove(struct platform_device *of_dev) ++{ ++ struct device *dev = &of_dev->dev; ++ struct proxy_device *proxy_dev = dev_get_drvdata(dev); ++ ++ kfree(proxy_dev); ++ ++ dev_set_drvdata(dev, NULL); ++ ++ return 0; ++} ++ ++static const struct of_device_id dpa_proxy_match[] = { ++ { ++ .compatible = "fsl,dpa-ethernet-init" ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, dpa_proxy_match); ++ ++static struct platform_driver dpa_proxy_driver = { ++ .driver = { ++ .name = KBUILD_MODNAME "-proxy", ++ .of_match_table = dpa_proxy_match, ++ .owner = THIS_MODULE, ++ .pm = PROXY_PM_OPS, ++ }, ++ .probe = dpaa_eth_proxy_probe, ++ .remove = dpa_eth_proxy_remove ++}; ++ ++static int __init __cold dpa_proxy_load(void) ++{ ++ int _errno; ++ ++ pr_info(DPA_DESCRIPTION " (" VERSION ")\n"); ++ ++ /* Initialize dpaa_eth mirror values */ ++ dpa_rx_extra_headroom = fm_get_rx_extra_headroom(); ++ dpa_max_frm = fm_get_max_frm(); ++ ++ _errno = platform_driver_register(&dpa_proxy_driver); ++ if (unlikely(_errno < 0)) { ++ pr_err(KBUILD_MODNAME ++ ": %s:%hu:%s(): platform_driver_register() = %d\n", ++ KBUILD_BASENAME".c", __LINE__, __func__, _errno); ++ } ++ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ return _errno; ++} ++module_init(dpa_proxy_load); ++ ++static void __exit __cold dpa_proxy_unload(void) ++{ ++ platform_driver_unregister(&dpa_proxy_driver); ++ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++} ++module_exit(dpa_proxy_unload); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +new file mode 100644 +index 0000000..1da4f73 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +@@ -0,0 +1,976 @@ ++/* Copyright 2012 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. ++ */ ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUG ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++#else ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": " fmt ++#endif ++ ++#include ++#include ++#include ++#include ++ ++#include "dpaa_eth.h" ++#include "dpaa_eth_common.h" ++#ifdef CONFIG_FSL_DPAA_1588 ++#include "dpaa_1588.h" ++#endif ++ ++/* DMA map and add a page frag back into the bpool. ++ * @vaddr fragment must have been allocated with netdev_alloc_frag(), ++ * specifically for fitting into @dpa_bp. ++ */ ++static void dpa_bp_recycle_frag(struct dpa_bp *dpa_bp, unsigned long vaddr, ++ int *count_ptr) ++{ ++ struct bm_buffer bmb; ++ dma_addr_t addr; ++ ++ addr = dma_map_single(dpa_bp->dev, (void *)vaddr, dpa_bp->size, ++ DMA_BIDIRECTIONAL); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { ++ dev_err(dpa_bp->dev, "DMA mapping failed"); ++ return; ++ } ++ ++ bm_buffer_set64(&bmb, addr); ++ ++ while (bman_release(dpa_bp->pool, &bmb, 1, 0)) ++ cpu_relax(); ++ ++ (*count_ptr)++; ++} ++ ++static int _dpa_bp_add_8_bufs(const struct dpa_bp *dpa_bp) ++{ ++ struct bm_buffer bmb[8]; ++ void *new_buf; ++ dma_addr_t addr; ++ uint8_t i; ++ struct device *dev = dpa_bp->dev; ++ struct sk_buff *skb, **skbh; ++ ++ memset(bmb, 0, sizeof(struct bm_buffer) * 8); ++ ++ for (i = 0; i < 8; i++) { ++ /* We'll prepend the skb back-pointer; can't use the DPA ++ * priv space, because FMan will overwrite it (from offset 0) ++ * if it ends up being the second, third, etc. fragment ++ * in a S/G frame. ++ * ++ * We only need enough space to store a pointer, but allocate ++ * an entire cacheline for performance reasons. ++ */ ++ new_buf = netdev_alloc_frag(SMP_CACHE_BYTES + DPA_BP_RAW_SIZE); ++ if (unlikely(!new_buf)) ++ goto netdev_alloc_failed; ++ new_buf = PTR_ALIGN(new_buf + SMP_CACHE_BYTES, SMP_CACHE_BYTES); ++ ++ skb = build_skb(new_buf, DPA_SKB_SIZE(dpa_bp->size) + ++ SKB_DATA_ALIGN(sizeof(struct skb_shared_info))); ++ if (unlikely(!skb)) { ++ put_page(virt_to_head_page(new_buf)); ++ goto build_skb_failed; ++ } ++ DPA_WRITE_SKB_PTR(skb, skbh, new_buf, -1); ++ ++ addr = dma_map_single(dev, new_buf, ++ dpa_bp->size, DMA_BIDIRECTIONAL); ++ if (unlikely(dma_mapping_error(dev, addr))) ++ goto dma_map_failed; ++ ++ bm_buffer_set64(&bmb[i], addr); ++ } ++ ++release_bufs: ++ /* Release the buffers. In case bman is busy, keep trying ++ * until successful. bman_release() is guaranteed to succeed ++ * in a reasonable amount of time ++ */ ++ while (unlikely(bman_release(dpa_bp->pool, bmb, i, 0))) ++ cpu_relax(); ++ return i; ++ ++dma_map_failed: ++ kfree_skb(skb); ++ ++build_skb_failed: ++netdev_alloc_failed: ++ net_err_ratelimited("dpa_bp_add_8_bufs() failed\n"); ++ WARN_ONCE(1, "Memory allocation failure on Rx\n"); ++ ++ bm_buffer_set64(&bmb[i], 0); ++ /* Avoid releasing a completely null buffer; bman_release() requires ++ * at least one buffer. ++ */ ++ if (likely(i)) ++ goto release_bufs; ++ ++ return 0; ++} ++ ++/* Cold path wrapper over _dpa_bp_add_8_bufs(). */ ++static void dpa_bp_add_8_bufs(const struct dpa_bp *dpa_bp, int cpu) ++{ ++ int *count_ptr = per_cpu_ptr(dpa_bp->percpu_count, cpu); ++ *count_ptr += _dpa_bp_add_8_bufs(dpa_bp); ++} ++ ++int dpa_bp_priv_seed(struct dpa_bp *dpa_bp) ++{ ++ int i; ++ ++ /* Give each CPU an allotment of "config_count" buffers */ ++ for_each_possible_cpu(i) { ++ int j; ++ ++ /* Although we access another CPU's counters here ++ * we do it at boot time so it is safe ++ */ ++ for (j = 0; j < dpa_bp->config_count; j += 8) ++ dpa_bp_add_8_bufs(dpa_bp, i); ++ } ++ return 0; ++} ++EXPORT_SYMBOL(dpa_bp_priv_seed); ++ ++/* Add buffers/(pages) for Rx processing whenever bpool count falls below ++ * REFILL_THRESHOLD. ++ */ ++int dpaa_eth_refill_bpools(struct dpa_bp *dpa_bp, int *countptr) ++{ ++ int count = *countptr; ++ int new_bufs; ++ ++ if (unlikely(count < CONFIG_FSL_DPAA_ETH_REFILL_THRESHOLD)) { ++ do { ++ new_bufs = _dpa_bp_add_8_bufs(dpa_bp); ++ if (unlikely(!new_bufs)) { ++ /* Avoid looping forever if we've temporarily ++ * run out of memory. We'll try again at the ++ * next NAPI cycle. ++ */ ++ break; ++ } ++ count += new_bufs; ++ } while (count < CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT); ++ ++ *countptr = count; ++ if (unlikely(count < CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT)) ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(dpaa_eth_refill_bpools); ++ ++/* Cleanup function for outgoing frame descriptors that were built on Tx path, ++ * either contiguous frames or scatter/gather ones. ++ * Skb freeing is not handled here. ++ * ++ * This function may be called on error paths in the Tx function, so guard ++ * against cases when not all fd relevant fields were filled in. ++ * ++ * Return the skb backpointer, since for S/G frames the buffer containing it ++ * gets freed here. ++ */ ++struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv, ++ const struct qm_fd *fd) ++{ ++ const struct qm_sg_entry *sgt; ++ int i; ++ struct dpa_bp *dpa_bp = priv->dpa_bp; ++ dma_addr_t addr = qm_fd_addr(fd); ++ dma_addr_t sg_addr; ++ struct sk_buff **skbh; ++ struct sk_buff *skb = NULL; ++ const enum dma_data_direction dma_dir = DMA_TO_DEVICE; ++ int nr_frags; ++ ++ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, dma_dir); ++ ++ /* retrieve skb back pointer */ ++ DPA_READ_SKB_PTR(skb, skbh, phys_to_virt(addr), 0); ++ nr_frags = skb_shinfo(skb)->nr_frags; ++ ++ if (fd->format == qm_fd_sg) { ++ /* The sgt buffer has been allocated with netdev_alloc_frag(), ++ * it's from lowmem. ++ */ ++ sgt = phys_to_virt(addr + dpa_fd_offset(fd)); ++#ifdef CONFIG_FSL_DPAA_1588 ++ if (priv->tsu && priv->tsu->valid && ++ priv->tsu->hwts_tx_en_ioctl) ++ dpa_ptp_store_txstamp(priv, skb, (void *)skbh); ++#endif ++#ifdef CONFIG_FSL_DPAA_TS ++ if (unlikely(priv->ts_tx_en && ++ skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { ++ struct skb_shared_hwtstamps shhwtstamps; ++ ++ dpa_get_ts(priv, TX, &shhwtstamps, (void *)skbh); ++ skb_tstamp_tx(skb, &shhwtstamps); ++ } ++#endif /* CONFIG_FSL_DPAA_TS */ ++ ++ /* sgt[0] is from lowmem, was dma_map_single()-ed */ ++ /* TODO: sg_addr should be in CPU endianess */ ++ sg_addr = qm_sg_addr(&sgt[0]); ++ dma_unmap_single(dpa_bp->dev, sg_addr, ++ be32_to_cpu(sgt[0].length), dma_dir); ++ ++ /* remaining pages were mapped with dma_map_page() */ ++ for (i = 1; i < nr_frags; i++) { ++ DPA_BUG_ON(sgt[i].extension); ++ /* TODO: sg_addr should be in CPU endianess */ ++ sg_addr = qm_sg_addr(&sgt[i]); ++ dma_unmap_page(dpa_bp->dev, sg_addr, ++ be32_to_cpu(sgt[i].length), dma_dir); ++ } ++ ++ /* Free the page frag that we allocated on Tx */ ++ put_page(virt_to_head_page(sgt)); ++ } ++#ifdef CONFIG_FSL_DPAA_TS ++ else { ++ /* get the timestamp for non-SG frames */ ++#ifdef CONFIG_FSL_DPAA_1588 ++ if (priv->tsu && priv->tsu->valid && ++ priv->tsu->hwts_tx_en_ioctl) ++ dpa_ptp_store_txstamp(priv, skb, (void *)skbh); ++#endif ++ if (unlikely(priv->ts_tx_en && ++ skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { ++ struct skb_shared_hwtstamps shhwtstamps; ++ ++ dpa_get_ts(priv, TX, &shhwtstamps, (void *)skbh); ++ skb_tstamp_tx(skb, &shhwtstamps); ++ } ++ } ++#endif ++ ++ return skb; ++} ++EXPORT_SYMBOL(_dpa_cleanup_tx_fd); ++ ++#ifndef CONFIG_FSL_DPAA_TS ++bool dpa_skb_is_recyclable(struct sk_buff *skb) ++{ ++ /* No recycling possible if skb buffer is kmalloc'ed */ ++ if (skb->head_frag == 0) ++ return false; ++ ++ /* or if it's an userspace buffer */ ++ if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) ++ return false; ++ ++ /* or if it's cloned or shared */ ++ if (skb_shared(skb) || skb_cloned(skb) || ++ skb->fclone != SKB_FCLONE_UNAVAILABLE) ++ return false; ++ ++ return true; ++} ++EXPORT_SYMBOL(dpa_skb_is_recyclable); ++ ++bool dpa_buf_is_recyclable(struct sk_buff *skb, ++ uint32_t min_size, ++ uint16_t min_offset, ++ unsigned char **new_buf_start) ++{ ++ unsigned char *new; ++ ++ /* In order to recycle a buffer, the following conditions must be met: ++ * - buffer size no less than the buffer pool size ++ * - buffer size no higher than an upper limit (to avoid moving too much ++ * system memory to the buffer pools) ++ * - buffer address aligned to cacheline bytes ++ * - offset of data from start of buffer no lower than a minimum value ++ * - offset of data from start of buffer no higher than a maximum value ++ */ ++ new = min(skb_end_pointer(skb) - min_size, skb->data - min_offset); ++ ++ /* left align to the nearest cacheline */ ++ new = (unsigned char *)((unsigned long)new & ~(SMP_CACHE_BYTES - 1)); ++ ++ if (likely(new >= skb->head && ++ new >= (skb->data - DPA_MAX_FD_OFFSET) && ++ skb_end_pointer(skb) - new <= DPA_RECYCLE_MAX_SIZE)) { ++ *new_buf_start = new; ++ return true; ++ } ++ ++ return false; ++} ++EXPORT_SYMBOL(dpa_buf_is_recyclable); ++#endif ++ ++/* Build a linear skb around the received buffer. ++ * We are guaranteed there is enough room at the end of the data buffer to ++ * accommodate the shared info area of the skb. ++ */ ++static struct sk_buff *__hot contig_fd_to_skb(const struct dpa_priv_s *priv, ++ const struct qm_fd *fd, int *use_gro) ++{ ++ dma_addr_t addr = qm_fd_addr(fd); ++ ssize_t fd_off = dpa_fd_offset(fd); ++ void *vaddr; ++ const fm_prs_result_t *parse_results; ++ struct sk_buff *skb = NULL, **skbh; ++ ++ vaddr = phys_to_virt(addr); ++ DPA_BUG_ON(!IS_ALIGNED((unsigned long)vaddr, SMP_CACHE_BYTES)); ++ ++ /* Retrieve the skb and adjust data and tail pointers, to make sure ++ * forwarded skbs will have enough space on Tx if extra headers ++ * are added. ++ */ ++ DPA_READ_SKB_PTR(skb, skbh, vaddr, -1); ++ ++#ifdef CONFIG_FSL_DPAA_ETH_JUMBO_FRAME ++ /* When using jumbo Rx buffers, we risk having frames dropped due to ++ * the socket backlog reaching its maximum allowed size. ++ * Use the frame length for the skb truesize instead of the buffer ++ * size, as this is the size of the data that actually gets copied to ++ * userspace. ++ */ ++ skb->truesize = SKB_TRUESIZE(dpa_fd_length(fd)); ++#endif ++ ++ DPA_BUG_ON(fd_off != priv->rx_headroom); ++ skb_reserve(skb, fd_off); ++ skb_put(skb, dpa_fd_length(fd)); ++ ++ /* Peek at the parse results for csum validation */ ++ parse_results = (const fm_prs_result_t *)(vaddr + ++ DPA_RX_PRIV_DATA_SIZE); ++ _dpa_process_parse_results(parse_results, fd, skb, use_gro); ++ ++#ifdef CONFIG_FSL_DPAA_1588 ++ if (priv->tsu && priv->tsu->valid && priv->tsu->hwts_rx_en_ioctl) ++ dpa_ptp_store_rxstamp(priv, skb, vaddr); ++#endif ++#ifdef CONFIG_FSL_DPAA_TS ++ if (priv->ts_rx_en) ++ dpa_get_ts(priv, RX, skb_hwtstamps(skb), vaddr); ++#endif /* CONFIG_FSL_DPAA_TS */ ++ ++ return skb; ++} ++ ++ ++/* Build an skb with the data of the first S/G entry in the linear portion and ++ * the rest of the frame as skb fragments. ++ * ++ * The page fragment holding the S/G Table is recycled here. ++ */ ++static struct sk_buff *__hot sg_fd_to_skb(const struct dpa_priv_s *priv, ++ const struct qm_fd *fd, int *use_gro, ++ int *count_ptr) ++{ ++ const struct qm_sg_entry *sgt; ++ dma_addr_t addr = qm_fd_addr(fd); ++ ssize_t fd_off = dpa_fd_offset(fd); ++ dma_addr_t sg_addr; ++ void *vaddr, *sg_vaddr; ++ struct dpa_bp *dpa_bp; ++ struct page *page, *head_page; ++ int frag_offset, frag_len; ++ int page_offset; ++ int i; ++ const fm_prs_result_t *parse_results; ++ struct sk_buff *skb = NULL, *skb_tmp, **skbh; ++ ++ vaddr = phys_to_virt(addr); ++ DPA_BUG_ON(!IS_ALIGNED((unsigned long)vaddr, SMP_CACHE_BYTES)); ++ ++ dpa_bp = priv->dpa_bp; ++ /* Iterate through the SGT entries and add data buffers to the skb */ ++ sgt = vaddr + fd_off; ++ for (i = 0; i < DPA_SGT_MAX_ENTRIES; i++) { ++ /* Extension bit is not supported */ ++ DPA_BUG_ON(sgt[i].extension); ++ ++ /* We use a single global Rx pool */ ++ DPA_BUG_ON(dpa_bp != dpa_bpid2pool(sgt[i].bpid)); ++ ++ /* TODO: sg_addr should be in CPU endianess */ ++ sg_addr = qm_sg_addr(&sgt[i]); ++ sg_vaddr = phys_to_virt(sg_addr); ++ DPA_BUG_ON(!IS_ALIGNED((unsigned long)sg_vaddr, ++ SMP_CACHE_BYTES)); ++ ++ dma_unmap_single(dpa_bp->dev, sg_addr, dpa_bp->size, ++ DMA_BIDIRECTIONAL); ++ if (i == 0) { ++ DPA_READ_SKB_PTR(skb, skbh, sg_vaddr, -1); ++ DPA_BUG_ON(skb->head != sg_vaddr); ++#ifdef CONFIG_FSL_DPAA_1588 ++ if (priv->tsu && priv->tsu->valid && ++ priv->tsu->hwts_rx_en_ioctl) ++ dpa_ptp_store_rxstamp(priv, skb, vaddr); ++#endif ++#ifdef CONFIG_FSL_DPAA_TS ++ if (priv->ts_rx_en) ++ dpa_get_ts(priv, RX, skb_hwtstamps(skb), vaddr); ++#endif /* CONFIG_FSL_DPAA_TS */ ++ ++ /* In the case of a SG frame, FMan stores the Internal ++ * Context in the buffer containing the sgt. ++ * Inspect the parse results before anything else. ++ */ ++ parse_results = (const fm_prs_result_t *)(vaddr + ++ DPA_RX_PRIV_DATA_SIZE); ++ _dpa_process_parse_results(parse_results, fd, skb, ++ use_gro); ++ ++ /* Make sure forwarded skbs will have enough space ++ * on Tx, if extra headers are added. ++ */ ++ DPA_BUG_ON(fd_off != priv->rx_headroom); ++ skb_reserve(skb, fd_off); ++ skb_put(skb, be32_to_cpu(sgt[i].length)); ++ } else { ++ /* Not the first S/G entry; all data from buffer will ++ * be added in an skb fragment; fragment index is offset ++ * by one since first S/G entry was incorporated in the ++ * linear part of the skb. ++ * ++ * Caution: 'page' may be a tail page. ++ */ ++ DPA_READ_SKB_PTR(skb_tmp, skbh, sg_vaddr, -1); ++ page = virt_to_page(sg_vaddr); ++ head_page = virt_to_head_page(sg_vaddr); ++ ++ /* Free (only) the skbuff shell because its data buffer ++ * is already a frag in the main skb. ++ */ ++ get_page(head_page); ++ dev_kfree_skb(skb_tmp); ++ ++ /* Compute offset in (possibly tail) page */ ++ page_offset = ((unsigned long)sg_vaddr & ++ (PAGE_SIZE - 1)) + ++ (page_address(page) - page_address(head_page)); ++ /* page_offset only refers to the beginning of sgt[i]; ++ * but the buffer itself may have an internal offset. ++ */ ++ frag_offset = be16_to_cpu(sgt[i].offset) + page_offset; ++ frag_len = be32_to_cpu(sgt[i].length); ++ /* skb_add_rx_frag() does no checking on the page; if ++ * we pass it a tail page, we'll end up with ++ * bad page accounting and eventually with segafults. ++ */ ++ skb_add_rx_frag(skb, i - 1, head_page, frag_offset, ++ frag_len, dpa_bp->size); ++ } ++ /* Update the pool count for the current {cpu x bpool} */ ++ (*count_ptr)--; ++ ++ if (sgt[i].final) ++ break; ++ } ++ WARN_ONCE(i == DPA_SGT_MAX_ENTRIES, "No final bit on SGT\n"); ++ ++ /* recycle the SGT fragment */ ++ DPA_BUG_ON(dpa_bp != dpa_bpid2pool(fd->bpid)); ++ dpa_bp_recycle_frag(dpa_bp, (unsigned long)vaddr, count_ptr); ++ return skb; ++} ++ ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP ++static inline int dpa_skb_loop(const struct dpa_priv_s *priv, ++ struct sk_buff *skb) ++{ ++ if (unlikely(priv->loop_to < 0)) ++ return 0; /* loop disabled by default */ ++ ++ skb_push(skb, ETH_HLEN); /* compensate for eth_type_trans */ ++ dpa_tx(skb, dpa_loop_netdevs[priv->loop_to]); ++ ++ return 1; /* Frame Tx on the selected interface */ ++} ++#endif ++ ++void __hot _dpa_rx(struct net_device *net_dev, ++ struct qman_portal *portal, ++ const struct dpa_priv_s *priv, ++ struct dpa_percpu_priv_s *percpu_priv, ++ const struct qm_fd *fd, ++ u32 fqid, ++ int *count_ptr) ++{ ++ struct dpa_bp *dpa_bp; ++ struct sk_buff *skb; ++ dma_addr_t addr = qm_fd_addr(fd); ++ u32 fd_status = fd->status; ++ unsigned int skb_len; ++ struct rtnl_link_stats64 *percpu_stats = &percpu_priv->stats; ++ int use_gro = net_dev->features & NETIF_F_GRO; ++ ++ if (unlikely(fd_status & FM_FD_STAT_RX_ERRORS) != 0) { ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_warn(net_dev, "FD status = 0x%08x\n", ++ fd_status & FM_FD_STAT_RX_ERRORS); ++ ++ percpu_stats->rx_errors++; ++ goto _release_frame; ++ } ++ ++ dpa_bp = priv->dpa_bp; ++ DPA_BUG_ON(dpa_bp != dpa_bpid2pool(fd->bpid)); ++ ++ /* prefetch the first 64 bytes of the frame or the SGT start */ ++ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, DMA_BIDIRECTIONAL); ++ prefetch(phys_to_virt(addr) + dpa_fd_offset(fd)); ++ ++ /* The only FD types that we may receive are contig and S/G */ ++ DPA_BUG_ON((fd->format != qm_fd_contig) && (fd->format != qm_fd_sg)); ++ ++ if (likely(fd->format == qm_fd_contig)) { ++#ifdef CONFIG_FSL_DPAA_HOOKS ++ /* Execute the Rx processing hook, if it exists. */ ++ if (dpaa_eth_hooks.rx_default && ++ dpaa_eth_hooks.rx_default((void *)fd, net_dev, ++ fqid) == DPAA_ETH_STOLEN) { ++ /* won't count the rx bytes in */ ++ return; ++ } ++#endif ++ skb = contig_fd_to_skb(priv, fd, &use_gro); ++ } else ++ skb = sg_fd_to_skb(priv, fd, &use_gro, count_ptr); ++ ++ /* Account for either the contig buffer or the SGT buffer (depending on ++ * which case we were in) having been removed from the pool. ++ */ ++ (*count_ptr)--; ++ skb->protocol = eth_type_trans(skb, net_dev); ++ ++ /* IP Reassembled frames are allowed to be larger than MTU */ ++ if (unlikely(dpa_check_rx_mtu(skb, net_dev->mtu) && ++ !(fd_status & FM_FD_IPR))) { ++ percpu_stats->rx_dropped++; ++ goto drop_bad_frame; ++ } ++ ++ skb_len = skb->len; ++ ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP ++ if (dpa_skb_loop(priv, skb)) { ++ percpu_stats->rx_packets++; ++ percpu_stats->rx_bytes += skb_len; ++ return; ++ } ++#endif ++ ++ if (use_gro) { ++ gro_result_t gro_result; ++ const struct qman_portal_config *pc = ++ qman_p_get_portal_config(portal); ++ struct dpa_napi_portal *np = &percpu_priv->np[pc->index]; ++ ++ np->p = portal; ++ gro_result = napi_gro_receive(&np->napi, skb); ++ /* If frame is dropped by the stack, rx_dropped counter is ++ * incremented automatically, so no need for us to update it ++ */ ++ if (unlikely(gro_result == GRO_DROP)) ++ goto packet_dropped; ++ } else if (unlikely(netif_receive_skb(skb) == NET_RX_DROP)) ++ goto packet_dropped; ++ ++ percpu_stats->rx_packets++; ++ percpu_stats->rx_bytes += skb_len; ++ ++packet_dropped: ++ return; ++ ++drop_bad_frame: ++ dev_kfree_skb(skb); ++ return; ++ ++_release_frame: ++ dpa_fd_release(net_dev, fd); ++} ++ ++int __hot skb_to_contig_fd(struct dpa_priv_s *priv, ++ struct sk_buff *skb, struct qm_fd *fd, ++ int *count_ptr, int *offset) ++{ ++ struct sk_buff **skbh; ++ dma_addr_t addr; ++ struct dpa_bp *dpa_bp = priv->dpa_bp; ++ struct net_device *net_dev = priv->net_dev; ++ int err; ++ enum dma_data_direction dma_dir; ++ unsigned char *buffer_start; ++ ++#ifndef CONFIG_FSL_DPAA_TS ++ /* Check recycling conditions; only if timestamp support is not ++ * enabled, otherwise we need the fd back on tx confirmation ++ */ ++ ++ /* We can recycle the buffer if: ++ * - the pool is not full ++ * - the buffer meets the skb recycling conditions ++ * - the buffer meets our own (size, offset, align) conditions ++ */ ++ if (likely((*count_ptr < dpa_bp->target_count) && ++ dpa_skb_is_recyclable(skb) && ++ dpa_buf_is_recyclable(skb, dpa_bp->size, ++ priv->tx_headroom, &buffer_start))) { ++ /* Buffer is recyclable; use the new start address ++ * and set fd parameters and DMA mapping direction ++ */ ++ fd->bpid = dpa_bp->bpid; ++ DPA_BUG_ON(skb->data - buffer_start > DPA_MAX_FD_OFFSET); ++ fd->offset = (uint16_t)(skb->data - buffer_start); ++ dma_dir = DMA_BIDIRECTIONAL; ++ ++ DPA_WRITE_SKB_PTR(skb, skbh, buffer_start, -1); ++ *offset = skb_headroom(skb) - fd->offset; ++ } else ++#endif ++ { ++ /* Not recyclable. ++ * We are guaranteed to have at least tx_headroom bytes ++ * available, so just use that for offset. ++ */ ++ fd->bpid = 0xff; ++ buffer_start = skb->data - priv->tx_headroom; ++ fd->offset = priv->tx_headroom; ++ dma_dir = DMA_TO_DEVICE; ++ ++ /* The buffer will be Tx-confirmed, but the TxConf cb must ++ * necessarily look at our Tx private data to retrieve the ++ * skbuff. (In short: can't use DPA_WRITE_SKB_PTR() here.) ++ */ ++ DPA_WRITE_SKB_PTR(skb, skbh, buffer_start, 0); ++ } ++ ++ /* Enable L3/L4 hardware checksum computation. ++ * ++ * We must do this before dma_map_single(DMA_TO_DEVICE), because we may ++ * need to write into the skb. ++ */ ++ err = dpa_enable_tx_csum(priv, skb, fd, ++ ((char *)skbh) + DPA_TX_PRIV_DATA_SIZE); ++ if (unlikely(err < 0)) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, "HW csum error: %d\n", err); ++ return err; ++ } ++ ++ /* Fill in the rest of the FD fields */ ++ fd->format = qm_fd_contig; ++ fd->length20 = skb->len; ++ fd->cmd |= FM_FD_CMD_FCO; ++ ++ /* Map the entire buffer size that may be seen by FMan, but no more */ ++ addr = dma_map_single(dpa_bp->dev, skbh, ++ skb_end_pointer(skb) - buffer_start, dma_dir); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, "dma_map_single() failed\n"); ++ return -EINVAL; ++ } ++ fd->addr = addr; ++ ++ ++ return 0; ++} ++EXPORT_SYMBOL(skb_to_contig_fd); ++ ++int __hot skb_to_sg_fd(struct dpa_priv_s *priv, ++ struct sk_buff *skb, struct qm_fd *fd) ++{ ++ struct dpa_bp *dpa_bp = priv->dpa_bp; ++ dma_addr_t addr; ++ struct sk_buff **skbh; ++ struct net_device *net_dev = priv->net_dev; ++ int err; ++ ++ struct qm_sg_entry *sgt; ++ void *sgt_buf; ++ void *buffer_start; ++ skb_frag_t *frag; ++ int i, j; ++ const enum dma_data_direction dma_dir = DMA_TO_DEVICE; ++ const int nr_frags = skb_shinfo(skb)->nr_frags; ++ ++ fd->format = qm_fd_sg; ++ ++ /* get a page frag to store the SGTable */ ++ sgt_buf = netdev_alloc_frag(priv->tx_headroom + ++ sizeof(struct qm_sg_entry) * (1 + nr_frags)); ++ if (unlikely(!sgt_buf)) { ++ dev_err(dpa_bp->dev, "netdev_alloc_frag() failed\n"); ++ return -ENOMEM; ++ } ++ ++ /* Enable L3/L4 hardware checksum computation. ++ * ++ * We must do this before dma_map_single(DMA_TO_DEVICE), because we may ++ * need to write into the skb. ++ */ ++ err = dpa_enable_tx_csum(priv, skb, fd, ++ sgt_buf + DPA_TX_PRIV_DATA_SIZE); ++ if (unlikely(err < 0)) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, "HW csum error: %d\n", err); ++ goto csum_failed; ++ } ++ ++ sgt = (struct qm_sg_entry *)(sgt_buf + priv->tx_headroom); ++ sgt[0].bpid = 0xff; ++ sgt[0].offset = 0; ++ sgt[0].length = cpu_to_be32(skb_headlen(skb)); ++ sgt[0].extension = 0; ++ sgt[0].final = 0; ++ addr = dma_map_single(dpa_bp->dev, skb->data, sgt[0].length, dma_dir); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { ++ dev_err(dpa_bp->dev, "DMA mapping failed"); ++ err = -EINVAL; ++ goto sg0_map_failed; ++ ++ } ++ sgt[0].addr_hi = (uint8_t)upper_32_bits(addr); ++ sgt[0].addr_lo = cpu_to_be32(lower_32_bits(addr)); ++ ++ /* populate the rest of SGT entries */ ++ for (i = 1; i <= nr_frags; i++) { ++ frag = &skb_shinfo(skb)->frags[i - 1]; ++ sgt[i].bpid = 0xff; ++ sgt[i].offset = 0; ++ sgt[i].length = cpu_to_be32(frag->size); ++ sgt[i].extension = 0; ++ sgt[i].final = 0; ++ ++ DPA_BUG_ON(!skb_frag_page(frag)); ++ addr = skb_frag_dma_map(dpa_bp->dev, frag, 0, sgt[i].length, ++ dma_dir); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { ++ dev_err(dpa_bp->dev, "DMA mapping failed"); ++ err = -EINVAL; ++ goto sg_map_failed; ++ } ++ ++ /* keep the offset in the address */ ++ sgt[i].addr_hi = (uint8_t)upper_32_bits(addr); ++ sgt[i].addr_lo = cpu_to_be32(lower_32_bits(addr)); ++ } ++ sgt[i - 1].final = 1; ++ ++ fd->length20 = skb->len; ++ fd->offset = priv->tx_headroom; ++ ++ /* DMA map the SGT page */ ++ buffer_start = (void *)sgt - dpa_fd_offset(fd); ++ /* Can't write at "negative" offset in buffer_start, because this skb ++ * may not have been allocated by us. ++ */ ++ DPA_WRITE_SKB_PTR(skb, skbh, buffer_start, 0); ++ ++ addr = dma_map_single(dpa_bp->dev, buffer_start, ++ skb_end_pointer(skb) - (unsigned char *)buffer_start, dma_dir); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { ++ dev_err(dpa_bp->dev, "DMA mapping failed"); ++ err = -EINVAL; ++ goto sgt_map_failed; ++ } ++ ++ fd->bpid = 0xff; ++ fd->cmd |= FM_FD_CMD_FCO; ++ fd->addr_hi = (uint8_t)upper_32_bits(addr); ++ fd->addr_lo = lower_32_bits(addr); ++ ++ return 0; ++ ++sgt_map_failed: ++sg_map_failed: ++ for (j = 0; j < i; j++) ++ dma_unmap_page(dpa_bp->dev, qm_sg_addr(&sgt[j]), ++ be32_to_cpu(sgt[j].length), dma_dir); ++sg0_map_failed: ++csum_failed: ++ put_page(virt_to_head_page(sgt_buf)); ++ ++ return err; ++} ++EXPORT_SYMBOL(skb_to_sg_fd); ++ ++int __hot dpa_tx(struct sk_buff *skb, struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv; ++ const int queue_mapping = dpa_get_queue_mapping(skb); ++ struct qman_fq *egress_fq, *conf_fq; ++ ++#ifdef CONFIG_FSL_DPAA_HOOKS ++ /* If there is a Tx hook, run it. */ ++ if (dpaa_eth_hooks.tx && ++ dpaa_eth_hooks.tx(skb, net_dev) == DPAA_ETH_STOLEN) ++ /* won't update any Tx stats */ ++ return NETDEV_TX_OK; ++#endif ++ ++ priv = netdev_priv(net_dev); ++ egress_fq = priv->egress_fqs[queue_mapping]; ++ conf_fq = priv->conf_fqs[queue_mapping]; ++ ++ return dpa_tx_extended(skb, net_dev, egress_fq, conf_fq); ++} ++ ++int __hot dpa_tx_extended(struct sk_buff *skb, struct net_device *net_dev, ++ struct qman_fq *egress_fq, struct qman_fq *conf_fq) ++{ ++ struct dpa_priv_s *priv; ++ struct qm_fd fd; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct rtnl_link_stats64 *percpu_stats; ++ int err = 0; ++ const bool nonlinear = skb_is_nonlinear(skb); ++ int *countptr, offset = 0; ++ ++ priv = netdev_priv(net_dev); ++ /* Non-migratable context, safe to use raw_cpu_ptr */ ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ percpu_stats = &percpu_priv->stats; ++ countptr = raw_cpu_ptr(priv->dpa_bp->percpu_count); ++ ++ clear_fd(&fd); ++ ++#ifdef CONFIG_FSL_DPAA_1588 ++ if (priv->tsu && priv->tsu->valid && priv->tsu->hwts_tx_en_ioctl) ++ fd.cmd |= FM_FD_CMD_UPD; ++#endif ++#ifdef CONFIG_FSL_DPAA_TS ++ if (unlikely(priv->ts_tx_en && ++ skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) ++ fd.cmd |= FM_FD_CMD_UPD; ++ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; ++#endif /* CONFIG_FSL_DPAA_TS */ ++ ++ /* MAX_SKB_FRAGS is larger than our DPA_SGT_MAX_ENTRIES; make sure ++ * we don't feed FMan with more fragments than it supports. ++ * Btw, we're using the first sgt entry to store the linear part of ++ * the skb, so we're one extra frag short. ++ */ ++ if (nonlinear && ++ likely(skb_shinfo(skb)->nr_frags < DPA_SGT_MAX_ENTRIES)) { ++ /* Just create a S/G fd based on the skb */ ++ err = skb_to_sg_fd(priv, skb, &fd); ++ percpu_priv->tx_frag_skbuffs++; ++ } else { ++ /* Make sure we have enough headroom to accommodate private ++ * data, parse results, etc. Normally this shouldn't happen if ++ * we're here via the standard kernel stack. ++ */ ++ if (unlikely(skb_headroom(skb) < priv->tx_headroom)) { ++ struct sk_buff *skb_new; ++ ++ skb_new = skb_realloc_headroom(skb, priv->tx_headroom); ++ if (unlikely(!skb_new)) { ++ dev_kfree_skb(skb); ++ percpu_stats->tx_errors++; ++ return NETDEV_TX_OK; ++ } ++ dev_kfree_skb(skb); ++ skb = skb_new; ++ } ++ ++ /* We're going to store the skb backpointer at the beginning ++ * of the data buffer, so we need a privately owned skb ++ */ ++ ++ /* Code borrowed from skb_unshare(). */ ++ if (skb_cloned(skb)) { ++ struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC); ++ kfree_skb(skb); ++ skb = nskb; ++ /* skb_copy() has now linearized the skbuff. */ ++ } else if (unlikely(nonlinear)) { ++ /* We are here because the egress skb contains ++ * more fragments than we support. In this case, ++ * we have no choice but to linearize it ourselves. ++ */ ++ err = __skb_linearize(skb); ++ } ++ if (unlikely(!skb || err < 0)) ++ /* Common out-of-memory error path */ ++ goto enomem; ++ ++ /* Finally, create a contig FD from this skb */ ++ err = skb_to_contig_fd(priv, skb, &fd, countptr, &offset); ++ } ++ if (unlikely(err < 0)) ++ goto skb_to_fd_failed; ++ ++ if (fd.bpid != 0xff) { ++ skb_recycle(skb); ++ /* skb_recycle() reserves NET_SKB_PAD as skb headroom, ++ * but we need the skb to look as if returned by build_skb(). ++ * We need to manually adjust the tailptr as well. ++ */ ++ skb->data = skb->head + offset; ++ skb_reset_tail_pointer(skb); ++ ++ (*countptr)++; ++ percpu_priv->tx_returned++; ++ } ++ ++ if (unlikely(dpa_xmit(priv, percpu_stats, &fd, egress_fq, conf_fq) < 0)) ++ goto xmit_failed; ++ ++ net_dev->trans_start = jiffies; ++ return NETDEV_TX_OK; ++ ++xmit_failed: ++ if (fd.bpid != 0xff) { ++ (*countptr)--; ++ percpu_priv->tx_returned--; ++ dpa_fd_release(net_dev, &fd); ++ percpu_stats->tx_errors++; ++ return NETDEV_TX_OK; ++ } ++ _dpa_cleanup_tx_fd(priv, &fd); ++skb_to_fd_failed: ++enomem: ++ percpu_stats->tx_errors++; ++ dev_kfree_skb(skb); ++ return NETDEV_TX_OK; ++} ++EXPORT_SYMBOL(dpa_tx_extended); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_shared.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_shared.c +new file mode 100644 +index 0000000..987b9dc +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_shared.c +@@ -0,0 +1,910 @@ ++/* Copyright 2008-2013 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. ++ */ ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUG ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++#else ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": " fmt ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "dpaa_eth.h" ++#include "dpaa_eth_common.h" ++#include "dpaa_eth_base.h" ++#include "lnxwrp_fsl_fman.h" /* fm_get_rx_extra_headroom(), fm_get_max_frm() */ ++#include "mac.h" ++ ++/* forward declarations */ ++static enum qman_cb_dqrr_result __hot ++shared_rx_dqrr(struct qman_portal *portal, struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq); ++static enum qman_cb_dqrr_result __hot ++shared_tx_default_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq); ++static enum qman_cb_dqrr_result ++shared_tx_error_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq); ++static void shared_ern(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_mr_entry *msg); ++ ++#define DPA_DESCRIPTION "FSL DPAA Shared Ethernet driver" ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++MODULE_DESCRIPTION(DPA_DESCRIPTION); ++ ++/* This has to work in tandem with the DPA_CS_THRESHOLD_xxx values. */ ++static uint16_t shared_tx_timeout = 1000; ++module_param(shared_tx_timeout, ushort, S_IRUGO); ++MODULE_PARM_DESC(shared_tx_timeout, "The Tx timeout in ms"); ++ ++static const struct of_device_id dpa_shared_match[]; ++ ++static const struct net_device_ops dpa_shared_ops = { ++ .ndo_open = dpa_start, ++ .ndo_start_xmit = dpa_shared_tx, ++ .ndo_stop = dpa_stop, ++ .ndo_tx_timeout = dpa_timeout, ++ .ndo_get_stats64 = dpa_get_stats64, ++ .ndo_set_mac_address = dpa_set_mac_address, ++ .ndo_validate_addr = eth_validate_addr, ++#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE ++ .ndo_select_queue = dpa_select_queue, ++#endif ++ .ndo_change_mtu = dpa_change_mtu, ++ .ndo_set_rx_mode = dpa_set_rx_mode, ++ .ndo_init = dpa_ndo_init, ++ .ndo_set_features = dpa_set_features, ++ .ndo_fix_features = dpa_fix_features, ++ .ndo_do_ioctl = dpa_ioctl, ++}; ++ ++const struct dpa_fq_cbs_t shared_fq_cbs = { ++ .rx_defq = { .cb = { .dqrr = shared_rx_dqrr } }, ++ .tx_defq = { .cb = { .dqrr = shared_tx_default_dqrr } }, ++ .rx_errq = { .cb = { .dqrr = shared_rx_dqrr } }, ++ .tx_errq = { .cb = { .dqrr = shared_tx_error_dqrr } }, ++ .egress_ern = { .cb = { .ern = shared_ern } } ++}; ++EXPORT_SYMBOL(shared_fq_cbs); ++ ++static inline void * __must_check __attribute__((nonnull)) ++dpa_phys2virt(const struct dpa_bp *dpa_bp, dma_addr_t addr) ++{ ++ return dpa_bp->vaddr + (addr - dpa_bp->paddr); ++} ++ ++static struct dpa_bp *dpa_size2pool(struct dpa_priv_s *priv, size_t size) ++{ ++ int i; ++ ++ for (i = 0; i < priv->bp_count; i++) ++ if ((size + priv->tx_headroom) <= priv->dpa_bp[i].size) ++ return dpa_bpid2pool(priv->dpa_bp[i].bpid); ++ return ERR_PTR(-ENODEV); ++} ++ ++/* Copy to a memory region that requires kmapping from a linear buffer, ++ * taking into account page boundaries in the destination ++ */ ++static void ++copy_to_unmapped_area(dma_addr_t phys_start, void *src, size_t buf_size) ++{ ++ struct page *page; ++ size_t size, offset; ++ void *page_vaddr; ++ ++ while (buf_size > 0) { ++ offset = offset_in_page(phys_start); ++ size = (offset + buf_size > PAGE_SIZE) ? ++ PAGE_SIZE - offset : buf_size; ++ ++ page = pfn_to_page(phys_start >> PAGE_SHIFT); ++ page_vaddr = kmap_atomic(page); ++ ++ memcpy(page_vaddr + offset, src, size); ++ ++ kunmap_atomic(page_vaddr); ++ ++ phys_start += size; ++ src += size; ++ buf_size -= size; ++ } ++} ++ ++/* Copy from a memory region that requires kmapping to a linear buffer, ++ * taking into account page boundaries in the source ++ */ ++static void ++copy_from_unmapped_area(void *dest, dma_addr_t phys_start, size_t buf_size) ++{ ++ struct page *page; ++ size_t size, offset; ++ void *page_vaddr; ++ ++ while (buf_size > 0) { ++ offset = offset_in_page(phys_start); ++ size = (offset + buf_size > PAGE_SIZE) ? ++ PAGE_SIZE - offset : buf_size; ++ ++ page = pfn_to_page(phys_start >> PAGE_SHIFT); ++ page_vaddr = kmap_atomic(page); ++ ++ memcpy(dest, page_vaddr + offset, size); ++ ++ kunmap_atomic(page_vaddr); ++ ++ phys_start += size; ++ dest += size; ++ buf_size -= size; ++ } ++} ++ ++static void ++dpa_fd_release_sg(const struct net_device *net_dev, ++ const struct qm_fd *fd) ++{ ++ const struct dpa_priv_s *priv; ++ struct qm_sg_entry *sgt; ++ struct dpa_bp *_dpa_bp; ++ struct bm_buffer _bmb; ++ ++ priv = netdev_priv(net_dev); ++ ++ _bmb.hi = fd->addr_hi; ++ _bmb.lo = fd->addr_lo; ++ ++ _dpa_bp = dpa_bpid2pool(fd->bpid); ++ BUG_ON(!_dpa_bp); ++ ++ if (_dpa_bp->vaddr) { ++ sgt = dpa_phys2virt(_dpa_bp, bm_buf_addr(&_bmb)) + ++ dpa_fd_offset(fd); ++ dpa_release_sgt(sgt); ++ } else { ++ sgt = kmalloc(DPA_SGT_MAX_ENTRIES * sizeof(*sgt), GFP_ATOMIC); ++ if (sgt == NULL) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, ++ "Memory allocation failed\n"); ++ return; ++ } ++ ++ copy_from_unmapped_area(sgt, bm_buf_addr(&_bmb) + ++ dpa_fd_offset(fd), ++ min(DPA_SGT_MAX_ENTRIES * sizeof(*sgt), ++ _dpa_bp->size)); ++ dpa_release_sgt(sgt); ++ kfree(sgt); ++ } ++ ++ while (bman_release(_dpa_bp->pool, &_bmb, 1, 0)) ++ cpu_relax(); ++} ++ ++static enum qman_cb_dqrr_result __hot ++shared_rx_dqrr(struct qman_portal *portal, struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ const struct qm_fd *fd = &dq->fd; ++ struct dpa_bp *dpa_bp; ++ struct sk_buff *skb; ++ struct qm_sg_entry *sgt; ++ int i; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ ++ dpa_bp = dpa_bpid2pool(fd->bpid); ++ BUG_ON(!dpa_bp); ++ ++ if (unlikely(fd->status & FM_FD_STAT_RX_ERRORS) != 0) { ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_warn(net_dev, "FD status = 0x%08x\n", ++ fd->status & FM_FD_STAT_RX_ERRORS); ++ ++ percpu_priv->stats.rx_errors++; ++ ++ goto out; ++ } ++ ++ skb = __netdev_alloc_skb(net_dev, ++ priv->tx_headroom + dpa_fd_length(fd), ++ GFP_ATOMIC); ++ if (unlikely(skb == NULL)) { ++ if (netif_msg_rx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, "Could not alloc skb\n"); ++ ++ percpu_priv->stats.rx_dropped++; ++ ++ goto out; ++ } ++ ++ skb_reserve(skb, priv->tx_headroom); ++ ++ if (fd->format == qm_fd_sg) { ++ if (dpa_bp->vaddr) { ++ sgt = dpa_phys2virt(dpa_bp, qm_fd_addr(fd)) + ++ dpa_fd_offset(fd); ++ ++ for (i = 0; i < DPA_SGT_MAX_ENTRIES; i++) { ++ void *frag_addr = dpa_phys2virt(dpa_bp, ++ qm_sg_addr(&sgt[i]) + ++ be16_to_cpu(sgt[i].offset)); ++ u32 frag_length = be32_to_cpu(sgt[i].length); ++ BUG_ON(sgt[i].extension); ++ ++ /* copy from sgt[i] */ ++ memcpy(skb_put(skb, frag_length), frag_addr, ++ frag_length); ++ if (sgt[i].final) ++ break; ++ } ++ } else { ++ sgt = kmalloc(DPA_SGT_MAX_ENTRIES * sizeof(*sgt), ++ GFP_ATOMIC); ++ if (unlikely(sgt == NULL)) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, ++ "Memory allocation failed\n"); ++ return -ENOMEM; ++ } ++ ++ copy_from_unmapped_area(sgt, ++ qm_fd_addr(fd) + dpa_fd_offset(fd), ++ min(DPA_SGT_MAX_ENTRIES * sizeof(*sgt), ++ dpa_bp->size)); ++ ++ for (i = 0; i < DPA_SGT_MAX_ENTRIES; i++) { ++ u32 frag_length = be32_to_cpu(sgt[i].length); ++ BUG_ON(sgt[i].extension); ++ copy_from_unmapped_area( ++ skb_put(skb, frag_length), ++ qm_sg_addr(&sgt[i]) + ++ be16_to_cpu(sgt[i].offset), ++ frag_length); ++ ++ if (sgt[i].final) ++ break; ++ } ++ ++ kfree(sgt); ++ } ++ goto skb_copied; ++ } ++ ++ /* otherwise fd->format == qm_fd_contig */ ++ if (dpa_bp->vaddr) { ++ /* Fill the SKB */ ++ memcpy(skb_put(skb, dpa_fd_length(fd)), ++ dpa_phys2virt(dpa_bp, qm_fd_addr(fd)) + ++ dpa_fd_offset(fd), dpa_fd_length(fd)); ++ } else { ++ copy_from_unmapped_area(skb_put(skb, dpa_fd_length(fd)), ++ qm_fd_addr(fd) + dpa_fd_offset(fd), ++ dpa_fd_length(fd)); ++ } ++ ++skb_copied: ++ skb->protocol = eth_type_trans(skb, net_dev); ++ ++ /* IP Reassembled frames are allowed to be larger than MTU */ ++ if (unlikely(dpa_check_rx_mtu(skb, net_dev->mtu) && ++ !(fd->status & FM_FD_IPR))) { ++ percpu_priv->stats.rx_dropped++; ++ dev_kfree_skb_any(skb); ++ goto out; ++ } ++ ++ if (unlikely(netif_rx(skb) != NET_RX_SUCCESS)) ++ goto out; ++ else { ++ percpu_priv->stats.rx_packets++; ++ percpu_priv->stats.rx_bytes += dpa_fd_length(fd); ++ } ++ ++out: ++ if (fd->format == qm_fd_sg) ++ dpa_fd_release_sg(net_dev, fd); ++ else ++ dpa_fd_release(net_dev, fd); ++ ++ return qman_cb_dqrr_consume; ++} ++ ++static enum qman_cb_dqrr_result ++shared_tx_error_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct dpa_bp *dpa_bp; ++ const struct qm_fd *fd = &dq->fd; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ ++ dpa_bp = dpa_bpid2pool(fd->bpid); ++ BUG_ON(!dpa_bp); ++ ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_warn(net_dev, "FD status = 0x%08x\n", ++ fd->status & FM_FD_STAT_TX_ERRORS); ++ ++ if ((fd->format == qm_fd_sg) && (!dpa_bp->vaddr)) ++ dpa_fd_release_sg(net_dev, fd); ++ else ++ dpa_fd_release(net_dev, fd); ++ ++ percpu_priv->stats.tx_errors++; ++ ++ return qman_cb_dqrr_consume; ++} ++ ++static enum qman_cb_dqrr_result __hot ++shared_tx_default_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct dpa_bp *dpa_bp; ++ const struct qm_fd *fd = &dq->fd; ++ ++ net_dev = ((struct dpa_fq *)fq)->net_dev; ++ priv = netdev_priv(net_dev); ++ ++ dpa_bp = dpa_bpid2pool(fd->bpid); ++ BUG_ON(!dpa_bp); ++ ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ ++ if (unlikely(fd->status & FM_FD_STAT_TX_ERRORS) != 0) { ++ if (netif_msg_hw(priv) && net_ratelimit()) ++ netdev_warn(net_dev, "FD status = 0x%08x\n", ++ fd->status & FM_FD_STAT_TX_ERRORS); ++ ++ percpu_priv->stats.tx_errors++; ++ } ++ ++ if ((fd->format == qm_fd_sg) && (!dpa_bp->vaddr)) ++ dpa_fd_release_sg(net_dev, fd); ++ else ++ dpa_fd_release(net_dev, fd); ++ ++ percpu_priv->tx_confirm++; ++ ++ return qman_cb_dqrr_consume; ++} ++ ++static void shared_ern(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_mr_entry *msg) ++{ ++ struct net_device *net_dev; ++ const struct dpa_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct dpa_fq *dpa_fq = (struct dpa_fq *)fq; ++ ++ net_dev = dpa_fq->net_dev; ++ priv = netdev_priv(net_dev); ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ ++ dpa_fd_release(net_dev, &msg->ern.fd); ++ ++ percpu_priv->stats.tx_dropped++; ++ percpu_priv->stats.tx_fifo_errors++; ++ count_ern(percpu_priv, msg); ++} ++ ++int __hot dpa_shared_tx(struct sk_buff *skb, struct net_device *net_dev) ++{ ++ struct dpa_bp *dpa_bp; ++ struct bm_buffer bmb; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct dpa_priv_s *priv; ++ struct qm_fd fd; ++ int queue_mapping; ++ int err; ++ void *dpa_bp_vaddr; ++ fm_prs_result_t parse_results; ++ fm_prs_result_t *parse_results_ref; ++ struct qman_fq *egress_fq, *conf_fq; ++ ++ priv = netdev_priv(net_dev); ++ percpu_priv = raw_cpu_ptr(priv->percpu_priv); ++ ++ memset(&fd, 0, sizeof(fd)); ++ fd.format = qm_fd_contig; ++ ++ queue_mapping = smp_processor_id(); ++ ++ dpa_bp = dpa_size2pool(priv, skb_headlen(skb)); ++ if (unlikely(!dpa_bp)) { ++ percpu_priv->stats.tx_errors++; ++ err = PTR_ERR(dpa_bp); ++ goto bpools_too_small_error; ++ } ++ ++ err = bman_acquire(dpa_bp->pool, &bmb, 1, 0); ++ if (unlikely(err <= 0)) { ++ percpu_priv->stats.tx_errors++; ++ if (err == 0) ++ err = -ENOMEM; ++ goto buf_acquire_failed; ++ } ++ fd.bpid = dpa_bp->bpid; ++ ++ fd.length20 = skb_headlen(skb); ++ fd.addr_hi = (uint8_t)bmb.hi; ++ fd.addr_lo = bmb.lo; ++ fd.offset = priv->tx_headroom; ++ ++ /* The virtual address of the buffer pool is expected to be NULL ++ * in scenarios like MAC-less or Shared-MAC between Linux and ++ * USDPAA. In this case the buffers are dynamically mapped/unmapped. ++ */ ++ if (dpa_bp->vaddr) { ++ dpa_bp_vaddr = dpa_phys2virt(dpa_bp, bm_buf_addr(&bmb)); ++ ++ /* Copy the packet payload */ ++ skb_copy_from_linear_data(skb, ++ dpa_bp_vaddr + dpa_fd_offset(&fd), ++ dpa_fd_length(&fd)); ++ ++ /* if no mac device or peer set it's macless */ ++ if (!priv->mac_dev || priv->peer) { ++ parse_results_ref = (fm_prs_result_t *) (dpa_bp_vaddr + ++ DPA_TX_PRIV_DATA_SIZE); ++ /* Default values; FMan will not generate/validate ++ * CSUM; ++ */ ++ parse_results_ref->l3r = 0; ++ parse_results_ref->l4r = 0; ++ parse_results_ref->ip_off[0] = 0xff; ++ parse_results_ref->ip_off[1] = 0xff; ++ parse_results_ref->l4_off = 0xff; ++ ++ fd.cmd |= FM_FD_CMD_DTC | FM_FD_CMD_RPD; ++ } else { ++ /* Enable L3/L4 hardware checksum computation, ++ * if applicable ++ */ ++ err = dpa_enable_tx_csum(priv, skb, &fd, ++ dpa_bp_vaddr + DPA_TX_PRIV_DATA_SIZE); ++ ++ if (unlikely(err < 0)) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, ++ "Tx HW csum error: %d\n", err); ++ percpu_priv->stats.tx_errors++; ++ goto l3_l4_csum_failed; ++ } ++ } ++ ++ } else { ++ if (!priv->mac_dev || priv->peer) { ++ /* Default values; FMan will not generate/validate ++ * CSUM; ++ */ ++ parse_results.l3r = 0; ++ parse_results.l4r = 0; ++ parse_results.ip_off[0] = 0xff; ++ parse_results.ip_off[1] = 0xff; ++ parse_results.l4_off = 0xff; ++ ++ fd.cmd |= FM_FD_CMD_DTC | FM_FD_CMD_RPD; ++ } else { ++ /* Enable L3/L4 hardware checksum computation, ++ * if applicable ++ */ ++ err = dpa_enable_tx_csum(priv, skb, &fd, ++ (char *)&parse_results); ++ ++ if (unlikely(err < 0)) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, ++ "Tx HW csum error: %d\n", err); ++ percpu_priv->stats.tx_errors++; ++ goto l3_l4_csum_failed; ++ } ++ ++ } ++ ++ copy_to_unmapped_area(bm_buf_addr(&bmb) + DPA_TX_PRIV_DATA_SIZE, ++ &parse_results, ++ DPA_PARSE_RESULTS_SIZE); ++ ++ copy_to_unmapped_area(bm_buf_addr(&bmb) + dpa_fd_offset(&fd), ++ skb->data, ++ dpa_fd_length(&fd)); ++ } ++ ++ egress_fq = priv->egress_fqs[queue_mapping]; ++ conf_fq = priv->conf_fqs[queue_mapping]; ++ ++ err = dpa_xmit(priv, &percpu_priv->stats, &fd, egress_fq, conf_fq); ++ ++l3_l4_csum_failed: ++bpools_too_small_error: ++buf_acquire_failed: ++ /* We're done with the skb */ ++ dev_kfree_skb(skb); ++ ++ /* err remains unused, NETDEV_TX_OK must be returned here */ ++ return NETDEV_TX_OK; ++} ++EXPORT_SYMBOL(dpa_shared_tx); ++ ++static int dpa_shared_netdev_init(struct device_node *dpa_node, ++ struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ const uint8_t *mac_addr; ++ ++ net_dev->netdev_ops = &dpa_shared_ops; ++ ++ net_dev->mem_start = priv->mac_dev->res->start; ++ net_dev->mem_end = priv->mac_dev->res->end; ++ ++ mac_addr = priv->mac_dev->addr; ++ ++ net_dev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | ++ NETIF_F_LLTX); ++ ++ return dpa_netdev_init(net_dev, mac_addr, shared_tx_timeout); ++} ++ ++#ifdef CONFIG_PM ++ ++static int dpa_shared_suspend(struct device *dev) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct mac_device *mac_dev; ++ int err = 0; ++ ++ net_dev = dev_get_drvdata(dev); ++ if (net_dev->flags & IFF_UP) { ++ priv = netdev_priv(net_dev); ++ mac_dev = priv->mac_dev; ++ ++ err = fm_port_suspend(mac_dev->port_dev[RX]); ++ if (err) ++ goto port_suspend_failed; ++ ++ err = fm_port_suspend(mac_dev->port_dev[TX]); ++ if (err) ++ err = fm_port_resume(mac_dev->port_dev[RX]); ++ } ++ ++port_suspend_failed: ++ return err; ++} ++ ++static int dpa_shared_resume(struct device *dev) ++{ ++ struct net_device *net_dev; ++ struct dpa_priv_s *priv; ++ struct mac_device *mac_dev; ++ int err = 0; ++ ++ net_dev = dev_get_drvdata(dev); ++ if (net_dev->flags & IFF_UP) { ++ priv = netdev_priv(net_dev); ++ mac_dev = priv->mac_dev; ++ ++ err = fm_port_resume(mac_dev->port_dev[TX]); ++ if (err) ++ goto port_resume_failed; ++ ++ err = fm_port_resume(mac_dev->port_dev[RX]); ++ if (err) ++ err = fm_port_suspend(mac_dev->port_dev[TX]); ++ } ++ ++port_resume_failed: ++ return err; ++} ++ ++static const struct dev_pm_ops shared_pm_ops = { ++ .suspend = dpa_shared_suspend, ++ .resume = dpa_shared_resume, ++}; ++ ++#define SHARED_PM_OPS (&shared_pm_ops) ++ ++#else /* CONFIG_PM */ ++ ++#define SHARED_PM_OPS NULL ++ ++#endif /* CONFIG_PM */ ++ ++static int ++dpaa_eth_shared_probe(struct platform_device *_of_dev) ++{ ++ int err = 0, i, channel; ++ struct device *dev; ++ struct device_node *dpa_node; ++ struct dpa_bp *dpa_bp; ++ struct dpa_fq *dpa_fq, *tmp; ++ size_t count; ++ struct net_device *net_dev = NULL; ++ struct dpa_priv_s *priv = NULL; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct fm_port_fqs port_fqs; ++ struct dpa_buffer_layout_s *buf_layout = NULL; ++ struct mac_device *mac_dev; ++ struct task_struct *kth; ++ ++ dev = &_of_dev->dev; ++ ++ dpa_node = dev->of_node; ++ ++ if (!of_device_is_available(dpa_node)) ++ return -ENODEV; ++ ++ /* Get the buffer pools assigned to this interface */ ++ dpa_bp = dpa_bp_probe(_of_dev, &count); ++ if (IS_ERR(dpa_bp)) ++ return PTR_ERR(dpa_bp); ++ ++ for (i = 0; i < count; i++) ++ dpa_bp[i].seed_cb = dpa_bp_shared_port_seed; ++ ++ /* Allocate this early, so we can store relevant information in ++ * the private area (needed by 1588 code in dpa_mac_probe) ++ */ ++ net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA_ETH_TX_QUEUES); ++ if (!net_dev) { ++ dev_err(dev, "alloc_etherdev_mq() failed\n"); ++ return -ENOMEM; ++ } ++ ++ /* Do this here, so we can be verbose early */ ++ SET_NETDEV_DEV(net_dev, dev); ++ dev_set_drvdata(dev, net_dev); ++ ++ priv = netdev_priv(net_dev); ++ priv->net_dev = net_dev; ++ strcpy(priv->if_type, "shared"); ++ ++ priv->msg_enable = netif_msg_init(advanced_debug, -1); ++ ++ mac_dev = dpa_mac_probe(_of_dev); ++ if (IS_ERR(mac_dev) || !mac_dev) { ++ err = PTR_ERR(mac_dev); ++ goto mac_probe_failed; ++ } ++ ++ /* We have physical ports, so we need to establish ++ * the buffer layout. ++ */ ++ buf_layout = devm_kzalloc(dev, 2 * sizeof(*buf_layout), ++ GFP_KERNEL); ++ if (!buf_layout) { ++ dev_err(dev, "devm_kzalloc() failed\n"); ++ goto alloc_failed; ++ } ++ dpa_set_buffers_layout(mac_dev, buf_layout); ++ ++ INIT_LIST_HEAD(&priv->dpa_fq_list); ++ ++ memset(&port_fqs, 0, sizeof(port_fqs)); ++ ++ err = dpa_fq_probe_mac(dev, &priv->dpa_fq_list, &port_fqs, ++ false, RX); ++ if (!err) ++ err = dpa_fq_probe_mac(dev, &priv->dpa_fq_list, ++ &port_fqs, false, TX); ++ if (err < 0) ++ goto fq_probe_failed; ++ ++ /* bp init */ ++ priv->bp_count = count; ++ err = dpa_bp_create(net_dev, dpa_bp, count); ++ if (err < 0) ++ goto bp_create_failed; ++ ++ priv->mac_dev = mac_dev; ++ ++ channel = dpa_get_channel(); ++ ++ if (channel < 0) { ++ err = channel; ++ goto get_channel_failed; ++ } ++ ++ priv->channel = (uint16_t)channel; ++ ++ /* Start a thread that will walk the cpus with affine portals ++ * and add this pool channel to each's dequeue mask. ++ */ ++ kth = kthread_run(dpaa_eth_add_channel, ++ (void *)(unsigned long)priv->channel, ++ "dpaa_%p:%d", net_dev, priv->channel); ++ if (!kth) { ++ err = -ENOMEM; ++ goto add_channel_failed; ++ } ++ ++ dpa_fq_setup(priv, &shared_fq_cbs, priv->mac_dev->port_dev[TX]); ++ ++ /* Create a congestion group for this netdev, with ++ * dynamically-allocated CGR ID. ++ * Must be executed after probing the MAC, but before ++ * assigning the egress FQs to the CGRs. ++ */ ++ err = dpaa_eth_cgr_init(priv); ++ if (err < 0) { ++ dev_err(dev, "Error initializing CGR\n"); ++ goto cgr_init_failed; ++ } ++ ++ /* Add the FQs to the interface, and make them active */ ++ list_for_each_entry_safe(dpa_fq, tmp, &priv->dpa_fq_list, list) { ++ err = dpa_fq_init(dpa_fq, false); ++ if (err < 0) ++ goto fq_alloc_failed; ++ } ++ ++ priv->buf_layout = buf_layout; ++ priv->tx_headroom = ++ dpa_get_headroom(&priv->buf_layout[TX]); ++ ++ /* All real interfaces need their ports initialized */ ++ dpaa_eth_init_ports(mac_dev, dpa_bp, count, &port_fqs, ++ buf_layout, dev); ++ ++ /* Now we need to initialize either a private or shared interface */ ++ priv->percpu_priv = devm_alloc_percpu(dev, *priv->percpu_priv); ++ ++ if (priv->percpu_priv == NULL) { ++ dev_err(dev, "devm_alloc_percpu() failed\n"); ++ err = -ENOMEM; ++ goto alloc_percpu_failed; ++ } ++ for_each_possible_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ memset(percpu_priv, 0, sizeof(*percpu_priv)); ++ } ++ ++ err = dpa_shared_netdev_init(dpa_node, net_dev); ++ ++ if (err < 0) ++ goto netdev_init_failed; ++ ++ dpaa_eth_sysfs_init(&net_dev->dev); ++ ++ pr_info("fsl_dpa_shared: Probed shared interface %s\n", ++ net_dev->name); ++ ++ return 0; ++ ++netdev_init_failed: ++alloc_percpu_failed: ++fq_alloc_failed: ++ if (net_dev) { ++ dpa_fq_free(dev, &priv->dpa_fq_list); ++ qman_release_cgrid(priv->cgr_data.cgr.cgrid); ++ qman_delete_cgr(&priv->cgr_data.cgr); ++ } ++cgr_init_failed: ++add_channel_failed: ++get_channel_failed: ++ if (net_dev) ++ dpa_bp_free(priv); ++bp_create_failed: ++fq_probe_failed: ++ devm_kfree(dev, buf_layout); ++alloc_failed: ++mac_probe_failed: ++ dev_set_drvdata(dev, NULL); ++ if (net_dev) ++ free_netdev(net_dev); ++ ++ return err; ++} ++ ++static const struct of_device_id dpa_shared_match[] = { ++ { ++ .compatible = "fsl,dpa-ethernet-shared" ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, dpa_shared_match); ++ ++static struct platform_driver dpa_shared_driver = { ++ .driver = { ++ .name = KBUILD_MODNAME "-shared", ++ .of_match_table = dpa_shared_match, ++ .owner = THIS_MODULE, ++ .pm = SHARED_PM_OPS, ++ }, ++ .probe = dpaa_eth_shared_probe, ++ .remove = dpa_remove ++}; ++ ++static int __init __cold dpa_shared_load(void) ++{ ++ int _errno; ++ ++ pr_info(DPA_DESCRIPTION " (" VERSION ")\n"); ++ ++ /* Initialize dpaa_eth mirror values */ ++ dpa_rx_extra_headroom = fm_get_rx_extra_headroom(); ++ dpa_max_frm = fm_get_max_frm(); ++ ++ _errno = platform_driver_register(&dpa_shared_driver); ++ if (unlikely(_errno < 0)) { ++ pr_err(KBUILD_MODNAME ++ ": %s:%hu:%s(): platform_driver_register() = %d\n", ++ KBUILD_BASENAME".c", __LINE__, __func__, _errno); ++ } ++ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ return _errno; ++} ++module_init(dpa_shared_load); ++ ++static void __exit __cold dpa_shared_unload(void) ++{ ++ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ platform_driver_unregister(&dpa_shared_driver); ++} ++module_exit(dpa_shared_unload); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sysfs.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sysfs.c +new file mode 100644 +index 0000000..95fa461 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sysfs.c +@@ -0,0 +1,275 @@ ++/* Copyright 2008-2012 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 ++#include ++#include ++#include ++#include ++#include "dpaa_eth.h" ++#include "mac.h" /* struct mac_device */ ++#ifdef CONFIG_FSL_DPAA_1588 ++#include "dpaa_1588.h" ++#endif ++ ++static ssize_t dpaa_eth_show_addr(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ struct mac_device *mac_dev = priv->mac_dev; ++ ++ if (mac_dev) ++ return sprintf(buf, "%llx", ++ (unsigned long long)mac_dev->res->start); ++ else ++ return sprintf(buf, "none"); ++} ++ ++static ssize_t dpaa_eth_show_type(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ ssize_t res = 0; ++ ++ if (priv) ++ res = sprintf(buf, "%s", priv->if_type); ++ ++ return res; ++} ++ ++static ssize_t dpaa_eth_show_fqids(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ ssize_t bytes = 0; ++ int i = 0; ++ char *str; ++ struct dpa_fq *fq; ++ struct dpa_fq *tmp; ++ struct dpa_fq *prev = NULL; ++ u32 first_fqid = 0; ++ u32 last_fqid = 0; ++ char *prevstr = NULL; ++ ++ list_for_each_entry_safe(fq, tmp, &priv->dpa_fq_list, list) { ++ switch (fq->fq_type) { ++ case FQ_TYPE_RX_DEFAULT: ++ str = "Rx default"; ++ break; ++ case FQ_TYPE_RX_ERROR: ++ str = "Rx error"; ++ break; ++ case FQ_TYPE_RX_PCD: ++ str = "Rx PCD"; ++ break; ++ case FQ_TYPE_TX_CONFIRM: ++ str = "Tx default confirmation"; ++ break; ++ case FQ_TYPE_TX_CONF_MQ: ++ str = "Tx confirmation (mq)"; ++ break; ++ case FQ_TYPE_TX_ERROR: ++ str = "Tx error"; ++ break; ++ case FQ_TYPE_TX: ++ str = "Tx"; ++ break; ++ default: ++ str = "Unknown"; ++ } ++ ++ if (prev && (abs(fq->fqid - prev->fqid) != 1 || ++ str != prevstr)) { ++ if (last_fqid == first_fqid) ++ bytes += sprintf(buf + bytes, ++ "%s: %d\n", prevstr, prev->fqid); ++ else ++ bytes += sprintf(buf + bytes, ++ "%s: %d - %d\n", prevstr, ++ first_fqid, last_fqid); ++ } ++ ++ if (prev && abs(fq->fqid - prev->fqid) == 1 && str == prevstr) ++ last_fqid = fq->fqid; ++ else ++ first_fqid = last_fqid = fq->fqid; ++ ++ prev = fq; ++ prevstr = str; ++ i++; ++ } ++ ++ if (prev) { ++ if (last_fqid == first_fqid) ++ bytes += sprintf(buf + bytes, "%s: %d\n", prevstr, ++ prev->fqid); ++ else ++ bytes += sprintf(buf + bytes, "%s: %d - %d\n", prevstr, ++ first_fqid, last_fqid); ++ } ++ ++ return bytes; ++} ++ ++static ssize_t dpaa_eth_show_bpids(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ ssize_t bytes = 0; ++ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ struct dpa_bp *dpa_bp = priv->dpa_bp; ++ int i = 0; ++ ++ for (i = 0; i < priv->bp_count; i++) ++ bytes += snprintf(buf + bytes, PAGE_SIZE, "%u\n", ++ dpa_bp[i].bpid); ++ ++ return bytes; ++} ++ ++static ssize_t dpaa_eth_show_mac_regs(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ struct mac_device *mac_dev = priv->mac_dev; ++ int n = 0; ++ ++ if (mac_dev) ++ n = fm_mac_dump_regs(mac_dev, buf, n); ++ else ++ return sprintf(buf, "no mac registers\n"); ++ ++ return n; ++} ++ ++static ssize_t dpaa_eth_show_mac_rx_stats(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ struct mac_device *mac_dev = priv->mac_dev; ++ int n = 0; ++ ++ if (mac_dev) ++ n = fm_mac_dump_rx_stats(mac_dev, buf, n); ++ else ++ return sprintf(buf, "no mac rx stats\n"); ++ ++ return n; ++} ++ ++static ssize_t dpaa_eth_show_mac_tx_stats(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ struct mac_device *mac_dev = priv->mac_dev; ++ int n = 0; ++ ++ if (mac_dev) ++ n = fm_mac_dump_tx_stats(mac_dev, buf, n); ++ else ++ return sprintf(buf, "no mac tx stats\n"); ++ ++ return n; ++} ++ ++#ifdef CONFIG_FSL_DPAA_1588 ++static ssize_t dpaa_eth_show_ptp_1588(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ ++ if (priv->tsu && priv->tsu->valid) ++ return sprintf(buf, "1\n"); ++ else ++ return sprintf(buf, "0\n"); ++} ++ ++static ssize_t dpaa_eth_set_ptp_1588(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev)); ++ unsigned int num; ++ unsigned long flags; ++ ++ if (kstrtouint(buf, 0, &num) < 0) ++ return -EINVAL; ++ ++ local_irq_save(flags); ++ ++ if (num) { ++ if (priv->tsu) ++ priv->tsu->valid = TRUE; ++ } else { ++ if (priv->tsu) ++ priv->tsu->valid = FALSE; ++ } ++ ++ local_irq_restore(flags); ++ ++ return count; ++} ++#endif ++ ++static struct device_attribute dpaa_eth_attrs[] = { ++ __ATTR(device_addr, S_IRUGO, dpaa_eth_show_addr, NULL), ++ __ATTR(device_type, S_IRUGO, dpaa_eth_show_type, NULL), ++ __ATTR(fqids, S_IRUGO, dpaa_eth_show_fqids, NULL), ++ __ATTR(bpids, S_IRUGO, dpaa_eth_show_bpids, NULL), ++ __ATTR(mac_regs, S_IRUGO, dpaa_eth_show_mac_regs, NULL), ++ __ATTR(mac_rx_stats, S_IRUGO, dpaa_eth_show_mac_rx_stats, NULL), ++ __ATTR(mac_tx_stats, S_IRUGO, dpaa_eth_show_mac_tx_stats, NULL), ++#ifdef CONFIG_FSL_DPAA_1588 ++ __ATTR(ptp_1588, S_IRUGO | S_IWUSR, dpaa_eth_show_ptp_1588, ++ dpaa_eth_set_ptp_1588), ++#endif ++}; ++ ++void dpaa_eth_sysfs_init(struct device *dev) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(dpaa_eth_attrs); i++) ++ if (device_create_file(dev, &dpaa_eth_attrs[i])) { ++ dev_err(dev, "Error creating sysfs file\n"); ++ while (i > 0) ++ device_remove_file(dev, &dpaa_eth_attrs[--i]); ++ return; ++ } ++} ++EXPORT_SYMBOL(dpaa_eth_sysfs_init); ++ ++void dpaa_eth_sysfs_remove(struct device *dev) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(dpaa_eth_attrs); i++) ++ device_remove_file(dev, &dpaa_eth_attrs[i]); ++} +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_trace.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_trace.h +new file mode 100644 +index 0000000..30069ef +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_trace.h +@@ -0,0 +1,144 @@ ++/* Copyright 2013 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 dpaa_eth ++ ++#if !defined(_DPAA_ETH_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _DPAA_ETH_TRACE_H ++ ++#include ++#include ++#include "dpaa_eth.h" ++#include ++ ++#define fd_format_name(format) { qm_fd_##format, #format } ++#define fd_format_list \ ++ fd_format_name(contig), \ ++ fd_format_name(sg) ++#define TR_FMT "[%s] fqid=%d, fd: addr=0x%llx, format=%s, off=%u, len=%u," \ ++ " status=0x%08x" ++ ++/* This is used to declare a class of events. ++ * individual events of this type will be defined below. ++ */ ++ ++/* Store details about a frame descriptor and the FQ on which it was ++ * transmitted/received. ++ */ ++DECLARE_EVENT_CLASS(dpaa_eth_fd, ++ /* Trace function prototype */ ++ TP_PROTO(struct net_device *netdev, ++ struct qman_fq *fq, ++ const struct qm_fd *fd), ++ ++ /* Repeat argument list here */ ++ TP_ARGS(netdev, fq, 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(u32, fqid) ++ __field(u64, fd_addr) ++ __field(u8, fd_format) ++ __field(u16, fd_offset) ++ __field(u32, fd_length) ++ __field(u32, fd_status) ++ __string(name, netdev->name) ++ ), ++ ++ /* The function that assigns values to the above declared fields */ ++ TP_fast_assign( ++ __entry->fqid = fq->fqid; ++ __entry->fd_addr = qm_fd_addr_get64(fd); ++ __entry->fd_format = fd->format; ++ __entry->fd_offset = dpa_fd_offset(fd); ++ __entry->fd_length = dpa_fd_length(fd); ++ __entry->fd_status = fd->status; ++ __assign_str(name, netdev->name); ++ ), ++ ++ /* This is what gets printed when the trace event is triggered */ ++ /* TODO: print the status using __print_flags() */ ++ TP_printk(TR_FMT, ++ __get_str(name), __entry->fqid, __entry->fd_addr, ++ __print_symbolic(__entry->fd_format, fd_format_list), ++ __entry->fd_offset, __entry->fd_length, __entry->fd_status) ++); ++ ++/* 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(dpaa_eth_fd, dpa_tx_fd, ++ ++ TP_PROTO(struct net_device *netdev, ++ struct qman_fq *fq, ++ const struct qm_fd *fd), ++ ++ TP_ARGS(netdev, fq, fd) ++); ++ ++/* Rx fd */ ++DEFINE_EVENT(dpaa_eth_fd, dpa_rx_fd, ++ ++ TP_PROTO(struct net_device *netdev, ++ struct qman_fq *fq, ++ const struct qm_fd *fd), ++ ++ TP_ARGS(netdev, fq, fd) ++); ++ ++/* Tx confirmation fd */ ++DEFINE_EVENT(dpaa_eth_fd, dpa_tx_conf_fd, ++ ++ TP_PROTO(struct net_device *netdev, ++ struct qman_fq *fq, ++ const struct qm_fd *fd), ++ ++ TP_ARGS(netdev, fq, fd) ++); ++ ++/* 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 /* _DPAA_ETH_TRACE_H */ ++ ++/* This must be outside ifdef _DPAA_ETH_TRACE_H */ ++#undef TRACE_INCLUDE_PATH ++#define TRACE_INCLUDE_PATH . ++#undef TRACE_INCLUDE_FILE ++#define TRACE_INCLUDE_FILE dpaa_eth_trace ++#include +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c +new file mode 100644 +index 0000000..60a1b22 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c +@@ -0,0 +1,333 @@ ++/* Copyright 2008-2012 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. ++ */ ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUG ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++#else ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": " fmt ++#endif ++ ++#include ++ ++#include "dpaa_eth.h" ++#include "mac.h" /* struct mac_device */ ++#include "dpaa_eth_common.h" ++ ++static int __cold dpa_get_settings(struct net_device *net_dev, ++ struct ethtool_cmd *et_cmd) ++{ ++ int _errno; ++ struct dpa_priv_s *priv; ++ ++ priv = netdev_priv(net_dev); ++ ++ if (priv->mac_dev == NULL) { ++ netdev_info(net_dev, "This is a MAC-less interface\n"); ++ return -ENODEV; ++ } ++ if (unlikely(priv->mac_dev->phy_dev == NULL)) { ++ netdev_dbg(net_dev, "phy device not initialized\n"); ++ return 0; ++ } ++ ++ _errno = phy_ethtool_gset(priv->mac_dev->phy_dev, et_cmd); ++ if (unlikely(_errno < 0)) ++ netdev_err(net_dev, "phy_ethtool_gset() = %d\n", _errno); ++ ++ return _errno; ++} ++ ++static int __cold dpa_set_settings(struct net_device *net_dev, ++ struct ethtool_cmd *et_cmd) ++{ ++ int _errno; ++ struct dpa_priv_s *priv; ++ ++ priv = netdev_priv(net_dev); ++ ++ if (priv->mac_dev == NULL) { ++ netdev_info(net_dev, "This is a MAC-less interface\n"); ++ return -ENODEV; ++ } ++ if (unlikely(priv->mac_dev->phy_dev == NULL)) { ++ netdev_err(net_dev, "phy device not initialized\n"); ++ return -ENODEV; ++ } ++ ++ _errno = phy_ethtool_sset(priv->mac_dev->phy_dev, et_cmd); ++ if (unlikely(_errno < 0)) ++ netdev_err(net_dev, "phy_ethtool_sset() = %d\n", _errno); ++ ++ return _errno; ++} ++ ++static void __cold dpa_get_drvinfo(struct net_device *net_dev, ++ struct ethtool_drvinfo *drvinfo) ++{ ++ int _errno; ++ ++ strncpy(drvinfo->driver, KBUILD_MODNAME, ++ sizeof(drvinfo->driver) - 1)[sizeof(drvinfo->driver)-1] = 0; ++ strncpy(drvinfo->version, VERSION, ++ sizeof(drvinfo->driver) - 1)[sizeof(drvinfo->version)-1] = 0; ++ _errno = snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), ++ "%X", 0); ++ ++ if (unlikely(_errno >= sizeof(drvinfo->fw_version))) { ++ /* Truncated output */ ++ netdev_notice(net_dev, "snprintf() = %d\n", _errno); ++ } else if (unlikely(_errno < 0)) { ++ netdev_warn(net_dev, "snprintf() = %d\n", _errno); ++ memset(drvinfo->fw_version, 0, sizeof(drvinfo->fw_version)); ++ } ++ strncpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent), ++ sizeof(drvinfo->bus_info)-1)[sizeof(drvinfo->bus_info)-1] = 0; ++} ++ ++static uint32_t __cold dpa_get_msglevel(struct net_device *net_dev) ++{ ++ return ((struct dpa_priv_s *)netdev_priv(net_dev))->msg_enable; ++} ++ ++static void __cold dpa_set_msglevel(struct net_device *net_dev, ++ uint32_t msg_enable) ++{ ++ ((struct dpa_priv_s *)netdev_priv(net_dev))->msg_enable = msg_enable; ++} ++ ++static int __cold dpa_nway_reset(struct net_device *net_dev) ++{ ++ int _errno; ++ struct dpa_priv_s *priv; ++ ++ priv = netdev_priv(net_dev); ++ ++ if (priv->mac_dev == NULL) { ++ netdev_info(net_dev, "This is a MAC-less interface\n"); ++ return -ENODEV; ++ } ++ if (unlikely(priv->mac_dev->phy_dev == NULL)) { ++ netdev_err(net_dev, "phy device not initialized\n"); ++ return -ENODEV; ++ } ++ ++ _errno = 0; ++ if (priv->mac_dev->phy_dev->autoneg) { ++ _errno = phy_start_aneg(priv->mac_dev->phy_dev); ++ if (unlikely(_errno < 0)) ++ netdev_err(net_dev, "phy_start_aneg() = %d\n", ++ _errno); ++ } ++ ++ return _errno; ++} ++ ++static void __cold dpa_get_ringparam(struct net_device *net_dev, ++ struct ethtool_ringparam *et_ringparam) ++{ ++ et_ringparam->rx_max_pending = 0; ++ et_ringparam->rx_mini_max_pending = 0; ++ et_ringparam->rx_jumbo_max_pending = 0; ++ et_ringparam->tx_max_pending = 0; ++ ++ et_ringparam->rx_pending = 0; ++ et_ringparam->rx_mini_pending = 0; ++ et_ringparam->rx_jumbo_pending = 0; ++ et_ringparam->tx_pending = 0; ++} ++ ++static void __cold dpa_get_pauseparam(struct net_device *net_dev, ++ struct ethtool_pauseparam *epause) ++{ ++ struct dpa_priv_s *priv; ++ struct mac_device *mac_dev; ++ struct phy_device *phy_dev; ++ ++ priv = netdev_priv(net_dev); ++ mac_dev = priv->mac_dev; ++ ++ if (mac_dev == NULL) { ++ netdev_info(net_dev, "This is a MAC-less interface\n"); ++ return; ++ } ++ ++ phy_dev = mac_dev->phy_dev; ++ if (unlikely(phy_dev == NULL)) { ++ netdev_err(net_dev, "phy device not initialized\n"); ++ return; ++ } ++ ++ epause->autoneg = mac_dev->autoneg_pause; ++ epause->rx_pause = mac_dev->rx_pause_active; ++ epause->tx_pause = mac_dev->tx_pause_active; ++} ++ ++static int __cold dpa_set_pauseparam(struct net_device *net_dev, ++ struct ethtool_pauseparam *epause) ++{ ++ struct dpa_priv_s *priv; ++ struct mac_device *mac_dev; ++ struct phy_device *phy_dev; ++ int _errno; ++ u32 newadv, oldadv; ++ bool rx_pause, tx_pause; ++ ++ priv = netdev_priv(net_dev); ++ mac_dev = priv->mac_dev; ++ ++ if (mac_dev == NULL) { ++ netdev_info(net_dev, "This is a MAC-less interface\n"); ++ return -ENODEV; ++ } ++ ++ phy_dev = mac_dev->phy_dev; ++ if (unlikely(phy_dev == NULL)) { ++ netdev_err(net_dev, "phy device not initialized\n"); ++ return -ENODEV; ++ } ++ ++ if (!(phy_dev->supported & SUPPORTED_Pause) || ++ (!(phy_dev->supported & SUPPORTED_Asym_Pause) && ++ (epause->rx_pause != epause->tx_pause))) ++ return -EINVAL; ++ ++ /* The MAC should know how to handle PAUSE frame autonegotiation before ++ * adjust_link is triggered by a forced renegotiation of sym/asym PAUSE ++ * settings. ++ */ ++ mac_dev->autoneg_pause = !!epause->autoneg; ++ mac_dev->rx_pause_req = !!epause->rx_pause; ++ mac_dev->tx_pause_req = !!epause->tx_pause; ++ ++ /* Determine the sym/asym advertised PAUSE capabilities from the desired ++ * rx/tx pause settings. ++ */ ++ newadv = 0; ++ if (epause->rx_pause) ++ newadv = ADVERTISED_Pause | ADVERTISED_Asym_Pause; ++ if (epause->tx_pause) ++ newadv |= ADVERTISED_Asym_Pause; ++ ++ oldadv = phy_dev->advertising & ++ (ADVERTISED_Pause | ADVERTISED_Asym_Pause); ++ ++ /* If there are differences between the old and the new advertised ++ * values, restart PHY autonegotiation and advertise the new values. ++ */ ++ if (oldadv != newadv) { ++ phy_dev->advertising &= ~(ADVERTISED_Pause ++ | ADVERTISED_Asym_Pause); ++ phy_dev->advertising |= newadv; ++ if (phy_dev->autoneg) { ++ _errno = phy_start_aneg(phy_dev); ++ if (unlikely(_errno < 0)) ++ netdev_err(net_dev, "phy_start_aneg() = %d\n", ++ _errno); ++ } ++ } ++ ++ get_pause_cfg(mac_dev, &rx_pause, &tx_pause); ++ _errno = set_mac_active_pause(mac_dev, rx_pause, tx_pause); ++ if (unlikely(_errno < 0)) ++ netdev_err(net_dev, "set_mac_active_pause() = %d\n", _errno); ++ ++ return _errno; ++} ++ ++#ifdef CONFIG_PM ++static void dpa_get_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ ++ wol->supported = 0; ++ wol->wolopts = 0; ++ ++ if (!priv->wol || !device_can_wakeup(net_dev->dev.parent)) ++ return; ++ ++ if (priv->wol & DPAA_WOL_MAGIC) { ++ wol->supported = WAKE_MAGIC; ++ wol->wolopts = WAKE_MAGIC; ++ } ++} ++ ++static int dpa_set_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ ++ if (priv->mac_dev == NULL) { ++ netdev_info(net_dev, "This is a MAC-less interface\n"); ++ return -ENODEV; ++ } ++ ++ if (unlikely(priv->mac_dev->phy_dev == NULL)) { ++ netdev_dbg(net_dev, "phy device not initialized\n"); ++ return -ENODEV; ++ } ++ ++ if (!device_can_wakeup(net_dev->dev.parent) || ++ (wol->wolopts & ~WAKE_MAGIC)) ++ return -EOPNOTSUPP; ++ ++ priv->wol = 0; ++ ++ if (wol->wolopts & WAKE_MAGIC) { ++ priv->wol = DPAA_WOL_MAGIC; ++ device_set_wakeup_enable(net_dev->dev.parent, 1); ++ } else { ++ device_set_wakeup_enable(net_dev->dev.parent, 0); ++ } ++ ++ return 0; ++} ++#endif ++ ++const struct ethtool_ops dpa_ethtool_ops = { ++ .get_settings = dpa_get_settings, ++ .set_settings = dpa_set_settings, ++ .get_drvinfo = dpa_get_drvinfo, ++ .get_msglevel = dpa_get_msglevel, ++ .set_msglevel = dpa_set_msglevel, ++ .nway_reset = dpa_nway_reset, ++ .get_ringparam = dpa_get_ringparam, ++ .get_pauseparam = dpa_get_pauseparam, ++ .set_pauseparam = dpa_set_pauseparam, ++ .self_test = NULL, /* TODO invoke the cold-boot unit-test? */ ++ .get_ethtool_stats = NULL, /* TODO other stats, currently in debugfs */ ++ .get_link = ethtool_op_get_link, ++#ifdef CONFIG_PM ++ .get_wol = dpa_get_wol, ++ .set_wol = dpa_set_wol, ++#endif ++}; +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.c +new file mode 100644 +index 0000000..b53c289 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.c +@@ -0,0 +1,277 @@ ++/* Copyright 2013 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 ++#include ++#include ++ ++#include "dpaa_eth_generic.h" ++ ++#define DPA_DEBUGFS_DESCRIPTION "FSL DPAA Ethernet debugfs entries" ++#define DPA_GENERIC_ETH_DEBUGFS_ROOT "fsl_generic_dpa" ++ ++static int __cold dpa_generic_debugfs_open(struct inode *inode, ++ struct file *file); ++ ++static struct dentry *dpa_debugfs_root; ++static const struct file_operations dpa_debugfs_fops = { ++ .open = dpa_generic_debugfs_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int dpa_generic_debugfs_show(struct seq_file *file, void *offset) ++{ ++ int i; ++ struct dpa_generic_priv_s *priv; ++ struct dpa_percpu_priv_s *percpu_priv, total; ++ struct dpa_bp *bp; ++ unsigned int dpa_bp_count = 0; ++ unsigned int count_total = 0; ++ ++ BUG_ON(offset == NULL); ++ ++ priv = netdev_priv((struct net_device *)file->private); ++ ++ bp = priv->rx_bp; ++ ++ memset(&total, 0, sizeof(total)); ++ ++ /* "Standard" counters */ ++ seq_printf(file, "\nDPA counters for %s:\n", priv->net_dev->name); ++ seq_puts(file, "CPU irqs rx tx recycle "); ++ seq_puts(file, "confirm tx sg tx err rx err bp count\n"); ++ ++ ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ if (bp->percpu_count) ++ dpa_bp_count = *(per_cpu_ptr(bp->percpu_count, i)); ++ ++ total.in_interrupt += percpu_priv->in_interrupt; ++ total.stats.rx_packets += percpu_priv->stats.rx_packets; ++ total.stats.tx_packets += percpu_priv->stats.tx_packets; ++ total.tx_returned += percpu_priv->tx_returned; ++ total.tx_confirm += percpu_priv->tx_confirm; ++ total.tx_frag_skbuffs += percpu_priv->tx_frag_skbuffs; ++ total.stats.tx_errors += percpu_priv->stats.tx_errors; ++ total.stats.rx_errors += percpu_priv->stats.rx_errors; ++ count_total += dpa_bp_count; ++ ++ seq_printf(file, " %hu %8llu %8llu %8llu %8llu ", ++ i, ++ percpu_priv->in_interrupt, ++ percpu_priv->stats.rx_packets, ++ percpu_priv->stats.tx_packets, ++ percpu_priv->tx_returned); ++ seq_printf(file, "%8llu %8llu %8llu %8llu %8d\n", ++ percpu_priv->tx_confirm, ++ percpu_priv->tx_frag_skbuffs, ++ percpu_priv->stats.tx_errors, ++ percpu_priv->stats.rx_errors, ++ dpa_bp_count); ++ } ++ seq_printf(file, "Total %8llu %8llu %8llu %8llu ", ++ total.in_interrupt, ++ total.stats.rx_packets, ++ total.stats.tx_packets, ++ total.tx_returned); ++ seq_printf(file, "%8llu %8llu %8llu %8llu %8d\n", ++ total.tx_confirm, ++ total.tx_frag_skbuffs, ++ total.stats.tx_errors, ++ total.stats.rx_errors, ++ count_total); ++ ++ /* Draining Buffer Pool counters */ ++ seq_printf(file, "\nCounters for Draining Buffer Pool (bpid:%d) %s:\n", ++ bp->bpid, priv->net_dev->name); ++ seq_puts(file, "CPU bp count\n"); ++ ++ bp = priv->draining_tx_bp; ++ dpa_bp_count = 0; ++ count_total = 0; ++ ++ for_each_online_cpu(i) { ++ if (bp->percpu_count) ++ dpa_bp_count = *(per_cpu_ptr(bp->percpu_count, i)); ++ count_total += dpa_bp_count; ++ ++ seq_printf(file, " %hu %8d\n", i, dpa_bp_count); ++ } ++ seq_printf(file, "Total %8d\n", count_total); ++ ++ ++ /* Rx Errors demultiplexing */ ++ seq_puts(file, "\nDPA RX Errors:\nCPU dma err phys err"); ++ seq_puts(file, " size err hdr err csum err\n"); ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ total.rx_errors.dme += percpu_priv->rx_errors.dme; ++ total.rx_errors.fpe += percpu_priv->rx_errors.fpe; ++ total.rx_errors.fse += percpu_priv->rx_errors.fse; ++ total.rx_errors.phe += percpu_priv->rx_errors.phe; ++ total.rx_errors.cse += percpu_priv->rx_errors.cse; ++ ++ seq_printf(file, " %hu %8llu %8llu ", ++ i, ++ percpu_priv->rx_errors.dme, ++ percpu_priv->rx_errors.fpe); ++ seq_printf(file, "%8llu %8llu %8llu\n", ++ percpu_priv->rx_errors.fse, ++ percpu_priv->rx_errors.phe, ++ percpu_priv->rx_errors.cse); ++ } ++ seq_printf(file, "Total %8llu %8llu %8llu %8llu %8llu\n", ++ total.rx_errors.dme, ++ total.rx_errors.fpe, ++ total.rx_errors.fse, ++ total.rx_errors.phe, ++ total.rx_errors.cse); ++ ++ /* ERN demultiplexing */ ++ seq_puts(file, "\nDPA ERN counters:\n CPU cg_td wred "); ++ seq_puts(file, "err_cond early_w late_w fq_td fq_ret"); ++ seq_puts(file, " orp_z\n"); ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ total.ern_cnt.cg_tdrop += percpu_priv->ern_cnt.cg_tdrop; ++ total.ern_cnt.wred += percpu_priv->ern_cnt.wred; ++ total.ern_cnt.err_cond += percpu_priv->ern_cnt.err_cond; ++ total.ern_cnt.early_window += percpu_priv->ern_cnt.early_window; ++ total.ern_cnt.late_window += percpu_priv->ern_cnt.late_window; ++ total.ern_cnt.fq_tdrop += percpu_priv->ern_cnt.fq_tdrop; ++ total.ern_cnt.fq_retired += percpu_priv->ern_cnt.fq_retired; ++ total.ern_cnt.orp_zero += percpu_priv->ern_cnt.orp_zero; ++ ++ seq_printf(file, " %hu %8llu %8llu %8llu %8llu ", ++ i, ++ percpu_priv->ern_cnt.cg_tdrop, ++ percpu_priv->ern_cnt.wred, ++ percpu_priv->ern_cnt.err_cond, ++ percpu_priv->ern_cnt.early_window); ++ seq_printf(file, "%8llu %8llu %8llu %8llu\n", ++ percpu_priv->ern_cnt.late_window, ++ percpu_priv->ern_cnt.fq_tdrop, ++ percpu_priv->ern_cnt.fq_retired, ++ percpu_priv->ern_cnt.orp_zero); ++ } ++ seq_printf(file, "Total%8llu %8llu %8llu %8llu ", ++ total.ern_cnt.cg_tdrop, ++ total.ern_cnt.wred, ++ total.ern_cnt.err_cond, ++ total.ern_cnt.early_window); ++ seq_printf(file, "%8llu %8llu %8llu %8llu\n", ++ total.ern_cnt.late_window, ++ total.ern_cnt.fq_tdrop, ++ total.ern_cnt.fq_retired, ++ total.ern_cnt.orp_zero); ++ ++ return 0; ++} ++ ++static int __cold dpa_generic_debugfs_open(struct inode *inode, ++ struct file *file) ++{ ++ int _errno; ++ const struct net_device *net_dev = ++ (struct net_device *)inode->i_private; ++ ++ _errno = single_open(file, dpa_generic_debugfs_show, inode->i_private); ++ if (unlikely(_errno < 0)) ++ if (netif_msg_drv((struct dpa_generic_priv_s *) ++ netdev_priv(net_dev))) ++ netdev_err(net_dev, "single_open() = %d\n", _errno); ++ ++ return _errno; ++} ++ ++int dpa_generic_debugfs_create(struct net_device *net_dev) ++{ ++ struct dpa_generic_priv_s *priv = netdev_priv(net_dev); ++ ++ if (unlikely(dpa_debugfs_root == NULL)) { ++ pr_err(KBUILD_MODNAME ": %s:%hu:%s(): \t%s\n", ++ KBUILD_BASENAME".c", __LINE__, __func__, ++ "root debugfs missing, possible module ordering issue"); ++ return -ENOMEM; ++ } ++ ++ priv->debugfs_file = debugfs_create_file(net_dev->name, ++ S_IRUGO, ++ dpa_debugfs_root, ++ net_dev, ++ &dpa_debugfs_fops); ++ if (unlikely(priv->debugfs_file == NULL)) { ++ netdev_err(net_dev, "debugfs_create_file(%s/%s)", ++ dpa_debugfs_root->d_iname, ++ net_dev->name); ++ ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ ++void dpa_generic_debugfs_remove(struct net_device *net_dev) ++{ ++ struct dpa_generic_priv_s *priv = netdev_priv(net_dev); ++ ++ debugfs_remove(priv->debugfs_file); ++} ++ ++int __init dpa_generic_debugfs_module_init(void) ++{ ++ int _errno = 0; ++ ++ pr_info(KBUILD_MODNAME ": " DPA_DEBUGFS_DESCRIPTION " (" VERSION ")\n"); ++ ++ dpa_debugfs_root = debugfs_create_dir(DPA_GENERIC_ETH_DEBUGFS_ROOT, ++ NULL); ++ if (unlikely(dpa_debugfs_root == NULL)) { ++ _errno = -ENOMEM; ++ pr_err(KBUILD_MODNAME ": %s:%hu:%s():\n", ++ KBUILD_BASENAME".c", __LINE__, __func__); ++ pr_err("\tdebugfs_create_dir(%s/"KBUILD_MODNAME") = %d\n", ++ DPA_GENERIC_ETH_DEBUGFS_ROOT, _errno); ++ } ++ ++ return _errno; ++} ++ ++void __exit dpa_generic_debugfs_module_exit(void) ++{ ++ debugfs_remove(dpa_debugfs_root); ++} +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.h +new file mode 100644 +index 0000000..56e7fb3 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.h +@@ -0,0 +1,41 @@ ++/* Copyright 2013 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 DPAA_GENERIC_DEBUGFS_H_ ++#define DPAA_GENERIC_DEBUGFS_H_ ++ ++#include ++#include ++ ++int dpa_generic_debugfs_create(struct net_device *net_dev); ++void dpa_generic_debugfs_remove(struct net_device *net_dev); ++ ++#endif /* DPAA_GENERIC_DEBUGFS_H_ */ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c +new file mode 100644 +index 0000000..b9c8623 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c +@@ -0,0 +1,125 @@ ++/* Copyright 2008-2012 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. ++ */ ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUG ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++#else ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": " fmt ++#endif ++ ++#include ++ ++#include "dpaa_eth.h" ++#include "dpaa_eth_common.h" ++#include "dpaa_eth_generic.h" ++ ++static int __cold dpa_generic_get_settings(struct net_device *net_dev, ++ struct ethtool_cmd *et_cmd) ++{ ++ netdev_info(net_dev, "This interface does not have a MAC device in its control\n"); ++ return -ENODEV; ++} ++ ++static int __cold dpa_generic_set_settings(struct net_device *net_dev, ++ struct ethtool_cmd *et_cmd) ++{ ++ netdev_info(net_dev, "This interface does not have a MAC device in its control\n"); ++ return -ENODEV; ++} ++ ++static void __cold dpa_generic_get_drvinfo(struct net_device *net_dev, ++ struct ethtool_drvinfo *drvinfo) ++{ ++ int _errno; ++ ++ strncpy(drvinfo->driver, KBUILD_MODNAME, ++ sizeof(drvinfo->driver) - 1)[sizeof(drvinfo->driver)-1] = 0; ++ strncpy(drvinfo->version, VERSION, ++ sizeof(drvinfo->driver) - 1)[sizeof(drvinfo->version)-1] = 0; ++ _errno = snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), ++ "%X", 0); ++ ++ if (unlikely(_errno >= sizeof(drvinfo->fw_version))) { ++ /* Truncated output */ ++ netdev_notice(net_dev, "snprintf() = %d\n", _errno); ++ } else if (unlikely(_errno < 0)) { ++ netdev_warn(net_dev, "snprintf() = %d\n", _errno); ++ memset(drvinfo->fw_version, 0, sizeof(drvinfo->fw_version)); ++ } ++ strncpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent), ++ sizeof(drvinfo->bus_info)-1)[sizeof(drvinfo->bus_info)-1] = 0; ++} ++ ++static uint32_t __cold dpa_generic_get_msglevel(struct net_device *net_dev) ++{ ++ return ((struct dpa_generic_priv_s *)netdev_priv(net_dev))->msg_enable; ++} ++ ++static void __cold dpa_generic_set_msglevel(struct net_device *net_dev, ++ uint32_t msg_enable) ++{ ++ ((struct dpa_generic_priv_s *)netdev_priv(net_dev))->msg_enable = ++ msg_enable; ++} ++ ++static int __cold dpa_generic_nway_reset(struct net_device *net_dev) ++{ ++ netdev_info(net_dev, "This interface does not have a MAC device in its control\n"); ++ return -ENODEV; ++} ++ ++static void __cold dpa_generic_get_ringparam(struct net_device *net_dev, ++ struct ethtool_ringparam *et_ringparam) ++{ ++ et_ringparam->rx_max_pending = 0; ++ et_ringparam->rx_mini_max_pending = 0; ++ et_ringparam->rx_jumbo_max_pending = 0; ++ et_ringparam->tx_max_pending = 0; ++ ++ et_ringparam->rx_pending = 0; ++ et_ringparam->rx_mini_pending = 0; ++ et_ringparam->rx_jumbo_pending = 0; ++ et_ringparam->tx_pending = 0; ++} ++ ++const struct ethtool_ops dpa_generic_ethtool_ops = { ++ .get_settings = dpa_generic_get_settings, ++ .set_settings = dpa_generic_set_settings, ++ .get_drvinfo = dpa_generic_get_drvinfo, ++ .get_msglevel = dpa_generic_get_msglevel, ++ .set_msglevel = dpa_generic_set_msglevel, ++ .nway_reset = dpa_generic_nway_reset, ++ .get_ringparam = dpa_generic_get_ringparam, ++ .get_link = ethtool_op_get_link, ++}; +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ptp.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ptp.c +new file mode 100644 +index 0000000..e883f23 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ptp.c +@@ -0,0 +1,287 @@ ++/* ++ * DPAA Ethernet Driver -- PTP 1588 clock using the dTSEC ++ * ++ * Author: Yangbo Lu ++ * ++ * Copyright 2014 Freescale Semiconductor, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "dpaa_eth.h" ++#include "mac.h" ++ ++struct ptp_clock *clock; ++ ++static struct mac_device *mac_dev; ++static u32 freqCompensation; ++ ++/* Bit definitions for the TMR_CTRL register */ ++#define ALM1P (1<<31) /* Alarm1 output polarity */ ++#define ALM2P (1<<30) /* Alarm2 output polarity */ ++#define FS (1<<28) /* FIPER start indication */ ++#define PP1L (1<<27) /* Fiper1 pulse loopback mode enabled. */ ++#define PP2L (1<<26) /* Fiper2 pulse loopback mode enabled. */ ++#define TCLK_PERIOD_SHIFT (16) /* 1588 timer reference clock period. */ ++#define TCLK_PERIOD_MASK (0x3ff) ++#define RTPE (1<<15) /* Record Tx Timestamp to PAL Enable. */ ++#define FRD (1<<14) /* FIPER Realignment Disable */ ++#define ESFDP (1<<11) /* External Tx/Rx SFD Polarity. */ ++#define ESFDE (1<<10) /* External Tx/Rx SFD Enable. */ ++#define ETEP2 (1<<9) /* External trigger 2 edge polarity */ ++#define ETEP1 (1<<8) /* External trigger 1 edge polarity */ ++#define COPH (1<<7) /* Generated clock output phase. */ ++#define CIPH (1<<6) /* External oscillator input clock phase */ ++#define TMSR (1<<5) /* Timer soft reset. */ ++#define BYP (1<<3) /* Bypass drift compensated clock */ ++#define TE (1<<2) /* 1588 timer enable. */ ++#define CKSEL_SHIFT (0) /* 1588 Timer reference clock source */ ++#define CKSEL_MASK (0x3) ++ ++/* Bit definitions for the TMR_TEVENT register */ ++#define ETS2 (1<<25) /* External trigger 2 timestamp sampled */ ++#define ETS1 (1<<24) /* External trigger 1 timestamp sampled */ ++#define ALM2 (1<<17) /* Current time = alarm time register 2 */ ++#define ALM1 (1<<16) /* Current time = alarm time register 1 */ ++#define PP1 (1<<7) /* periodic pulse generated on FIPER1 */ ++#define PP2 (1<<6) /* periodic pulse generated on FIPER2 */ ++#define PP3 (1<<5) /* periodic pulse generated on FIPER3 */ ++ ++/* Bit definitions for the TMR_TEMASK register */ ++#define ETS2EN (1<<25) /* External trigger 2 timestamp enable */ ++#define ETS1EN (1<<24) /* External trigger 1 timestamp enable */ ++#define ALM2EN (1<<17) /* Timer ALM2 event enable */ ++#define ALM1EN (1<<16) /* Timer ALM1 event enable */ ++#define PP1EN (1<<7) /* Periodic pulse event 1 enable */ ++#define PP2EN (1<<6) /* Periodic pulse event 2 enable */ ++ ++/* Bit definitions for the TMR_PEVENT register */ ++#define TXP2 (1<<9) /* PTP transmitted timestamp im TXTS2 */ ++#define TXP1 (1<<8) /* PTP transmitted timestamp in TXTS1 */ ++#define RXP (1<<0) /* PTP frame has been received */ ++ ++/* Bit definitions for the TMR_PEMASK register */ ++#define TXP2EN (1<<9) /* Transmit PTP packet event 2 enable */ ++#define TXP1EN (1<<8) /* Transmit PTP packet event 1 enable */ ++#define RXPEN (1<<0) /* Receive PTP packet event enable */ ++ ++/* Bit definitions for the TMR_STAT register */ ++#define STAT_VEC_SHIFT (0) /* Timer general purpose status vector */ ++#define STAT_VEC_MASK (0x3f) ++ ++/* Bit definitions for the TMR_PRSC register */ ++#define PRSC_OCK_SHIFT (0) /* Output clock division/prescale factor. */ ++#define PRSC_OCK_MASK (0xffff) ++ ++ ++#define N_EXT_TS 2 ++ ++static void set_alarm(void) ++{ ++ u64 ns; ++ ++ if (mac_dev->fm_rtc_get_cnt) ++ mac_dev->fm_rtc_get_cnt(mac_dev->fm_dev, &ns); ++ ns += 1500000000ULL; ++ ns = div_u64(ns, 1000000000UL) * 1000000000ULL; ++ ns -= DPA_PTP_NOMINAL_FREQ_PERIOD_NS; ++ if (mac_dev->fm_rtc_set_alarm) ++ mac_dev->fm_rtc_set_alarm(mac_dev->fm_dev, 0, ns); ++} ++ ++static void set_fipers(void) ++{ ++ u64 fiper; ++ ++ if (mac_dev->fm_rtc_disable) ++ mac_dev->fm_rtc_disable(mac_dev->fm_dev); ++ ++ set_alarm(); ++ fiper = 1000000000ULL - DPA_PTP_NOMINAL_FREQ_PERIOD_NS; ++ if (mac_dev->fm_rtc_set_fiper) ++ mac_dev->fm_rtc_set_fiper(mac_dev->fm_dev, 0, fiper); ++ ++ if (mac_dev->fm_rtc_enable) ++ mac_dev->fm_rtc_enable(mac_dev->fm_dev); ++} ++ ++/* PTP clock operations */ ++ ++static int ptp_dpa_adjfreq(struct ptp_clock_info *ptp, s32 ppb) ++{ ++ u64 adj; ++ u32 diff, tmr_add; ++ int neg_adj = 0; ++ ++ if (ppb < 0) { ++ neg_adj = 1; ++ ppb = -ppb; ++ } ++ ++ tmr_add = freqCompensation; ++ adj = tmr_add; ++ adj *= ppb; ++ diff = div_u64(adj, 1000000000ULL); ++ ++ tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff; ++ ++ if (mac_dev->fm_rtc_set_drift) ++ mac_dev->fm_rtc_set_drift(mac_dev->fm_dev, tmr_add); ++ ++ return 0; ++} ++ ++static int ptp_dpa_adjtime(struct ptp_clock_info *ptp, s64 delta) ++{ ++ s64 now; ++ ++ if (mac_dev->fm_rtc_get_cnt) ++ mac_dev->fm_rtc_get_cnt(mac_dev->fm_dev, &now); ++ ++ now += delta; ++ ++ if (mac_dev->fm_rtc_set_cnt) ++ mac_dev->fm_rtc_set_cnt(mac_dev->fm_dev, now); ++ set_fipers(); ++ ++ return 0; ++} ++ ++static int ptp_dpa_gettime(struct ptp_clock_info *ptp, struct timespec *ts) ++{ ++ u64 ns; ++ u32 remainder; ++ ++ if (mac_dev->fm_rtc_get_cnt) ++ mac_dev->fm_rtc_get_cnt(mac_dev->fm_dev, &ns); ++ ++ ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder); ++ ts->tv_nsec = remainder; ++ return 0; ++} ++ ++static int ptp_dpa_settime(struct ptp_clock_info *ptp, ++ const struct timespec *ts) ++{ ++ u64 ns; ++ ++ ns = ts->tv_sec * 1000000000ULL; ++ ns += ts->tv_nsec; ++ ++ if (mac_dev->fm_rtc_set_cnt) ++ mac_dev->fm_rtc_set_cnt(mac_dev->fm_dev, ns); ++ set_fipers(); ++ return 0; ++} ++ ++static int ptp_dpa_enable(struct ptp_clock_info *ptp, ++ struct ptp_clock_request *rq, int on) ++{ ++ u32 bit; ++ ++ switch (rq->type) { ++ case PTP_CLK_REQ_EXTTS: ++ switch (rq->extts.index) { ++ case 0: ++ bit = ETS1EN; ++ break; ++ case 1: ++ bit = ETS2EN; ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (on) { ++ if (mac_dev->fm_rtc_enable_interrupt) ++ mac_dev->fm_rtc_enable_interrupt( ++ mac_dev->fm_dev, bit); ++ } else { ++ if (mac_dev->fm_rtc_disable_interrupt) ++ mac_dev->fm_rtc_disable_interrupt( ++ mac_dev->fm_dev, bit); ++ } ++ return 0; ++ ++ case PTP_CLK_REQ_PPS: ++ if (on) { ++ if (mac_dev->fm_rtc_enable_interrupt) ++ mac_dev->fm_rtc_enable_interrupt( ++ mac_dev->fm_dev, PP1EN); ++ } else { ++ if (mac_dev->fm_rtc_disable_interrupt) ++ mac_dev->fm_rtc_disable_interrupt( ++ mac_dev->fm_dev, PP1EN); ++ } ++ return 0; ++ ++ default: ++ break; ++ } ++ ++ return -EOPNOTSUPP; ++} ++ ++static struct ptp_clock_info ptp_dpa_caps = { ++ .owner = THIS_MODULE, ++ .name = "dpaa clock", ++ .max_adj = 512000, ++ .n_alarm = 0, ++ .n_ext_ts = N_EXT_TS, ++ .n_per_out = 0, ++ .pps = 1, ++ .adjfreq = ptp_dpa_adjfreq, ++ .adjtime = ptp_dpa_adjtime, ++ .gettime = ptp_dpa_gettime, ++ .settime = ptp_dpa_settime, ++ .enable = ptp_dpa_enable, ++}; ++ ++static int __init __cold dpa_ptp_load(void) ++{ ++ struct device *ptp_dev; ++ struct timespec now; ++ int dpa_phc_index; ++ int err; ++ ++ ptp_dev = &ptp_priv.of_dev->dev; ++ mac_dev = ptp_priv.mac_dev; ++ ++ if (mac_dev->fm_rtc_get_drift) ++ mac_dev->fm_rtc_get_drift(mac_dev->fm_dev, &freqCompensation); ++ ++ getnstimeofday(&now); ++ ptp_dpa_settime(&ptp_dpa_caps, &now); ++ ++ clock = ptp_clock_register(&ptp_dpa_caps, ptp_dev); ++ if (IS_ERR(clock)) { ++ err = PTR_ERR(clock); ++ return err; ++ } ++ dpa_phc_index = ptp_clock_index(clock); ++ return 0; ++} ++module_init(dpa_ptp_load); ++ ++static void __exit __cold dpa_ptp_unload(void) ++{ ++ if (mac_dev->fm_rtc_disable_interrupt) ++ mac_dev->fm_rtc_disable_interrupt(mac_dev->fm_dev, 0xffffffff); ++ ptp_clock_unregister(clock); ++} ++module_exit(dpa_ptp_unload); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c b/drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c +new file mode 100644 +index 0000000..462543c +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c +@@ -0,0 +1,909 @@ ++/* Copyright 2008-2012 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. ++ */ ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUG ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++#else ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": " fmt ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dpaa_eth.h" ++#include "mac.h" ++#include "lnxwrp_fsl_fman.h" ++ ++#include "error_ext.h" /* GET_ERROR_TYPE, E_OK */ ++ ++#include "fsl_fman_dtsec.h" ++#include "fsl_fman_tgec.h" ++#include "fsl_fman_memac.h" ++#include "../sdk_fman/src/wrapper/lnxwrp_sysfs_fm.h" ++ ++#define MAC_DESCRIPTION "FSL FMan MAC API based driver" ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++MODULE_AUTHOR("Emil Medve "); ++ ++MODULE_DESCRIPTION(MAC_DESCRIPTION); ++ ++struct mac_priv_s { ++ struct fm_mac_dev *fm_mac; ++}; ++ ++const char *mac_driver_description __initconst = MAC_DESCRIPTION; ++const size_t mac_sizeof_priv[] = { ++ [DTSEC] = sizeof(struct mac_priv_s), ++ [XGMAC] = sizeof(struct mac_priv_s), ++ [MEMAC] = sizeof(struct mac_priv_s) ++}; ++ ++static const enet_mode_t _100[] = { ++ [PHY_INTERFACE_MODE_MII] = e_ENET_MODE_MII_100, ++ [PHY_INTERFACE_MODE_RMII] = e_ENET_MODE_RMII_100 ++}; ++ ++static const enet_mode_t _1000[] = { ++ [PHY_INTERFACE_MODE_GMII] = e_ENET_MODE_GMII_1000, ++ [PHY_INTERFACE_MODE_SGMII] = e_ENET_MODE_SGMII_1000, ++ [PHY_INTERFACE_MODE_TBI] = e_ENET_MODE_TBI_1000, ++ [PHY_INTERFACE_MODE_RGMII] = e_ENET_MODE_RGMII_1000, ++ [PHY_INTERFACE_MODE_RGMII_ID] = e_ENET_MODE_RGMII_1000, ++ [PHY_INTERFACE_MODE_RGMII_RXID] = e_ENET_MODE_RGMII_1000, ++ [PHY_INTERFACE_MODE_RGMII_TXID] = e_ENET_MODE_RGMII_1000, ++ [PHY_INTERFACE_MODE_RTBI] = e_ENET_MODE_RTBI_1000 ++}; ++ ++static enet_mode_t __cold __attribute__((nonnull)) ++macdev2enetinterface(const struct mac_device *mac_dev) ++{ ++ switch (mac_dev->max_speed) { ++ case SPEED_100: ++ return _100[mac_dev->phy_if]; ++ case SPEED_1000: ++ return _1000[mac_dev->phy_if]; ++ case SPEED_2500: ++ return e_ENET_MODE_SGMII_2500; ++ case SPEED_10000: ++ return e_ENET_MODE_XGMII_10000; ++ default: ++ return e_ENET_MODE_MII_100; ++ } ++} ++ ++static void mac_exception(handle_t _mac_dev, e_FmMacExceptions exception) ++{ ++ struct mac_device *mac_dev; ++ ++ mac_dev = (struct mac_device *)_mac_dev; ++ ++ if (e_FM_MAC_EX_10G_RX_FIFO_OVFL == exception) { ++ /* don't flag RX FIFO after the first */ ++ fm_mac_set_exception(mac_dev->get_mac_handle(mac_dev), ++ e_FM_MAC_EX_10G_RX_FIFO_OVFL, false); ++ dev_err(mac_dev->dev, "10G MAC got RX FIFO Error = %x\n", ++ exception); ++ } ++ ++ dev_dbg(mac_dev->dev, "%s:%s() -> %d\n", KBUILD_BASENAME".c", __func__, ++ exception); ++} ++ ++static int __cold init(struct mac_device *mac_dev) ++{ ++ int _errno; ++ struct mac_priv_s *priv; ++ t_FmMacParams param; ++ uint32_t version; ++ ++ priv = macdev_priv(mac_dev); ++ ++ param.baseAddr = (typeof(param.baseAddr))(uintptr_t)devm_ioremap( ++ mac_dev->dev, mac_dev->res->start, 0x2000); ++ param.enetMode = macdev2enetinterface(mac_dev); ++ memcpy(¶m.addr, mac_dev->addr, min(sizeof(param.addr), ++ sizeof(mac_dev->addr))); ++ param.macId = mac_dev->cell_index; ++ param.h_Fm = (handle_t)mac_dev->fm; ++ param.mdioIrq = NO_IRQ; ++ param.f_Exception = mac_exception; ++ param.f_Event = mac_exception; ++ param.h_App = mac_dev; ++ ++ priv->fm_mac = fm_mac_config(¶m); ++ if (unlikely(priv->fm_mac == NULL)) { ++ _errno = -EINVAL; ++ goto _return; ++ } ++ ++ fm_mac_set_handle(mac_dev->fm_dev, priv->fm_mac, ++ (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) ? ++ param.macId : param.macId + FM_MAX_NUM_OF_1G_MACS); ++ ++ _errno = fm_mac_config_max_frame_length(priv->fm_mac, ++ fm_get_max_frm()); ++ if (unlikely(_errno < 0)) ++ goto _return_fm_mac_free; ++ ++ if (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) { ++ /* 10G always works with pad and CRC */ ++ _errno = fm_mac_config_pad_and_crc(priv->fm_mac, true); ++ if (unlikely(_errno < 0)) ++ goto _return_fm_mac_free; ++ ++ _errno = fm_mac_config_half_duplex(priv->fm_mac, ++ mac_dev->half_duplex); ++ if (unlikely(_errno < 0)) ++ goto _return_fm_mac_free; ++ } else { ++ _errno = fm_mac_config_reset_on_init(priv->fm_mac, true); ++ if (unlikely(_errno < 0)) ++ goto _return_fm_mac_free; ++ } ++ ++ _errno = fm_mac_init(priv->fm_mac); ++ if (unlikely(_errno < 0)) ++ goto _return_fm_mac_free; ++ ++#ifndef CONFIG_FMAN_MIB_CNT_OVF_IRQ_EN ++ /* For 1G MAC, disable by default the MIB counters overflow interrupt */ ++ if (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) { ++ _errno = fm_mac_set_exception(mac_dev->get_mac_handle(mac_dev), ++ e_FM_MAC_EX_1G_RX_MIB_CNT_OVFL, FALSE); ++ if (unlikely(_errno < 0)) ++ goto _return_fm_mac_free; ++ } ++#endif /* !CONFIG_FMAN_MIB_CNT_OVF_IRQ_EN */ ++ ++ /* For 10G MAC, disable Tx ECC exception */ ++ if (macdev2enetinterface(mac_dev) == e_ENET_MODE_XGMII_10000) { ++ _errno = fm_mac_set_exception(mac_dev->get_mac_handle(mac_dev), ++ e_FM_MAC_EX_10G_1TX_ECC_ER, FALSE); ++ if (unlikely(_errno < 0)) ++ goto _return_fm_mac_free; ++ } ++ ++ _errno = fm_mac_get_version(priv->fm_mac, &version); ++ if (unlikely(_errno < 0)) ++ goto _return_fm_mac_free; ++ ++ dev_info(mac_dev->dev, "FMan %s version: 0x%08x\n", ++ ((macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) ? ++ "dTSEC" : "XGEC"), version); ++ ++ goto _return; ++ ++ ++_return_fm_mac_free: ++ fm_mac_free(mac_dev->get_mac_handle(mac_dev)); ++ ++_return: ++ return _errno; ++} ++ ++static int __cold memac_init(struct mac_device *mac_dev) ++{ ++ int _errno; ++ struct mac_priv_s *priv; ++ t_FmMacParams param; ++ ++ priv = macdev_priv(mac_dev); ++ ++ param.baseAddr = (typeof(param.baseAddr))(uintptr_t)devm_ioremap( ++ mac_dev->dev, mac_dev->res->start, 0x2000); ++ param.enetMode = macdev2enetinterface(mac_dev); ++ memcpy(¶m.addr, mac_dev->addr, sizeof(mac_dev->addr)); ++ param.macId = mac_dev->cell_index; ++ param.h_Fm = (handle_t)mac_dev->fm; ++ param.mdioIrq = NO_IRQ; ++ param.f_Exception = mac_exception; ++ param.f_Event = mac_exception; ++ param.h_App = mac_dev; ++ ++ priv->fm_mac = fm_mac_config(¶m); ++ if (unlikely(priv->fm_mac == NULL)) { ++ _errno = -EINVAL; ++ goto _return; ++ } ++ ++ _errno = fm_mac_config_max_frame_length(priv->fm_mac, fm_get_max_frm()); ++ if (unlikely(_errno < 0)) ++ goto _return_fm_mac_free; ++ ++ _errno = fm_mac_config_reset_on_init(priv->fm_mac, true); ++ if (unlikely(_errno < 0)) ++ goto _return_fm_mac_free; ++ ++ _errno = fm_mac_init(priv->fm_mac); ++ if (unlikely(_errno < 0)) ++ goto _return_fm_mac_free; ++ ++ dev_info(mac_dev->dev, "FMan MEMAC\n"); ++ ++ goto _return; ++ ++_return_fm_mac_free: ++ fm_mac_free(priv->fm_mac); ++ ++_return: ++ return _errno; ++} ++ ++static int __cold start(struct mac_device *mac_dev) ++{ ++ int _errno; ++ struct phy_device *phy_dev = mac_dev->phy_dev; ++ ++ _errno = fm_mac_enable(mac_dev->get_mac_handle(mac_dev)); ++ ++ if (!_errno && phy_dev) { ++ if (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) ++ phy_start(phy_dev); ++ else if (phy_dev->drv->read_status) ++ phy_dev->drv->read_status(phy_dev); ++ } ++ ++ return _errno; ++} ++ ++static int __cold stop(struct mac_device *mac_dev) ++{ ++ if (mac_dev->phy_dev && ++ (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000)) ++ phy_stop(mac_dev->phy_dev); ++ ++ return fm_mac_disable(mac_dev->get_mac_handle(mac_dev)); ++} ++ ++static int __cold set_multi(struct net_device *net_dev, ++ struct mac_device *mac_dev) ++{ ++ struct mac_priv_s *mac_priv; ++ struct mac_address *old_addr, *tmp; ++ struct netdev_hw_addr *ha; ++ int _errno; ++ ++ mac_priv = macdev_priv(mac_dev); ++ ++ /* Clear previous address list */ ++ list_for_each_entry_safe(old_addr, tmp, &mac_dev->mc_addr_list, list) { ++ _errno = fm_mac_remove_hash_mac_addr(mac_priv->fm_mac, ++ (t_EnetAddr *)old_addr->addr); ++ if (_errno < 0) ++ return _errno; ++ ++ list_del(&old_addr->list); ++ kfree(old_addr); ++ } ++ ++ /* Add all the addresses from the new list */ ++ netdev_for_each_mc_addr(ha, net_dev) { ++ _errno = fm_mac_add_hash_mac_addr(mac_priv->fm_mac, ++ (t_EnetAddr *)ha->addr); ++ if (_errno < 0) ++ return _errno; ++ ++ tmp = kmalloc(sizeof(struct mac_address), GFP_ATOMIC); ++ if (!tmp) { ++ dev_err(mac_dev->dev, "Out of memory\n"); ++ return -ENOMEM; ++ } ++ memcpy(tmp->addr, ha->addr, ETH_ALEN); ++ list_add(&tmp->list, &mac_dev->mc_addr_list); ++ } ++ return 0; ++} ++ ++/* Avoid redundant calls to FMD, if the MAC driver already contains the desired ++ * active PAUSE settings. Otherwise, the new active settings should be reflected ++ * in FMan. ++ */ ++int set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx) ++{ ++ struct fm_mac_dev *fm_mac_dev = mac_dev->get_mac_handle(mac_dev); ++ int _errno = 0; ++ ++ if (unlikely(rx != mac_dev->rx_pause_active)) { ++ _errno = fm_mac_set_rx_pause_frames(fm_mac_dev, rx); ++ if (likely(_errno == 0)) ++ mac_dev->rx_pause_active = rx; ++ } ++ ++ if (unlikely(tx != mac_dev->tx_pause_active)) { ++ _errno = fm_mac_set_tx_pause_frames(fm_mac_dev, tx); ++ if (likely(_errno == 0)) ++ mac_dev->tx_pause_active = tx; ++ } ++ ++ return _errno; ++} ++EXPORT_SYMBOL(set_mac_active_pause); ++ ++/* Determine the MAC RX/TX PAUSE frames settings based on PHY ++ * autonegotiation or values set by eththool. ++ */ ++void get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause, bool *tx_pause) ++{ ++ struct phy_device *phy_dev = mac_dev->phy_dev; ++ u16 lcl_adv, rmt_adv; ++ u8 flowctrl; ++ ++ *rx_pause = *tx_pause = false; ++ ++ if (!phy_dev->duplex) ++ return; ++ ++ /* If PAUSE autonegotiation is disabled, the TX/RX PAUSE settings ++ * are those set by ethtool. ++ */ ++ if (!mac_dev->autoneg_pause) { ++ *rx_pause = mac_dev->rx_pause_req; ++ *tx_pause = mac_dev->tx_pause_req; ++ return; ++ } ++ ++ /* Else if PAUSE autonegotiation is enabled, the TX/RX PAUSE ++ * settings depend on the result of the link negotiation. ++ */ ++ ++ /* get local capabilities */ ++ lcl_adv = 0; ++ if (phy_dev->advertising & ADVERTISED_Pause) ++ lcl_adv |= ADVERTISE_PAUSE_CAP; ++ if (phy_dev->advertising & ADVERTISED_Asym_Pause) ++ lcl_adv |= ADVERTISE_PAUSE_ASYM; ++ ++ /* get link partner capabilities */ ++ rmt_adv = 0; ++ if (phy_dev->pause) ++ rmt_adv |= LPA_PAUSE_CAP; ++ if (phy_dev->asym_pause) ++ rmt_adv |= LPA_PAUSE_ASYM; ++ ++ /* Calculate TX/RX settings based on local and peer advertised ++ * symmetric/asymmetric PAUSE capabilities. ++ */ ++ flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); ++ if (flowctrl & FLOW_CTRL_RX) ++ *rx_pause = true; ++ if (flowctrl & FLOW_CTRL_TX) ++ *tx_pause = true; ++} ++EXPORT_SYMBOL(get_pause_cfg); ++ ++static void adjust_link(struct net_device *net_dev) ++{ ++ struct dpa_priv_s *priv = netdev_priv(net_dev); ++ struct mac_device *mac_dev = priv->mac_dev; ++ struct phy_device *phy_dev = mac_dev->phy_dev; ++ struct fm_mac_dev *fm_mac_dev; ++ bool rx_pause, tx_pause; ++ int _errno; ++ ++ fm_mac_dev = mac_dev->get_mac_handle(mac_dev); ++ fm_mac_adjust_link(fm_mac_dev, phy_dev->link, phy_dev->speed, ++ phy_dev->duplex); ++ ++ get_pause_cfg(mac_dev, &rx_pause, &tx_pause); ++ _errno = set_mac_active_pause(mac_dev, rx_pause, tx_pause); ++ if (unlikely(_errno < 0)) ++ netdev_err(net_dev, "set_mac_active_pause() = %d\n", _errno); ++} ++ ++/* Initializes driver's PHY state, and attaches to the PHY. ++ * Returns 0 on success. ++ */ ++static int dtsec_init_phy(struct net_device *net_dev, ++ struct mac_device *mac_dev) ++{ ++ struct phy_device *phy_dev; ++ ++ if (!mac_dev->phy_node) ++ phy_dev = phy_connect(net_dev, mac_dev->fixed_bus_id, ++ &adjust_link, mac_dev->phy_if); ++ else ++ phy_dev = of_phy_connect(net_dev, mac_dev->phy_node, ++ &adjust_link, 0, mac_dev->phy_if); ++ if (unlikely(phy_dev == NULL) || IS_ERR(phy_dev)) { ++ netdev_err(net_dev, "Could not connect to PHY %s\n", ++ mac_dev->phy_node ? ++ mac_dev->phy_node->full_name : ++ mac_dev->fixed_bus_id); ++ return phy_dev == NULL ? -ENODEV : PTR_ERR(phy_dev); ++ } ++ ++ /* Remove any features not supported by the controller */ ++ phy_dev->supported &= mac_dev->if_support; ++ /* Enable the symmetric and asymmetric PAUSE frame advertisements, ++ * as most of the PHY drivers do not enable them by default. ++ */ ++ phy_dev->supported |= (SUPPORTED_Pause | SUPPORTED_Asym_Pause); ++ phy_dev->advertising = phy_dev->supported; ++ ++ mac_dev->phy_dev = phy_dev; ++ ++ return 0; ++} ++ ++static int xgmac_init_phy(struct net_device *net_dev, ++ struct mac_device *mac_dev) ++{ ++ struct phy_device *phy_dev; ++ ++ if (!mac_dev->phy_node) ++ phy_dev = phy_attach(net_dev, mac_dev->fixed_bus_id, ++ mac_dev->phy_if); ++ else ++ phy_dev = of_phy_attach(net_dev, mac_dev->phy_node, 0, ++ mac_dev->phy_if); ++ if (unlikely(phy_dev == NULL) || IS_ERR(phy_dev)) { ++ netdev_err(net_dev, "Could not attach to PHY %s\n", ++ mac_dev->phy_node ? ++ mac_dev->phy_node->full_name : ++ mac_dev->fixed_bus_id); ++ return phy_dev == NULL ? -ENODEV : PTR_ERR(phy_dev); ++ } ++ ++ phy_dev->supported &= mac_dev->if_support; ++ /* Enable the symmetric and asymmetric PAUSE frame advertisements, ++ * as most of the PHY drivers do not enable them by default. ++ */ ++ phy_dev->supported |= (SUPPORTED_Pause | SUPPORTED_Asym_Pause); ++ phy_dev->advertising = phy_dev->supported; ++ ++ mac_dev->phy_dev = phy_dev; ++ ++ return 0; ++} ++ ++static int memac_init_phy(struct net_device *net_dev, ++ struct mac_device *mac_dev) ++{ ++ struct phy_device *phy_dev; ++ ++ if ((macdev2enetinterface(mac_dev) == e_ENET_MODE_XGMII_10000) || ++ (macdev2enetinterface(mac_dev) == e_ENET_MODE_SGMII_2500)){ ++ if (!mac_dev->phy_node) { ++ mac_dev->phy_dev = NULL; ++ return 0; ++ } else ++ phy_dev = of_phy_attach(net_dev, mac_dev->phy_node, 0, ++ mac_dev->phy_if); ++ } else { ++ if (!mac_dev->phy_node) ++ phy_dev = phy_connect(net_dev, mac_dev->fixed_bus_id, ++ &adjust_link, mac_dev->phy_if); ++ else ++ phy_dev = of_phy_connect(net_dev, mac_dev->phy_node, ++ &adjust_link, 0, ++ mac_dev->phy_if); ++ } ++ ++ if (unlikely(phy_dev == NULL) || IS_ERR(phy_dev)) { ++ netdev_err(net_dev, "Could not connect to PHY %s\n", ++ mac_dev->phy_node ? ++ mac_dev->phy_node->full_name : ++ mac_dev->fixed_bus_id); ++ return phy_dev == NULL ? -ENODEV : PTR_ERR(phy_dev); ++ } ++ ++ /* Remove any features not supported by the controller */ ++ phy_dev->supported &= mac_dev->if_support; ++ /* Enable the symmetric and asymmetric PAUSE frame advertisements, ++ * as most of the PHY drivers do not enable them by default. ++ */ ++ phy_dev->supported |= (SUPPORTED_Pause | SUPPORTED_Asym_Pause); ++ phy_dev->advertising = phy_dev->supported; ++ ++ mac_dev->phy_dev = phy_dev; ++ ++ return 0; ++} ++ ++static int __cold uninit(struct fm_mac_dev *fm_mac_dev) ++{ ++ int _errno, __errno; ++ ++ _errno = fm_mac_disable(fm_mac_dev); ++ __errno = fm_mac_free(fm_mac_dev); ++ ++ if (unlikely(__errno < 0)) ++ _errno = __errno; ++ ++ return _errno; ++} ++ ++static struct fm_mac_dev *get_mac_handle(struct mac_device *mac_dev) ++{ ++ const struct mac_priv_s *priv; ++ priv = macdev_priv(mac_dev); ++ return priv->fm_mac; ++} ++ ++static int dtsec_dump_regs(struct mac_device *h_mac, char *buf, int nn) ++{ ++ struct dtsec_regs *p_mm = (struct dtsec_regs *) h_mac->vaddr; ++ int i = 0, n = nn; ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ ++ FM_DMP_TITLE(buf, n, p_mm, "FM MAC - DTSEC-%d", h_mac->cell_index); ++ ++ FM_DMP_V32(buf, n, p_mm, tsec_id); ++ FM_DMP_V32(buf, n, p_mm, tsec_id2); ++ FM_DMP_V32(buf, n, p_mm, ievent); ++ FM_DMP_V32(buf, n, p_mm, imask); ++ FM_DMP_V32(buf, n, p_mm, ecntrl); ++ FM_DMP_V32(buf, n, p_mm, ptv); ++ FM_DMP_V32(buf, n, p_mm, tmr_ctrl); ++ FM_DMP_V32(buf, n, p_mm, tmr_pevent); ++ FM_DMP_V32(buf, n, p_mm, tmr_pemask); ++ FM_DMP_V32(buf, n, p_mm, tctrl); ++ FM_DMP_V32(buf, n, p_mm, rctrl); ++ FM_DMP_V32(buf, n, p_mm, maccfg1); ++ FM_DMP_V32(buf, n, p_mm, maccfg2); ++ FM_DMP_V32(buf, n, p_mm, ipgifg); ++ FM_DMP_V32(buf, n, p_mm, hafdup); ++ FM_DMP_V32(buf, n, p_mm, maxfrm); ++ ++ FM_DMP_V32(buf, n, p_mm, macstnaddr1); ++ FM_DMP_V32(buf, n, p_mm, macstnaddr2); ++ ++ for (i = 0; i < 7; ++i) { ++ FM_DMP_V32(buf, n, p_mm, macaddr[i].exact_match1); ++ FM_DMP_V32(buf, n, p_mm, macaddr[i].exact_match2); ++ } ++ ++ FM_DMP_V32(buf, n, p_mm, car1); ++ FM_DMP_V32(buf, n, p_mm, car2); ++ ++ return n; ++} ++ ++static int xgmac_dump_regs(struct mac_device *h_mac, char *buf, int nn) ++{ ++ struct tgec_regs *p_mm = (struct tgec_regs *) h_mac->vaddr; ++ int n = nn; ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ FM_DMP_TITLE(buf, n, p_mm, "FM MAC - TGEC -%d", h_mac->cell_index); ++ ++ FM_DMP_V32(buf, n, p_mm, tgec_id); ++ FM_DMP_V32(buf, n, p_mm, command_config); ++ FM_DMP_V32(buf, n, p_mm, mac_addr_0); ++ FM_DMP_V32(buf, n, p_mm, mac_addr_1); ++ FM_DMP_V32(buf, n, p_mm, maxfrm); ++ FM_DMP_V32(buf, n, p_mm, pause_quant); ++ FM_DMP_V32(buf, n, p_mm, rx_fifo_sections); ++ FM_DMP_V32(buf, n, p_mm, tx_fifo_sections); ++ FM_DMP_V32(buf, n, p_mm, rx_fifo_almost_f_e); ++ FM_DMP_V32(buf, n, p_mm, tx_fifo_almost_f_e); ++ FM_DMP_V32(buf, n, p_mm, hashtable_ctrl); ++ FM_DMP_V32(buf, n, p_mm, mdio_cfg_status); ++ FM_DMP_V32(buf, n, p_mm, mdio_command); ++ FM_DMP_V32(buf, n, p_mm, mdio_data); ++ FM_DMP_V32(buf, n, p_mm, mdio_regaddr); ++ FM_DMP_V32(buf, n, p_mm, status); ++ FM_DMP_V32(buf, n, p_mm, tx_ipg_len); ++ FM_DMP_V32(buf, n, p_mm, mac_addr_2); ++ FM_DMP_V32(buf, n, p_mm, mac_addr_3); ++ FM_DMP_V32(buf, n, p_mm, rx_fifo_ptr_rd); ++ FM_DMP_V32(buf, n, p_mm, rx_fifo_ptr_wr); ++ FM_DMP_V32(buf, n, p_mm, tx_fifo_ptr_rd); ++ FM_DMP_V32(buf, n, p_mm, tx_fifo_ptr_wr); ++ FM_DMP_V32(buf, n, p_mm, imask); ++ FM_DMP_V32(buf, n, p_mm, ievent); ++ ++ return n; ++} ++ ++static int memac_dump_regs(struct mac_device *h_mac, char *buf, int nn) ++{ ++ struct memac_regs *p_mm = (struct memac_regs *) h_mac->vaddr; ++ int i = 0, n = nn; ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ FM_DMP_TITLE(buf, n, p_mm, "FM MAC - MEMAC -%d", h_mac->cell_index); ++ ++ FM_DMP_V32(buf, n, p_mm, command_config); ++ FM_DMP_V32(buf, n, p_mm, mac_addr0.mac_addr_l); ++ FM_DMP_V32(buf, n, p_mm, mac_addr0.mac_addr_u); ++ FM_DMP_V32(buf, n, p_mm, maxfrm); ++ FM_DMP_V32(buf, n, p_mm, hashtable_ctrl); ++ FM_DMP_V32(buf, n, p_mm, ievent); ++ FM_DMP_V32(buf, n, p_mm, tx_ipg_length); ++ FM_DMP_V32(buf, n, p_mm, imask); ++ ++ for (i = 0; i < 4; ++i) ++ FM_DMP_V32(buf, n, p_mm, pause_quanta[i]); ++ ++ for (i = 0; i < 4; ++i) ++ FM_DMP_V32(buf, n, p_mm, pause_thresh[i]); ++ ++ FM_DMP_V32(buf, n, p_mm, rx_pause_status); ++ ++ for (i = 0; i < MEMAC_NUM_OF_PADDRS; ++i) { ++ FM_DMP_V32(buf, n, p_mm, mac_addr[i].mac_addr_l); ++ FM_DMP_V32(buf, n, p_mm, mac_addr[i].mac_addr_u); ++ } ++ ++ FM_DMP_V32(buf, n, p_mm, lpwake_timer); ++ FM_DMP_V32(buf, n, p_mm, sleep_timer); ++ FM_DMP_V32(buf, n, p_mm, statn_config); ++ FM_DMP_V32(buf, n, p_mm, if_mode); ++ FM_DMP_V32(buf, n, p_mm, if_status); ++ FM_DMP_V32(buf, n, p_mm, hg_config); ++ FM_DMP_V32(buf, n, p_mm, hg_pause_quanta); ++ FM_DMP_V32(buf, n, p_mm, hg_pause_thresh); ++ FM_DMP_V32(buf, n, p_mm, hgrx_pause_status); ++ FM_DMP_V32(buf, n, p_mm, hg_fifos_status); ++ FM_DMP_V32(buf, n, p_mm, rhm); ++ FM_DMP_V32(buf, n, p_mm, thm); ++ ++ return n; ++} ++ ++static int memac_dump_regs_rx(struct mac_device *h_mac, char *buf, int nn) ++{ ++ struct memac_regs *p_mm = (struct memac_regs *) h_mac->vaddr; ++ int n = nn; ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ FM_DMP_TITLE(buf, n, p_mm, "FM MAC - MEMAC -%d Rx stats", h_mac->cell_index); ++ ++ /* Rx Statistics Counter */ ++ FM_DMP_V32(buf, n, p_mm, reoct_l); ++ FM_DMP_V32(buf, n, p_mm, reoct_u); ++ FM_DMP_V32(buf, n, p_mm, roct_l); ++ FM_DMP_V32(buf, n, p_mm, roct_u); ++ FM_DMP_V32(buf, n, p_mm, raln_l); ++ FM_DMP_V32(buf, n, p_mm, raln_u); ++ FM_DMP_V32(buf, n, p_mm, rxpf_l); ++ FM_DMP_V32(buf, n, p_mm, rxpf_u); ++ FM_DMP_V32(buf, n, p_mm, rfrm_l); ++ FM_DMP_V32(buf, n, p_mm, rfrm_u); ++ FM_DMP_V32(buf, n, p_mm, rfcs_l); ++ FM_DMP_V32(buf, n, p_mm, rfcs_u); ++ FM_DMP_V32(buf, n, p_mm, rvlan_l); ++ FM_DMP_V32(buf, n, p_mm, rvlan_u); ++ FM_DMP_V32(buf, n, p_mm, rerr_l); ++ FM_DMP_V32(buf, n, p_mm, rerr_u); ++ FM_DMP_V32(buf, n, p_mm, ruca_l); ++ FM_DMP_V32(buf, n, p_mm, ruca_u); ++ FM_DMP_V32(buf, n, p_mm, rmca_l); ++ FM_DMP_V32(buf, n, p_mm, rmca_u); ++ FM_DMP_V32(buf, n, p_mm, rbca_l); ++ FM_DMP_V32(buf, n, p_mm, rbca_u); ++ FM_DMP_V32(buf, n, p_mm, rdrp_l); ++ FM_DMP_V32(buf, n, p_mm, rdrp_u); ++ FM_DMP_V32(buf, n, p_mm, rpkt_l); ++ FM_DMP_V32(buf, n, p_mm, rpkt_u); ++ FM_DMP_V32(buf, n, p_mm, rund_l); ++ FM_DMP_V32(buf, n, p_mm, rund_u); ++ FM_DMP_V32(buf, n, p_mm, r64_l); ++ FM_DMP_V32(buf, n, p_mm, r64_u); ++ FM_DMP_V32(buf, n, p_mm, r127_l); ++ FM_DMP_V32(buf, n, p_mm, r127_u); ++ FM_DMP_V32(buf, n, p_mm, r255_l); ++ FM_DMP_V32(buf, n, p_mm, r255_u); ++ FM_DMP_V32(buf, n, p_mm, r511_l); ++ FM_DMP_V32(buf, n, p_mm, r511_u); ++ FM_DMP_V32(buf, n, p_mm, r1023_l); ++ FM_DMP_V32(buf, n, p_mm, r1023_u); ++ FM_DMP_V32(buf, n, p_mm, r1518_l); ++ FM_DMP_V32(buf, n, p_mm, r1518_u); ++ FM_DMP_V32(buf, n, p_mm, r1519x_l); ++ FM_DMP_V32(buf, n, p_mm, r1519x_u); ++ FM_DMP_V32(buf, n, p_mm, rovr_l); ++ FM_DMP_V32(buf, n, p_mm, rovr_u); ++ FM_DMP_V32(buf, n, p_mm, rjbr_l); ++ FM_DMP_V32(buf, n, p_mm, rjbr_u); ++ FM_DMP_V32(buf, n, p_mm, rfrg_l); ++ FM_DMP_V32(buf, n, p_mm, rfrg_u); ++ FM_DMP_V32(buf, n, p_mm, rcnp_l); ++ FM_DMP_V32(buf, n, p_mm, rcnp_u); ++ FM_DMP_V32(buf, n, p_mm, rdrntp_l); ++ FM_DMP_V32(buf, n, p_mm, rdrntp_u); ++ ++ return n; ++} ++ ++static int memac_dump_regs_tx(struct mac_device *h_mac, char *buf, int nn) ++{ ++ struct memac_regs *p_mm = (struct memac_regs *) h_mac->vaddr; ++ int n = nn; ++ ++ FM_DMP_SUBTITLE(buf, n, "\n"); ++ FM_DMP_TITLE(buf, n, p_mm, "FM MAC - MEMAC -%d Tx stats", h_mac->cell_index); ++ ++ ++ /* Tx Statistics Counter */ ++ FM_DMP_V32(buf, n, p_mm, teoct_l); ++ FM_DMP_V32(buf, n, p_mm, teoct_u); ++ FM_DMP_V32(buf, n, p_mm, toct_l); ++ FM_DMP_V32(buf, n, p_mm, toct_u); ++ FM_DMP_V32(buf, n, p_mm, txpf_l); ++ FM_DMP_V32(buf, n, p_mm, txpf_u); ++ FM_DMP_V32(buf, n, p_mm, tfrm_l); ++ FM_DMP_V32(buf, n, p_mm, tfrm_u); ++ FM_DMP_V32(buf, n, p_mm, tfcs_l); ++ FM_DMP_V32(buf, n, p_mm, tfcs_u); ++ FM_DMP_V32(buf, n, p_mm, tvlan_l); ++ FM_DMP_V32(buf, n, p_mm, tvlan_u); ++ FM_DMP_V32(buf, n, p_mm, terr_l); ++ FM_DMP_V32(buf, n, p_mm, terr_u); ++ FM_DMP_V32(buf, n, p_mm, tuca_l); ++ FM_DMP_V32(buf, n, p_mm, tuca_u); ++ FM_DMP_V32(buf, n, p_mm, tmca_l); ++ FM_DMP_V32(buf, n, p_mm, tmca_u); ++ FM_DMP_V32(buf, n, p_mm, tbca_l); ++ FM_DMP_V32(buf, n, p_mm, tbca_u); ++ FM_DMP_V32(buf, n, p_mm, tpkt_l); ++ FM_DMP_V32(buf, n, p_mm, tpkt_u); ++ FM_DMP_V32(buf, n, p_mm, tund_l); ++ FM_DMP_V32(buf, n, p_mm, tund_u); ++ FM_DMP_V32(buf, n, p_mm, t64_l); ++ FM_DMP_V32(buf, n, p_mm, t64_u); ++ FM_DMP_V32(buf, n, p_mm, t127_l); ++ FM_DMP_V32(buf, n, p_mm, t127_u); ++ FM_DMP_V32(buf, n, p_mm, t255_l); ++ FM_DMP_V32(buf, n, p_mm, t255_u); ++ FM_DMP_V32(buf, n, p_mm, t511_l); ++ FM_DMP_V32(buf, n, p_mm, t511_u); ++ FM_DMP_V32(buf, n, p_mm, t1023_l); ++ FM_DMP_V32(buf, n, p_mm, t1023_u); ++ FM_DMP_V32(buf, n, p_mm, t1518_l); ++ FM_DMP_V32(buf, n, p_mm, t1518_u); ++ FM_DMP_V32(buf, n, p_mm, t1519x_l); ++ FM_DMP_V32(buf, n, p_mm, t1519x_u); ++ FM_DMP_V32(buf, n, p_mm, tcnp_l); ++ FM_DMP_V32(buf, n, p_mm, tcnp_u); ++ ++ return n; ++} ++ ++int fm_mac_dump_regs(struct mac_device *h_mac, char *buf, int nn) ++{ ++ int n = nn; ++ ++ n = h_mac->dump_mac_regs(h_mac, buf, n); ++ ++ return n; ++} ++EXPORT_SYMBOL(fm_mac_dump_regs); ++ ++int fm_mac_dump_rx_stats(struct mac_device *h_mac, char *buf, int nn) ++{ ++ int n = nn; ++ ++ if(h_mac->dump_mac_rx_stats) ++ n = h_mac->dump_mac_rx_stats(h_mac, buf, n); ++ ++ return n; ++} ++EXPORT_SYMBOL(fm_mac_dump_rx_stats); ++ ++int fm_mac_dump_tx_stats(struct mac_device *h_mac, char *buf, int nn) ++{ ++ int n = nn; ++ ++ if(h_mac->dump_mac_tx_stats) ++ n = h_mac->dump_mac_tx_stats(h_mac, buf, n); ++ ++ return n; ++} ++EXPORT_SYMBOL(fm_mac_dump_tx_stats); ++ ++static void __cold setup_dtsec(struct mac_device *mac_dev) ++{ ++ mac_dev->init_phy = dtsec_init_phy; ++ mac_dev->init = init; ++ mac_dev->start = start; ++ mac_dev->stop = stop; ++ mac_dev->set_promisc = fm_mac_set_promiscuous; ++ mac_dev->change_addr = fm_mac_modify_mac_addr; ++ mac_dev->set_multi = set_multi; ++ mac_dev->uninit = uninit; ++ mac_dev->ptp_enable = fm_mac_enable_1588_time_stamp; ++ mac_dev->ptp_disable = fm_mac_disable_1588_time_stamp; ++ mac_dev->get_mac_handle = get_mac_handle; ++ mac_dev->set_tx_pause = fm_mac_set_tx_pause_frames; ++ mac_dev->set_rx_pause = fm_mac_set_rx_pause_frames; ++ mac_dev->fm_rtc_enable = fm_rtc_enable; ++ mac_dev->fm_rtc_disable = fm_rtc_disable; ++ mac_dev->fm_rtc_get_cnt = fm_rtc_get_cnt; ++ mac_dev->fm_rtc_set_cnt = fm_rtc_set_cnt; ++ mac_dev->fm_rtc_get_drift = fm_rtc_get_drift; ++ mac_dev->fm_rtc_set_drift = fm_rtc_set_drift; ++ mac_dev->fm_rtc_set_alarm = fm_rtc_set_alarm; ++ mac_dev->fm_rtc_set_fiper = fm_rtc_set_fiper; ++ mac_dev->set_wol = fm_mac_set_wol; ++ mac_dev->dump_mac_regs = dtsec_dump_regs; ++} ++ ++static void __cold setup_xgmac(struct mac_device *mac_dev) ++{ ++ mac_dev->init_phy = xgmac_init_phy; ++ mac_dev->init = init; ++ mac_dev->start = start; ++ mac_dev->stop = stop; ++ mac_dev->set_promisc = fm_mac_set_promiscuous; ++ mac_dev->change_addr = fm_mac_modify_mac_addr; ++ mac_dev->set_multi = set_multi; ++ mac_dev->uninit = uninit; ++ mac_dev->get_mac_handle = get_mac_handle; ++ mac_dev->set_tx_pause = fm_mac_set_tx_pause_frames; ++ mac_dev->set_rx_pause = fm_mac_set_rx_pause_frames; ++ mac_dev->set_wol = fm_mac_set_wol; ++ mac_dev->dump_mac_regs = xgmac_dump_regs; ++} ++ ++static void __cold setup_memac(struct mac_device *mac_dev) ++{ ++ mac_dev->init_phy = memac_init_phy; ++ mac_dev->init = memac_init; ++ mac_dev->start = start; ++ mac_dev->stop = stop; ++ mac_dev->set_promisc = fm_mac_set_promiscuous; ++ mac_dev->change_addr = fm_mac_modify_mac_addr; ++ mac_dev->set_multi = set_multi; ++ mac_dev->uninit = uninit; ++ mac_dev->get_mac_handle = get_mac_handle; ++ mac_dev->set_tx_pause = fm_mac_set_tx_pause_frames; ++ mac_dev->set_rx_pause = fm_mac_set_rx_pause_frames; ++ mac_dev->fm_rtc_enable = fm_rtc_enable; ++ mac_dev->fm_rtc_disable = fm_rtc_disable; ++ mac_dev->fm_rtc_get_cnt = fm_rtc_get_cnt; ++ mac_dev->fm_rtc_set_cnt = fm_rtc_set_cnt; ++ mac_dev->fm_rtc_get_drift = fm_rtc_get_drift; ++ mac_dev->fm_rtc_set_drift = fm_rtc_set_drift; ++ mac_dev->fm_rtc_set_alarm = fm_rtc_set_alarm; ++ mac_dev->fm_rtc_set_fiper = fm_rtc_set_fiper; ++ mac_dev->set_wol = fm_mac_set_wol; ++ mac_dev->dump_mac_regs = memac_dump_regs; ++ mac_dev->dump_mac_rx_stats = memac_dump_regs_rx; ++ mac_dev->dump_mac_tx_stats = memac_dump_regs_tx; ++} ++ ++void (*const mac_setup[])(struct mac_device *mac_dev) = { ++ [DTSEC] = setup_dtsec, ++ [XGMAC] = setup_xgmac, ++ [MEMAC] = setup_memac ++}; +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/mac.c b/drivers/net/ethernet/freescale/sdk_dpaa/mac.c +new file mode 100644 +index 0000000..f36d091 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/mac.c +@@ -0,0 +1,469 @@ ++/* Copyright 2008-2012 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. ++ */ ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUG ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++#else ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": " fmt ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "lnxwrp_fm_ext.h" ++ ++#include "mac.h" ++ ++#define DTSEC_SUPPORTED \ ++ (SUPPORTED_10baseT_Half \ ++ | SUPPORTED_10baseT_Full \ ++ | SUPPORTED_100baseT_Half \ ++ | SUPPORTED_100baseT_Full \ ++ | SUPPORTED_Autoneg \ ++ | SUPPORTED_Pause \ ++ | SUPPORTED_Asym_Pause \ ++ | SUPPORTED_MII) ++ ++static const char phy_str[][11] = { ++ [PHY_INTERFACE_MODE_MII] = "mii", ++ [PHY_INTERFACE_MODE_GMII] = "gmii", ++ [PHY_INTERFACE_MODE_SGMII] = "sgmii", ++ [PHY_INTERFACE_MODE_TBI] = "tbi", ++ [PHY_INTERFACE_MODE_RMII] = "rmii", ++ [PHY_INTERFACE_MODE_RGMII] = "rgmii", ++ [PHY_INTERFACE_MODE_RGMII_ID] = "rgmii-id", ++ [PHY_INTERFACE_MODE_RGMII_RXID] = "rgmii-rxid", ++ [PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid", ++ [PHY_INTERFACE_MODE_RTBI] = "rtbi", ++ [PHY_INTERFACE_MODE_XGMII] = "xgmii", ++ [PHY_INTERFACE_MODE_QSGMII] = "sgmii-2500" ++}; ++ ++static phy_interface_t __pure __attribute__((nonnull)) str2phy(const char *str) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(phy_str); i++) ++ if (strcmp(str, phy_str[i]) == 0) ++ return (phy_interface_t)i; ++ ++ return PHY_INTERFACE_MODE_MII; ++} ++ ++static const uint16_t phy2speed[] = { ++ [PHY_INTERFACE_MODE_MII] = SPEED_100, ++ [PHY_INTERFACE_MODE_GMII] = SPEED_1000, ++ [PHY_INTERFACE_MODE_SGMII] = SPEED_1000, ++ [PHY_INTERFACE_MODE_TBI] = SPEED_1000, ++ [PHY_INTERFACE_MODE_RMII] = SPEED_100, ++ [PHY_INTERFACE_MODE_RGMII] = SPEED_1000, ++ [PHY_INTERFACE_MODE_RGMII_ID] = SPEED_1000, ++ [PHY_INTERFACE_MODE_RGMII_RXID] = SPEED_1000, ++ [PHY_INTERFACE_MODE_RGMII_TXID] = SPEED_1000, ++ [PHY_INTERFACE_MODE_RTBI] = SPEED_1000, ++ [PHY_INTERFACE_MODE_XGMII] = SPEED_10000, ++ [PHY_INTERFACE_MODE_QSGMII] = SPEED_2500 ++}; ++ ++static struct mac_device * __cold ++alloc_macdev(struct device *dev, size_t sizeof_priv, ++ void (*setup)(struct mac_device *mac_dev)) ++{ ++ struct mac_device *mac_dev; ++ ++ mac_dev = devm_kzalloc(dev, sizeof(*mac_dev) + sizeof_priv, GFP_KERNEL); ++ if (unlikely(mac_dev == NULL)) ++ mac_dev = ERR_PTR(-ENOMEM); ++ else { ++ mac_dev->dev = dev; ++ dev_set_drvdata(dev, mac_dev); ++ setup(mac_dev); ++ } ++ ++ return mac_dev; ++} ++ ++static int __cold free_macdev(struct mac_device *mac_dev) ++{ ++ dev_set_drvdata(mac_dev->dev, NULL); ++ ++ return mac_dev->uninit(mac_dev->get_mac_handle(mac_dev)); ++} ++ ++static const struct of_device_id mac_match[] = { ++ [DTSEC] = { ++ .compatible = "fsl,fman-1g-mac" ++ }, ++ [XGMAC] = { ++ .compatible = "fsl,fman-10g-mac" ++ }, ++ [MEMAC] = { ++ .compatible = "fsl,fman-memac" ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, mac_match); ++ ++static int __cold mac_probe(struct platform_device *_of_dev) ++{ ++ int _errno, i; ++ struct device *dev; ++ struct device_node *mac_node, *dev_node; ++ struct mac_device *mac_dev; ++ struct platform_device *of_dev; ++ struct resource res; ++ const uint8_t *mac_addr; ++ const char *char_prop; ++ int nph; ++ u32 cell_index; ++ const struct of_device_id *match; ++ ++ dev = &_of_dev->dev; ++ mac_node = dev->of_node; ++ ++ match = of_match_device(mac_match, dev); ++ if (!match) ++ return -EINVAL; ++ ++ for (i = 0; i < ARRAY_SIZE(mac_match) - 1 && match != mac_match + i; ++ i++) ++ ; ++ BUG_ON(i >= ARRAY_SIZE(mac_match) - 1); ++ ++ mac_dev = alloc_macdev(dev, mac_sizeof_priv[i], mac_setup[i]); ++ if (IS_ERR(mac_dev)) { ++ _errno = PTR_ERR(mac_dev); ++ dev_err(dev, "alloc_macdev() = %d\n", _errno); ++ goto _return; ++ } ++ ++ INIT_LIST_HEAD(&mac_dev->mc_addr_list); ++ ++ /* Get the FM node */ ++ dev_node = of_get_parent(mac_node); ++ if (unlikely(dev_node == NULL)) { ++ dev_err(dev, "of_get_parent(%s) failed\n", ++ mac_node->full_name); ++ _errno = -EINVAL; ++ goto _return_dev_set_drvdata; ++ } ++ ++ of_dev = of_find_device_by_node(dev_node); ++ if (unlikely(of_dev == NULL)) { ++ dev_err(dev, "of_find_device_by_node(%s) failed\n", ++ dev_node->full_name); ++ _errno = -EINVAL; ++ goto _return_of_node_put; ++ } ++ ++ mac_dev->fm_dev = fm_bind(&of_dev->dev); ++ if (unlikely(mac_dev->fm_dev == NULL)) { ++ dev_err(dev, "fm_bind(%s) failed\n", dev_node->full_name); ++ _errno = -ENODEV; ++ goto _return_of_node_put; ++ } ++ ++ mac_dev->fm = (void *)fm_get_handle(mac_dev->fm_dev); ++ of_node_put(dev_node); ++ ++ /* Get the address of the memory mapped registers */ ++ _errno = of_address_to_resource(mac_node, 0, &res); ++ if (unlikely(_errno < 0)) { ++ dev_err(dev, "of_address_to_resource(%s) = %d\n", ++ mac_node->full_name, _errno); ++ goto _return_dev_set_drvdata; ++ } ++ ++ mac_dev->res = __devm_request_region( ++ dev, ++ fm_get_mem_region(mac_dev->fm_dev), ++ res.start, res.end + 1 - res.start, "mac"); ++ if (unlikely(mac_dev->res == NULL)) { ++ dev_err(dev, "__devm_request_mem_region(mac) failed\n"); ++ _errno = -EBUSY; ++ goto _return_dev_set_drvdata; ++ } ++ ++ mac_dev->vaddr = devm_ioremap(dev, mac_dev->res->start, ++ mac_dev->res->end + 1 ++ - mac_dev->res->start); ++ if (unlikely(mac_dev->vaddr == NULL)) { ++ dev_err(dev, "devm_ioremap() failed\n"); ++ _errno = -EIO; ++ goto _return_dev_set_drvdata; ++ } ++ ++#define TBIPA_OFFSET 0x1c ++#define TBIPA_DEFAULT_ADDR 5 /* override if used as external PHY addr. */ ++ mac_dev->tbi_node = of_parse_phandle(mac_node, "tbi-handle", 0); ++ if (mac_dev->tbi_node) { ++ u32 tbiaddr = TBIPA_DEFAULT_ADDR; ++ const __be32 *tbi_reg; ++ void __iomem *addr; ++ ++ tbi_reg = of_get_property(mac_dev->tbi_node, "reg", NULL); ++ if (tbi_reg) ++ tbiaddr = be32_to_cpup(tbi_reg); ++ addr = mac_dev->vaddr + TBIPA_OFFSET; ++ /* TODO: out_be32 does not exist on ARM */ ++ out_be32(addr, tbiaddr); ++ } ++ ++ if (!of_device_is_available(mac_node)) { ++ devm_iounmap(dev, mac_dev->vaddr); ++ __devm_release_region(dev, fm_get_mem_region(mac_dev->fm_dev), ++ res.start, res.end + 1 - res.start); ++ fm_unbind(mac_dev->fm_dev); ++ devm_kfree(dev, mac_dev); ++ dev_set_drvdata(dev, NULL); ++ return -ENODEV; ++ } ++ ++ /* Get the cell-index */ ++ _errno = of_property_read_u32(mac_node, "cell-index", &cell_index); ++ if (unlikely(_errno)) { ++ dev_err(dev, "Cannot read cell-index of mac node %s from device tree\n", ++ mac_node->full_name); ++ goto _return_dev_set_drvdata; ++ } ++ mac_dev->cell_index = (uint8_t)cell_index; ++ ++ /* Get the MAC address */ ++ mac_addr = of_get_mac_address(mac_node); ++ if (unlikely(mac_addr == NULL)) { ++ dev_err(dev, "of_get_mac_address(%s) failed\n", ++ mac_node->full_name); ++ _errno = -EINVAL; ++ goto _return_dev_set_drvdata; ++ } ++ memcpy(mac_dev->addr, mac_addr, sizeof(mac_dev->addr)); ++ ++ /* Verify the number of port handles */ ++ nph = of_count_phandle_with_args(mac_node, "fsl,port-handles", NULL); ++ if (unlikely(nph < 0)) { ++ dev_err(dev, "Cannot read port handles of mac node %s from device tree\n", ++ mac_node->full_name); ++ _errno = nph; ++ goto _return_dev_set_drvdata; ++ } ++ ++ if (nph != ARRAY_SIZE(mac_dev->port_dev)) { ++ dev_err(dev, "Not supported number of port handles of mac node %s from device tree\n", ++ mac_node->full_name); ++ _errno = -EINVAL; ++ goto _return_dev_set_drvdata; ++ } ++ ++ for_each_port_device(i, mac_dev->port_dev) { ++ dev_node = of_parse_phandle(mac_node, "fsl,port-handles", i); ++ if (unlikely(dev_node == NULL)) { ++ dev_err(dev, "Cannot find port node referenced by mac node %s from device tree\n", ++ mac_node->full_name); ++ _errno = -EINVAL; ++ goto _return_of_node_put; ++ } ++ ++ of_dev = of_find_device_by_node(dev_node); ++ if (unlikely(of_dev == NULL)) { ++ dev_err(dev, "of_find_device_by_node(%s) failed\n", ++ dev_node->full_name); ++ _errno = -EINVAL; ++ goto _return_of_node_put; ++ } ++ ++ mac_dev->port_dev[i] = fm_port_bind(&of_dev->dev); ++ if (unlikely(mac_dev->port_dev[i] == NULL)) { ++ dev_err(dev, "dev_get_drvdata(%s) failed\n", ++ dev_node->full_name); ++ _errno = -EINVAL; ++ goto _return_of_node_put; ++ } ++ of_node_put(dev_node); ++ } ++ ++ /* Get the PHY connection type */ ++ _errno = of_property_read_string(mac_node, "phy-connection-type", ++ &char_prop); ++ if (unlikely(_errno)) { ++ dev_warn(dev, ++ "Cannot read PHY connection type of mac node %s from device tree. Defaulting to MII\n", ++ mac_node->full_name); ++ mac_dev->phy_if = PHY_INTERFACE_MODE_MII; ++ } else ++ mac_dev->phy_if = str2phy(char_prop); ++ ++ mac_dev->link = false; ++ mac_dev->half_duplex = false; ++ mac_dev->speed = phy2speed[mac_dev->phy_if]; ++ mac_dev->max_speed = mac_dev->speed; ++ mac_dev->if_support = DTSEC_SUPPORTED; ++ /* We don't support half-duplex in SGMII mode */ ++ if (strstr(char_prop, "sgmii")) ++ mac_dev->if_support &= ~(SUPPORTED_10baseT_Half | ++ SUPPORTED_100baseT_Half); ++ ++ if (strstr(char_prop, "sgmii-2500")) ++ mac_dev->if_support &= ~(SUPPORTED_10baseT_Half | ++ SUPPORTED_100baseT_Half); ++ ++ /* Gigabit support (no half-duplex) */ ++ if (mac_dev->max_speed == 1000) ++ mac_dev->if_support |= SUPPORTED_1000baseT_Full; ++ ++ /* The 10G interface only supports one mode */ ++ if (strstr(char_prop, "xgmii")) ++ mac_dev->if_support = SUPPORTED_10000baseT_Full; ++ ++ /* Get the rest of the PHY information */ ++ mac_dev->phy_node = of_parse_phandle(mac_node, "phy-handle", 0); ++ if (mac_dev->phy_node == NULL) { ++ u32 phy_id; ++ ++ _errno = of_property_read_u32(mac_node, "fixed-link", &phy_id); ++ if (_errno) { ++ dev_err(dev, "No PHY (or fixed link) found\n"); ++ _errno = -EINVAL; ++ goto _return_dev_set_drvdata; ++ } ++ ++ sprintf(mac_dev->fixed_bus_id, PHY_ID_FMT, "fixed-0", ++ phy_id); ++ } ++ ++ _errno = mac_dev->init(mac_dev); ++ if (unlikely(_errno < 0)) { ++ dev_err(dev, "mac_dev->init() = %d\n", _errno); ++ goto _return_dev_set_drvdata; ++ } ++ ++ /* pause frame autonegotiation enabled*/ ++ mac_dev->autoneg_pause = true; ++ ++ /* by intializing the values to false, force FMD to enable PAUSE frames ++ * on RX and TX ++ */ ++ mac_dev->rx_pause_req = mac_dev->tx_pause_req = true; ++ mac_dev->rx_pause_active = mac_dev->tx_pause_active = false; ++ _errno = set_mac_active_pause(mac_dev, true, true); ++ if (unlikely(_errno < 0)) ++ dev_err(dev, "set_mac_active_pause() = %d\n", _errno); ++ ++ dev_info(dev, ++ "FMan MAC address: %02hx:%02hx:%02hx:%02hx:%02hx:%02hx\n", ++ mac_dev->addr[0], mac_dev->addr[1], mac_dev->addr[2], ++ mac_dev->addr[3], mac_dev->addr[4], mac_dev->addr[5]); ++ ++ goto _return; ++ ++_return_of_node_put: ++ of_node_put(dev_node); ++_return_dev_set_drvdata: ++ dev_set_drvdata(dev, NULL); ++_return: ++ return _errno; ++} ++ ++static int __cold mac_remove(struct platform_device *of_dev) ++{ ++ int i, _errno; ++ struct device *dev; ++ struct mac_device *mac_dev; ++ ++ dev = &of_dev->dev; ++ mac_dev = (struct mac_device *)dev_get_drvdata(dev); ++ ++ for_each_port_device(i, mac_dev->port_dev) ++ fm_port_unbind(mac_dev->port_dev[i]); ++ ++ fm_unbind(mac_dev->fm_dev); ++ ++ _errno = free_macdev(mac_dev); ++ ++ return _errno; ++} ++ ++static struct platform_driver mac_driver = { ++ .driver = { ++ .name = KBUILD_MODNAME, ++ .of_match_table = mac_match, ++ .owner = THIS_MODULE, ++ }, ++ .probe = mac_probe, ++ .remove = mac_remove ++}; ++ ++static int __init __cold mac_load(void) ++{ ++ int _errno; ++ ++ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ pr_info(KBUILD_MODNAME ": %s (" VERSION ")\n", ++ mac_driver_description); ++ ++ _errno = platform_driver_register(&mac_driver); ++ if (unlikely(_errno < 0)) { ++ pr_err(KBUILD_MODNAME ": %s:%hu:%s(): platform_driver_register() = %d\n", ++ KBUILD_BASENAME".c", __LINE__, __func__, _errno); ++ goto _return; ++ } ++ ++ goto _return; ++ ++_return: ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ return _errno; ++} ++module_init(mac_load); ++ ++static void __exit __cold mac_unload(void) ++{ ++ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ platform_driver_unregister(&mac_driver); ++ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++} ++module_exit(mac_unload); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/mac.h b/drivers/net/ethernet/freescale/sdk_dpaa/mac.h +new file mode 100644 +index 0000000..16d5a0d +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/mac.h +@@ -0,0 +1,134 @@ ++/* Copyright 2008-2011 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 __MAC_H ++#define __MAC_H ++ ++#include /* struct device, BUS_ID_SIZE */ ++#include /* ETH_ALEN */ ++#include /* phy_interface_t, struct phy_device */ ++#include ++ ++#include "lnxwrp_fsl_fman.h" /* struct port_device */ ++ ++enum {DTSEC, XGMAC, MEMAC}; ++ ++struct mac_device { ++ struct device *dev; ++ void *priv; ++ uint8_t cell_index; ++ struct resource *res; ++ void __iomem *vaddr; ++ uint8_t addr[ETH_ALEN]; ++ bool promisc; ++ ++ struct fm *fm_dev; ++ struct fm_port *port_dev[2]; ++ ++ phy_interface_t phy_if; ++ u32 if_support; ++ bool link; ++ bool half_duplex; ++ uint16_t speed; ++ uint16_t max_speed; ++ struct device_node *phy_node; ++ char fixed_bus_id[MII_BUS_ID_SIZE + 3]; ++ struct device_node *tbi_node; ++ struct phy_device *phy_dev; ++ void *fm; ++ /* List of multicast addresses */ ++ struct list_head mc_addr_list; ++ ++ bool autoneg_pause; ++ bool rx_pause_req; ++ bool tx_pause_req; ++ bool rx_pause_active; ++ bool tx_pause_active; ++ ++ struct fm_mac_dev *(*get_mac_handle)(struct mac_device *mac_dev); ++ int (*init_phy)(struct net_device *net_dev, struct mac_device *mac_dev); ++ int (*init)(struct mac_device *mac_dev); ++ int (*start)(struct mac_device *mac_dev); ++ int (*stop)(struct mac_device *mac_dev); ++ int (*set_promisc)(struct fm_mac_dev *fm_mac_dev, bool enable); ++ int (*change_addr)(struct fm_mac_dev *fm_mac_dev, uint8_t *addr); ++ int (*set_multi)(struct net_device *net_dev, ++ struct mac_device *mac_dev); ++ int (*uninit)(struct fm_mac_dev *fm_mac_dev); ++ int (*ptp_enable)(struct fm_mac_dev *fm_mac_dev); ++ int (*ptp_disable)(struct fm_mac_dev *fm_mac_dev); ++ int (*set_rx_pause)(struct fm_mac_dev *fm_mac_dev, bool en); ++ int (*set_tx_pause)(struct fm_mac_dev *fm_mac_dev, bool en); ++ int (*fm_rtc_enable)(struct fm *fm_dev); ++ int (*fm_rtc_disable)(struct fm *fm_dev); ++ int (*fm_rtc_get_cnt)(struct fm *fm_dev, uint64_t *ts); ++ int (*fm_rtc_set_cnt)(struct fm *fm_dev, uint64_t ts); ++ int (*fm_rtc_get_drift)(struct fm *fm_dev, uint32_t *drift); ++ int (*fm_rtc_set_drift)(struct fm *fm_dev, uint32_t drift); ++ int (*fm_rtc_set_alarm)(struct fm *fm_dev, uint32_t id, uint64_t time); ++ int (*fm_rtc_set_fiper)(struct fm *fm_dev, uint32_t id, ++ uint64_t fiper); ++#ifdef CONFIG_PTP_1588_CLOCK_DPAA ++ int (*fm_rtc_enable_interrupt)(struct fm *fm_dev, uint32_t events); ++ int (*fm_rtc_disable_interrupt)(struct fm *fm_dev, uint32_t events); ++#endif ++ int (*set_wol)(struct fm_port *port, struct fm_mac_dev *fm_mac_dev, ++ bool en); ++ int (*dump_mac_regs)(struct mac_device *h_mac, char *buf, int nn); ++ int (*dump_mac_rx_stats)(struct mac_device *h_mac, char *buf, int nn); ++ int (*dump_mac_tx_stats)(struct mac_device *h_mac, char *buf, int nn); ++}; ++ ++struct mac_address { ++ uint8_t addr[ETH_ALEN]; ++ struct list_head list; ++}; ++ ++#define get_fm_handle(net_dev) \ ++ (((struct dpa_priv_s *)netdev_priv(net_dev))->mac_dev->fm_dev) ++ ++#define for_each_port_device(i, port_dev) \ ++ for (i = 0; i < ARRAY_SIZE(port_dev); i++) ++ ++static inline __attribute((nonnull)) void *macdev_priv( ++ const struct mac_device *mac_dev) ++{ ++ return (void *)mac_dev + sizeof(*mac_dev); ++} ++ ++extern const char *mac_driver_description; ++extern const size_t mac_sizeof_priv[]; ++extern void (*const mac_setup[])(struct mac_device *mac_dev); ++ ++int set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx); ++void get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause, bool *tx_pause); ++ ++#endif /* __MAC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/offline_port.c b/drivers/net/ethernet/freescale/sdk_dpaa/offline_port.c +new file mode 100644 +index 0000000..ddbfdce +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/offline_port.c +@@ -0,0 +1,848 @@ ++/* Copyright 2011-2012 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. ++ */ ++ ++/* Offline Parsing / Host Command port driver for FSL QorIQ FMan. ++ * Validates device-tree configuration and sets up the offline ports. ++ */ ++ ++#ifdef CONFIG_FSL_DPAA_ETH_DEBUG ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \ ++ KBUILD_BASENAME".c", __LINE__, __func__ ++#else ++#define pr_fmt(fmt) \ ++ KBUILD_MODNAME ": " fmt ++#endif ++ ++ ++#include ++#include ++#include ++#include ++ ++#include "offline_port.h" ++#include "dpaa_eth.h" ++#include "dpaa_eth_common.h" ++ ++#define OH_MOD_DESCRIPTION "FSL FMan Offline Parsing port driver" ++/* Manip extra space and data alignment for fragmentation */ ++#define FRAG_MANIP_SPACE 128 ++#define FRAG_DATA_ALIGN 64 ++ ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_AUTHOR("Bogdan Hamciuc "); ++MODULE_DESCRIPTION(OH_MOD_DESCRIPTION); ++ ++ ++static const struct of_device_id oh_port_match_table[] = { ++ { ++ .compatible = "fsl,dpa-oh" ++ }, ++ { ++ .compatible = "fsl,dpa-oh-shared" ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, oh_port_match_table); ++ ++#ifdef CONFIG_PM ++ ++static int oh_suspend(struct device *dev) ++{ ++ struct dpa_oh_config_s *oh_config; ++ ++ oh_config = dev_get_drvdata(dev); ++ return fm_port_suspend(oh_config->oh_port); ++} ++ ++static int oh_resume(struct device *dev) ++{ ++ struct dpa_oh_config_s *oh_config; ++ ++ oh_config = dev_get_drvdata(dev); ++ return fm_port_resume(oh_config->oh_port); ++} ++ ++static const struct dev_pm_ops oh_pm_ops = { ++ .suspend = oh_suspend, ++ .resume = oh_resume, ++}; ++ ++#define OH_PM_OPS (&oh_pm_ops) ++ ++#else /* CONFIG_PM */ ++ ++#define OH_PM_OPS NULL ++ ++#endif /* CONFIG_PM */ ++ ++/* Creates Frame Queues */ ++static uint32_t oh_fq_create(struct qman_fq *fq, ++ uint32_t fq_id, uint16_t channel, ++ uint16_t wq_id) ++{ ++ struct qm_mcc_initfq fq_opts; ++ uint32_t create_flags, init_flags; ++ uint32_t ret = 0; ++ ++ if (fq == NULL) ++ return 1; ++ ++ /* Set flags for FQ create */ ++ create_flags = QMAN_FQ_FLAG_LOCKED | QMAN_FQ_FLAG_TO_DCPORTAL; ++ ++ /* Create frame queue */ ++ ret = qman_create_fq(fq_id, create_flags, fq); ++ if (ret != 0) ++ return 1; ++ ++ /* Set flags for FQ init */ ++ init_flags = QMAN_INITFQ_FLAG_SCHED; ++ ++ /* Set FQ init options. Specify destination WQ ID and channel */ ++ fq_opts.we_mask = QM_INITFQ_WE_DESTWQ; ++ fq_opts.fqd.dest.wq = wq_id; ++ fq_opts.fqd.dest.channel = channel; ++ ++ /* Initialize frame queue */ ++ ret = qman_init_fq(fq, init_flags, &fq_opts); ++ if (ret != 0) { ++ qman_destroy_fq(fq, 0); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void dump_fq(struct device *dev, int fqid, uint16_t channel) ++{ ++ if (channel) { ++ /* display fqs with a valid (!= 0) destination channel */ ++ dev_info(dev, "FQ ID:%d Channel ID:%d\n", fqid, channel); ++ } ++} ++ ++static void dump_fq_duple(struct device *dev, struct qman_fq *fqs, ++ int fqs_count, uint16_t channel_id) ++{ ++ int i; ++ for (i = 0; i < fqs_count; i++) ++ dump_fq(dev, (fqs + i)->fqid, channel_id); ++} ++ ++static void dump_oh_config(struct device *dev, struct dpa_oh_config_s *conf) ++{ ++ struct list_head *fq_list; ++ struct fq_duple *fqd; ++ int i; ++ ++ dev_info(dev, "Default egress frame queue: %d\n", conf->default_fqid); ++ dev_info(dev, "Default error frame queue: %d\n", conf->error_fqid); ++ ++ /* TX queues (old initialization) */ ++ dev_info(dev, "Initialized queues:"); ++ for (i = 0; i < conf->egress_cnt; i++) ++ dump_fq_duple(dev, conf->egress_fqs, conf->egress_cnt, ++ conf->channel); ++ ++ /* initialized ingress queues */ ++ list_for_each(fq_list, &conf->fqs_ingress_list) { ++ fqd = list_entry(fq_list, struct fq_duple, fq_list); ++ dump_fq_duple(dev, fqd->fqs, fqd->fqs_count, fqd->channel_id); ++ } ++ ++ /* initialized egress queues */ ++ list_for_each(fq_list, &conf->fqs_egress_list) { ++ fqd = list_entry(fq_list, struct fq_duple, fq_list); ++ dump_fq_duple(dev, fqd->fqs, fqd->fqs_count, fqd->channel_id); ++ } ++} ++ ++/* Destroys Frame Queues */ ++static void oh_fq_destroy(struct qman_fq *fq) ++{ ++ int _errno = 0; ++ ++ _errno = qman_retire_fq(fq, NULL); ++ if (unlikely(_errno < 0)) ++ pr_err(KBUILD_MODNAME": %s:%hu:%s(): qman_retire_fq(%u)=%d\n", ++ KBUILD_BASENAME".c", __LINE__, __func__, ++ qman_fq_fqid(fq), _errno); ++ ++ _errno = qman_oos_fq(fq); ++ if (unlikely(_errno < 0)) { ++ pr_err(KBUILD_MODNAME": %s:%hu:%s(): qman_oos_fq(%u)=%d\n", ++ KBUILD_BASENAME".c", __LINE__, __func__, ++ qman_fq_fqid(fq), _errno); ++ } ++ ++ qman_destroy_fq(fq, 0); ++} ++ ++/* Allocation code for the OH port's PCD frame queues */ ++static int __cold oh_alloc_pcd_fqids(struct device *dev, ++ uint32_t num, ++ uint8_t alignment, ++ uint32_t *base_fqid) ++{ ++ dev_crit(dev, "callback not implemented!\n"); ++ BUG(); ++ ++ return 0; ++} ++ ++static int __cold oh_free_pcd_fqids(struct device *dev, uint32_t base_fqid) ++{ ++ dev_crit(dev, "callback not implemented!\n"); ++ BUG(); ++ ++ return 0; ++} ++ ++static void oh_set_buffer_layout(struct fm_port *port, ++ struct dpa_buffer_layout_s *layout) ++{ ++ struct fm_port_params params; ++ ++ layout->priv_data_size = DPA_TX_PRIV_DATA_SIZE; ++ layout->parse_results = true; ++ layout->hash_results = true; ++ layout->time_stamp = false; ++ ++ fm_port_get_buff_layout_ext_params(port, ¶ms); ++ layout->manip_extra_space = params.manip_extra_space; ++ layout->data_align = params.data_align; ++} ++ ++static int ++oh_port_probe(struct platform_device *_of_dev) ++{ ++ struct device *dpa_oh_dev; ++ struct device_node *dpa_oh_node; ++ int lenp, _errno = 0, fq_idx, duple_idx; ++ int n_size, i, j, ret, duples_count; ++ struct platform_device *oh_of_dev; ++ struct device_node *oh_node, *bpool_node = NULL, *root_node; ++ struct device *oh_dev; ++ struct dpa_oh_config_s *oh_config = NULL; ++ const __be32 *oh_all_queues; ++ const __be32 *channel_ids; ++ const __be32 *oh_tx_queues; ++ uint32_t queues_count; ++ uint32_t crt_fqid_base; ++ uint32_t crt_fq_count; ++ bool frag_enabled = false; ++ struct fm_port_params oh_port_tx_params; ++ struct fm_port_pcd_param oh_port_pcd_params; ++ struct dpa_buffer_layout_s buf_layout; ++ ++ /* True if the current partition owns the OH port. */ ++ bool init_oh_port; ++ ++ const struct of_device_id *match; ++ int crt_ext_pools_count; ++ u32 ext_pool_size; ++ u32 port_id; ++ u32 channel_id; ++ ++ int channel_ids_count; ++ int channel_idx; ++ struct fq_duple *fqd; ++ struct list_head *fq_list, *fq_list_tmp; ++ ++ const __be32 *bpool_cfg; ++ uint32_t bpid; ++ ++ memset(&oh_port_tx_params, 0, sizeof(oh_port_tx_params)); ++ dpa_oh_dev = &_of_dev->dev; ++ dpa_oh_node = dpa_oh_dev->of_node; ++ BUG_ON(dpa_oh_node == NULL); ++ ++ match = of_match_device(oh_port_match_table, dpa_oh_dev); ++ if (!match) ++ return -EINVAL; ++ ++ dev_dbg(dpa_oh_dev, "Probing OH port...\n"); ++ ++ /* Find the referenced OH node */ ++ oh_node = of_parse_phandle(dpa_oh_node, "fsl,fman-oh-port", 0); ++ if (oh_node == NULL) { ++ dev_err(dpa_oh_dev, ++ "Can't find OH node referenced from node %s\n", ++ dpa_oh_node->full_name); ++ return -EINVAL; ++ } ++ dev_info(dpa_oh_dev, "Found OH node handle compatible with %s\n", ++ match->compatible); ++ ++ _errno = of_property_read_u32(oh_node, "cell-index", &port_id); ++ if (_errno) { ++ dev_err(dpa_oh_dev, "No port id found in node %s\n", ++ dpa_oh_node->full_name); ++ goto return_kfree; ++ } ++ ++ _errno = of_property_read_u32(oh_node, "fsl,qman-channel-id", ++ &channel_id); ++ if (_errno) { ++ dev_err(dpa_oh_dev, "No channel id found in node %s\n", ++ dpa_oh_node->full_name); ++ goto return_kfree; ++ } ++ ++ oh_of_dev = of_find_device_by_node(oh_node); ++ BUG_ON(oh_of_dev == NULL); ++ oh_dev = &oh_of_dev->dev; ++ ++ /* The OH port must be initialized exactly once. ++ * The following scenarios are of interest: ++ * - the node is Linux-private (will always initialize it); ++ * - the node is shared between two Linux partitions ++ * (only one of them will initialize it); ++ * - the node is shared between a Linux and a LWE partition ++ * (Linux will initialize it) - "fsl,dpa-oh-shared" ++ */ ++ ++ /* Check if the current partition owns the OH port ++ * and ought to initialize it. It may be the case that we leave this ++ * to another (also Linux) partition. ++ */ ++ init_oh_port = strcmp(match->compatible, "fsl,dpa-oh-shared"); ++ ++ /* If we aren't the "owner" of the OH node, we're done here. */ ++ if (!init_oh_port) { ++ dev_dbg(dpa_oh_dev, ++ "Not owning the shared OH port %s, will not initialize it.\n", ++ oh_node->full_name); ++ of_node_put(oh_node); ++ return 0; ++ } ++ ++ /* Allocate OH dev private data */ ++ oh_config = devm_kzalloc(dpa_oh_dev, sizeof(*oh_config), GFP_KERNEL); ++ if (oh_config == NULL) { ++ dev_err(dpa_oh_dev, ++ "Can't allocate private data for OH node %s referenced from node %s!\n", ++ oh_node->full_name, dpa_oh_node->full_name); ++ _errno = -ENOMEM; ++ goto return_kfree; ++ } ++ ++ INIT_LIST_HEAD(&oh_config->fqs_ingress_list); ++ INIT_LIST_HEAD(&oh_config->fqs_egress_list); ++ ++ /* FQs that enter OH port */ ++ lenp = 0; ++ oh_all_queues = of_get_property(dpa_oh_node, ++ "fsl,qman-frame-queues-ingress", &lenp); ++ if (lenp % (2 * sizeof(*oh_all_queues))) { ++ dev_warn(dpa_oh_dev, ++ "Wrong ingress queues format for OH node %s referenced from node %s!\n", ++ oh_node->full_name, dpa_oh_node->full_name); ++ /* just ignore the last unpaired value */ ++ } ++ ++ duples_count = lenp / (2 * sizeof(*oh_all_queues)); ++ dev_err(dpa_oh_dev, "Allocating %d ingress frame queues duples\n", ++ duples_count); ++ for (duple_idx = 0; duple_idx < duples_count; duple_idx++) { ++ crt_fqid_base = be32_to_cpu(oh_all_queues[2 * duple_idx]); ++ crt_fq_count = be32_to_cpu(oh_all_queues[2 * duple_idx + 1]); ++ ++ fqd = devm_kzalloc(dpa_oh_dev, ++ sizeof(struct fq_duple), GFP_KERNEL); ++ if (!fqd) { ++ dev_err(dpa_oh_dev, "Can't allocate structures for ingress frame queues for OH node %s referenced from node %s!\n", ++ oh_node->full_name, ++ dpa_oh_node->full_name); ++ _errno = -ENOMEM; ++ goto return_kfree; ++ } ++ ++ fqd->fqs = devm_kzalloc(dpa_oh_dev, ++ crt_fq_count * sizeof(struct qman_fq), ++ GFP_KERNEL); ++ if (!fqd->fqs) { ++ dev_err(dpa_oh_dev, "Can't allocate structures for ingress frame queues for OH node %s referenced from node %s!\n", ++ oh_node->full_name, ++ dpa_oh_node->full_name); ++ _errno = -ENOMEM; ++ goto return_kfree; ++ } ++ ++ for (j = 0; j < crt_fq_count; j++) ++ (fqd->fqs + j)->fqid = crt_fqid_base + j; ++ fqd->fqs_count = crt_fq_count; ++ fqd->channel_id = (uint16_t)channel_id; ++ list_add(&fqd->fq_list, &oh_config->fqs_ingress_list); ++ } ++ ++ /* create the ingress queues */ ++ list_for_each(fq_list, &oh_config->fqs_ingress_list) { ++ fqd = list_entry(fq_list, struct fq_duple, fq_list); ++ ++ for (j = 0; j < fqd->fqs_count; j++) { ++ ret = oh_fq_create(fqd->fqs + j, ++ (fqd->fqs + j)->fqid, ++ fqd->channel_id, 3); ++ if (ret != 0) { ++ dev_err(dpa_oh_dev, "Unable to create ingress frame queue %d for OH node %s referenced from node %s!\n", ++ (fqd->fqs + j)->fqid, ++ oh_node->full_name, ++ dpa_oh_node->full_name); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ } ++ } ++ ++ /* FQs that exit OH port */ ++ lenp = 0; ++ oh_all_queues = of_get_property(dpa_oh_node, ++ "fsl,qman-frame-queues-egress", &lenp); ++ if (lenp % (2 * sizeof(*oh_all_queues))) { ++ dev_warn(dpa_oh_dev, ++ "Wrong egress queues format for OH node %s referenced from node %s!\n", ++ oh_node->full_name, dpa_oh_node->full_name); ++ /* just ignore the last unpaired value */ ++ } ++ ++ duples_count = lenp / (2 * sizeof(*oh_all_queues)); ++ dev_dbg(dpa_oh_dev, "Allocating %d egress frame queues duples\n", ++ duples_count); ++ for (duple_idx = 0; duple_idx < duples_count; duple_idx++) { ++ crt_fqid_base = be32_to_cpu(oh_all_queues[2 * duple_idx]); ++ crt_fq_count = be32_to_cpu(oh_all_queues[2 * duple_idx + 1]); ++ ++ fqd = devm_kzalloc(dpa_oh_dev, ++ sizeof(struct fq_duple), GFP_KERNEL); ++ if (!fqd) { ++ dev_err(dpa_oh_dev, "Can't allocate structures for egress frame queues for OH node %s referenced from node %s!\n", ++ oh_node->full_name, ++ dpa_oh_node->full_name); ++ _errno = -ENOMEM; ++ goto return_kfree; ++ } ++ ++ fqd->fqs = devm_kzalloc(dpa_oh_dev, ++ crt_fq_count * sizeof(struct qman_fq), ++ GFP_KERNEL); ++ if (!fqd->fqs) { ++ dev_err(dpa_oh_dev, ++ "Can't allocate structures for egress frame queues for OH node %s referenced from node %s!\n", ++ oh_node->full_name, ++ dpa_oh_node->full_name); ++ _errno = -ENOMEM; ++ goto return_kfree; ++ } ++ ++ for (j = 0; j < crt_fq_count; j++) ++ (fqd->fqs + j)->fqid = crt_fqid_base + j; ++ fqd->fqs_count = crt_fq_count; ++ /* channel ID is specified in another attribute */ ++ fqd->channel_id = 0; ++ list_add_tail(&fqd->fq_list, &oh_config->fqs_egress_list); ++ ++ /* allocate the queue */ ++ ++ } ++ ++ /* channel_ids for FQs that exit OH port */ ++ lenp = 0; ++ channel_ids = of_get_property(dpa_oh_node, ++ "fsl,qman-channel-ids-egress", &lenp); ++ ++ channel_ids_count = lenp / (sizeof(*channel_ids)); ++ if (channel_ids_count != duples_count) { ++ dev_warn(dpa_oh_dev, ++ "Not all egress queues have a channel id for OH node %s referenced from node %s!\n", ++ oh_node->full_name, dpa_oh_node->full_name); ++ /* just ignore the queues that do not have a Channel ID */ ++ } ++ ++ channel_idx = 0; ++ list_for_each(fq_list, &oh_config->fqs_egress_list) { ++ if (channel_idx + 1 > channel_ids_count) ++ break; ++ fqd = list_entry(fq_list, struct fq_duple, fq_list); ++ fqd->channel_id = ++ (uint16_t)be32_to_cpu(channel_ids[channel_idx++]); ++ } ++ ++ /* create egress queues */ ++ list_for_each(fq_list, &oh_config->fqs_egress_list) { ++ fqd = list_entry(fq_list, struct fq_duple, fq_list); ++ ++ if (fqd->channel_id == 0) { ++ /* missing channel id in dts */ ++ continue; ++ } ++ ++ for (j = 0; j < fqd->fqs_count; j++) { ++ ret = oh_fq_create(fqd->fqs + j, ++ (fqd->fqs + j)->fqid, ++ fqd->channel_id, 3); ++ if (ret != 0) { ++ dev_err(dpa_oh_dev, "Unable to create egress frame queue %d for OH node %s referenced from node %s!\n", ++ (fqd->fqs + j)->fqid, ++ oh_node->full_name, ++ dpa_oh_node->full_name); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ } ++ } ++ ++ /* Read FQ ids/nums for the DPA OH node */ ++ oh_all_queues = of_get_property(dpa_oh_node, ++ "fsl,qman-frame-queues-oh", &lenp); ++ if (oh_all_queues == NULL) { ++ dev_err(dpa_oh_dev, ++ "No frame queues have been defined for OH node %s referenced from node %s\n", ++ oh_node->full_name, dpa_oh_node->full_name); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ ++ /* Check that the OH error and default FQs are there */ ++ BUG_ON(lenp % (2 * sizeof(*oh_all_queues))); ++ queues_count = lenp / (2 * sizeof(*oh_all_queues)); ++ if (queues_count != 2) { ++ dev_err(dpa_oh_dev, ++ "Error and Default queues must be defined for OH node %s referenced from node %s\n", ++ oh_node->full_name, dpa_oh_node->full_name); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ ++ /* Read the FQIDs defined for this OH port */ ++ dev_dbg(dpa_oh_dev, "Reading %d queues...\n", queues_count); ++ fq_idx = 0; ++ ++ /* Error FQID - must be present */ ++ crt_fqid_base = be32_to_cpu(oh_all_queues[fq_idx++]); ++ crt_fq_count = be32_to_cpu(oh_all_queues[fq_idx++]); ++ if (crt_fq_count != 1) { ++ dev_err(dpa_oh_dev, ++ "Only 1 Error FQ allowed in OH node %s referenced from node %s (read: %d FQIDs).\n", ++ oh_node->full_name, dpa_oh_node->full_name, ++ crt_fq_count); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ oh_config->error_fqid = crt_fqid_base; ++ dev_dbg(dpa_oh_dev, "Read Error FQID 0x%x for OH port %s.\n", ++ oh_config->error_fqid, oh_node->full_name); ++ ++ /* Default FQID - must be present */ ++ crt_fqid_base = be32_to_cpu(oh_all_queues[fq_idx++]); ++ crt_fq_count = be32_to_cpu(oh_all_queues[fq_idx++]); ++ if (crt_fq_count != 1) { ++ dev_err(dpa_oh_dev, ++ "Only 1 Default FQ allowed in OH node %s referenced from %s (read: %d FQIDs).\n", ++ oh_node->full_name, dpa_oh_node->full_name, ++ crt_fq_count); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ oh_config->default_fqid = crt_fqid_base; ++ dev_dbg(dpa_oh_dev, "Read Default FQID 0x%x for OH port %s.\n", ++ oh_config->default_fqid, oh_node->full_name); ++ ++ /* TX FQID - presence is optional */ ++ oh_tx_queues = of_get_property(dpa_oh_node, "fsl,qman-frame-queues-tx", ++ &lenp); ++ if (oh_tx_queues == NULL) { ++ dev_dbg(dpa_oh_dev, ++ "No tx queues have been defined for OH node %s referenced from node %s\n", ++ oh_node->full_name, dpa_oh_node->full_name); ++ goto config_port; ++ } ++ ++ /* Check that queues-tx has only a base and a count defined */ ++ BUG_ON(lenp % (2 * sizeof(*oh_tx_queues))); ++ queues_count = lenp / (2 * sizeof(*oh_tx_queues)); ++ if (queues_count != 1) { ++ dev_err(dpa_oh_dev, ++ "TX queues must be defined in only one tuple for OH node %s referenced from node %s\n", ++ oh_node->full_name, dpa_oh_node->full_name); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ ++ fq_idx = 0; ++ crt_fqid_base = be32_to_cpu(oh_tx_queues[fq_idx++]); ++ crt_fq_count = be32_to_cpu(oh_tx_queues[fq_idx++]); ++ oh_config->egress_cnt = crt_fq_count; ++ ++ /* Allocate TX queues */ ++ dev_dbg(dpa_oh_dev, "Allocating %d queues for TX...\n", crt_fq_count); ++ oh_config->egress_fqs = devm_kzalloc(dpa_oh_dev, ++ crt_fq_count * sizeof(struct qman_fq), GFP_KERNEL); ++ if (oh_config->egress_fqs == NULL) { ++ dev_err(dpa_oh_dev, ++ "Can't allocate private data for TX queues for OH node %s referenced from node %s!\n", ++ oh_node->full_name, dpa_oh_node->full_name); ++ _errno = -ENOMEM; ++ goto return_kfree; ++ } ++ ++ /* Create TX queues */ ++ for (i = 0; i < crt_fq_count; i++) { ++ ret = oh_fq_create(oh_config->egress_fqs + i, ++ crt_fqid_base + i, (uint16_t)channel_id, 3); ++ if (ret != 0) { ++ dev_err(dpa_oh_dev, ++ "Unable to create TX frame queue %d for OH node %s referenced from node %s!\n", ++ crt_fqid_base + i, oh_node->full_name, ++ dpa_oh_node->full_name); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ } ++ ++config_port: ++ /* Get a handle to the fm_port so we can set ++ * its configuration params ++ */ ++ oh_config->oh_port = fm_port_bind(oh_dev); ++ if (oh_config->oh_port == NULL) { ++ dev_err(dpa_oh_dev, "NULL drvdata from fm port dev %s!\n", ++ oh_node->full_name); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ ++ oh_set_buffer_layout(oh_config->oh_port, &buf_layout); ++ ++ /* read the pool handlers */ ++ crt_ext_pools_count = of_count_phandle_with_args(dpa_oh_node, ++ "fsl,bman-buffer-pools", NULL); ++ if (crt_ext_pools_count <= 0) { ++ dev_info(dpa_oh_dev, ++ "OH port %s has no buffer pool. Fragmentation will not be enabled\n", ++ oh_node->full_name); ++ goto init_port; ++ } ++ ++ /* used for reading ext_pool_size*/ ++ root_node = of_find_node_by_path("/"); ++ if (root_node == NULL) { ++ dev_err(dpa_oh_dev, "of_find_node_by_path(/) failed\n"); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ ++ n_size = of_n_size_cells(root_node); ++ of_node_put(root_node); ++ ++ dev_dbg(dpa_oh_dev, "OH port number of pools = %d\n", ++ crt_ext_pools_count); ++ ++ oh_port_tx_params.num_pools = (uint8_t)crt_ext_pools_count; ++ ++ for (i = 0; i < crt_ext_pools_count; i++) { ++ bpool_node = of_parse_phandle(dpa_oh_node, ++ "fsl,bman-buffer-pools", i); ++ if (bpool_node == NULL) { ++ dev_err(dpa_oh_dev, "Invalid Buffer pool node\n"); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ ++ _errno = of_property_read_u32(bpool_node, "fsl,bpid", &bpid); ++ if (_errno) { ++ dev_err(dpa_oh_dev, "Invalid Buffer Pool ID\n"); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ ++ oh_port_tx_params.pool_param[i].id = (uint8_t)bpid; ++ dev_dbg(dpa_oh_dev, "OH port bpool id = %u\n", bpid); ++ ++ bpool_cfg = of_get_property(bpool_node, ++ "fsl,bpool-ethernet-cfg", &lenp); ++ if (bpool_cfg == NULL) { ++ dev_err(dpa_oh_dev, "Invalid Buffer pool config params\n"); ++ _errno = -EINVAL; ++ goto return_kfree; ++ } ++ ++ ext_pool_size = of_read_number(bpool_cfg + n_size, n_size); ++ oh_port_tx_params.pool_param[i].size = (uint16_t)ext_pool_size; ++ dev_dbg(dpa_oh_dev, "OH port bpool size = %u\n", ++ ext_pool_size); ++ of_node_put(bpool_node); ++ ++ } ++ ++ if (buf_layout.data_align != FRAG_DATA_ALIGN || ++ buf_layout.manip_extra_space != FRAG_MANIP_SPACE) ++ goto init_port; ++ ++ frag_enabled = true; ++ dev_info(dpa_oh_dev, "IP Fragmentation enabled for OH port %d", ++ port_id); ++ ++init_port: ++ of_node_put(oh_node); ++ /* Set Tx params */ ++ dpaa_eth_init_port(tx, oh_config->oh_port, oh_port_tx_params, ++ oh_config->error_fqid, oh_config->default_fqid, (&buf_layout), ++ frag_enabled); ++ /* Set PCD params */ ++ oh_port_pcd_params.cba = oh_alloc_pcd_fqids; ++ oh_port_pcd_params.cbf = oh_free_pcd_fqids; ++ oh_port_pcd_params.dev = dpa_oh_dev; ++ fm_port_pcd_bind(oh_config->oh_port, &oh_port_pcd_params); ++ ++ dev_set_drvdata(dpa_oh_dev, oh_config); ++ ++ /* Enable the OH port */ ++ _errno = fm_port_enable(oh_config->oh_port); ++ if (_errno) ++ goto return_kfree; ++ ++ dev_info(dpa_oh_dev, "OH port %s enabled.\n", oh_node->full_name); ++ ++ /* print of all referenced & created queues */ ++ dump_oh_config(dpa_oh_dev, oh_config); ++ ++ return 0; ++ ++return_kfree: ++ if (bpool_node) ++ of_node_put(bpool_node); ++ if (oh_node) ++ of_node_put(oh_node); ++ if (oh_config && oh_config->egress_fqs) ++ devm_kfree(dpa_oh_dev, oh_config->egress_fqs); ++ ++ list_for_each_safe(fq_list, fq_list_tmp, &oh_config->fqs_ingress_list) { ++ fqd = list_entry(fq_list, struct fq_duple, fq_list); ++ list_del(fq_list); ++ devm_kfree(dpa_oh_dev, fqd->fqs); ++ devm_kfree(dpa_oh_dev, fqd); ++ } ++ ++ list_for_each_safe(fq_list, fq_list_tmp, &oh_config->fqs_egress_list) { ++ fqd = list_entry(fq_list, struct fq_duple, fq_list); ++ list_del(fq_list); ++ devm_kfree(dpa_oh_dev, fqd->fqs); ++ devm_kfree(dpa_oh_dev, fqd); ++ } ++ ++ devm_kfree(dpa_oh_dev, oh_config); ++ return _errno; ++} ++ ++static int __cold oh_port_remove(struct platform_device *_of_dev) ++{ ++ int _errno = 0, i; ++ struct dpa_oh_config_s *oh_config; ++ ++ pr_info("Removing OH port...\n"); ++ ++ oh_config = dev_get_drvdata(&_of_dev->dev); ++ if (oh_config == NULL) { ++ pr_err(KBUILD_MODNAME ++ ": %s:%hu:%s(): No OH config in device private data!\n", ++ KBUILD_BASENAME".c", __LINE__, __func__); ++ _errno = -ENODEV; ++ goto return_error; ++ } ++ ++ if (oh_config->egress_fqs) ++ for (i = 0; i < oh_config->egress_cnt; i++) ++ oh_fq_destroy(oh_config->egress_fqs + i); ++ ++ if (oh_config->oh_port == NULL) { ++ pr_err(KBUILD_MODNAME ++ ": %s:%hu:%s(): No fm port in device private data!\n", ++ KBUILD_BASENAME".c", __LINE__, __func__); ++ _errno = -EINVAL; ++ goto free_egress_fqs; ++ } ++ ++ _errno = fm_port_disable(oh_config->oh_port); ++ ++free_egress_fqs: ++ if (oh_config->egress_fqs) ++ devm_kfree(&_of_dev->dev, oh_config->egress_fqs); ++ devm_kfree(&_of_dev->dev, oh_config); ++ dev_set_drvdata(&_of_dev->dev, NULL); ++ ++return_error: ++ return _errno; ++} ++ ++static struct platform_driver oh_port_driver = { ++ .driver = { ++ .name = KBUILD_MODNAME, ++ .of_match_table = oh_port_match_table, ++ .owner = THIS_MODULE, ++ .pm = OH_PM_OPS, ++ }, ++ .probe = oh_port_probe, ++ .remove = oh_port_remove ++}; ++ ++static int __init __cold oh_port_load(void) ++{ ++ int _errno; ++ ++ pr_info(OH_MOD_DESCRIPTION " (" VERSION ")\n"); ++ ++ _errno = platform_driver_register(&oh_port_driver); ++ if (_errno < 0) { ++ pr_err(KBUILD_MODNAME ++ ": %s:%hu:%s(): platform_driver_register() = %d\n", ++ KBUILD_BASENAME".c", __LINE__, __func__, _errno); ++ } ++ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++ return _errno; ++} ++module_init(oh_port_load); ++ ++static void __exit __cold oh_port_unload(void) ++{ ++ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n", ++ KBUILD_BASENAME".c", __func__); ++ ++ platform_driver_unregister(&oh_port_driver); ++ ++ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", ++ KBUILD_BASENAME".c", __func__); ++} ++module_exit(oh_port_unload); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/offline_port.h b/drivers/net/ethernet/freescale/sdk_dpaa/offline_port.h +new file mode 100644 +index 0000000..432ee88 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/offline_port.h +@@ -0,0 +1,59 @@ ++/* Copyright 2011 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 __OFFLINE_PORT_H ++#define __OFFLINE_PORT_H ++ ++struct fm_port; ++struct qman_fq; ++ ++/* fqs are defined in duples (base_fq, fq_count) */ ++struct fq_duple { ++ struct qman_fq *fqs; ++ int fqs_count; ++ uint16_t channel_id; ++ struct list_head fq_list; ++}; ++ ++/* OH port configuration */ ++struct dpa_oh_config_s { ++ uint32_t error_fqid; ++ uint32_t default_fqid; ++ struct fm_port *oh_port; ++ uint32_t egress_cnt; ++ struct qman_fq *egress_fqs; ++ uint16_t channel; ++ ++ struct list_head fqs_ingress_list; ++ struct list_head fqs_egress_list; ++}; ++ ++#endif /* __OFFLINE_PORT_H */ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0025-dt-move-guts-devicetree-doc-out-of-powerpc-directory.patch b/target/linux/layerscape-64b/patches-4.1/0025-dt-move-guts-devicetree-doc-out-of-powerpc-directory.patch new file mode 100644 index 0000000..46b01b7 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0025-dt-move-guts-devicetree-doc-out-of-powerpc-directory.patch @@ -0,0 +1,107 @@ +From 1d0e648e11b9bc1dc601db18b81b2856b2fe6cde Mon Sep 17 00:00:00 2001 +From: Yangbo Lu +Date: Mon, 25 Jan 2016 14:27:27 +0800 +Subject: [PATCH 025/151] dt: move guts devicetree doc out of powerpc directory + +Move guts devicetree doc to Documentation/devicetree/bindings/soc/fsl/ +since it's used by not only PowerPC but also ARM. And add a specification +for 'little-endian' property. + +Signed-off-by: Yangbo Lu +--- + .../devicetree/bindings/powerpc/fsl/guts.txt | 36 -------------------- + Documentation/devicetree/bindings/soc/fsl/guts.txt | 39 ++++++++++++++++++++++ + 2 files changed, 39 insertions(+), 36 deletions(-) + delete mode 100644 Documentation/devicetree/bindings/powerpc/fsl/guts.txt + create mode 100644 Documentation/devicetree/bindings/soc/fsl/guts.txt + +diff --git a/Documentation/devicetree/bindings/powerpc/fsl/guts.txt b/Documentation/devicetree/bindings/powerpc/fsl/guts.txt +deleted file mode 100644 +index 7f150b5..0000000 +--- a/Documentation/devicetree/bindings/powerpc/fsl/guts.txt ++++ /dev/null +@@ -1,36 +0,0 @@ +-* Global Utilities Block +- +-The global utilities block controls power management, I/O device +-enabling, power-on-reset configuration monitoring, general-purpose +-I/O signal configuration, alternate function selection for multiplexed +-signals, and clock control. +- +-Required properties: +- +- - compatible : Should define the compatible device type for +- global-utilities. +- - reg : Offset and length of the register set for the device. +- +-Recommended properties: +- +- - fsl,has-rstcr : Indicates that the global utilities register set +- contains a functioning "reset control register" (i.e. the board +- is wired to reset upon setting the HRESET_REQ bit in this register). +- +- - fsl,liodn-bits : Indicates the number of defined bits in the LIODN +- registers, for those SOCs that have a PAMU device. +- +-Examples: +- global-utilities at e0000 { /* global utilities block */ +- compatible = "fsl,mpc8548-guts"; +- reg = ; +- fsl,has-rstcr; +- }; +- +- guts: global-utilities at e0000 { +- compatible = "fsl,qoriq-device-config-1.0"; +- reg = <0xe0000 0xe00>; +- fsl,has-rstcr; +- #sleep-cells = <1>; +- fsl,liodn-bits = <12>; +- }; +diff --git a/Documentation/devicetree/bindings/soc/fsl/guts.txt b/Documentation/devicetree/bindings/soc/fsl/guts.txt +new file mode 100644 +index 0000000..77f2532 +--- /dev/null ++++ b/Documentation/devicetree/bindings/soc/fsl/guts.txt +@@ -0,0 +1,39 @@ ++* Global Utilities Block ++ ++The global utilities block controls power management, I/O device ++enabling, power-on-reset configuration monitoring, general-purpose ++I/O signal configuration, alternate function selection for multiplexed ++signals, and clock control. ++ ++Required properties: ++ ++ - compatible : Should define the compatible device type for ++ global-utilities. ++ - reg : Offset and length of the register set for the device. ++ ++Recommended properties: ++ ++ - fsl,has-rstcr : Indicates that the global utilities register set ++ contains a functioning "reset control register" (i.e. the board ++ is wired to reset upon setting the HRESET_REQ bit in this register). ++ ++ - fsl,liodn-bits : Indicates the number of defined bits in the LIODN ++ registers, for those SOCs that have a PAMU device. ++ ++ - little-endian : Indicates that the global utilities block is little ++ endian. The default is big endian. ++ ++Examples: ++ global-utilities at e0000 { /* global utilities block */ ++ compatible = "fsl,mpc8548-guts"; ++ reg = ; ++ fsl,has-rstcr; ++ }; ++ ++ guts: global-utilities at e0000 { ++ compatible = "fsl,qoriq-device-config-1.0"; ++ reg = <0xe0000 0xe00>; ++ fsl,has-rstcr; ++ #sleep-cells = <1>; ++ fsl,liodn-bits = <12>; ++ }; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0026-powerpc-fsl-move-mpc85xx.h-to-include-linux-fsl.patch b/target/linux/layerscape-64b/patches-4.1/0026-powerpc-fsl-move-mpc85xx.h-to-include-linux-fsl.patch new file mode 100644 index 0000000..d1cacdf --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0026-powerpc-fsl-move-mpc85xx.h-to-include-linux-fsl.patch @@ -0,0 +1,300 @@ +From d6ec2dba89c2a1f292daeb1c5a15cb8dc8b1ba36 Mon Sep 17 00:00:00 2001 +From: Yangbo Lu +Date: Tue, 12 Apr 2016 14:21:19 +0800 +Subject: [PATCH 026/151] powerpc/fsl: move mpc85xx.h to include/linux/fsl + +commit 2a76fbe35c14717b4f4a145e0ab83517b1f4ab4a +[context adjustment] +[doesn't apply arch/powerpc/kernel/cpu_setup_fsl_booke.S] +[doesn't apply arch/powerpc/sysdev/mpic_timer.c] + +Move mpc85xx.h to include/linux/fsl and rename it to svr.h as +a common header file. It has been used for mpc85xx and it will +be used for ARM-based SoC as well. + +Signed-off-by: Yangbo Lu +Integrated-by: Zhao Qiang +--- + arch/powerpc/include/asm/mpc85xx.h | 95 -------------------------------- + drivers/clk/clk-qoriq.c | 2 +- + drivers/i2c/busses/i2c-mpc.c | 2 +- + drivers/iommu/fsl_pamu.c | 2 +- + drivers/net/ethernet/freescale/gianfar.c | 2 +- + include/linux/fsl/svr.h | 95 ++++++++++++++++++++++++++++++++ + 6 files changed, 99 insertions(+), 99 deletions(-) + delete mode 100644 arch/powerpc/include/asm/mpc85xx.h + create mode 100644 include/linux/fsl/svr.h + +diff --git a/arch/powerpc/include/asm/mpc85xx.h b/arch/powerpc/include/asm/mpc85xx.h +deleted file mode 100644 +index 213f3a8..0000000 +--- a/arch/powerpc/include/asm/mpc85xx.h ++++ /dev/null +@@ -1,95 +0,0 @@ +-/* +- * MPC85xx cpu type detection +- * +- * Copyright 2011-2012 Freescale Semiconductor, Inc. +- * +- * This is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- */ +- +-#ifndef __ASM_PPC_MPC85XX_H +-#define __ASM_PPC_MPC85XX_H +- +-#define SVR_REV(svr) ((svr) & 0xFF) /* SOC design resision */ +-#define SVR_MAJ(svr) (((svr) >> 4) & 0xF) /* Major revision field*/ +-#define SVR_MIN(svr) (((svr) >> 0) & 0xF) /* Minor revision field*/ +- +-/* Some parts define SVR[0:23] as the SOC version */ +-#define SVR_SOC_VER(svr) (((svr) >> 8) & 0xFFF7FF) /* SOC Version fields */ +- +-#define SVR_8533 0x803400 +-#define SVR_8535 0x803701 +-#define SVR_8536 0x803700 +-#define SVR_8540 0x803000 +-#define SVR_8541 0x807200 +-#define SVR_8543 0x803200 +-#define SVR_8544 0x803401 +-#define SVR_8545 0x803102 +-#define SVR_8547 0x803101 +-#define SVR_8548 0x803100 +-#define SVR_8555 0x807100 +-#define SVR_8560 0x807000 +-#define SVR_8567 0x807501 +-#define SVR_8568 0x807500 +-#define SVR_8569 0x808000 +-#define SVR_8572 0x80E000 +-#define SVR_P1010 0x80F100 +-#define SVR_P1011 0x80E500 +-#define SVR_P1012 0x80E501 +-#define SVR_P1013 0x80E700 +-#define SVR_P1014 0x80F101 +-#define SVR_P1017 0x80F700 +-#define SVR_P1020 0x80E400 +-#define SVR_P1021 0x80E401 +-#define SVR_P1022 0x80E600 +-#define SVR_P1023 0x80F600 +-#define SVR_P1024 0x80E402 +-#define SVR_P1025 0x80E403 +-#define SVR_P2010 0x80E300 +-#define SVR_P2020 0x80E200 +-#define SVR_P2040 0x821000 +-#define SVR_P2041 0x821001 +-#define SVR_P3041 0x821103 +-#define SVR_P4040 0x820100 +-#define SVR_P4080 0x820000 +-#define SVR_P5010 0x822100 +-#define SVR_P5020 0x822000 +-#define SVR_P5021 0X820500 +-#define SVR_P5040 0x820400 +-#define SVR_T4240 0x824000 +-#define SVR_T4120 0x824001 +-#define SVR_T4160 0x824100 +-#define SVR_T4080 0x824102 +-#define SVR_C291 0x850000 +-#define SVR_C292 0x850020 +-#define SVR_C293 0x850030 +-#define SVR_B4860 0X868000 +-#define SVR_G4860 0x868001 +-#define SVR_G4060 0x868003 +-#define SVR_B4440 0x868100 +-#define SVR_G4440 0x868101 +-#define SVR_B4420 0x868102 +-#define SVR_B4220 0x868103 +-#define SVR_T1040 0x852000 +-#define SVR_T1041 0x852001 +-#define SVR_T1042 0x852002 +-#define SVR_T1020 0x852100 +-#define SVR_T1021 0x852101 +-#define SVR_T1022 0x852102 +-#define SVR_T2080 0x853000 +-#define SVR_T2081 0x853100 +- +-#define SVR_8610 0x80A000 +-#define SVR_8641 0x809000 +-#define SVR_8641D 0x809001 +- +-#define SVR_9130 0x860001 +-#define SVR_9131 0x860000 +-#define SVR_9132 0x861000 +-#define SVR_9232 0x861400 +- +-#define SVR_Unknown 0xFFFFFF +- +-#endif +diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c +index f8739d0..72a6063 100644 +--- a/drivers/clk/clk-qoriq.c ++++ b/drivers/clk/clk-qoriq.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1148,7 +1149,6 @@ bad_args: + } + + #ifdef CONFIG_PPC +-#include + + static const u32 a4510_svrs[] __initconst = { + (SVR_P2040 << 8) | 0x10, /* P2040 1.0 */ +diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c +index 48ecffe..600704c 100644 +--- a/drivers/i2c/busses/i2c-mpc.c ++++ b/drivers/i2c/busses/i2c-mpc.c +@@ -27,9 +27,9 @@ + #include + #include + #include ++#include + + #include +-#include + #include + + #define DRV_NAME "mpc-i2c" +diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c +index a34355f..8cec711 100644 +--- a/drivers/iommu/fsl_pamu.c ++++ b/drivers/iommu/fsl_pamu.c +@@ -21,10 +21,10 @@ + #include "fsl_pamu.h" + + #include ++#include + #include + #include + +-#include + + /* define indexes for each operation mapping scenario */ + #define OMI_QMAN 0x00 +diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c +index 4ee080d..692ec62 100644 +--- a/drivers/net/ethernet/freescale/gianfar.c ++++ b/drivers/net/ethernet/freescale/gianfar.c +@@ -86,11 +86,11 @@ + #include + #include + #include ++#include + + #include + #ifdef CONFIG_PPC + #include +-#include + #endif + #include + #include +diff --git a/include/linux/fsl/svr.h b/include/linux/fsl/svr.h +new file mode 100644 +index 0000000..8d13836 +--- /dev/null ++++ b/include/linux/fsl/svr.h +@@ -0,0 +1,95 @@ ++/* ++ * MPC85xx cpu type detection ++ * ++ * Copyright 2011-2012 Freescale Semiconductor, Inc. ++ * ++ * This is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#ifndef FSL_SVR_H ++#define FSL_SVR_H ++ ++#define SVR_REV(svr) ((svr) & 0xFF) /* SOC design resision */ ++#define SVR_MAJ(svr) (((svr) >> 4) & 0xF) /* Major revision field*/ ++#define SVR_MIN(svr) (((svr) >> 0) & 0xF) /* Minor revision field*/ ++ ++/* Some parts define SVR[0:23] as the SOC version */ ++#define SVR_SOC_VER(svr) (((svr) >> 8) & 0xFFF7FF) /* SOC Version fields */ ++ ++#define SVR_8533 0x803400 ++#define SVR_8535 0x803701 ++#define SVR_8536 0x803700 ++#define SVR_8540 0x803000 ++#define SVR_8541 0x807200 ++#define SVR_8543 0x803200 ++#define SVR_8544 0x803401 ++#define SVR_8545 0x803102 ++#define SVR_8547 0x803101 ++#define SVR_8548 0x803100 ++#define SVR_8555 0x807100 ++#define SVR_8560 0x807000 ++#define SVR_8567 0x807501 ++#define SVR_8568 0x807500 ++#define SVR_8569 0x808000 ++#define SVR_8572 0x80E000 ++#define SVR_P1010 0x80F100 ++#define SVR_P1011 0x80E500 ++#define SVR_P1012 0x80E501 ++#define SVR_P1013 0x80E700 ++#define SVR_P1014 0x80F101 ++#define SVR_P1017 0x80F700 ++#define SVR_P1020 0x80E400 ++#define SVR_P1021 0x80E401 ++#define SVR_P1022 0x80E600 ++#define SVR_P1023 0x80F600 ++#define SVR_P1024 0x80E402 ++#define SVR_P1025 0x80E403 ++#define SVR_P2010 0x80E300 ++#define SVR_P2020 0x80E200 ++#define SVR_P2040 0x821000 ++#define SVR_P2041 0x821001 ++#define SVR_P3041 0x821103 ++#define SVR_P4040 0x820100 ++#define SVR_P4080 0x820000 ++#define SVR_P5010 0x822100 ++#define SVR_P5020 0x822000 ++#define SVR_P5021 0X820500 ++#define SVR_P5040 0x820400 ++#define SVR_T4240 0x824000 ++#define SVR_T4120 0x824001 ++#define SVR_T4160 0x824100 ++#define SVR_T4080 0x824102 ++#define SVR_C291 0x850000 ++#define SVR_C292 0x850020 ++#define SVR_C293 0x850030 ++#define SVR_B4860 0X868000 ++#define SVR_G4860 0x868001 ++#define SVR_G4060 0x868003 ++#define SVR_B4440 0x868100 ++#define SVR_G4440 0x868101 ++#define SVR_B4420 0x868102 ++#define SVR_B4220 0x868103 ++#define SVR_T1040 0x852000 ++#define SVR_T1041 0x852001 ++#define SVR_T1042 0x852002 ++#define SVR_T1020 0x852100 ++#define SVR_T1021 0x852101 ++#define SVR_T1022 0x852102 ++#define SVR_T2080 0x853000 ++#define SVR_T2081 0x853100 ++ ++#define SVR_8610 0x80A000 ++#define SVR_8641 0x809000 ++#define SVR_8641D 0x809001 ++ ++#define SVR_9130 0x860001 ++#define SVR_9131 0x860000 ++#define SVR_9132 0x861000 ++#define SVR_9232 0x861400 ++ ++#define SVR_Unknown 0xFFFFFF ++ ++#endif +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0027-fman-update-an-outdated-header.patch b/target/linux/layerscape-64b/patches-4.1/0027-fman-update-an-outdated-header.patch new file mode 100644 index 0000000..28aa4ae --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0027-fman-update-an-outdated-header.patch @@ -0,0 +1,56 @@ +From 222385da7c1099e75be1cbc557b1bbb2e78c9500 Mon Sep 17 00:00:00 2001 +From: Camelia Groza +Date: Fri, 5 Feb 2016 15:17:14 +0200 +Subject: [PATCH 027/151] fman: update an outdated header + +mpc85xx.h has been moved to include/linux/fsl/svr.h + +Signed-off-by: Camelia Groza +--- + drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.c | 2 +- + drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm_port.c | 2 +- + drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.c +index 7b9f084..71ef3a2 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.c +@@ -47,7 +47,7 @@ + #include "fm_common.h" + #include "fm_ipc.h" + #include "fm.h" +-#include ++#include + #include "fsl_fman.h" + + +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm_port.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm_port.c +index fa73867..2cba7a5 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm_port.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm_port.c +@@ -51,7 +51,7 @@ + #include + #include + #include +-#include ++#include + + #include "sprint_ext.h" + #include "fm_common.h" +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c +index fcc0198..2476dfa 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c +@@ -60,7 +60,7 @@ + #include + #include + #include +-#include ++#include + + #if defined(CONFIG_COMPAT) + #include +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0028-dpaa_eth-add-promisc-handler-for-proxy-driver.patch b/target/linux/layerscape-64b/patches-4.1/0028-dpaa_eth-add-promisc-handler-for-proxy-driver.patch new file mode 100644 index 0000000..6a824ff --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0028-dpaa_eth-add-promisc-handler-for-proxy-driver.patch @@ -0,0 +1,37 @@ +From 288ec5b00ce5eada8da9003f84e3f90b6e90e7bc Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Tue, 8 Dec 2015 18:18:18 +0200 +Subject: [PATCH 028/151] dpaa_eth: add promisc handler for proxy driver + +This patch adds promisc capability to the macless over proxy feature. +Currently, using the standard kernel interface you cannot set the MAC device +controlled by the macless driver into the promiscuous mode. + +Signed-off-by: Marian-Cristian Rotariu +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_proxy.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_proxy.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_proxy.c +index bc8f5f7..8ad015d 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_proxy.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_proxy.c +@@ -228,6 +228,15 @@ int dpa_proxy_set_rx_mode(struct proxy_device *proxy_dev, + struct mac_device *mac_dev = proxy_dev->mac_dev; + int _errno; + ++ if (!!(net_dev->flags & IFF_PROMISC) != mac_dev->promisc) { ++ mac_dev->promisc = !mac_dev->promisc; ++ _errno = mac_dev->set_promisc(mac_dev->get_mac_handle(mac_dev), ++ mac_dev->promisc); ++ if (unlikely(_errno < 0)) ++ netdev_err(net_dev, "mac_dev->set_promisc() = %d\n", ++ _errno); ++ } ++ + _errno = mac_dev->set_multi(net_dev, mac_dev); + if (unlikely(_errno < 0)) + return _errno; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0029-dpaa_eth-remove-VERSION-and-dpa_get_ringparam.patch b/target/linux/layerscape-64b/patches-4.1/0029-dpaa_eth-remove-VERSION-and-dpa_get_ringparam.patch new file mode 100644 index 0000000..8f6ecd5 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0029-dpaa_eth-remove-VERSION-and-dpa_get_ringparam.patch @@ -0,0 +1,241 @@ +From e59f277fa0b1a0b62ef8f297ac0ce239792e9a39 Mon Sep 17 00:00:00 2001 +From: "ioana.ciornei" +Date: Wed, 15 Jul 2015 12:43:39 +0300 +Subject: [PATCH 029/151] dpaa_eth: remove VERSION and dpa_get_ringparam + +Removed VERSION parameter and get_ringparam callback since there is +no need for this functionality. + +Signed-off-by: Ioana Ciornei +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.c | 2 +- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c | 2 +- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c | 2 +- + .../net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c | 2 +- + .../net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c | 2 +- + .../net/ethernet/freescale/sdk_dpaa/dpaa_eth_proxy.c | 2 +- + .../net/ethernet/freescale/sdk_dpaa/dpaa_eth_shared.c | 2 +- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c | 17 ----------------- + .../ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.c | 2 +- + .../ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c | 17 ----------------- + drivers/net/ethernet/freescale/sdk_dpaa/mac.c | 3 +-- + drivers/net/ethernet/freescale/sdk_dpaa/offline_port.c | 2 +- + 12 files changed, 10 insertions(+), 45 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.c +index 59c7338..cb070f5 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.c +@@ -366,7 +366,7 @@ int __init dpa_debugfs_module_init(void) + { + int _errno = 0; + +- pr_info(KBUILD_MODNAME ": " DPA_DEBUGFS_DESCRIPTION " (" VERSION ")\n"); ++ pr_info(KBUILD_MODNAME ": " DPA_DEBUGFS_DESCRIPTION "\n"); + + dpa_debugfs_root = debugfs_create_dir(DPA_ETH_DEBUGFS_ROOT, NULL); + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c +index a5fb44f..92e697e 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c +@@ -1131,7 +1131,7 @@ static int __init __cold dpa_load(void) + { + int _errno; + +- pr_info(DPA_DESCRIPTION " (" VERSION ")\n"); ++ pr_info(DPA_DESCRIPTION "\n"); + + #ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS + dpa_debugfs_module_init(); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c +index 9f55496..459823e 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c +@@ -235,7 +235,7 @@ EXPORT_SYMBOL(dpa_bp_create); + + static int __init __cold dpa_advanced_load(void) + { +- pr_info(DPA_DESCRIPTION " (" VERSION ")\n"); ++ pr_info(DPA_DESCRIPTION "\n"); + + return 0; + } +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +index 37effc1..f672420 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +@@ -1548,7 +1548,7 @@ static int __init __cold dpa_generic_load(void) + { + int _errno; + +- pr_info(KBUILD_MODNAME ": " DPA_GENERIC_DESCRIPTION " (" VERSION ")\n"); ++ pr_info(KBUILD_MODNAME ": " DPA_GENERIC_DESCRIPTION "\n"); + + #ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS + dpa_generic_debugfs_module_init(); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c +index bd97536..68b6e5b 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c +@@ -468,7 +468,7 @@ static int __init __cold dpa_macless_load(void) + { + int _errno; + +- pr_info(DPA_DESCRIPTION " (" VERSION ")\n"); ++ pr_info(DPA_DESCRIPTION "\n"); + + /* Initialize dpaa_eth mirror values */ + dpa_rx_extra_headroom = fm_get_rx_extra_headroom(); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_proxy.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_proxy.c +index 8ad015d..994d38c 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_proxy.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_proxy.c +@@ -351,7 +351,7 @@ static int __init __cold dpa_proxy_load(void) + { + int _errno; + +- pr_info(DPA_DESCRIPTION " (" VERSION ")\n"); ++ pr_info(DPA_DESCRIPTION "\n"); + + /* Initialize dpaa_eth mirror values */ + dpa_rx_extra_headroom = fm_get_rx_extra_headroom(); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_shared.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_shared.c +index 987b9dc..6564758 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_shared.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_shared.c +@@ -880,7 +880,7 @@ static int __init __cold dpa_shared_load(void) + { + int _errno; + +- pr_info(DPA_DESCRIPTION " (" VERSION ")\n"); ++ pr_info(DPA_DESCRIPTION "\n"); + + /* Initialize dpaa_eth mirror values */ + dpa_rx_extra_headroom = fm_get_rx_extra_headroom(); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c +index 60a1b22..68daa39 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c +@@ -99,8 +99,6 @@ static void __cold dpa_get_drvinfo(struct net_device *net_dev, + + strncpy(drvinfo->driver, KBUILD_MODNAME, + sizeof(drvinfo->driver) - 1)[sizeof(drvinfo->driver)-1] = 0; +- strncpy(drvinfo->version, VERSION, +- sizeof(drvinfo->driver) - 1)[sizeof(drvinfo->version)-1] = 0; + _errno = snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), + "%X", 0); + +@@ -153,20 +151,6 @@ static int __cold dpa_nway_reset(struct net_device *net_dev) + return _errno; + } + +-static void __cold dpa_get_ringparam(struct net_device *net_dev, +- struct ethtool_ringparam *et_ringparam) +-{ +- et_ringparam->rx_max_pending = 0; +- et_ringparam->rx_mini_max_pending = 0; +- et_ringparam->rx_jumbo_max_pending = 0; +- et_ringparam->tx_max_pending = 0; +- +- et_ringparam->rx_pending = 0; +- et_ringparam->rx_mini_pending = 0; +- et_ringparam->rx_jumbo_pending = 0; +- et_ringparam->tx_pending = 0; +-} +- + static void __cold dpa_get_pauseparam(struct net_device *net_dev, + struct ethtool_pauseparam *epause) + { +@@ -320,7 +304,6 @@ const struct ethtool_ops dpa_ethtool_ops = { + .get_msglevel = dpa_get_msglevel, + .set_msglevel = dpa_set_msglevel, + .nway_reset = dpa_nway_reset, +- .get_ringparam = dpa_get_ringparam, + .get_pauseparam = dpa_get_pauseparam, + .set_pauseparam = dpa_set_pauseparam, + .self_test = NULL, /* TODO invoke the cold-boot unit-test? */ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.c +index b53c289..a442876 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.c +@@ -256,7 +256,7 @@ int __init dpa_generic_debugfs_module_init(void) + { + int _errno = 0; + +- pr_info(KBUILD_MODNAME ": " DPA_DEBUGFS_DESCRIPTION " (" VERSION ")\n"); ++ pr_info(KBUILD_MODNAME ": " DPA_DEBUGFS_DESCRIPTION "\n"); + + dpa_debugfs_root = debugfs_create_dir(DPA_GENERIC_ETH_DEBUGFS_ROOT, + NULL); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c +index b9c8623..ef41ce3 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c +@@ -65,8 +65,6 @@ static void __cold dpa_generic_get_drvinfo(struct net_device *net_dev, + + strncpy(drvinfo->driver, KBUILD_MODNAME, + sizeof(drvinfo->driver) - 1)[sizeof(drvinfo->driver)-1] = 0; +- strncpy(drvinfo->version, VERSION, +- sizeof(drvinfo->driver) - 1)[sizeof(drvinfo->version)-1] = 0; + _errno = snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), + "%X", 0); + +@@ -99,20 +97,6 @@ static int __cold dpa_generic_nway_reset(struct net_device *net_dev) + return -ENODEV; + } + +-static void __cold dpa_generic_get_ringparam(struct net_device *net_dev, +- struct ethtool_ringparam *et_ringparam) +-{ +- et_ringparam->rx_max_pending = 0; +- et_ringparam->rx_mini_max_pending = 0; +- et_ringparam->rx_jumbo_max_pending = 0; +- et_ringparam->tx_max_pending = 0; +- +- et_ringparam->rx_pending = 0; +- et_ringparam->rx_mini_pending = 0; +- et_ringparam->rx_jumbo_pending = 0; +- et_ringparam->tx_pending = 0; +-} +- + const struct ethtool_ops dpa_generic_ethtool_ops = { + .get_settings = dpa_generic_get_settings, + .set_settings = dpa_generic_set_settings, +@@ -120,6 +104,5 @@ const struct ethtool_ops dpa_generic_ethtool_ops = { + .get_msglevel = dpa_generic_get_msglevel, + .set_msglevel = dpa_generic_set_msglevel, + .nway_reset = dpa_generic_nway_reset, +- .get_ringparam = dpa_generic_get_ringparam, + .get_link = ethtool_op_get_link, + }; +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/mac.c b/drivers/net/ethernet/freescale/sdk_dpaa/mac.c +index f36d091..d004038 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/mac.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/mac.c +@@ -436,8 +436,7 @@ static int __init __cold mac_load(void) + pr_debug(KBUILD_MODNAME ": -> %s:%s()\n", + KBUILD_BASENAME".c", __func__); + +- pr_info(KBUILD_MODNAME ": %s (" VERSION ")\n", +- mac_driver_description); ++ pr_info(KBUILD_MODNAME ": %s\n", mac_driver_description); + + _errno = platform_driver_register(&mac_driver); + if (unlikely(_errno < 0)) { +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/offline_port.c b/drivers/net/ethernet/freescale/sdk_dpaa/offline_port.c +index ddbfdce..fb084af 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/offline_port.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/offline_port.c +@@ -820,7 +820,7 @@ static int __init __cold oh_port_load(void) + { + int _errno; + +- pr_info(OH_MOD_DESCRIPTION " (" VERSION ")\n"); ++ pr_info(OH_MOD_DESCRIPTION "\n"); + + _errno = platform_driver_register(&oh_port_driver); + if (_errno < 0) { +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0030-dpaa_eth-add-EEE-callbacks-in-ethtool.patch b/target/linux/layerscape-64b/patches-4.1/0030-dpaa_eth-add-EEE-callbacks-in-ethtool.patch new file mode 100644 index 0000000..e3426ee --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0030-dpaa_eth-add-EEE-callbacks-in-ethtool.patch @@ -0,0 +1,71 @@ +From 983cdae3d6890aaf82038ea195b8429b2b58ff64 Mon Sep 17 00:00:00 2001 +From: Ioana Ciornei +Date: Fri, 31 Jul 2015 10:47:23 +0300 +Subject: [PATCH 030/151] dpaa_eth: add EEE callbacks in ethtool + +Add EEE functionality to the ethtool interface + +Signed-off-by: Ioana Ciornei +--- + .../net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c | 38 ++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c +index 68daa39..bb1cc71 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c +@@ -297,6 +297,42 @@ static int dpa_set_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol) + } + #endif + ++static int dpa_get_eee(struct net_device *net_dev, struct ethtool_eee *et_eee) ++{ ++ struct dpa_priv_s *priv; ++ ++ priv = netdev_priv(net_dev); ++ if (priv->mac_dev == NULL) { ++ netdev_info(net_dev, "This is a MAC-less interface\n"); ++ return -ENODEV; ++ } ++ ++ if (unlikely(priv->mac_dev->phy_dev == NULL)) { ++ netdev_err(net_dev, "phy device not initialized\n"); ++ return -ENODEV; ++ } ++ ++ return phy_ethtool_get_eee(priv->mac_dev->phy_dev, et_eee); ++} ++ ++static int dpa_set_eee(struct net_device *net_dev, struct ethtool_eee *et_eee) ++{ ++ struct dpa_priv_s *priv; ++ ++ priv = netdev_priv(net_dev); ++ if (priv->mac_dev == NULL) { ++ netdev_info(net_dev, "This is a MAC-less interface\n"); ++ return -ENODEV; ++ } ++ ++ if (unlikely(priv->mac_dev->phy_dev == NULL)) { ++ netdev_err(net_dev, "phy device not initialized\n"); ++ return -ENODEV; ++ } ++ ++ return phy_ethtool_set_eee(priv->mac_dev->phy_dev, et_eee); ++} ++ + const struct ethtool_ops dpa_ethtool_ops = { + .get_settings = dpa_get_settings, + .set_settings = dpa_set_settings, +@@ -309,6 +345,8 @@ const struct ethtool_ops dpa_ethtool_ops = { + .self_test = NULL, /* TODO invoke the cold-boot unit-test? */ + .get_ethtool_stats = NULL, /* TODO other stats, currently in debugfs */ + .get_link = ethtool_op_get_link, ++ .get_eee = dpa_get_eee, ++ .set_eee = dpa_set_eee, + #ifdef CONFIG_PM + .get_wol = dpa_get_wol, + .set_wol = dpa_set_wol, +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0031-dpaa_eth-Move-exported-counters-from-debugfs-into-et.patch b/target/linux/layerscape-64b/patches-4.1/0031-dpaa_eth-Move-exported-counters-from-debugfs-into-et.patch new file mode 100644 index 0000000..fa14c8c --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0031-dpaa_eth-Move-exported-counters-from-debugfs-into-et.patch @@ -0,0 +1,619 @@ +From 4a4040976dcca3d1aa6063e4ec5f82cacb46f75b Mon Sep 17 00:00:00 2001 +From: Ioana Ciornei +Date: Tue, 25 Aug 2015 11:52:56 +0300 +Subject: [PATCH 031/151] dpaa_eth: Move exported counters from debugfs into + ethtool stats + +Signed-off-by: Ioana Ciornei +--- + drivers/net/ethernet/freescale/sdk_dpaa/Makefile | 2 +- + .../net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.c | 211 +-------------------- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c | 12 +- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h | 3 - + .../ethernet/freescale/sdk_dpaa/dpaa_eth_common.c | 12 +- + .../net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c | 188 +++++++++++++++++- + 6 files changed, 202 insertions(+), 226 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/Makefile b/drivers/net/ethernet/freescale/sdk_dpaa/Makefile +index 7d11df6..acb7415 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/Makefile ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/Makefile +@@ -12,7 +12,7 @@ obj-$(CONFIG_FSL_SDK_DPAA_ETH) += fsl_mac.o fsl_dpa.o + obj-$(CONFIG_PTP_1588_CLOCK_DPAA) += dpaa_ptp.o + + fsl_dpa-objs += dpaa_ethtool.o dpaa_eth_sysfs.o dpaa_eth.o dpaa_eth_sg.o dpaa_eth_common.o +-ifeq ($(CONFIG_FSL_DPAA_ETH_DEBUGFS),y) ++ifeq ($(CONFIG_FSL_DPAA_DBG_LOOP),y) + fsl_dpa-objs += dpaa_debugfs.o + endif + ifeq ($(CONFIG_FSL_DPAA_1588),y) +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.c +index cb070f5..25d9f5f 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs.c +@@ -38,23 +38,12 @@ + #define DPA_DEBUGFS_DESCRIPTION "FSL DPAA Ethernet debugfs entries" + #define DPA_ETH_DEBUGFS_ROOT "fsl_dpa" + +-static int __cold dpa_debugfs_open(struct inode *inode, struct file *file); ++static struct dentry *dpa_debugfs_root; + +-#ifdef CONFIG_FSL_DPAA_DBG_LOOP + static int __cold dpa_debugfs_loop_open(struct inode *inode, struct file *file); + static ssize_t dpa_loop_write(struct file *f, + const char __user *buf, size_t count, loff_t *off); +-#endif + +-static struct dentry *dpa_debugfs_root; +-static const struct file_operations dpa_debugfs_fops = { +- .open = dpa_debugfs_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +-}; +- +-#ifdef CONFIG_FSL_DPAA_DBG_LOOP + static const struct file_operations dpa_debugfs_lp_fops = { + .open = dpa_debugfs_loop_open, + .write = dpa_loop_write, +@@ -62,165 +51,7 @@ static const struct file_operations dpa_debugfs_lp_fops = { + .llseek = seq_lseek, + .release = single_release, + }; +-#endif +- +-static int dpa_debugfs_show(struct seq_file *file, void *offset) +-{ +- int i; +- struct dpa_priv_s *priv; +- struct dpa_percpu_priv_s *percpu_priv, total; +- struct dpa_bp *dpa_bp; +- unsigned int dpa_bp_count = 0; +- unsigned int count_total = 0; +- struct qm_mcr_querycgr query_cgr; +- +- BUG_ON(offset == NULL); +- +- priv = netdev_priv((struct net_device *)file->private); +- +- dpa_bp = priv->dpa_bp; +- +- memset(&total, 0, sizeof(total)); +- +- /* "Standard" counters */ +- seq_printf(file, "\nDPA counters for %s:\n", priv->net_dev->name); +- seq_puts(file, "CPU irqs rx tx recycle "); +- seq_puts(file, "confirm tx sg tx err rx err bp count\n"); +- +- +- for_each_online_cpu(i) { +- percpu_priv = per_cpu_ptr(priv->percpu_priv, i); +- +- if (dpa_bp->percpu_count) +- dpa_bp_count = *(per_cpu_ptr(dpa_bp->percpu_count, i)); +- +- total.in_interrupt += percpu_priv->in_interrupt; +- total.stats.rx_packets += percpu_priv->stats.rx_packets; +- total.stats.tx_packets += percpu_priv->stats.tx_packets; +- total.tx_returned += percpu_priv->tx_returned; +- total.tx_confirm += percpu_priv->tx_confirm; +- total.tx_frag_skbuffs += percpu_priv->tx_frag_skbuffs; +- total.stats.tx_errors += percpu_priv->stats.tx_errors; +- total.stats.rx_errors += percpu_priv->stats.rx_errors; +- count_total += dpa_bp_count; +- +- seq_printf(file, " %hu %8llu %8llu %8llu %8llu ", +- i, +- percpu_priv->in_interrupt, +- percpu_priv->stats.rx_packets, +- percpu_priv->stats.tx_packets, +- percpu_priv->tx_returned); +- seq_printf(file, "%8llu %8llu %8llu %8llu %8d\n", +- percpu_priv->tx_confirm, +- percpu_priv->tx_frag_skbuffs, +- percpu_priv->stats.tx_errors, +- percpu_priv->stats.rx_errors, +- dpa_bp_count); +- } +- seq_printf(file, "Total %8llu %8llu %8llu %8llu ", +- total.in_interrupt, +- total.stats.rx_packets, +- total.stats.tx_packets, +- total.tx_returned); +- seq_printf(file, "%8llu %8llu %8llu %8llu %8d\n", +- total.tx_confirm, +- total.tx_frag_skbuffs, +- total.stats.tx_errors, +- total.stats.rx_errors, +- count_total); +- +- /* Congestion stats */ +- seq_puts(file, "\nDevice congestion stats:\n"); +- seq_printf(file, "Device has been congested for %d ms.\n", +- jiffies_to_msecs(priv->cgr_data.congested_jiffies)); +- +- if (qman_query_cgr(&priv->cgr_data.cgr, &query_cgr) != 0) { +- seq_printf(file, "CGR id %d - failed to query values\n", +- priv->cgr_data.cgr.cgrid); +- } else { +- seq_printf(file, "CGR id %d avg count: %llu\n", +- priv->cgr_data.cgr.cgrid, +- qm_mcr_querycgr_a_get64(&query_cgr)); +- seq_printf(file, "Device entered congestion %u times. ", +- priv->cgr_data.cgr_congested_count); +- seq_printf(file, "Current congestion state is: %s.\n", +- query_cgr.cgr.cs ? "congested" : "not congested"); +- /* Reset congestion stats (like QMan CGR API does) */ +- priv->cgr_data.congested_jiffies = 0; +- priv->cgr_data.cgr_congested_count = 0; +- } +- +- /* Rx Errors demultiplexing */ +- seq_puts(file, "\nDPA RX Errors:\nCPU dma err phys err"); +- seq_puts(file, " size err hdr err csum err\n"); +- for_each_online_cpu(i) { +- percpu_priv = per_cpu_ptr(priv->percpu_priv, i); +- +- total.rx_errors.dme += percpu_priv->rx_errors.dme; +- total.rx_errors.fpe += percpu_priv->rx_errors.fpe; +- total.rx_errors.fse += percpu_priv->rx_errors.fse; +- total.rx_errors.phe += percpu_priv->rx_errors.phe; +- total.rx_errors.cse += percpu_priv->rx_errors.cse; +- +- seq_printf(file, " %hu %8llu %8llu ", +- i, +- percpu_priv->rx_errors.dme, +- percpu_priv->rx_errors.fpe); +- seq_printf(file, "%8llu %8llu %8llu\n", +- percpu_priv->rx_errors.fse, +- percpu_priv->rx_errors.phe, +- percpu_priv->rx_errors.cse); +- } +- seq_printf(file, "Total %8llu %8llu %8llu %8llu %8llu\n", +- total.rx_errors.dme, +- total.rx_errors.fpe, +- total.rx_errors.fse, +- total.rx_errors.phe, +- total.rx_errors.cse); +- +- /* ERN demultiplexing */ +- seq_puts(file, "\nDPA ERN counters:\n CPU cg_td wred "); +- seq_puts(file, "err_cond early_w late_w fq_td fq_ret"); +- seq_puts(file, " orp_z\n"); +- for_each_online_cpu(i) { +- percpu_priv = per_cpu_ptr(priv->percpu_priv, i); +- +- total.ern_cnt.cg_tdrop += percpu_priv->ern_cnt.cg_tdrop; +- total.ern_cnt.wred += percpu_priv->ern_cnt.wred; +- total.ern_cnt.err_cond += percpu_priv->ern_cnt.err_cond; +- total.ern_cnt.early_window += percpu_priv->ern_cnt.early_window; +- total.ern_cnt.late_window += percpu_priv->ern_cnt.late_window; +- total.ern_cnt.fq_tdrop += percpu_priv->ern_cnt.fq_tdrop; +- total.ern_cnt.fq_retired += percpu_priv->ern_cnt.fq_retired; +- total.ern_cnt.orp_zero += percpu_priv->ern_cnt.orp_zero; +- +- seq_printf(file, " %hu %8llu %8llu %8llu %8llu ", +- i, +- percpu_priv->ern_cnt.cg_tdrop, +- percpu_priv->ern_cnt.wred, +- percpu_priv->ern_cnt.err_cond, +- percpu_priv->ern_cnt.early_window); +- seq_printf(file, "%8llu %8llu %8llu %8llu\n", +- percpu_priv->ern_cnt.late_window, +- percpu_priv->ern_cnt.fq_tdrop, +- percpu_priv->ern_cnt.fq_retired, +- percpu_priv->ern_cnt.orp_zero); +- } +- seq_printf(file, "Total %8llu %8llu %8llu %8llu ", +- total.ern_cnt.cg_tdrop, +- total.ern_cnt.wred, +- total.ern_cnt.err_cond, +- total.ern_cnt.early_window); +- seq_printf(file, "%8llu %8llu %8llu %8llu\n", +- total.ern_cnt.late_window, +- total.ern_cnt.fq_tdrop, +- total.ern_cnt.fq_retired, +- total.ern_cnt.orp_zero); +- +- return 0; +-} + +-#ifdef CONFIG_FSL_DPAA_DBG_LOOP + static int dpa_debugfs_loop_show(struct seq_file *file, void *offset) + { + struct dpa_priv_s *priv; +@@ -286,32 +117,13 @@ static int __cold dpa_debugfs_loop_open(struct inode *inode, struct file *file) + + return _errno; + } +-#endif /* CONFIG_FSL_DPAA_DBG_LOOP */ + +-static int __cold dpa_debugfs_open(struct inode *inode, struct file *file) +-{ +- int _errno; +- const struct net_device *net_dev; +- +- _errno = single_open(file, dpa_debugfs_show, inode->i_private); +- if (unlikely(_errno < 0)) { +- net_dev = (struct net_device *)inode->i_private; +- +- if (netif_msg_drv((struct dpa_priv_s *)netdev_priv(net_dev))) +- netdev_err(net_dev, "single_open() = %d\n", +- _errno); +- } +- return _errno; +-} + + int dpa_netdev_debugfs_create(struct net_device *net_dev) + { + struct dpa_priv_s *priv = netdev_priv(net_dev); + static int cnt; +- char debugfs_file_name[100]; +-#ifdef CONFIG_FSL_DPAA_DBG_LOOP + char loop_file_name[100]; +-#endif + + if (unlikely(dpa_debugfs_root == NULL)) { + pr_err(KBUILD_MODNAME ": %s:%hu:%s(): \t%s\n", +@@ -320,22 +132,7 @@ int dpa_netdev_debugfs_create(struct net_device *net_dev) + return -ENOMEM; + } + +- snprintf(debugfs_file_name, 100, "eth%d", ++cnt); +- priv->debugfs_file = debugfs_create_file(debugfs_file_name, +- S_IRUGO, +- dpa_debugfs_root, +- net_dev, +- &dpa_debugfs_fops); +- if (unlikely(priv->debugfs_file == NULL)) { +- netdev_err(net_dev, "debugfs_create_file(%s/%s)", +- dpa_debugfs_root->d_iname, +- debugfs_file_name); +- +- return -ENOMEM; +- } +- +-#ifdef CONFIG_FSL_DPAA_DBG_LOOP +- sprintf(loop_file_name, "eth%d_loop", cnt); ++ sprintf(loop_file_name, "eth%d_loop", ++cnt); + priv->debugfs_loop_file = debugfs_create_file(loop_file_name, + S_IRUGO, + dpa_debugfs_root, +@@ -348,7 +145,6 @@ int dpa_netdev_debugfs_create(struct net_device *net_dev) + + return -ENOMEM; + } +-#endif + return 0; + } + +@@ -356,10 +152,7 @@ void dpa_netdev_debugfs_remove(struct net_device *net_dev) + { + struct dpa_priv_s *priv = netdev_priv(net_dev); + +- debugfs_remove(priv->debugfs_file); +-#ifdef CONFIG_FSL_DPAA_DBG_LOOP + debugfs_remove(priv->debugfs_loop_file); +-#endif + } + + int __init dpa_debugfs_module_init(void) +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c +index 92e697e..1192645 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c +@@ -65,9 +65,9 @@ + #include "mac.h" + #include "dpaa_eth.h" + #include "dpaa_eth_common.h" +-#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP + #include "dpaa_debugfs.h" +-#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++#endif /* CONFIG_FSL_DPAA_DBG_LOOP */ + + /* CREATE_TRACE_POINTS only needs to be defined once. Other dpa files + * using trace events only need to #include +@@ -1133,9 +1133,9 @@ static int __init __cold dpa_load(void) + + pr_info(DPA_DESCRIPTION "\n"); + +-#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP + dpa_debugfs_module_init(); +-#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++#endif /* CONFIG_FSL_DPAA_DBG_LOOP */ + + /* initialise dpaa_eth mirror values */ + dpa_rx_extra_headroom = fm_get_rx_extra_headroom(); +@@ -1167,9 +1167,9 @@ static void __exit __cold dpa_unload(void) + + platform_driver_unregister(&dpa_driver); + +-#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP + dpa_debugfs_module_exit(); +-#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++#endif /* CONFIG_FSL_DPAA_DBG_LOOP */ + + /* Only one channel is used and needs to be relased after all + * interfaces are removed +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +index b5c1bf8..f3b6ddd 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +@@ -346,9 +346,6 @@ struct dpa_priv_s { + uint16_t channel; /* "fsl,qman-channel-id" */ + struct list_head dpa_fq_list; + +-#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS +- struct dentry *debugfs_file; +-#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ + #ifdef CONFIG_FSL_DPAA_DBG_LOOP + struct dentry *debugfs_loop_file; + #endif +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +index 2015996..452b5e2 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +@@ -47,9 +47,9 @@ + #ifdef CONFIG_FSL_DPAA_1588 + #include "dpaa_1588.h" + #endif +-#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP + #include "dpaa_debugfs.h" +-#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++#endif /* CONFIG_FSL_DPAA_DBG_LOOP */ + #include "mac.h" + + /* DPAA platforms benefit from hardware-assisted queue management */ +@@ -135,14 +135,14 @@ int dpa_netdev_init(struct net_device *net_dev, + return err; + } + +-#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP + /* create debugfs entry for this net_device */ + err = dpa_netdev_debugfs_create(net_dev); + if (err) { + unregister_netdev(net_dev); + return err; + } +-#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++#endif /* CONFIG_FSL_DPAA_DBG_LOOP */ + + return 0; + } +@@ -527,10 +527,10 @@ int __cold dpa_remove(struct platform_device *of_dev) + if (priv->buf_layout) + devm_kfree(dev, priv->buf_layout); + +-#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS ++#ifdef CONFIG_FSL_DPAA_DBG_LOOP + /* remove debugfs entry for this net_device */ + dpa_netdev_debugfs_remove(net_dev); +-#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ ++#endif /* CONFIG_FSL_DPAA_DBG_LOOP */ + + #ifdef CONFIG_FSL_DPAA_1588 + if (priv->tsu && priv->tsu->valid) +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c +index bb1cc71..f0ca8b8 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c +@@ -44,6 +44,45 @@ + #include "mac.h" /* struct mac_device */ + #include "dpaa_eth_common.h" + ++static const char dpa_stats_percpu[][ETH_GSTRING_LEN] = { ++ "interrupts", ++ "rx packets", ++ "tx packets", ++ "tx returned", ++ "tx confirm", ++ "tx S/G", ++ "tx error", ++ "rx error", ++ "bp count" ++}; ++ ++static char dpa_stats_global[][ETH_GSTRING_LEN] = { ++ /* dpa rx errors */ ++ "rx dma error", ++ "rx frame physical error", ++ "rx frame size error", ++ "rx header error", ++ "rx csum error", ++ ++ /* demultiplexing errors */ ++ "qman cg_tdrop", ++ "qman wred", ++ "qman error cond", ++ "qman early window", ++ "qman late window", ++ "qman fq tdrop", ++ "qman fq retired", ++ "qman orp disabled", ++ ++ /* congestion related stats */ ++ "congestion time (ms)", ++ "entered congestion", ++ "congested (0/1)" ++}; ++ ++#define DPA_STATS_PERCPU_LEN ARRAY_SIZE(dpa_stats_percpu) ++#define DPA_STATS_GLOBAL_LEN ARRAY_SIZE(dpa_stats_global) ++ + static int __cold dpa_get_settings(struct net_device *net_dev, + struct ethtool_cmd *et_cmd) + { +@@ -333,6 +372,151 @@ static int dpa_set_eee(struct net_device *net_dev, struct ethtool_eee *et_eee) + return phy_ethtool_set_eee(priv->mac_dev->phy_dev, et_eee); + } + ++static int dpa_get_sset_count(struct net_device *net_dev, int type) ++{ ++ unsigned int total_stats, num_stats; ++ ++ num_stats = num_online_cpus() + 1; ++ total_stats = num_stats * DPA_STATS_PERCPU_LEN + DPA_STATS_GLOBAL_LEN; ++ ++ switch (type) { ++ case ETH_SS_STATS: ++ return total_stats; ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static void copy_stats(struct dpa_percpu_priv_s *percpu_priv, int num_cpus, ++ int crr_cpu, u64 bp_count, u64 *data) ++{ ++ int num_stat_values = num_cpus + 1; ++ int crr_stat = 0; ++ ++ /* update current CPU's stats and also add them to the total values */ ++ data[crr_stat * num_stat_values + crr_cpu] = percpu_priv->in_interrupt; ++ data[crr_stat++ * num_stat_values + num_cpus] += percpu_priv->in_interrupt; ++ ++ data[crr_stat * num_stat_values + crr_cpu] = percpu_priv->stats.rx_packets; ++ data[crr_stat++ * num_stat_values + num_cpus] += percpu_priv->stats.rx_packets; ++ ++ data[crr_stat * num_stat_values + crr_cpu] = percpu_priv->stats.tx_packets; ++ data[crr_stat++ * num_stat_values + num_cpus] += percpu_priv->stats.tx_packets; ++ ++ data[crr_stat * num_stat_values + crr_cpu] = percpu_priv->tx_returned; ++ data[crr_stat++ * num_stat_values + num_cpus] += percpu_priv->tx_returned; ++ ++ data[crr_stat * num_stat_values + crr_cpu] = percpu_priv->tx_confirm; ++ data[crr_stat++ * num_stat_values + num_cpus] += percpu_priv->tx_confirm; ++ ++ data[crr_stat * num_stat_values + crr_cpu] = percpu_priv->tx_frag_skbuffs; ++ data[crr_stat++ * num_stat_values + num_cpus] += percpu_priv->tx_frag_skbuffs; ++ ++ data[crr_stat * num_stat_values + crr_cpu] = percpu_priv->stats.tx_errors; ++ data[crr_stat++ * num_stat_values + num_cpus] += percpu_priv->stats.tx_errors; ++ ++ data[crr_stat * num_stat_values + crr_cpu] = percpu_priv->stats.rx_errors; ++ data[crr_stat++ * num_stat_values + num_cpus] += percpu_priv->stats.rx_errors; ++ ++ data[crr_stat * num_stat_values + crr_cpu] = bp_count; ++ data[crr_stat++ * num_stat_values + num_cpus] += bp_count; ++} ++ ++static void dpa_get_ethtool_stats(struct net_device *net_dev, ++ struct ethtool_stats *stats, u64 *data) ++{ ++ u64 bp_count, cg_time, cg_num, cg_status; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct qm_mcr_querycgr query_cgr; ++ struct dpa_rx_errors rx_errors; ++ struct dpa_ern_cnt ern_cnt; ++ struct dpa_priv_s *priv; ++ unsigned int num_cpus, offset; ++ struct dpa_bp *dpa_bp; ++ int total_stats, i; ++ ++ total_stats = dpa_get_sset_count(net_dev, ETH_SS_STATS); ++ priv = netdev_priv(net_dev); ++ dpa_bp = priv->dpa_bp; ++ num_cpus = num_online_cpus(); ++ bp_count = 0; ++ ++ memset(&rx_errors, 0, sizeof(struct dpa_rx_errors)); ++ memset(&ern_cnt, 0, sizeof(struct dpa_ern_cnt)); ++ memset(data, 0, total_stats * sizeof(u64)); ++ ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ if (dpa_bp->percpu_count) ++ bp_count = *(per_cpu_ptr(dpa_bp->percpu_count, i)); ++ ++ rx_errors.dme += percpu_priv->rx_errors.dme; ++ rx_errors.fpe += percpu_priv->rx_errors.fpe; ++ rx_errors.fse += percpu_priv->rx_errors.fse; ++ rx_errors.phe += percpu_priv->rx_errors.phe; ++ rx_errors.cse += percpu_priv->rx_errors.cse; ++ ++ ern_cnt.cg_tdrop += percpu_priv->ern_cnt.cg_tdrop; ++ ern_cnt.wred += percpu_priv->ern_cnt.wred; ++ ern_cnt.err_cond += percpu_priv->ern_cnt.err_cond; ++ ern_cnt.early_window += percpu_priv->ern_cnt.early_window; ++ ern_cnt.late_window += percpu_priv->ern_cnt.late_window; ++ ern_cnt.fq_tdrop += percpu_priv->ern_cnt.fq_tdrop; ++ ern_cnt.fq_retired += percpu_priv->ern_cnt.fq_retired; ++ ern_cnt.orp_zero += percpu_priv->ern_cnt.orp_zero; ++ ++ copy_stats(percpu_priv, num_cpus, i, bp_count, data); ++ } ++ ++ offset = (num_cpus + 1) * DPA_STATS_PERCPU_LEN; ++ memcpy(data + offset, &rx_errors, sizeof(struct dpa_rx_errors)); ++ ++ offset += sizeof(struct dpa_rx_errors) / sizeof(u64); ++ memcpy(data + offset, &ern_cnt, sizeof(struct dpa_ern_cnt)); ++ ++ /* gather congestion related counters */ ++ cg_num = 0; ++ cg_status = 0; ++ cg_time = jiffies_to_msecs(priv->cgr_data.congested_jiffies); ++ if (qman_query_cgr(&priv->cgr_data.cgr, &query_cgr) == 0) { ++ cg_num = priv->cgr_data.cgr_congested_count; ++ cg_status = query_cgr.cgr.cs; ++ ++ /* reset congestion stats (like QMan API does */ ++ priv->cgr_data.congested_jiffies = 0; ++ priv->cgr_data.cgr_congested_count = 0; ++ } ++ ++ offset += sizeof(struct dpa_ern_cnt) / sizeof(u64); ++ data[offset++] = cg_time; ++ data[offset++] = cg_num; ++ data[offset++] = cg_status; ++} ++ ++static void dpa_get_strings(struct net_device *net_dev, u32 stringset, u8 *data) ++{ ++ unsigned int i, j, num_cpus, size; ++ char stat_string_cpu[ETH_GSTRING_LEN]; ++ u8 *strings; ++ ++ strings = data; ++ num_cpus = num_online_cpus(); ++ size = DPA_STATS_GLOBAL_LEN * ETH_GSTRING_LEN; ++ ++ for (i = 0; i < DPA_STATS_PERCPU_LEN; i++) { ++ for (j = 0; j < num_cpus; j++) { ++ snprintf(stat_string_cpu, ETH_GSTRING_LEN, "%s [CPU %d]", dpa_stats_percpu[i], j); ++ memcpy(strings, stat_string_cpu, ETH_GSTRING_LEN); ++ strings += ETH_GSTRING_LEN; ++ } ++ snprintf(stat_string_cpu, ETH_GSTRING_LEN, "%s [TOTAL]", dpa_stats_percpu[i]); ++ memcpy(strings, stat_string_cpu, ETH_GSTRING_LEN); ++ strings += ETH_GSTRING_LEN; ++ } ++ memcpy(strings, dpa_stats_global, size); ++} ++ + const struct ethtool_ops dpa_ethtool_ops = { + .get_settings = dpa_get_settings, + .set_settings = dpa_set_settings, +@@ -343,10 +527,12 @@ const struct ethtool_ops dpa_ethtool_ops = { + .get_pauseparam = dpa_get_pauseparam, + .set_pauseparam = dpa_set_pauseparam, + .self_test = NULL, /* TODO invoke the cold-boot unit-test? */ +- .get_ethtool_stats = NULL, /* TODO other stats, currently in debugfs */ + .get_link = ethtool_op_get_link, + .get_eee = dpa_get_eee, + .set_eee = dpa_set_eee, ++ .get_sset_count = dpa_get_sset_count, ++ .get_ethtool_stats = dpa_get_ethtool_stats, ++ .get_strings = dpa_get_strings, + #ifdef CONFIG_PM + .get_wol = dpa_get_wol, + .set_wol = dpa_set_wol, +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0032-dpaa_eth-set-MAC-handle-for-MEMAC.patch b/target/linux/layerscape-64b/patches-4.1/0032-dpaa_eth-set-MAC-handle-for-MEMAC.patch new file mode 100644 index 0000000..b41f394 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0032-dpaa_eth-set-MAC-handle-for-MEMAC.patch @@ -0,0 +1,28 @@ +From 89a5e3d7101e4cf05c7ca864f9a40bd3fab6e561 Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Mon, 14 Dec 2015 19:31:14 +0200 +Subject: [PATCH 032/151] dpaa_eth: set MAC handle for MEMAC + +Signed-off-by: Madalin Bucur +--- + drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c b/drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c +index 462543c..ad764af 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c +@@ -243,6 +243,10 @@ static int __cold memac_init(struct mac_device *mac_dev) + goto _return; + } + ++ fm_mac_set_handle(mac_dev->fm_dev, priv->fm_mac, ++ (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) ? ++ param.macId : param.macId + FM_MAX_NUM_OF_1G_MACS); ++ + _errno = fm_mac_config_max_frame_length(priv->fm_mac, fm_get_max_frm()); + if (unlikely(_errno < 0)) + goto _return_fm_mac_free; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0033-dpaa_eth-rename-ethtool-statistic.patch b/target/linux/layerscape-64b/patches-4.1/0033-dpaa_eth-rename-ethtool-statistic.patch new file mode 100644 index 0000000..229314c --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0033-dpaa_eth-rename-ethtool-statistic.patch @@ -0,0 +1,26 @@ +From a9df8b4c51dffa29e1eb53e9bd4fc20a87aefcc4 Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Mon, 31 Aug 2015 19:25:15 +0300 +Subject: [PATCH 033/151] dpaa_eth: rename ethtool statistic + +Signed-off-by: Madalin Bucur +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c +index f0ca8b8..c346d8a 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c +@@ -48,7 +48,7 @@ static const char dpa_stats_percpu[][ETH_GSTRING_LEN] = { + "interrupts", + "rx packets", + "tx packets", +- "tx returned", ++ "tx recycled", + "tx confirm", + "tx S/G", + "tx error", +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0034-dpaa_eth-Remove-PPC-dependencies-from-the-macsec-deb.patch b/target/linux/layerscape-64b/patches-4.1/0034-dpaa_eth-Remove-PPC-dependencies-from-the-macsec-deb.patch new file mode 100644 index 0000000..7f57378 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0034-dpaa_eth-Remove-PPC-dependencies-from-the-macsec-deb.patch @@ -0,0 +1,54 @@ +From 4fd8c932c298b461850204f566e486d4e9bbdc21 Mon Sep 17 00:00:00 2001 +From: Camelia Groza +Date: Wed, 12 Aug 2015 13:57:49 +0300 +Subject: [PATCH 034/151] dpaa_eth: Remove PPC dependencies from the macsec + debugfs + +Signed-off-by: Camelia Groza +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.c +index 64e8a39..72de669 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.c +@@ -31,7 +31,6 @@ + + #include + #include +-#include + #include "dpaa_eth_macsec.h" + #include "dpaa_eth.h" + +@@ -148,8 +147,7 @@ int macsec_netdev_debugfs_create(struct net_device *net_dev) + net_dev, + &macsec_debugfs_fops); + if (unlikely(selected_macsec_priv->debugfs_file == NULL)) { +- netdev_err(net_dev, "debugfs_create_file(%s/%s/%s)", +- powerpc_debugfs_root->d_iname, ++ netdev_err(net_dev, "debugfs_create_file(%s/%s)", + dpa_debugfs_root->d_iname, + buf); + +@@ -173,14 +171,14 @@ int __init macsec_debugfs_module_init(void) + { + int _errno = 0; + +- dpa_debugfs_root = debugfs_create_dir(MACSEC_DEBUGFS_ROOT, +- powerpc_debugfs_root); ++ dpa_debugfs_root = debugfs_create_dir(MACSEC_DEBUGFS_ROOT, NULL); ++ + if (unlikely(dpa_debugfs_root == NULL)) { + _errno = -ENOMEM; + pr_err(KBUILD_MODNAME ": %s:%hu:%s():\n", + KBUILD_BASENAME".c", __LINE__, __func__); + pr_err("\tdebugfs_create_dir(%s/"KBUILD_MODNAME") = %d\n", +- powerpc_debugfs_root->d_iname, _errno); ++ MACSEC_DEBUGFS_ROOT, _errno); + } + + return _errno; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0035-dpaa_eth-Unmap-the-S-G-table-prior-to-iterate-throug.patch b/target/linux/layerscape-64b/patches-4.1/0035-dpaa_eth-Unmap-the-S-G-table-prior-to-iterate-throug.patch new file mode 100644 index 0000000..e9f5f38 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0035-dpaa_eth-Unmap-the-S-G-table-prior-to-iterate-throug.patch @@ -0,0 +1,112 @@ +From f62c3819738de3486f30c793f596696f7bf82678 Mon Sep 17 00:00:00 2001 +From: Cristian Sovaiala +Date: Thu, 9 Jul 2015 18:06:01 +0300 +Subject: [PATCH 035/151] dpaa_eth: Unmap the S/G table prior to iterate + through the fragments + +The S/G table must be unmapped before walking through the fragments +and releasing them back into the buffer pool. +Remap the S/G table after seeding of the fragments has finished and +put the S/G table's associated buffer back into the buffer pool. + +Also use dma_sync_single_for_cpu to access the parse results area +otherwise a dma_map_single is required and the frame descriptor +updated. + +memset the bm_buffer structures prior to use otherwise we risk +sending garbage to the Bman driver. + +Signed-off-by: Cristian Sovaiala +Change-Id: I99e445bda0602f064e6745ad6cea17f5b8db8897 +Reviewed-on: http://git.am.freescale.net:8181/39551 +Reviewed-by: Madalin-Cristian Bucur +Tested-by: Madalin-Cristian Bucur +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c | 3 +- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_common.c | 35 ++++++++++++++++------ + 2 files changed, 28 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c +index 1192645..6ec6e7a 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c +@@ -232,7 +232,8 @@ dpa_csum_validation(const struct dpa_priv_s *priv, + if (unlikely(!frm)) + return; + +- dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, DMA_BIDIRECTIONAL); ++ dma_sync_single_for_cpu(dpa_bp->dev, addr, DPA_RX_PRIV_DATA_SIZE + ++ DPA_PARSE_RESULTS_SIZE, DMA_BIDIRECTIONAL); + + parse_result = (fm_prs_result_t *)(frm + DPA_RX_PRIV_DATA_SIZE); + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +index 452b5e2..cc3968b 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +@@ -1537,6 +1537,8 @@ void dpa_release_sgt(struct qm_sg_entry *sgt) + struct bm_buffer bmb[DPA_BUFF_RELEASE_MAX]; + uint8_t i = 0, j; + ++ memset(bmb, 0, DPA_BUFF_RELEASE_MAX * sizeof(struct bm_buffer)); ++ + do { + dpa_bp = dpa_bpid2pool(sgt[i].bpid); + DPA_BUG_ON(!dpa_bp); +@@ -1548,6 +1550,7 @@ void dpa_release_sgt(struct qm_sg_entry *sgt) + bmb[j].hi = sgt[i].addr_hi; + bmb[j].lo = be32_to_cpu(sgt[i].addr_lo); + ++ + j++; i++; + } while (j < ARRAY_SIZE(bmb) && + !sgt[i-1].final && +@@ -1562,22 +1565,36 @@ EXPORT_SYMBOL(dpa_release_sgt); + void __attribute__((nonnull)) + dpa_fd_release(const struct net_device *net_dev, const struct qm_fd *fd) + { +- struct qm_sg_entry *sgt; +- struct dpa_bp *_dpa_bp; +- struct bm_buffer _bmb; ++ struct qm_sg_entry *sgt; ++ struct dpa_bp *dpa_bp; ++ struct bm_buffer bmb; ++ dma_addr_t addr; ++ void *vaddr; + +- _bmb.hi = fd->addr_hi; +- _bmb.lo = fd->addr_lo; ++ memset(&bmb, 0, sizeof(struct bm_buffer)); ++ bm_buffer_set64(&bmb, fd->addr); + +- _dpa_bp = dpa_bpid2pool(fd->bpid); +- DPA_BUG_ON(!_dpa_bp); ++ dpa_bp = dpa_bpid2pool(fd->bpid); ++ DPA_BUG_ON(!dpa_bp); + + if (fd->format == qm_fd_sg) { +- sgt = (phys_to_virt(bm_buf_addr(&_bmb)) + dpa_fd_offset(fd)); ++ vaddr = phys_to_virt(fd->addr); ++ sgt = vaddr + dpa_fd_offset(fd); ++ ++ dma_unmap_single(dpa_bp->dev, qm_fd_addr(fd), dpa_bp->size, ++ DMA_BIDIRECTIONAL); ++ + dpa_release_sgt(sgt); ++ addr = dma_map_single(dpa_bp->dev, vaddr, dpa_bp->size, ++ DMA_BIDIRECTIONAL); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { ++ dev_err(dpa_bp->dev, "DMA mapping failed"); ++ return; ++ } ++ bm_buffer_set64(&bmb, addr); + } + +- while (bman_release(_dpa_bp->pool, &_bmb, 1, 0)) ++ while (bman_release(dpa_bp->pool, &bmb, 1, 0)) + cpu_relax(); + } + EXPORT_SYMBOL(dpa_fd_release); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0036-dpaa_eth-memset-the-S-G-entry-structure.patch b/target/linux/layerscape-64b/patches-4.1/0036-dpaa_eth-memset-the-S-G-entry-structure.patch new file mode 100644 index 0000000..34575dc --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0036-dpaa_eth-memset-the-S-G-entry-structure.patch @@ -0,0 +1,30 @@ +From 28cb420c3876b66bfb7b6eac736d223b04c2c913 Mon Sep 17 00:00:00 2001 +From: Camelia Groza +Date: Tue, 2 Feb 2016 17:05:01 +0200 +Subject: [PATCH 036/151] dpaa_eth: memset the S/G entry structure + +Explicitly memset the Scatter-Gather entry structure to make sure there's no +garbage inside its fields. + +Signed-off-by: Cristian Sovaiala +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +index 1da4f73..3e4c652 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +@@ -742,6 +742,9 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + return -ENOMEM; + } + ++ memset(sgt_buf, 0, priv->tx_headroom + ++ sizeof(struct qm_sg_entry) * (1 + nr_frags)); ++ + /* Enable L3/L4 hardware checksum computation. + * + * We must do this before dma_map_single(DMA_TO_DEVICE), because we may +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0037-dpaa_eth-add-S-G-for-onic.patch b/target/linux/layerscape-64b/patches-4.1/0037-dpaa_eth-add-S-G-for-onic.patch new file mode 100644 index 0000000..64355c2 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0037-dpaa_eth-add-S-G-for-onic.patch @@ -0,0 +1,495 @@ +From 0fdd4235271f94691db060a030a199540623ebd4 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Fri, 22 Jan 2016 19:38:21 +0200 +Subject: [PATCH 037/151] dpaa_eth: add S/G for onic + +This patch adds Tx S/G for onic Ethernet driver. In order to achieve that, a +new specialiazed drainig buffer pool was created. + +By design, onic does not have confirmation capabilities. To release the +allocated space for transmission, a draining buffer pool is used. A periodic +routine flushes the draining buffer pool at each kernel tick. + +To accomodate different frame descriptors, S/G frames and contiguous frames, an +auxiliary dedicated draining buffer pool is filled with S/G fragments. These +buffer pools are transparent for the user/admin of the network interface. + +Signed-off-by: Marian-Cristian Rotariu +--- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c | 294 +++++++++++++++++---- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h | 1 + + 2 files changed, 249 insertions(+), 46 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +index f672420..1cf1e1d 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +@@ -51,6 +51,7 @@ + #include + #include + #include ++#include + + #include "dpaa_eth.h" + #include "dpaa_eth_common.h" +@@ -90,6 +91,7 @@ static void dpa_generic_ern(struct qman_portal *portal, + static int __hot dpa_generic_tx(struct sk_buff *skb, + struct net_device *netdev); + static void dpa_generic_drain_bp(struct dpa_bp *bp, u8 nbuf); ++static void dpa_generic_drain_sg_bp(struct dpa_bp *sg_bp, u8 nbuf); + + static const struct net_device_ops dpa_generic_ops = { + .ndo_open = dpa_generic_start, +@@ -110,6 +112,7 @@ static void dpa_generic_draining_timer(unsigned long arg) + + /* drain in pairs of 4 buffers */ + dpa_generic_drain_bp(priv->draining_tx_bp, 4); ++ dpa_generic_drain_sg_bp(priv->draining_tx_sg_bp, 4); + + if (atomic_read(&priv->ifup)) + mod_timer(&(priv->timer), jiffies + 1); +@@ -371,6 +374,7 @@ dpa_generic_rx_dqrr(struct qman_portal *portal, + * enough + */ + dpa_generic_drain_bp(priv->draining_tx_bp, 1); ++ dpa_generic_drain_sg_bp(priv->draining_tx_sg_bp, 1); + + if (unlikely(dpaa_eth_napi_schedule(percpu_priv, portal))) + return qman_cb_dqrr_stop; +@@ -450,6 +454,45 @@ qman_consume: + return qman_cb_dqrr_consume; + } + ++static void dpa_generic_drain_sg_bp(struct dpa_bp *sgbp, u8 nbuf) ++{ ++ int ret; ++ struct bm_buffer bmb[8]; ++ ++ do { ++ ret = bman_acquire(sgbp->pool, bmb, nbuf, 0); ++ } while (ret >= 0); ++} ++ ++inline void dpa_release_sg(struct sk_buff *skb, dma_addr_t addr, ++ struct dpa_bp *bp) ++{ ++ struct qm_sg_entry *sgt = phys_to_virt(addr + DPA_DEFAULT_TX_HEADROOM); ++ int nr_frags = skb_shinfo(skb)->nr_frags; ++ dma_addr_t sg_addr; ++ int j; ++ ++ dma_unmap_single(bp->dev, addr, DPA_DEFAULT_TX_HEADROOM + ++ sizeof(struct qm_sg_entry) * (1 + nr_frags), ++ DMA_BIDIRECTIONAL); ++ ++ for (j = 0; j <= nr_frags; j++) { ++ DPA_BUG_ON(sgt[j].extension); ++ sg_addr = qm_sg_addr(&sgt[j]); ++ dma_unmap_page(bp->dev, sg_addr, ++ sgt[j].length, DMA_BIDIRECTIONAL); ++ } ++ ++ dev_kfree_skb_any(skb); ++} ++ ++inline void dpa_release_contig(struct sk_buff *skb, dma_addr_t addr, ++ struct dpa_bp *bp) ++{ ++ dma_unmap_single(bp->dev, addr, bp->size, DMA_BIDIRECTIONAL); ++ dev_kfree_skb_any(skb); ++} ++ + static void dpa_generic_drain_bp(struct dpa_bp *bp, u8 nbuf) + { + int ret, i; +@@ -464,11 +507,15 @@ static void dpa_generic_drain_bp(struct dpa_bp *bp, u8 nbuf) + ret = bman_acquire(bp->pool, bmb, nbuf, 0); + if (ret > 0) { + for (i = 0; i < nbuf; i++) { +- addr = bm_buf_addr(&bmb[i]); ++ addr = bm_buffer_get64(&bmb[i]); + skbh = (struct sk_buff **)phys_to_virt(addr); + dma_unmap_single(bp->dev, addr, bp->size, + DMA_TO_DEVICE); +- dev_kfree_skb_any(*skbh); ++ ++ if (skb_is_nonlinear(*skbh)) ++ dpa_release_sg(*skbh, addr, bp); ++ else ++ dpa_release_contig(*skbh, addr, bp); + } + count -= i; + } +@@ -582,6 +629,128 @@ return_error: + return retval; + } + ++static inline int generic_skb_to_sg_fd(struct dpa_generic_priv_s *priv, ++ struct sk_buff *skb, struct qm_fd *fd) ++{ ++ struct dpa_bp *dpa_bp = priv->draining_tx_bp; ++ struct dpa_bp *dpa_sg_bp = priv->draining_tx_sg_bp; ++ dma_addr_t addr; ++ struct sk_buff **skbh; ++ struct net_device *net_dev = priv->net_dev; ++ int err; ++ ++ struct qm_sg_entry *sgt; ++ void *sgt_buf; ++ void *buffer_start; ++ skb_frag_t *frag; ++ int i, j; ++ const enum dma_data_direction dma_dir = DMA_BIDIRECTIONAL; ++ const int nr_frags = skb_shinfo(skb)->nr_frags; ++ ++ memset(fd, 0, sizeof(*fd)); ++ fd->format = qm_fd_sg; ++ ++ /* get a page frag to store the SGTable */ ++ sgt_buf = netdev_alloc_frag(priv->tx_headroom + ++ sizeof(struct qm_sg_entry) * (1 + nr_frags)); ++ if (unlikely(!sgt_buf)) { ++ dev_err(dpa_bp->dev, "netdev_alloc_frag() failed\n"); ++ return -ENOMEM; ++ } ++ ++ memset(sgt_buf, 0, priv->tx_headroom + ++ sizeof(struct qm_sg_entry) * (1 + nr_frags)); ++ ++ /* do this before dma_map_single(DMA_TO_DEVICE), because we may need to ++ * write into the skb. ++ */ ++ err = dpa_generic_tx_csum(priv, skb, fd, ++ sgt_buf + DPA_TX_PRIV_DATA_SIZE); ++ if (unlikely(err < 0)) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(net_dev, "HW csum error: %d\n", err); ++ goto csum_failed; ++ } ++ ++ sgt = (struct qm_sg_entry *)(sgt_buf + priv->tx_headroom); ++ sgt[0].bpid = dpa_sg_bp->bpid; ++ sgt[0].offset = 0; ++ sgt[0].length = skb_headlen(skb); ++ sgt[0].extension = 0; ++ sgt[0].final = 0; ++ ++ addr = dma_map_single(dpa_sg_bp->dev, skb->data, sgt[0].length, ++ dma_dir); ++ if (unlikely(dma_mapping_error(dpa_sg_bp->dev, addr))) { ++ dev_err(dpa_sg_bp->dev, "DMA mapping failed"); ++ err = -EINVAL; ++ goto sg0_map_failed; ++ } ++ ++ sgt[0].addr_hi = (uint8_t)upper_32_bits(addr); ++ sgt[0].addr_lo = cpu_to_be32(lower_32_bits(addr)); ++ ++ /* populate the rest of SGT entries */ ++ for (i = 1; i <= nr_frags; i++) { ++ frag = &skb_shinfo(skb)->frags[i - 1]; ++ sgt[i].bpid = dpa_sg_bp->bpid; ++ sgt[i].offset = 0; ++ sgt[i].length = frag->size; ++ sgt[i].extension = 0; ++ sgt[i].final = 0; ++ ++ DPA_BUG_ON(!skb_frag_page(frag)); ++ addr = skb_frag_dma_map(dpa_bp->dev, frag, 0, sgt[i].length, ++ dma_dir); ++ if (unlikely(dma_mapping_error(dpa_sg_bp->dev, addr))) { ++ dev_err(dpa_sg_bp->dev, "DMA mapping failed"); ++ err = -EINVAL; ++ goto sg_map_failed; ++ } ++ ++ /* keep the offset in the address */ ++ sgt[i].addr_hi = (uint8_t)upper_32_bits(addr); ++ sgt[i].addr_lo = cpu_to_be32(lower_32_bits(addr)); ++ } ++ sgt[i - 1].final = 1; ++ ++ fd->length20 = skb->len; ++ fd->offset = priv->tx_headroom; ++ ++ /* DMA map the SGT page */ ++ buffer_start = (void *)sgt - dpa_fd_offset(fd); ++ /* Can't write at "negative" offset in buffer_start, because this skb ++ * may not have been allocated by us. ++ */ ++ DPA_WRITE_SKB_PTR(skb, skbh, buffer_start, 0); ++ ++ addr = dma_map_single(dpa_bp->dev, buffer_start, ++ priv->tx_headroom + sizeof(struct qm_sg_entry) * (1 + nr_frags), ++ dma_dir); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { ++ dev_err(dpa_bp->dev, "DMA mapping failed"); ++ err = -EINVAL; ++ goto sgt_map_failed; ++ } ++ ++ fd->bpid = dpa_bp->bpid; ++ fd->addr_hi = (uint8_t)upper_32_bits(addr); ++ fd->addr_lo = lower_32_bits(addr); ++ ++ return 0; ++ ++sgt_map_failed: ++sg_map_failed: ++ for (j = 0; j < i; j++) ++ dma_unmap_page(dpa_sg_bp->dev, qm_sg_addr(&sgt[j]), ++ be32_to_cpu(sgt[j].length), dma_dir); ++sg0_map_failed: ++csum_failed: ++ put_page(virt_to_head_page(sgt_buf)); ++ ++ return err; ++} ++ + static int __hot dpa_generic_tx(struct sk_buff *skb, struct net_device *netdev) + { + struct dpa_generic_priv_s *priv = netdev_priv(netdev); +@@ -589,65 +758,72 @@ static int __hot dpa_generic_tx(struct sk_buff *skb, struct net_device *netdev) + raw_cpu_ptr(priv->percpu_priv); + struct rtnl_link_stats64 *percpu_stats = &percpu_priv->stats; + struct dpa_bp *bp = priv->draining_tx_bp; ++ struct dpa_bp *sg_bp = priv->draining_tx_sg_bp; + struct sk_buff **skbh = NULL; + dma_addr_t addr; + struct qm_fd fd; + int queue_mapping; + struct qman_fq *egress_fq; ++ const bool nonlinear = skb_is_nonlinear(skb); + int i = 0, err = 0; + int *countptr; + +- if (unlikely(skb_headroom(skb) < priv->tx_headroom)) { +- struct sk_buff *skb_new; ++ if (nonlinear && skb_shinfo(skb)->nr_frags < DPA_SGT_MAX_ENTRIES) { ++ err = generic_skb_to_sg_fd(priv, skb, &fd); ++ if (unlikely(err < 0)) ++ goto sg_failed; ++ percpu_priv->tx_frag_skbuffs++; ++ } else { ++ if (unlikely(skb_headroom(skb) < priv->tx_headroom)) { ++ struct sk_buff *skb_new; ++ ++ skb_new = skb_realloc_headroom(skb, priv->tx_headroom); ++ if (unlikely(!skb_new)) { ++ percpu_stats->tx_errors++; ++ kfree_skb(skb); ++ goto done; ++ } + +- skb_new = skb_realloc_headroom(skb, priv->tx_headroom); +- if (unlikely(!skb_new)) { +- percpu_stats->tx_errors++; + kfree_skb(skb); +- goto done; ++ skb = skb_new; + } +- kfree_skb(skb); +- skb = skb_new; +- } + +- clear_fd(&fd); ++ clear_fd(&fd); + +- /* store skb backpointer to release the skb later */ +- skbh = (struct sk_buff **)(skb->data - priv->tx_headroom); +- *skbh = skb; ++ /* store skb backpointer to release the skb later */ ++ skbh = (struct sk_buff **)(skb->data - priv->tx_headroom); ++ *skbh = skb; + +- /* TODO check if skb->len + priv->tx_headroom < bp->size */ ++ /* do this before dma_map_single(), because we may need to write ++ * into the skb. ++ */ ++ err = dpa_generic_tx_csum(priv, skb, &fd, ++ ((char *)skbh) + DPA_TX_PRIV_DATA_SIZE); ++ if (unlikely(err < 0)) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(netdev, "HW csum error: %d\n", err); ++ return err; ++ } + +- /* Enable L3/L4 hardware checksum computation. +- * +- * We must do this before dma_map_single(), because we may +- * need to write into the skb. +- */ +- err = dpa_generic_tx_csum(priv, skb, &fd, +- ((char *)skbh) + DPA_TX_PRIV_DATA_SIZE); +- if (unlikely(err < 0)) { +- if (netif_msg_tx_err(priv) && net_ratelimit()) +- netdev_err(netdev, "HW csum error: %d\n", err); +- return err; +- } ++ addr = dma_map_single(bp->dev, skbh, ++ skb->len + priv->tx_headroom, DMA_TO_DEVICE); ++ if (unlikely(dma_mapping_error(bp->dev, addr))) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ netdev_err(netdev, "dma_map_single() failed\n"); ++ goto dma_mapping_failed; ++ } + +- addr = dma_map_single(bp->dev, skbh, +- skb->len + priv->tx_headroom, DMA_TO_DEVICE); +- if (unlikely(dma_mapping_error(bp->dev, addr))) { +- if (netif_msg_tx_err(priv) && net_ratelimit()) +- netdev_err(netdev, "dma_map_single() failed\n"); +- goto dma_mapping_failed; ++ fd.format = qm_fd_contig; ++ fd.length20 = skb->len; ++ fd.offset = priv->tx_headroom; ++ fd.addr_hi = (uint8_t)upper_32_bits(addr); ++ fd.addr_lo = lower_32_bits(addr); ++ /* fd.cmd |= FM_FD_CMD_FCO; */ ++ fd.bpid = bp->bpid; + } + +- fd.format = qm_fd_contig; +- fd.length20 = skb->len; +- fd.offset = priv->tx_headroom; +- fd.addr_hi = (uint8_t)upper_32_bits(addr); +- fd.addr_lo = lower_32_bits(addr); +- /* fd.cmd |= FM_FD_CMD_FCO; */ +- fd.bpid = bp->bpid; +- + dpa_generic_drain_bp(bp, 1); ++ dpa_generic_drain_sg_bp(sg_bp, 1); + + queue_mapping = dpa_get_queue_mapping(skb); + egress_fq = priv->egress_fqs[queue_mapping]; +@@ -674,6 +850,7 @@ static int __hot dpa_generic_tx(struct sk_buff *skb, struct net_device *netdev) + + xmit_failed: + dma_unmap_single(bp->dev, addr, fd.offset + fd.length20, DMA_TO_DEVICE); ++sg_failed: + dma_mapping_failed: + percpu_stats->tx_errors++; + dev_kfree_skb(skb); +@@ -743,7 +920,7 @@ static int dpa_generic_netdev_init(struct device_node *dpa_node, + return -EINVAL; + } + +- netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; ++ netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_SG; + netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE; + netdev->features |= netdev->hw_features; + netdev->vlan_features = netdev->features; +@@ -986,7 +1163,7 @@ static int dpa_generic_rx_bp_probe(struct platform_device *_of_dev, + } + + bp[i].percpu_count = devm_alloc_percpu(dev, +- *bp[i].percpu_count); ++ *bp[i].percpu_count); + } + + of_node_put(oh_node); +@@ -1025,11 +1202,13 @@ _return_of_node_put: + static int dpa_generic_tx_bp_probe(struct platform_device *_of_dev, + struct fm_port *tx_port, + struct dpa_bp **draining_tx_bp, ++ struct dpa_bp **draining_tx_sg_bp, + struct dpa_buffer_layout_s **tx_buf_layout) + { + struct device *dev = &_of_dev->dev; + struct fm_port_params params; + struct dpa_bp *bp = NULL; ++ struct dpa_bp *bp_sg = NULL; + struct dpa_buffer_layout_s *buf_layout = NULL; + + buf_layout = devm_kzalloc(dev, sizeof(*buf_layout), GFP_KERNEL); +@@ -1058,6 +1237,19 @@ static int dpa_generic_tx_bp_probe(struct platform_device *_of_dev, + bp->target_count = CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT; + + *draining_tx_bp = bp; ++ ++ bp_sg = devm_kzalloc(dev, sizeof(*bp_sg), GFP_KERNEL); ++ if (unlikely(bp_sg == NULL)) { ++ dev_err(dev, "devm_kzalloc() failed\n"); ++ return -ENOMEM; ++ } ++ ++ bp_sg->size = dpa_bp_size(buf_layout); ++ bp_sg->percpu_count = alloc_percpu(*bp_sg->percpu_count); ++ bp_sg->target_count = CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT; ++ ++ *draining_tx_sg_bp = bp_sg; ++ + *tx_buf_layout = buf_layout; + + return 0; +@@ -1318,6 +1510,7 @@ static int dpa_generic_bp_create(struct net_device *net_dev, + struct dpa_bp *rx_bp, + struct dpa_buffer_layout_s *rx_buf_layout, + struct dpa_bp *draining_tx_bp, ++ struct dpa_bp *draining_tx_sg_bp, + struct dpa_buffer_layout_s *tx_buf_layout) + { + struct dpa_generic_priv_s *priv = netdev_priv(net_dev); +@@ -1328,6 +1521,7 @@ static int dpa_generic_bp_create(struct net_device *net_dev, + priv->rx_bp = rx_bp; + priv->rx_buf_layout = rx_buf_layout; + priv->draining_tx_bp = draining_tx_bp; ++ priv->draining_tx_sg_bp = draining_tx_sg_bp; + priv->tx_buf_layout = tx_buf_layout; + + err = dpa_bp_alloc(priv->rx_bp); +@@ -1344,6 +1538,13 @@ static int dpa_generic_bp_create(struct net_device *net_dev, + return err; + } + ++ err = dpa_bp_alloc(priv->draining_tx_sg_bp); ++ if (err < 0) { ++ /* _dpa_bp_free(priv->draining_tx_bp); */ ++ priv->draining_tx_sg_bp = NULL; ++ return err; ++ } ++ + return 0; + } + +@@ -1429,6 +1630,7 @@ static int dpa_generic_eth_probe(struct platform_device *_of_dev) + int rx_bp_count = 0; + int disable_buff_dealloc = 0; + struct dpa_bp *rx_bp = NULL, *draining_tx_bp = NULL; ++ struct dpa_bp *draining_tx_sg_bp = NULL; + struct dpa_buffer_layout_s *rx_buf_layout = NULL, *tx_buf_layout = NULL; + struct list_head *dpa_fq_list; + static u8 generic_idx; +@@ -1448,7 +1650,7 @@ static int dpa_generic_eth_probe(struct platform_device *_of_dev) + return err; + + err = dpa_generic_tx_bp_probe(_of_dev, tx_port, &draining_tx_bp, +- &tx_buf_layout); ++ &draining_tx_sg_bp, &tx_buf_layout); + if (err < 0) + return err; + +@@ -1481,7 +1683,7 @@ static int dpa_generic_eth_probe(struct platform_device *_of_dev) + priv->timer.function = dpa_generic_draining_timer; + + err = dpa_generic_bp_create(netdev, rx_bp_count, rx_bp, rx_buf_layout, +- draining_tx_bp, tx_buf_layout); ++ draining_tx_bp, draining_tx_sg_bp, tx_buf_layout); + if (err < 0) + goto bp_create_failed; + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h +index aa74edf..98f7073 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h +@@ -46,6 +46,7 @@ struct dpa_generic_priv_s { + struct dpa_buffer_layout_s *rx_buf_layout; + + struct dpa_bp *draining_tx_bp; ++ struct dpa_bp *draining_tx_sg_bp; + struct dpa_buffer_layout_s *tx_buf_layout; + + /* Store here the needed Tx headroom for convenience and speed +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0038-dpaa_eth-remove-copyright-statement.patch b/target/linux/layerscape-64b/patches-4.1/0038-dpaa_eth-remove-copyright-statement.patch new file mode 100644 index 0000000..873bc96 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0038-dpaa_eth-remove-copyright-statement.patch @@ -0,0 +1,28 @@ +From 6818af3bc7bdb6ea305fc2058518e2b46a8cbf16 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Mon, 25 Jan 2016 11:23:20 +0200 +Subject: [PATCH 038/151] dpaa_eth: remove copyright statement + +Signed-off-by: Marian-Cristian Rotariu +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +index 1cf1e1d..446fe2a 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +@@ -7,10 +7,6 @@ + * * 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 +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0039-dpaa_eth-remove-TODO-list.patch b/target/linux/layerscape-64b/patches-4.1/0039-dpaa_eth-remove-TODO-list.patch new file mode 100644 index 0000000..7e2e54e --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0039-dpaa_eth-remove-TODO-list.patch @@ -0,0 +1,39 @@ +From 45b7b1a75afc225f43ce71b924f3d6f41d09ea18 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Mon, 25 Jan 2016 11:28:17 +0200 +Subject: [PATCH 039/151] dpaa_eth: remove TODO list + +Signed-off-by: Marian-Cristian Rotariu +--- + .../net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c | 15 --------------- + 1 file changed, 15 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +index 446fe2a..c7eada5 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +@@ -25,21 +25,6 @@ + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +-/* "generic" flavour of DPAA Ethernet driver, called oNIC +- * +- * TODO: +- * 1. This file should be conditionally compiled. For the moment it is +- * compiled by default. +- * 2. Tx multiqueues (ndo_select queue, alloc_etherdev_mq) +- * 3. Fetch the buffer layouts from OH ports. +- * 4. Make the drive generic (can connect with multiple OH ports, +- * remove '2' hardcode from oh_ports, buffer_layout, etc.). +- * 5. Multiple buffer pools for RX (up to 4 supported on HW) +- * 6. Different queue initializations (enable taildrop) +- * 7. ethtool +- * 8. Recycling (draining buffer pool = default buffer pool) +- */ +- + #include + #include + #include +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0040-dpaa_eth-create-macro-def-for-numerical-constant.patch b/target/linux/layerscape-64b/patches-4.1/0040-dpaa_eth-create-macro-def-for-numerical-constant.patch new file mode 100644 index 0000000..d9f40f9 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0040-dpaa_eth-create-macro-def-for-numerical-constant.patch @@ -0,0 +1,38 @@ +From 4ec30971ed64a8f24bfccd81e4f61c803a409ada Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Mon, 25 Jan 2016 11:39:24 +0200 +Subject: [PATCH 040/151] dpaa_eth: create macro def for numerical constant + +Signed-off-by: Marian-Cristian Rotariu +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +index c7eada5..5bdcb83 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +@@ -44,6 +44,7 @@ + #define DPA_GENERIC_SKB_COPY_MAX_SIZE 256 + #define DPA_GENERIC_NAPI_WEIGHT 64 + #define DPA_GENERIC_DESCRIPTION "FSL DPAA Generic Ethernet driver" ++#define DPA_GENERIC_BUFFER_QUOTA 4 + + MODULE_LICENSE("Dual BSD/GPL"); + MODULE_DESCRIPTION(DPA_GENERIC_DESCRIPTION); +@@ -91,9 +92,9 @@ static void dpa_generic_draining_timer(unsigned long arg) + { + struct dpa_generic_priv_s *priv = (struct dpa_generic_priv_s *)arg; + +- /* drain in pairs of 4 buffers */ +- dpa_generic_drain_bp(priv->draining_tx_bp, 4); +- dpa_generic_drain_sg_bp(priv->draining_tx_sg_bp, 4); ++ dpa_generic_drain_bp(priv->draining_tx_bp, DPA_GENERIC_BUFFER_QUOTA); ++ dpa_generic_drain_sg_bp(priv->draining_tx_sg_bp, ++ DPA_GENERIC_BUFFER_QUOTA); + + if (atomic_read(&priv->ifup)) + mod_timer(&(priv->timer), jiffies + 1); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0041-dpaa_eth-use-IFF_UP-to-check-the-Eth-interface.patch b/target/linux/layerscape-64b/patches-4.1/0041-dpaa_eth-use-IFF_UP-to-check-the-Eth-interface.patch new file mode 100644 index 0000000..e122b53 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0041-dpaa_eth-use-IFF_UP-to-check-the-Eth-interface.patch @@ -0,0 +1,68 @@ +From 7fb00ce83d7e3d8cedf3daf5c7d0655e97579a87 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Mon, 25 Jan 2016 12:00:27 +0200 +Subject: [PATCH 041/151] dpaa_eth: use IFF_UP to check the Eth interface + +Currently, I use an atomic variable to check if an interface is up/down. In the +kernel there are other methods to check the interface state. One of them is by +using IFF_UP offset from the net_dev->flags variable. + +Signed-off-by: Marian-Cristian Rotariu +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c | 6 +----- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h | 1 - + 2 files changed, 1 insertion(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +index 5bdcb83..033f985 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +@@ -96,7 +96,7 @@ static void dpa_generic_draining_timer(unsigned long arg) + dpa_generic_drain_sg_bp(priv->draining_tx_sg_bp, + DPA_GENERIC_BUFFER_QUOTA); + +- if (atomic_read(&priv->ifup)) ++ if (priv->net_dev->flags & IFF_UP) + mod_timer(&(priv->timer), jiffies + 1); + } + +@@ -246,7 +246,6 @@ static int __cold dpa_generic_start(struct net_device *netdev) + netif_tx_start_all_queues(netdev); + + mod_timer(&priv->timer, jiffies + 100); +- atomic_dec(&priv->ifup); + + return 0; + } +@@ -258,8 +257,6 @@ static int __cold dpa_generic_stop(struct net_device *netdev) + netif_tx_stop_all_queues(netdev); + dpaa_generic_napi_disable(priv); + +- atomic_inc_not_zero(&priv->ifup); +- + return 0; + } + +@@ -1660,7 +1657,6 @@ static int dpa_generic_eth_probe(struct platform_device *_of_dev) + priv->tx_headroom = DPA_DEFAULT_TX_HEADROOM; + + init_timer(&priv->timer); +- atomic_set(&priv->ifup, 0); + priv->timer.data = (unsigned long)priv; + priv->timer.function = dpa_generic_draining_timer; + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h +index 98f7073..7618aaf 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h +@@ -81,7 +81,6 @@ struct dpa_generic_priv_s { + char if_type[30]; + + /* periodic drain */ +- atomic_t ifup; + struct timer_list timer; + }; + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0042-dpaa_eth-rename-variables-and-remove-comments.patch b/target/linux/layerscape-64b/patches-4.1/0042-dpaa_eth-rename-variables-and-remove-comments.patch new file mode 100644 index 0000000..968becd --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0042-dpaa_eth-rename-variables-and-remove-comments.patch @@ -0,0 +1,75 @@ +From a7c7b0d74d412f036fd862b0aac966dc4c6d05f6 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Mon, 25 Jan 2016 12:13:13 +0200 +Subject: [PATCH 042/151] dpaa_eth: rename variables and remove comments + +Some function/variable names are not consistent throughout the file and some +comments are not useful. + +Signed-off-by: Marian-Cristian Rotariu +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +index 033f985..6777bfe 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +@@ -162,7 +162,7 @@ static int get_port_ref(struct device_node *dev_node, + struct fm_port **port) + { + struct platform_device *port_of_dev = NULL; +- struct device *op_dev = NULL; ++ struct device *oh_dev = NULL; + struct device_node *port_node = NULL; + + port_node = of_parse_phandle(dev_node, "fsl,fman-oh-port", 0); +@@ -176,8 +176,8 @@ static int get_port_ref(struct device_node *dev_node, + return -EINVAL; + + /* get the reference to oh port from FMD */ +- op_dev = &port_of_dev->dev; +- *port = fm_port_bind(op_dev); ++ oh_dev = &port_of_dev->dev; ++ *port = fm_port_bind(oh_dev); + + if (*port == NULL) + return -EINVAL; +@@ -211,7 +211,7 @@ static void dpaa_generic_napi_disable(struct dpa_generic_priv_s *priv) + } + } + +-static struct device_node *get_rx_op_port_node(struct platform_device *_of_dev) ++static struct device_node *get_rx_oh_port_node(struct platform_device *_of_dev) + { + struct device *dev = &_of_dev->dev; + struct device_node *port_node = NULL; +@@ -391,7 +391,6 @@ dpa_generic_rx_dqrr(struct qman_portal *portal, + } + + bp = dpa_bpid2pool(fd->bpid); +- /* TODO add bp check on hot path? */ + + /* find out the pad */ + skb_addr = virt_to_phys(skb->head); +@@ -982,7 +981,7 @@ static struct list_head *dpa_generic_fq_probe(struct platform_device *_of_dev, + INIT_LIST_HEAD(list); + + /* RX queues (RX error, RX default) are specified in Rx O/H port node */ +- oh_node = get_rx_op_port_node(_of_dev); ++ oh_node = get_rx_oh_port_node(_of_dev); + fqids_off = of_get_property(oh_node, "fsl,qman-frame-queues-oh", &lenp); + if (fqids_off == NULL) { + dev_err(dev, "Need Rx FQ definition in dts for generic devices\n"); +@@ -1085,7 +1084,7 @@ static int dpa_generic_rx_bp_probe(struct platform_device *_of_dev, + int na = 0, ns = 0; + int err = 0, i = 0; + +- oh_node = get_rx_op_port_node(_of_dev); ++ oh_node = get_rx_oh_port_node(_of_dev); + + bp_count = of_count_phandle_with_args(oh_node, + "fsl,bman-buffer-pools", NULL); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0043-dpaa_eth-remove-dead-unnecessary-code.patch b/target/linux/layerscape-64b/patches-4.1/0043-dpaa_eth-remove-dead-unnecessary-code.patch new file mode 100644 index 0000000..3730b4a --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0043-dpaa_eth-remove-dead-unnecessary-code.patch @@ -0,0 +1,123 @@ +From 67cccc19c427d2bdc30ed9045c5f69f54e329b2c Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Mon, 25 Jan 2016 12:24:31 +0200 +Subject: [PATCH 043/151] dpaa_eth: remove dead/unnecessary code + +Signed-off-by: Marian-Cristian Rotariu +--- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c | 80 ++++++++++------------ + 1 file changed, 36 insertions(+), 44 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +index 6777bfe..6fc5193 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +@@ -1315,12 +1315,8 @@ static inline void dpa_generic_setup_egress( + fq->fq_base = *template; + fq->net_dev = priv->net_dev; + +- if (port) { +- fq->flags = QMAN_FQ_FLAG_TO_DCPORTAL; +- fq->channel = fm_get_tx_port_channel(port); +- } else { +- fq->flags = QMAN_FQ_FLAG_NO_MODIFY; +- } ++ fq->flags = QMAN_FQ_FLAG_TO_DCPORTAL; ++ fq->channel = fm_get_tx_port_channel(port); + } + + static void dpa_generic_fq_setup(struct dpa_generic_priv_s *priv, +@@ -1386,8 +1382,6 @@ static int dpa_generic_fq_init(struct dpa_fq *dpa_fq, int disable_buff_dealloc) + if (dpa_fq->fqid == 0) + dpa_fq->flags |= QMAN_FQ_FLAG_DYNAMIC_FQID; + +- dpa_fq->init = !(dpa_fq->flags & QMAN_FQ_FLAG_NO_MODIFY); +- + _errno = qman_create_fq(dpa_fq->fqid, dpa_fq->flags, &dpa_fq->fq_base); + if (_errno) { + dev_err(dev, "qman_create_fq() failed\n"); +@@ -1395,47 +1389,45 @@ static int dpa_generic_fq_init(struct dpa_fq *dpa_fq, int disable_buff_dealloc) + } + fq = &dpa_fq->fq_base; + +- if (dpa_fq->init) { +- initfq.we_mask = QM_INITFQ_WE_FQCTRL; +- /* FIXME: why would we want to keep an empty FQ in cache? */ +- initfq.fqd.fq_ctrl = QM_FQCTRL_PREFERINCACHE; ++ initfq.we_mask = QM_INITFQ_WE_FQCTRL; ++ /* FIXME: why would we want to keep an empty FQ in cache? */ ++ initfq.fqd.fq_ctrl = QM_FQCTRL_PREFERINCACHE; + +- /* FQ placement */ +- initfq.we_mask |= QM_INITFQ_WE_DESTWQ; ++ /* FQ placement */ ++ initfq.we_mask |= QM_INITFQ_WE_DESTWQ; + +- initfq.fqd.dest.channel = dpa_fq->channel; +- initfq.fqd.dest.wq = dpa_fq->wq; ++ initfq.fqd.dest.channel = dpa_fq->channel; ++ initfq.fqd.dest.wq = dpa_fq->wq; + +- if (dpa_fq->fq_type == FQ_TYPE_TX && !disable_buff_dealloc) { +- initfq.we_mask |= QM_INITFQ_WE_CONTEXTA; +- /* ContextA: A2V=1 (contextA A2 field is valid) +- * ContextA A2: EBD=1 (deallocate buffers inside FMan) +- */ +- initfq.fqd.context_a.hi = 0x10000000; +- initfq.fqd.context_a.lo = 0x80000000; +- } ++ if (dpa_fq->fq_type == FQ_TYPE_TX && !disable_buff_dealloc) { ++ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA; ++ /* ContextA: A2V=1 (contextA A2 field is valid) ++ * ContextA A2: EBD=1 (deallocate buffers inside FMan) ++ */ ++ initfq.fqd.context_a.hi = 0x10000000; ++ initfq.fqd.context_a.lo = 0x80000000; ++ } + +- /* Initialization common to all ingress queues */ +- if (dpa_fq->flags & QMAN_FQ_FLAG_NO_ENQUEUE) { +- initfq.we_mask |= QM_INITFQ_WE_CONTEXTA; +- initfq.fqd.fq_ctrl |= +- QM_FQCTRL_CTXASTASHING | QM_FQCTRL_AVOIDBLOCK; +- initfq.fqd.context_a.stashing.exclusive = +- QM_STASHING_EXCL_DATA | QM_STASHING_EXCL_CTX | +- QM_STASHING_EXCL_ANNOTATION; +- initfq.fqd.context_a.stashing.data_cl = 2; +- initfq.fqd.context_a.stashing.annotation_cl = 1; +- initfq.fqd.context_a.stashing.context_cl = +- DIV_ROUND_UP(sizeof(struct qman_fq), 64); +- } ++ /* Initialization common to all ingress queues */ ++ if (dpa_fq->flags & QMAN_FQ_FLAG_NO_ENQUEUE) { ++ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA; ++ initfq.fqd.fq_ctrl |= ++ QM_FQCTRL_CTXASTASHING | QM_FQCTRL_AVOIDBLOCK; ++ initfq.fqd.context_a.stashing.exclusive = ++ QM_STASHING_EXCL_DATA | QM_STASHING_EXCL_CTX | ++ QM_STASHING_EXCL_ANNOTATION; ++ initfq.fqd.context_a.stashing.data_cl = 2; ++ initfq.fqd.context_a.stashing.annotation_cl = 1; ++ initfq.fqd.context_a.stashing.context_cl = ++ DIV_ROUND_UP(sizeof(struct qman_fq), 64); ++ } + +- _errno = qman_init_fq(fq, QMAN_INITFQ_FLAG_SCHED, &initfq); +- if (_errno < 0) { +- dev_err(dev, "qman_init_fq(%u) = %d\n", +- qman_fq_fqid(fq), _errno); +- qman_destroy_fq(fq, 0); +- return _errno; +- } ++ _errno = qman_init_fq(fq, QMAN_INITFQ_FLAG_SCHED, &initfq); ++ if (_errno < 0) { ++ dev_err(dev, "qman_init_fq(%u) = %d\n", ++ qman_fq_fqid(fq), _errno); ++ qman_destroy_fq(fq, 0); ++ return _errno; + } + + dpa_fq->fqid = qman_fq_fqid(fq); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0044-dpaa_eth-use-common-preprocessor-procedure.patch b/target/linux/layerscape-64b/patches-4.1/0044-dpaa_eth-use-common-preprocessor-procedure.patch new file mode 100644 index 0000000..cae7950 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0044-dpaa_eth-use-common-preprocessor-procedure.patch @@ -0,0 +1,30 @@ +From bb31fba8a8fd77aafeea208c3a60345ab9b0271b Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Mon, 25 Jan 2016 12:29:39 +0200 +Subject: [PATCH 044/151] dpaa_eth: use common preprocessor procedure + +Signed-off-by: Marian-Cristian Rotariu +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +index 6fc5193..955e7c4 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +@@ -367,11 +367,7 @@ dpa_generic_rx_dqrr(struct qman_portal *portal, + goto qman_consume; + } + +- skbh = (struct sk_buff **)phys_to_virt(addr); +- /* according to the last common code (bp refill) the skb pointer is set +- * to another address shifted by sizeof(struct sk_buff) to the left +- */ +- skb = *(skbh - 1); ++ DPA_READ_SKB_PTR(skb, skbh, phys_to_virt(addr), -1); + + if (unlikely(fd_status & FM_FD_STAT_RX_ERRORS) != 0) { + if (netif_msg_hw(priv) && net_ratelimit()) +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0045-dpaa_eth-fix-unload-procedure-for-onic.patch b/target/linux/layerscape-64b/patches-4.1/0045-dpaa_eth-fix-unload-procedure-for-onic.patch new file mode 100644 index 0000000..e193f85 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0045-dpaa_eth-fix-unload-procedure-for-onic.patch @@ -0,0 +1,110 @@ +From ff5f5eae7b6781fe3d143350f0f187d5e0ed56b4 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Mon, 25 Jan 2016 18:28:18 +0200 +Subject: [PATCH 045/151] dpaa_eth: fix unload procedure for onic + +This patch fixes the module unload for onic in the context of creating the DPAA +Ethernet drivers as dynamic kernel modules that can be loaded/unloaded at +runtime. + +Signed-off-by: Marian-Cristian Rotariu +--- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c | 47 ++++++++-------------- + 1 file changed, 16 insertions(+), 31 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +index 955e7c4..1b7861a 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +@@ -1492,21 +1492,18 @@ static int dpa_generic_bp_create(struct net_device *net_dev, + + err = dpa_bp_alloc(priv->rx_bp); + if (err < 0) { +- /* _dpa_bp_free(priv->rx_bp); */ + priv->rx_bp = NULL; + return err; + } + + err = dpa_bp_alloc(priv->draining_tx_bp); + if (err < 0) { +- /* _dpa_bp_free(priv->draining_tx_bp); */ + priv->draining_tx_bp = NULL; + return err; + } + + err = dpa_bp_alloc(priv->draining_tx_sg_bp); + if (err < 0) { +- /* _dpa_bp_free(priv->draining_tx_bp); */ + priv->draining_tx_sg_bp = NULL; + return err; + } +@@ -1514,31 +1511,8 @@ static int dpa_generic_bp_create(struct net_device *net_dev, + return 0; + } + +-static void dpa_generic_bp_free(struct dpa_generic_priv_s *priv) ++static void dpa_generic_relase_bp(struct dpa_bp *bp) + { +- struct dpa_bp *bp = NULL; +- int i = 0; +- +- /* release the rx bpools */ +- for (i = 0; i < priv->rx_bp_count; i++) { +- bp = &priv->rx_bp[i]; +- if (!bp) +- continue; +- +- if (!atomic_dec_and_test(&bp->refs)) +- continue; +- +- if (bp->free_buf_cb) +- dpa_bp_drain(bp); +- +- bman_free_pool(bp->pool); +- +- if (bp->dev) +- platform_device_unregister(to_platform_device(bp->dev)); +- } +- +- /* release the tx draining bpool */ +- bp = priv->draining_tx_bp; + if (!bp) + return; + +@@ -1554,6 +1528,19 @@ static void dpa_generic_bp_free(struct dpa_generic_priv_s *priv) + platform_device_unregister(to_platform_device(bp->dev)); + } + ++static void dpa_generic_bp_free(struct dpa_generic_priv_s *priv) ++{ ++ int i = 0; ++ ++ /* release the rx bpools */ ++ for (i = 0; i < priv->rx_bp_count; i++) ++ dpa_generic_relase_bp(&priv->rx_bp[i]); ++ ++ /* release the tx draining bpools */ ++ dpa_generic_relase_bp(priv->draining_tx_bp); ++ dpa_generic_relase_bp(priv->draining_tx_sg_bp); ++} ++ + static int dpa_generic_remove(struct platform_device *of_dev) + { + int err; +@@ -1699,11 +1686,9 @@ alloc_percpu_failed: + if (netdev) + dpa_fq_free(dev, &priv->dpa_fq_list); + fq_create_failed: +- if (netdev) { +- /* _dpa_bp_free(priv->rx_bp); */ +- /* _dpa_bp_free(priv->draining_tx_bp); */ +- } + bp_create_failed: ++ if (netdev) ++ dpa_generic_bp_free(priv); + dev_set_drvdata(dev, NULL); + if (netdev) + free_netdev(netdev); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0046-dpaa_eth-fix-call-to-of_node_put-in-dts-parser.patch b/target/linux/layerscape-64b/patches-4.1/0046-dpaa_eth-fix-call-to-of_node_put-in-dts-parser.patch new file mode 100644 index 0000000..a3f3990 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0046-dpaa_eth-fix-call-to-of_node_put-in-dts-parser.patch @@ -0,0 +1,45 @@ +From e4e4e8d90ab720499fbb0471e53e8fe063008ed2 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Mon, 25 Jan 2016 19:52:20 +0200 +Subject: [PATCH 046/151] dpaa_eth: fix call to of_node_put in dts parser + +Signed-off-by: Marian-Cristian Rotariu +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +index 1b7861a..974f53a 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +@@ -1092,13 +1092,15 @@ static int dpa_generic_rx_bp_probe(struct platform_device *_of_dev, + bp = devm_kzalloc(dev, bp_count * sizeof(*bp), GFP_KERNEL); + if (unlikely(bp == NULL)) { + dev_err(dev, "devm_kzalloc() failed\n"); +- return -ENOMEM; ++ err = -ENOMEM; ++ goto _return_of_node_put; + } + + dev_node = of_find_node_by_path("/"); + if (unlikely(dev_node == NULL)) { + dev_err(dev, "of_find_node_by_path(/) failed\n"); +- return -EINVAL; ++ err = -EINVAL; ++ goto _return_of_node_put; + } + + na = of_n_addr_cells(dev_node); +@@ -1111,7 +1113,8 @@ static int dpa_generic_rx_bp_probe(struct platform_device *_of_dev, + "fsl,bman-buffer-pools", i); + if (dev_node == NULL) { + dev_err(dev, "Cannot find buffer pool node in the device tree\n"); +- return -EFAULT; ++ err = -EINVAL; ++ goto _return_of_node_put; + } + + err = of_property_read_u32(dev_node, "fsl,bpid", &bpid); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0047-dpaa_eth-generic-fix-an-uninitialized-variable.patch b/target/linux/layerscape-64b/patches-4.1/0047-dpaa_eth-generic-fix-an-uninitialized-variable.patch new file mode 100644 index 0000000..e71de11 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0047-dpaa_eth-generic-fix-an-uninitialized-variable.patch @@ -0,0 +1,25 @@ +From 0092e85b2aa5639f83666a3ac37d029c38f5041d Mon Sep 17 00:00:00 2001 +From: Camelia Groza +Date: Tue, 2 Feb 2016 18:56:38 +0200 +Subject: [PATCH 047/151] dpaa_eth: generic: fix an uninitialized variable + +Signed-off-by: Camelia Groza +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +index 974f53a..ad99dcd 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +@@ -747,6 +747,7 @@ static int __hot dpa_generic_tx(struct sk_buff *skb, struct net_device *netdev) + if (unlikely(err < 0)) + goto sg_failed; + percpu_priv->tx_frag_skbuffs++; ++ addr = qm_fd_addr(&fd); + } else { + if (unlikely(skb_headroom(skb) < priv->tx_headroom)) { + struct sk_buff *skb_new; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0048-dpaa_eth-Move-debugfs-into-ethtool-stats-for-macsec.patch b/target/linux/layerscape-64b/patches-4.1/0048-dpaa_eth-Move-debugfs-into-ethtool-stats-for-macsec.patch new file mode 100644 index 0000000..9660d77 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0048-dpaa_eth-Move-debugfs-into-ethtool-stats-for-macsec.patch @@ -0,0 +1,757 @@ +From 5c9a53470aaf796244bdb24d6506bb2a5e302c7d Mon Sep 17 00:00:00 2001 +From: Ioana Ciornei +Date: Mon, 18 Jan 2016 12:54:48 +0200 +Subject: [PATCH 048/151] dpaa_eth: Move debugfs into ethtool stats for macsec + +Signed-off-by: Ioana Ciornei +--- + drivers/net/ethernet/freescale/sdk_dpaa/Kconfig | 7 - + drivers/net/ethernet/freescale/sdk_dpaa/Makefile | 6 +- + .../freescale/sdk_dpaa/dpaa_debugfs_macsec.c | 191 ---------------- + .../freescale/sdk_dpaa/dpaa_debugfs_macsec.h | 45 ---- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.c | 83 ++++--- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.h | 13 +- + .../freescale/sdk_dpaa/dpaa_macsec_ethtool.c | 246 +++++++++++++++++++++ + 7 files changed, 295 insertions(+), 296 deletions(-) + delete mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.c + delete mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.h + create mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_macsec_ethtool.c + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig b/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig +index 760ac79..9af50cc 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig +@@ -154,13 +154,6 @@ config FSL_DPAA_ETH_DEBUGFS + ---help--- + This option compiles debugfs code for the DPAA Ethernet driver. + +-config FSL_DPAA_MACSEC_DEBUGFS +- bool "DPAA MACSEC debugfs interface" +- default y +- depends on DEBUG_FS && FSL_DPAA_MACSEC +- ---help--- +- This option compiles debugfs code for the DPAA Ethernet MACSEC driver. +- + config FSL_DPAA_ETH_DEBUG + bool "DPAA Ethernet Debug Support" + depends on FSL_SDK_DPAA_ETH +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/Makefile b/drivers/net/ethernet/freescale/sdk_dpaa/Makefile +index acb7415..d220f16 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/Makefile ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/Makefile +@@ -35,11 +35,7 @@ fsl_advanced-objs += dpaa_eth_base.o + fsl_proxy-objs += dpaa_eth_proxy.o + fsl_dpa_shared-objs += dpaa_eth_shared.o + fsl_dpa_macless-objs += dpaa_eth_macless.o +-fsl_dpa_macsec-objs += dpaa_eth_macsec.o +- +-ifeq ($(CONFIG_FSL_DPAA_MACSEC_DEBUGFS),y) +-fsl_dpa_macsec-objs += dpaa_debugfs_macsec.o +-endif ++fsl_dpa_macsec-objs += dpaa_eth_macsec.o dpaa_macsec_ethtool.o + + ifeq ($(CONFIG_FSL_DPAA_OFFLINE_PORTS),y) + obj-$(CONFIG_FSL_SDK_DPAA_ETH) += fsl_oh.o +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.c +deleted file mode 100644 +index 72de669..0000000 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.c ++++ /dev/null +@@ -1,191 +0,0 @@ +-/* 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 +-#include +-#include "dpaa_eth_macsec.h" +-#include "dpaa_eth.h" +- +-#define MACSEC_DEBUGFS_DESCRIPTION "FSL DPAA Ethernet MACsec debugfs entries" +-#define MACSEC_DEBUGFS_ROOT "fsl_macsec_dpa" +- +-static int __cold macsec_debugfs_open(struct inode *inode, struct file *file); +- +-static struct dentry *dpa_debugfs_root; +-static const struct file_operations macsec_debugfs_fops = { +- .open = macsec_debugfs_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +-}; +- +-static struct macsec_priv_s *macsec_priv[FM_MAX_NUM_OF_MACS]; +-void set_macsec_priv(struct macsec_priv_s *macsec_priv_src, int index) +-{ +- macsec_priv[index] = macsec_priv_src; +-} +-EXPORT_SYMBOL(set_macsec_priv); +- +-void unset_macsec_priv(int index) +-{ +- macsec_priv[index] = NULL; +-} +-EXPORT_SYMBOL(unset_macsec_priv); +- +-static int dpa_debugfs_show(struct seq_file *file, void *offset) +-{ +- int i; +- struct macsec_percpu_priv_s *percpu_priv, total; +- struct net_device *net_dev; +- struct macsec_priv_s *selected_macsec_priv; +- +- BUG_ON(offset == NULL); +- +- memset(&total, 0, sizeof(total)); +- +- net_dev = (struct net_device *)file->private; +- +- selected_macsec_priv = macsec_priv[net_dev->ifindex - 1]; +- if (unlikely(!selected_macsec_priv)) { +- pr_err("selected macsec_priv is null\n"); +- return -EFAULT; +- } +- +- /* "Standard" counters */ +- seq_printf(file, "\nMacsec counters for %s:\n", +- selected_macsec_priv->net_dev->name); +- seq_printf(file, "%s %8s %8s\n", "CPU", "tx", "rx"); +- +- +- for_each_online_cpu(i) { +- percpu_priv = per_cpu_ptr(selected_macsec_priv->percpu_priv, i); +- +- total.tx_macsec += percpu_priv->tx_macsec; +- total.rx_macsec += percpu_priv->rx_macsec; +- +- seq_printf(file, "%3hu %8llu %8llu\n", +- i, +- percpu_priv->tx_macsec, +- percpu_priv->rx_macsec); +- } +- seq_printf(file, "Total: %5llu %8llu\n", +- total.tx_macsec, +- total.rx_macsec); +- +- return 0; +-} +- +-static int __cold macsec_debugfs_open(struct inode *inode, struct file *file) +-{ +- int _errno; +- const struct net_device *net_dev; +- +- _errno = single_open(file, dpa_debugfs_show, inode->i_private); +- if (unlikely(_errno < 0)) { +- net_dev = (struct net_device *)inode->i_private; +- +- if (netif_msg_drv((struct macsec_priv_s *)netdev_priv(net_dev))) +- netdev_err(net_dev, "single_open() = %d\n", +- _errno); +- } +- return _errno; +-} +- +-int macsec_netdev_debugfs_create(struct net_device *net_dev) +-{ +- char buf[256]; +- struct macsec_priv_s *selected_macsec_priv; +- +- if (unlikely(dpa_debugfs_root == NULL)) { +- pr_err(KBUILD_MODNAME ": %s:%hu:%s(): \t%s\n", +- KBUILD_BASENAME".c", __LINE__, __func__, +- "root debugfs missing, possible module ordering issue"); +- return -EINVAL; +- } +- +- sprintf(buf, "%s_macsec", net_dev->name); +- +- selected_macsec_priv = macsec_priv[net_dev->ifindex - 1]; +- +- if (unlikely(!selected_macsec_priv)) { +- pr_err("selected macsec_priv is null\n"); +- return -EFAULT; +- } +- +- selected_macsec_priv->debugfs_file = debugfs_create_file( +- net_dev->name, +- S_IRUGO, +- dpa_debugfs_root, +- net_dev, +- &macsec_debugfs_fops); +- if (unlikely(selected_macsec_priv->debugfs_file == NULL)) { +- netdev_err(net_dev, "debugfs_create_file(%s/%s)", +- dpa_debugfs_root->d_iname, +- buf); +- +- return -EINVAL; +- } +- +- return 0; +-} +-EXPORT_SYMBOL(macsec_netdev_debugfs_create); +- +-void macsec_netdev_debugfs_remove(struct net_device *net_dev) +-{ +- struct macsec_priv_s *selected_macsec_priv; +- +- selected_macsec_priv = macsec_priv[net_dev->ifindex - 1]; +- debugfs_remove(selected_macsec_priv->debugfs_file); +-} +-EXPORT_SYMBOL(macsec_netdev_debugfs_remove); +- +-int __init macsec_debugfs_module_init(void) +-{ +- int _errno = 0; +- +- dpa_debugfs_root = debugfs_create_dir(MACSEC_DEBUGFS_ROOT, NULL); +- +- if (unlikely(dpa_debugfs_root == NULL)) { +- _errno = -ENOMEM; +- pr_err(KBUILD_MODNAME ": %s:%hu:%s():\n", +- KBUILD_BASENAME".c", __LINE__, __func__); +- pr_err("\tdebugfs_create_dir(%s/"KBUILD_MODNAME") = %d\n", +- MACSEC_DEBUGFS_ROOT, _errno); +- } +- +- return _errno; +-} +- +-void __exit macsec_debugfs_module_exit(void) +-{ +- debugfs_remove(dpa_debugfs_root); +-} +- +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.h +deleted file mode 100644 +index 3090f8f..0000000 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_debugfs_macsec.h ++++ /dev/null +@@ -1,45 +0,0 @@ +-/* 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 DPAA_DEBUGFS_MACSEC_H_ +-#define DPAA_DEBUGFS_MACSEC_H_ +- +-#include +-#include /* struct dentry needed in dpaa_eth.h */ +- +-int macsec_netdev_debugfs_create(struct net_device *net_dev); +-void macsec_netdev_debugfs_remove(struct net_device *net_dev); +-int set_macsec_priv(struct macsec_priv_s *macsec_priv_src, int index); +-void unset_macsec_priv(int index); +-int __init macsec_debugfs_module_init(void); +-void __exit macsec_debugfs_module_exit(void); +- +-#endif /* DPAA_DEBUGFS_MACSEC_H_ */ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.c +index 6275648..0a9da8f 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.c +@@ -45,34 +45,47 @@ + #include "dpaa_1588.h" + #endif + +-#ifdef CONFIG_FSL_DPAA_MACSEC_DEBUGFS +-#include "dpaa_debugfs_macsec.h" +-#endif /* CONFIG_FSL_DPAA_MACSEC_DEBUGFS */ +- + static struct sock *nl_sk; + static struct macsec_priv_s *macsec_priv[FM_MAX_NUM_OF_MACS]; + static char *macsec_ifs[FM_MAX_NUM_OF_MACS]; + static int macsec_ifs_cnt; + + static char ifs[MAX_LEN]; ++const struct ethtool_ops *dpa_ethtool_ops_prev; ++static struct ethtool_ops dpa_macsec_ethtool_ops; ++ + module_param_string(ifs, ifs, MAX_LEN, 0000); + MODULE_PARM_DESC(ifs, "Comma separated interface list"); + +-#ifdef CONFIG_FSL_DPAA_MACSEC_DEBUGFS +-static void remove_debugfs(int index) ++struct macsec_priv_s *dpa_macsec_get_priv(struct net_device *net_dev) + { +- struct net_device *net_dev; +- net_dev = first_net_device(&init_net); +- while (net_dev) { +- if (strcmp(net_dev->name, macsec_ifs[index]) == 0) { +- macsec_netdev_debugfs_remove(net_dev); +- unset_macsec_priv(index); +- break; +- } +- net_dev = next_net_device(net_dev); ++ return macsec_priv[net_dev->ifindex - 1]; ++} ++ ++static void macsec_setup_ethtool_ops(struct net_device *net_dev) ++{ ++ /* remember private driver's ethtool ops just once */ ++ if (!dpa_ethtool_ops_prev) { ++ dpa_ethtool_ops_prev = net_dev->ethtool_ops; ++ ++ memcpy(&dpa_macsec_ethtool_ops, net_dev->ethtool_ops, ++ sizeof(struct ethtool_ops)); ++ dpa_macsec_ethtool_ops.get_sset_count = ++ dpa_macsec_get_sset_count; ++ dpa_macsec_ethtool_ops.get_ethtool_stats = ++ dpa_macsec_get_ethtool_stats; ++ dpa_macsec_ethtool_ops.get_strings = ++ dpa_macsec_get_strings; + } ++ ++ net_dev->ethtool_ops = &dpa_macsec_ethtool_ops; + } +-#endif /* CONFIG_FSL_DPAA_MACSEC_DEBUGFS */ ++ ++static void macsec_restore_ethtool_ops(struct net_device *net_dev) ++{ ++ net_dev->ethtool_ops = dpa_ethtool_ops_prev; ++} ++ + + static int ifname_to_id(char *ifname) + { +@@ -1480,15 +1493,6 @@ static int macsec_setup(void) + + alloc_priv(percpu_priv, macsec_priv[macsec_id], dev); + +-#ifdef CONFIG_FSL_DPAA_MACSEC_DEBUGFS +- /* copy macsec_priv to dpaa_debugfs_macsec */ +- set_macsec_priv(macsec_priv[macsec_id], macsec_id); +- +- /* create debugfs entry for this net_device */ +- err = macsec_netdev_debugfs_create(net_dev); +- if (unlikely(err)) +- goto _err_debugfs_create; +-#endif /* CONFIG_FSL_DPAA_MACSEC_DEBUGFS */ + break; + } + if (macsec_priv[macsec_id]->net_dev == NULL) { +@@ -1496,13 +1500,12 @@ static int macsec_setup(void) + err = -EINVAL; + goto _error; + } ++ ++ /* setup specific ethtool ops for macsec */ ++ macsec_setup_ethtool_ops(net_dev); + } + return 0; +-#ifdef CONFIG_FSL_DPAA_MACSEC_DEBUGFS +-_err_debugfs_create: +- for (i = 0; i < macsec_ifs_cnt; i++) +- remove_debugfs(i); +-#endif /* CONFIG_FSL_DPAA_MACSEC_DEBUGFS */ ++ + _error: + for (j = 0; j < i; i++) { + net_dev = first_net_device(&init_net); +@@ -1516,6 +1519,7 @@ _error: + &macsec_priv[macsec_id]->dpa_fq_list); + break; + } ++ macsec_restore_ethtool_ops(macsec_priv[j]->net_dev); + kfree(macsec_priv[j]); + } + for (j = i; j < FM_MAX_NUM_OF_MACS; j++) +@@ -2008,10 +2012,6 @@ _release: + memset(&macsec_dpaa_eth_hooks, 0, sizeof(macsec_dpaa_eth_hooks)); + fsl_dpaa_eth_set_hooks(&macsec_dpaa_eth_hooks); + +-#ifdef CONFIG_FSL_DPAA_MACSEC_DEBUGFS +- for (i = 0; i < macsec_ifs_cnt; i++) +- remove_debugfs(i); +-#endif /* CONFIG_FSL_DPAA_MACSEC_DEBUGFS */ + for (i = 0; i < FM_MAX_NUM_OF_MACS; i++) { + + if (!macsec_priv[i]->net_dev) +@@ -2030,6 +2030,7 @@ _release: + pr_err("_dpa_fq_fre=%d\n", rv); + } + ++ macsec_restore_ethtool_ops(macsec_priv[i]->net_dev); + kfree(macsec_priv[i]); + macsec_priv[i] = NULL; + } +@@ -2060,10 +2061,6 @@ static int __init macsec_init(void) + } + } + +-#ifdef CONFIG_FSL_DPAA_MACSEC_DEBUGFS +- macsec_debugfs_module_init(); +-#endif /* CONFIG_FSL_DPAA_MACSEC_DEBUGFS */ +- + /* Actually send the info to the user through a given socket. */ + nl_sk = netlink_kernel_create(&init_net, NETLINK_USER, &ms_cfg); + if (unlikely(!nl_sk)) { +@@ -2120,13 +2117,6 @@ static void __exit macsec_exit(void) + memset(&macsec_dpaa_eth_hooks, 0, sizeof(macsec_dpaa_eth_hooks)); + fsl_dpaa_eth_set_hooks(&macsec_dpaa_eth_hooks); + +-#ifdef CONFIG_FSL_DPAA_MACSEC_DEBUGFS +- for (i = 0; i < macsec_ifs_cnt; i++) +- remove_debugfs(i); +- +- macsec_debugfs_module_exit(); +-#endif /* CONFIG_FSL_DPAA_MACSEC_DEBUGFS */ +- + for (i = 0; i < FM_MAX_NUM_OF_MACS; i++) { + + if (!macsec_priv[i]->net_dev) { +@@ -2148,6 +2138,9 @@ static void __exit macsec_exit(void) + } + } + ++ /* restore ethtool ops to the previous private ones */ ++ macsec_restore_ethtool_ops(macsec_priv[i]->net_dev); ++ + kfree(macsec_priv[i]); + } + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.h +index b7a8795..8d41e78 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.h ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.h +@@ -45,6 +45,14 @@ + + extern const struct dpa_fq_cbs_t private_fq_cbs; + ++extern int dpa_macsec_get_sset_count(struct net_device *net_dev, int type); ++extern void ++dpa_macsec_get_ethtool_stats(struct net_device *net_dev, ++ struct ethtool_stats *stats, u64 *data); ++extern void ++dpa_macsec_get_strings(struct net_device *net_dev, ++ u32 stringset, u8 *data); ++ + enum msg_type {ENABLE_MACSEC, + SET_EXCEPTION, + ENABLE_SECY, +@@ -266,9 +274,6 @@ struct macsec_priv_s { + struct qman_fq *egress_fqs[MACSEC_ETH_TX_QUEUES]; + struct qman_fq *conf_fqs[MACSEC_ETH_TX_QUEUES]; + struct list_head dpa_fq_list; +-#ifdef CONFIG_FSL_DPAA_MACSEC_DEBUGFS +- struct dentry *debugfs_file; +-#endif /* CONFIG_FSL_DPAA_MACSEC_DEBUGFS */ + uint32_t msg_enable; /* net_device message level */ + uint16_t channel; + struct fm_macsec_dev *fm_macsec; +@@ -284,4 +289,6 @@ struct macsec_priv_s { + struct resource *fman_resource; + }; + ++struct macsec_priv_s *dpa_macsec_get_priv(struct net_device *net_dev); ++ + #endif /* __DPAA_ETH_MACSEC_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_macsec_ethtool.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_macsec_ethtool.c +new file mode 100644 +index 0000000..6673996 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_macsec_ethtool.c +@@ -0,0 +1,246 @@ ++/* 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 ++ ++#include "dpaa_eth.h" ++#include "dpaa_eth_macsec.h" ++ ++static const char dpa_macsec_stats_percpu[][ETH_GSTRING_LEN] = { ++ "interrupts", ++ "rx packets", ++ "tx packets", ++ "tx recycled", ++ "tx confirm", ++ "tx S/G", ++ "tx error", ++ "rx error", ++ "bp count", ++ "tx macsec", ++ "rx macsec" ++}; ++ ++static char dpa_macsec_stats_global[][ETH_GSTRING_LEN] = { ++ /* dpa rx errors */ ++ "rx dma error", ++ "rx frame physical error", ++ "rx frame size error", ++ "rx header error", ++ "rx csum error", ++ ++ /* demultiplexing errors */ ++ "qman cg_tdrop", ++ "qman wred", ++ "qman error cond", ++ "qman early window", ++ "qman late window", ++ "qman fq tdrop", ++ "qman fq retired", ++ "qman orp disabled", ++ ++ /* congestion related stats */ ++ "congestion time (ms)", ++ "entered congestion", ++ "congested (0/1)" ++}; ++ ++#define DPA_MACSEC_STATS_PERCPU_LEN ARRAY_SIZE(dpa_macsec_stats_percpu) ++#define DPA_MACSEC_STATS_GLOBAL_LEN ARRAY_SIZE(dpa_macsec_stats_global) ++ ++static void copy_stats(struct dpa_percpu_priv_s *percpu_priv, int num_cpus, ++ int crr_cpu, u64 bp_count, u64 tx_macsec, ++ u64 rx_macsec, u64 *data) ++{ ++ int num_values = num_cpus + 1; ++ int crr = 0; ++ ++ /* update current CPU's stats and also add them to the total values */ ++ data[crr * num_values + crr_cpu] = percpu_priv->in_interrupt; ++ data[crr++ * num_values + num_cpus] += percpu_priv->in_interrupt; ++ ++ data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_packets; ++ data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_packets; ++ ++ data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_packets; ++ data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_packets; ++ ++ data[crr * num_values + crr_cpu] = percpu_priv->tx_returned; ++ data[crr++ * num_values + num_cpus] += percpu_priv->tx_returned; ++ ++ data[crr * num_values + crr_cpu] = percpu_priv->tx_confirm; ++ data[crr++ * num_values + num_cpus] += percpu_priv->tx_confirm; ++ ++ data[crr * num_values + crr_cpu] = percpu_priv->tx_frag_skbuffs; ++ data[crr++ * num_values + num_cpus] += percpu_priv->tx_frag_skbuffs; ++ ++ data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_errors; ++ data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_errors; ++ ++ data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_errors; ++ data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_errors; ++ ++ data[crr * num_values + crr_cpu] = bp_count; ++ data[crr++ * num_values + num_cpus] += bp_count; ++ ++ data[crr * num_values + crr_cpu] = tx_macsec; ++ data[crr++ * num_values + num_cpus] += tx_macsec; ++ ++ data[crr * num_values + crr_cpu] = rx_macsec; ++ data[crr++ * num_values + num_cpus] += rx_macsec; ++} ++ ++int dpa_macsec_get_sset_count(struct net_device *net_dev, int type) ++{ ++ unsigned int total_stats, num_stats; ++ ++ num_stats = num_online_cpus() + 1; ++ total_stats = num_stats * DPA_MACSEC_STATS_PERCPU_LEN + ++ DPA_MACSEC_STATS_GLOBAL_LEN; ++ ++ switch (type) { ++ case ETH_SS_STATS: ++ return total_stats; ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++void dpa_macsec_get_ethtool_stats(struct net_device *net_dev, ++ struct ethtool_stats *stats, u64 *data) ++{ ++ u64 bp_count, bp_total, cg_time, cg_num, cg_status; ++ struct macsec_percpu_priv_s *percpu_priv_macsec; ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct macsec_priv_s *macsec_priv; ++ struct qm_mcr_querycgr query_cgr; ++ struct dpa_rx_errors rx_errors; ++ struct dpa_ern_cnt ern_cnt; ++ struct dpa_priv_s *priv; ++ unsigned int num_cpus, offset; ++ struct dpa_bp *dpa_bp; ++ int total_stats, i; ++ ++ macsec_priv = dpa_macsec_get_priv(net_dev); ++ if (unlikely(!macsec_priv)) { ++ pr_err("selected macsec_priv is NULL\n"); ++ return; ++ } ++ ++ total_stats = dpa_macsec_get_sset_count(net_dev, ETH_SS_STATS); ++ priv = netdev_priv(net_dev); ++ dpa_bp = priv->dpa_bp; ++ num_cpus = num_online_cpus(); ++ bp_count = 0; ++ bp_total = 0; ++ ++ memset(&rx_errors, 0, sizeof(struct dpa_rx_errors)); ++ memset(&ern_cnt, 0, sizeof(struct dpa_ern_cnt)); ++ memset(data, 0, total_stats * sizeof(u64)); ++ ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ percpu_priv_macsec = per_cpu_ptr(macsec_priv->percpu_priv, i); ++ ++ if (dpa_bp->percpu_count) ++ bp_count = *(per_cpu_ptr(dpa_bp->percpu_count, i)); ++ ++ rx_errors.dme += percpu_priv->rx_errors.dme; ++ rx_errors.fpe += percpu_priv->rx_errors.fpe; ++ rx_errors.fse += percpu_priv->rx_errors.fse; ++ rx_errors.phe += percpu_priv->rx_errors.phe; ++ rx_errors.cse += percpu_priv->rx_errors.cse; ++ ++ ern_cnt.cg_tdrop += percpu_priv->ern_cnt.cg_tdrop; ++ ern_cnt.wred += percpu_priv->ern_cnt.wred; ++ ern_cnt.err_cond += percpu_priv->ern_cnt.err_cond; ++ ern_cnt.early_window += percpu_priv->ern_cnt.early_window; ++ ern_cnt.late_window += percpu_priv->ern_cnt.late_window; ++ ern_cnt.fq_tdrop += percpu_priv->ern_cnt.fq_tdrop; ++ ern_cnt.fq_retired += percpu_priv->ern_cnt.fq_retired; ++ ern_cnt.orp_zero += percpu_priv->ern_cnt.orp_zero; ++ ++ copy_stats(percpu_priv, num_cpus, i, bp_count, ++ percpu_priv_macsec->tx_macsec, ++ percpu_priv_macsec->rx_macsec, ++ data); ++ } ++ ++ offset = (num_cpus + 1) * DPA_MACSEC_STATS_PERCPU_LEN; ++ memcpy(data + offset, &rx_errors, sizeof(struct dpa_rx_errors)); ++ ++ offset += sizeof(struct dpa_rx_errors) / sizeof(u64); ++ memcpy(data + offset, &ern_cnt, sizeof(struct dpa_ern_cnt)); ++ ++ /* gather congestion related counters */ ++ cg_num = 0; ++ cg_status = 0; ++ cg_time = jiffies_to_msecs(priv->cgr_data.congested_jiffies); ++ if (qman_query_cgr(&priv->cgr_data.cgr, &query_cgr) == 0) { ++ cg_num = priv->cgr_data.cgr_congested_count; ++ cg_status = query_cgr.cgr.cs; ++ ++ /* reset congestion stats (like QMan API does */ ++ priv->cgr_data.congested_jiffies = 0; ++ priv->cgr_data.cgr_congested_count = 0; ++ } ++ ++ offset += sizeof(struct dpa_ern_cnt) / sizeof(u64); ++ data[offset++] = cg_time; ++ data[offset++] = cg_num; ++ data[offset++] = cg_status; ++} ++ ++void dpa_macsec_get_strings(struct net_device *net_dev, ++ u32 stringset, u8 *data) ++{ ++ unsigned int i, j, num_cpus, size; ++ char string_cpu[ETH_GSTRING_LEN]; ++ u8 *strings; ++ ++ strings = data; ++ num_cpus = num_online_cpus(); ++ size = DPA_MACSEC_STATS_GLOBAL_LEN * ETH_GSTRING_LEN; ++ ++ for (i = 0; i < DPA_MACSEC_STATS_PERCPU_LEN; i++) { ++ for (j = 0; j < num_cpus; j++) { ++ snprintf(string_cpu, ETH_GSTRING_LEN, "%s [CPU %d]", ++ dpa_macsec_stats_percpu[i], j); ++ memcpy(strings, string_cpu, ETH_GSTRING_LEN); ++ strings += ETH_GSTRING_LEN; ++ } ++ snprintf(string_cpu, ETH_GSTRING_LEN, "%s [TOTAL]", ++ dpa_macsec_stats_percpu[i]); ++ memcpy(strings, string_cpu, ETH_GSTRING_LEN); ++ strings += ETH_GSTRING_LEN; ++ } ++ memcpy(strings, dpa_macsec_stats_global, size); ++} ++ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0049-dpaa_eth-Move-debugfs-into-ethtool-stats-for-oNIC.patch b/target/linux/layerscape-64b/patches-4.1/0049-dpaa_eth-Move-debugfs-into-ethtool-stats-for-oNIC.patch new file mode 100644 index 0000000..294aafd --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0049-dpaa_eth-Move-debugfs-into-ethtool-stats-for-oNIC.patch @@ -0,0 +1,667 @@ +From 7a7f17431d1daf33f3663de3e1d00e73a218ac8b Mon Sep 17 00:00:00 2001 +From: Ioana Ciornei +Date: Thu, 14 Jan 2016 19:14:05 +0200 +Subject: [PATCH 049/151] dpaa_eth: Move debugfs into ethtool stats for oNIC + +Signed-off-by: Ioana Ciornei +--- + drivers/net/ethernet/freescale/sdk_dpaa/Makefile | 3 - + .../ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c | 21 -- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h | 4 - + .../freescale/sdk_dpaa/dpaa_generic_debugfs.c | 277 --------------------- + .../freescale/sdk_dpaa/dpaa_generic_debugfs.h | 41 --- + .../freescale/sdk_dpaa/dpaa_generic_ethtool.c | 185 +++++++++++++- + 6 files changed, 181 insertions(+), 350 deletions(-) + delete mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.c + delete mode 100644 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.h + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/Makefile b/drivers/net/ethernet/freescale/sdk_dpaa/Makefile +index d220f16..1dd01e3 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/Makefile ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/Makefile +@@ -49,9 +49,6 @@ ifeq ($(CONFIG_FSL_DPAA_GENERIC_DRIVER),y) + obj-$(CONFIG_FSL_SDK_DPAA_ETH) += fsl_generic.o + + fsl_generic-objs += dpaa_eth_generic.o dpaa_eth_generic_sysfs.o dpaa_generic_ethtool.o +-ifeq ($(CONFIG_FSL_DPAA_ETH_DEBUGFS),y) +-fsl_generic-objs += dpaa_generic_debugfs.o +-endif + endif + + # Needed by the tracing framework +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +index ad99dcd..2ea3bac 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +@@ -38,7 +38,6 @@ + #include "dpaa_eth_common.h" + #include "dpaa_eth_base.h" + #include "dpaa_eth_generic.h" +-#include "dpaa_generic_debugfs.h" + + #define DPA_DEFAULT_TX_HEADROOM 64 + #define DPA_GENERIC_SKB_COPY_MAX_SIZE 256 +@@ -914,15 +913,6 @@ static int dpa_generic_netdev_init(struct device_node *dpa_node, + return err; + } + +-#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS +- /* create debugfs entry for this net_device */ +- err = dpa_generic_debugfs_create(netdev); +- if (err) { +- unregister_netdev(netdev); +- return err; +- } +-#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ +- + return 0; + } + +@@ -1567,9 +1557,6 @@ static int dpa_generic_remove(struct platform_device *of_dev) + + dpa_generic_bp_free(priv); + +-#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS +- dpa_generic_debugfs_remove(net_dev); +-#endif + free_netdev(net_dev); + + return err; +@@ -1706,10 +1693,6 @@ static int __init __cold dpa_generic_load(void) + + pr_info(KBUILD_MODNAME ": " DPA_GENERIC_DESCRIPTION "\n"); + +-#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS +- dpa_generic_debugfs_module_init(); +-#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ +- + /* initialise dpaa_eth mirror values */ + dpa_rx_extra_headroom = fm_get_rx_extra_headroom(); + dpa_max_frm = fm_get_max_frm(); +@@ -1739,10 +1722,6 @@ static void __exit __cold dpa_generic_unload(void) + + platform_driver_unregister(&dpa_generic_driver); + +-#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS +- dpa_generic_debugfs_module_exit(); +-#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ +- + pr_debug(KBUILD_MODNAME ": %s:%s() ->\n", + KBUILD_BASENAME".c", __func__); + } +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h +index 7618aaf..60dd16c 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.h +@@ -71,10 +71,6 @@ struct dpa_generic_priv_s { + uint16_t channel; /* "fsl,qman-channel-id" */ + struct list_head dpa_fq_list; + +-#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS +- struct dentry *debugfs_file; +-#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */ +- + uint32_t msg_enable; /* net_device message level */ + + struct dpa_buffer_layout_s *buf_layout; +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.c +deleted file mode 100644 +index a442876..0000000 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.c ++++ /dev/null +@@ -1,277 +0,0 @@ +-/* Copyright 2013 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 +-#include +-#include +- +-#include "dpaa_eth_generic.h" +- +-#define DPA_DEBUGFS_DESCRIPTION "FSL DPAA Ethernet debugfs entries" +-#define DPA_GENERIC_ETH_DEBUGFS_ROOT "fsl_generic_dpa" +- +-static int __cold dpa_generic_debugfs_open(struct inode *inode, +- struct file *file); +- +-static struct dentry *dpa_debugfs_root; +-static const struct file_operations dpa_debugfs_fops = { +- .open = dpa_generic_debugfs_open, +- .read = seq_read, +- .llseek = seq_lseek, +- .release = single_release, +-}; +- +-static int dpa_generic_debugfs_show(struct seq_file *file, void *offset) +-{ +- int i; +- struct dpa_generic_priv_s *priv; +- struct dpa_percpu_priv_s *percpu_priv, total; +- struct dpa_bp *bp; +- unsigned int dpa_bp_count = 0; +- unsigned int count_total = 0; +- +- BUG_ON(offset == NULL); +- +- priv = netdev_priv((struct net_device *)file->private); +- +- bp = priv->rx_bp; +- +- memset(&total, 0, sizeof(total)); +- +- /* "Standard" counters */ +- seq_printf(file, "\nDPA counters for %s:\n", priv->net_dev->name); +- seq_puts(file, "CPU irqs rx tx recycle "); +- seq_puts(file, "confirm tx sg tx err rx err bp count\n"); +- +- +- for_each_online_cpu(i) { +- percpu_priv = per_cpu_ptr(priv->percpu_priv, i); +- +- if (bp->percpu_count) +- dpa_bp_count = *(per_cpu_ptr(bp->percpu_count, i)); +- +- total.in_interrupt += percpu_priv->in_interrupt; +- total.stats.rx_packets += percpu_priv->stats.rx_packets; +- total.stats.tx_packets += percpu_priv->stats.tx_packets; +- total.tx_returned += percpu_priv->tx_returned; +- total.tx_confirm += percpu_priv->tx_confirm; +- total.tx_frag_skbuffs += percpu_priv->tx_frag_skbuffs; +- total.stats.tx_errors += percpu_priv->stats.tx_errors; +- total.stats.rx_errors += percpu_priv->stats.rx_errors; +- count_total += dpa_bp_count; +- +- seq_printf(file, " %hu %8llu %8llu %8llu %8llu ", +- i, +- percpu_priv->in_interrupt, +- percpu_priv->stats.rx_packets, +- percpu_priv->stats.tx_packets, +- percpu_priv->tx_returned); +- seq_printf(file, "%8llu %8llu %8llu %8llu %8d\n", +- percpu_priv->tx_confirm, +- percpu_priv->tx_frag_skbuffs, +- percpu_priv->stats.tx_errors, +- percpu_priv->stats.rx_errors, +- dpa_bp_count); +- } +- seq_printf(file, "Total %8llu %8llu %8llu %8llu ", +- total.in_interrupt, +- total.stats.rx_packets, +- total.stats.tx_packets, +- total.tx_returned); +- seq_printf(file, "%8llu %8llu %8llu %8llu %8d\n", +- total.tx_confirm, +- total.tx_frag_skbuffs, +- total.stats.tx_errors, +- total.stats.rx_errors, +- count_total); +- +- /* Draining Buffer Pool counters */ +- seq_printf(file, "\nCounters for Draining Buffer Pool (bpid:%d) %s:\n", +- bp->bpid, priv->net_dev->name); +- seq_puts(file, "CPU bp count\n"); +- +- bp = priv->draining_tx_bp; +- dpa_bp_count = 0; +- count_total = 0; +- +- for_each_online_cpu(i) { +- if (bp->percpu_count) +- dpa_bp_count = *(per_cpu_ptr(bp->percpu_count, i)); +- count_total += dpa_bp_count; +- +- seq_printf(file, " %hu %8d\n", i, dpa_bp_count); +- } +- seq_printf(file, "Total %8d\n", count_total); +- +- +- /* Rx Errors demultiplexing */ +- seq_puts(file, "\nDPA RX Errors:\nCPU dma err phys err"); +- seq_puts(file, " size err hdr err csum err\n"); +- for_each_online_cpu(i) { +- percpu_priv = per_cpu_ptr(priv->percpu_priv, i); +- +- total.rx_errors.dme += percpu_priv->rx_errors.dme; +- total.rx_errors.fpe += percpu_priv->rx_errors.fpe; +- total.rx_errors.fse += percpu_priv->rx_errors.fse; +- total.rx_errors.phe += percpu_priv->rx_errors.phe; +- total.rx_errors.cse += percpu_priv->rx_errors.cse; +- +- seq_printf(file, " %hu %8llu %8llu ", +- i, +- percpu_priv->rx_errors.dme, +- percpu_priv->rx_errors.fpe); +- seq_printf(file, "%8llu %8llu %8llu\n", +- percpu_priv->rx_errors.fse, +- percpu_priv->rx_errors.phe, +- percpu_priv->rx_errors.cse); +- } +- seq_printf(file, "Total %8llu %8llu %8llu %8llu %8llu\n", +- total.rx_errors.dme, +- total.rx_errors.fpe, +- total.rx_errors.fse, +- total.rx_errors.phe, +- total.rx_errors.cse); +- +- /* ERN demultiplexing */ +- seq_puts(file, "\nDPA ERN counters:\n CPU cg_td wred "); +- seq_puts(file, "err_cond early_w late_w fq_td fq_ret"); +- seq_puts(file, " orp_z\n"); +- for_each_online_cpu(i) { +- percpu_priv = per_cpu_ptr(priv->percpu_priv, i); +- +- total.ern_cnt.cg_tdrop += percpu_priv->ern_cnt.cg_tdrop; +- total.ern_cnt.wred += percpu_priv->ern_cnt.wred; +- total.ern_cnt.err_cond += percpu_priv->ern_cnt.err_cond; +- total.ern_cnt.early_window += percpu_priv->ern_cnt.early_window; +- total.ern_cnt.late_window += percpu_priv->ern_cnt.late_window; +- total.ern_cnt.fq_tdrop += percpu_priv->ern_cnt.fq_tdrop; +- total.ern_cnt.fq_retired += percpu_priv->ern_cnt.fq_retired; +- total.ern_cnt.orp_zero += percpu_priv->ern_cnt.orp_zero; +- +- seq_printf(file, " %hu %8llu %8llu %8llu %8llu ", +- i, +- percpu_priv->ern_cnt.cg_tdrop, +- percpu_priv->ern_cnt.wred, +- percpu_priv->ern_cnt.err_cond, +- percpu_priv->ern_cnt.early_window); +- seq_printf(file, "%8llu %8llu %8llu %8llu\n", +- percpu_priv->ern_cnt.late_window, +- percpu_priv->ern_cnt.fq_tdrop, +- percpu_priv->ern_cnt.fq_retired, +- percpu_priv->ern_cnt.orp_zero); +- } +- seq_printf(file, "Total%8llu %8llu %8llu %8llu ", +- total.ern_cnt.cg_tdrop, +- total.ern_cnt.wred, +- total.ern_cnt.err_cond, +- total.ern_cnt.early_window); +- seq_printf(file, "%8llu %8llu %8llu %8llu\n", +- total.ern_cnt.late_window, +- total.ern_cnt.fq_tdrop, +- total.ern_cnt.fq_retired, +- total.ern_cnt.orp_zero); +- +- return 0; +-} +- +-static int __cold dpa_generic_debugfs_open(struct inode *inode, +- struct file *file) +-{ +- int _errno; +- const struct net_device *net_dev = +- (struct net_device *)inode->i_private; +- +- _errno = single_open(file, dpa_generic_debugfs_show, inode->i_private); +- if (unlikely(_errno < 0)) +- if (netif_msg_drv((struct dpa_generic_priv_s *) +- netdev_priv(net_dev))) +- netdev_err(net_dev, "single_open() = %d\n", _errno); +- +- return _errno; +-} +- +-int dpa_generic_debugfs_create(struct net_device *net_dev) +-{ +- struct dpa_generic_priv_s *priv = netdev_priv(net_dev); +- +- if (unlikely(dpa_debugfs_root == NULL)) { +- pr_err(KBUILD_MODNAME ": %s:%hu:%s(): \t%s\n", +- KBUILD_BASENAME".c", __LINE__, __func__, +- "root debugfs missing, possible module ordering issue"); +- return -ENOMEM; +- } +- +- priv->debugfs_file = debugfs_create_file(net_dev->name, +- S_IRUGO, +- dpa_debugfs_root, +- net_dev, +- &dpa_debugfs_fops); +- if (unlikely(priv->debugfs_file == NULL)) { +- netdev_err(net_dev, "debugfs_create_file(%s/%s)", +- dpa_debugfs_root->d_iname, +- net_dev->name); +- +- return -ENOMEM; +- } +- +- return 0; +-} +- +-void dpa_generic_debugfs_remove(struct net_device *net_dev) +-{ +- struct dpa_generic_priv_s *priv = netdev_priv(net_dev); +- +- debugfs_remove(priv->debugfs_file); +-} +- +-int __init dpa_generic_debugfs_module_init(void) +-{ +- int _errno = 0; +- +- pr_info(KBUILD_MODNAME ": " DPA_DEBUGFS_DESCRIPTION "\n"); +- +- dpa_debugfs_root = debugfs_create_dir(DPA_GENERIC_ETH_DEBUGFS_ROOT, +- NULL); +- if (unlikely(dpa_debugfs_root == NULL)) { +- _errno = -ENOMEM; +- pr_err(KBUILD_MODNAME ": %s:%hu:%s():\n", +- KBUILD_BASENAME".c", __LINE__, __func__); +- pr_err("\tdebugfs_create_dir(%s/"KBUILD_MODNAME") = %d\n", +- DPA_GENERIC_ETH_DEBUGFS_ROOT, _errno); +- } +- +- return _errno; +-} +- +-void __exit dpa_generic_debugfs_module_exit(void) +-{ +- debugfs_remove(dpa_debugfs_root); +-} +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.h +deleted file mode 100644 +index 56e7fb3..0000000 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_debugfs.h ++++ /dev/null +@@ -1,41 +0,0 @@ +-/* Copyright 2013 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 DPAA_GENERIC_DEBUGFS_H_ +-#define DPAA_GENERIC_DEBUGFS_H_ +- +-#include +-#include +- +-int dpa_generic_debugfs_create(struct net_device *net_dev); +-void dpa_generic_debugfs_remove(struct net_device *net_dev); +- +-#endif /* DPAA_GENERIC_DEBUGFS_H_ */ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c +index ef41ce3..e152d69 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c +@@ -44,22 +44,57 @@ + #include "dpaa_eth_common.h" + #include "dpaa_eth_generic.h" + ++static const char dpa_stats_percpu[][ETH_GSTRING_LEN] = { ++ "interrupts", ++ "rx packets", ++ "tx packets", ++ "tx recycled", ++ "tx confirm", ++ "tx S/G", ++ "tx error", ++ "rx error", ++ "bp count", ++ "bp draining count" ++}; ++ ++static char dpa_stats_global[][ETH_GSTRING_LEN] = { ++ /* dpa rx errors */ ++ "rx dma error", ++ "rx frame physical error", ++ "rx frame size error", ++ "rx header error", ++ "rx csum error", ++ ++ /* demultiplexing errors */ ++ "qman cg_tdrop", ++ "qman wred", ++ "qman error cond", ++ "qman early window", ++ "qman late window", ++ "qman fq tdrop", ++ "qman fq retired", ++ "qman orp disabled", ++}; ++ ++#define DPA_STATS_PERCPU_LEN ARRAY_SIZE(dpa_stats_percpu) ++#define DPA_STATS_GLOBAL_LEN ARRAY_SIZE(dpa_stats_global) ++ + static int __cold dpa_generic_get_settings(struct net_device *net_dev, +- struct ethtool_cmd *et_cmd) ++ struct ethtool_cmd *et_cmd) + { + netdev_info(net_dev, "This interface does not have a MAC device in its control\n"); + return -ENODEV; + } + + static int __cold dpa_generic_set_settings(struct net_device *net_dev, +- struct ethtool_cmd *et_cmd) ++ struct ethtool_cmd *et_cmd) + { + netdev_info(net_dev, "This interface does not have a MAC device in its control\n"); + return -ENODEV; + } + + static void __cold dpa_generic_get_drvinfo(struct net_device *net_dev, +- struct ethtool_drvinfo *drvinfo) ++ struct ethtool_drvinfo *drvinfo) + { + int _errno; + +@@ -85,7 +120,7 @@ static uint32_t __cold dpa_generic_get_msglevel(struct net_device *net_dev) + } + + static void __cold dpa_generic_set_msglevel(struct net_device *net_dev, +- uint32_t msg_enable) ++ uint32_t msg_enable) + { + ((struct dpa_generic_priv_s *)netdev_priv(net_dev))->msg_enable = + msg_enable; +@@ -97,6 +132,145 @@ static int __cold dpa_generic_nway_reset(struct net_device *net_dev) + return -ENODEV; + } + ++static int dpa_generic_get_sset_count(struct net_device *net_dev, int type) ++{ ++ unsigned int total_stats, num_stats; ++ ++ num_stats = num_online_cpus() + 1; ++ total_stats = num_stats * DPA_STATS_PERCPU_LEN + DPA_STATS_GLOBAL_LEN; ++ ++ switch (type) { ++ case ETH_SS_STATS: ++ return total_stats; ++ default: ++ return -EOPNOTSUPP; ++ } ++} ++ ++static void copy_stats(struct dpa_percpu_priv_s *percpu_priv, ++ int num_cpus, int crr_cpu, u64 bp_count, ++ u64 bp_drain_count, u64 *data) ++{ ++ int num_values = num_cpus + 1; ++ int crr = 0; ++ ++ /* update current CPU's stats and also add them to the total values */ ++ data[crr * num_values + crr_cpu] = percpu_priv->in_interrupt; ++ data[crr++ * num_values + num_cpus] += percpu_priv->in_interrupt; ++ ++ data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_packets; ++ data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_packets; ++ ++ data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_packets; ++ data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_packets; ++ ++ data[crr * num_values + crr_cpu] = percpu_priv->tx_returned; ++ data[crr++ * num_values + num_cpus] += percpu_priv->tx_returned; ++ ++ data[crr * num_values + crr_cpu] = percpu_priv->tx_confirm; ++ data[crr++ * num_values + num_cpus] += percpu_priv->tx_confirm; ++ ++ data[crr * num_values + crr_cpu] = percpu_priv->tx_frag_skbuffs; ++ data[crr++ * num_values + num_cpus] += percpu_priv->tx_frag_skbuffs; ++ ++ data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_errors; ++ data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_errors; ++ ++ data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_errors; ++ data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_errors; ++ ++ data[crr * num_values + crr_cpu] = bp_count; ++ data[crr++ * num_values + num_cpus] += bp_count; ++ ++ data[crr * num_values + crr_cpu] = bp_drain_count; ++ data[crr++ * num_values + num_cpus] += bp_drain_count; ++} ++ ++static void dpa_generic_get_ethtool_stats(struct net_device *net_dev, ++ struct ethtool_stats *stats, ++ u64 *data) ++{ ++ struct dpa_percpu_priv_s *percpu_priv; ++ struct dpa_bp *dpa_bp, *drain_bp; ++ struct dpa_generic_priv_s *priv; ++ struct dpa_rx_errors rx_errors; ++ struct dpa_ern_cnt ern_cnt; ++ unsigned int num_cpus, offset; ++ u64 bp_cnt, drain_cnt; ++ int total_stats, i; ++ ++ total_stats = dpa_generic_get_sset_count(net_dev, ETH_SS_STATS); ++ priv = netdev_priv(net_dev); ++ drain_bp = priv->draining_tx_bp; ++ dpa_bp = priv->rx_bp; ++ num_cpus = num_online_cpus(); ++ drain_cnt = 0; ++ bp_cnt = 0; ++ ++ memset(&rx_errors, 0, sizeof(struct dpa_rx_errors)); ++ memset(&ern_cnt, 0, sizeof(struct dpa_ern_cnt)); ++ memset(data, 0, total_stats * sizeof(u64)); ++ ++ for_each_online_cpu(i) { ++ percpu_priv = per_cpu_ptr(priv->percpu_priv, i); ++ ++ if (dpa_bp->percpu_count) ++ bp_cnt = *(per_cpu_ptr(dpa_bp->percpu_count, i)); ++ ++ if (drain_bp->percpu_count) ++ drain_cnt = *(per_cpu_ptr(drain_bp->percpu_count, i)); ++ ++ rx_errors.dme += percpu_priv->rx_errors.dme; ++ rx_errors.fpe += percpu_priv->rx_errors.fpe; ++ rx_errors.fse += percpu_priv->rx_errors.fse; ++ rx_errors.phe += percpu_priv->rx_errors.phe; ++ rx_errors.cse += percpu_priv->rx_errors.cse; ++ ++ ern_cnt.cg_tdrop += percpu_priv->ern_cnt.cg_tdrop; ++ ern_cnt.wred += percpu_priv->ern_cnt.wred; ++ ern_cnt.err_cond += percpu_priv->ern_cnt.err_cond; ++ ern_cnt.early_window += percpu_priv->ern_cnt.early_window; ++ ern_cnt.late_window += percpu_priv->ern_cnt.late_window; ++ ern_cnt.fq_tdrop += percpu_priv->ern_cnt.fq_tdrop; ++ ern_cnt.fq_retired += percpu_priv->ern_cnt.fq_retired; ++ ern_cnt.orp_zero += percpu_priv->ern_cnt.orp_zero; ++ ++ copy_stats(percpu_priv, num_cpus, i, bp_cnt, drain_cnt, data); ++ } ++ ++ offset = (num_cpus + 1) * DPA_STATS_PERCPU_LEN; ++ memcpy(data + offset, &rx_errors, sizeof(struct dpa_rx_errors)); ++ ++ offset += sizeof(struct dpa_rx_errors) / sizeof(u64); ++ memcpy(data + offset, &ern_cnt, sizeof(struct dpa_ern_cnt)); ++} ++ ++static void dpa_generic_get_strings(struct net_device *net_dev, ++ u32 stringset, u8 *data) ++{ ++ unsigned int i, j, num_cpus, size; ++ char string_cpu[ETH_GSTRING_LEN]; ++ u8 *strings; ++ ++ strings = data; ++ num_cpus = num_online_cpus(); ++ size = DPA_STATS_GLOBAL_LEN * ETH_GSTRING_LEN; ++ ++ for (i = 0; i < DPA_STATS_PERCPU_LEN; i++) { ++ for (j = 0; j < num_cpus; j++) { ++ snprintf(string_cpu, ETH_GSTRING_LEN, "%s [CPU %d]", ++ dpa_stats_percpu[i], j); ++ memcpy(strings, string_cpu, ETH_GSTRING_LEN); ++ strings += ETH_GSTRING_LEN; ++ } ++ snprintf(string_cpu, ETH_GSTRING_LEN, "%s [TOTAL]", ++ dpa_stats_percpu[i]); ++ memcpy(strings, string_cpu, ETH_GSTRING_LEN); ++ strings += ETH_GSTRING_LEN; ++ } ++ memcpy(strings, dpa_stats_global, size); ++} ++ + const struct ethtool_ops dpa_generic_ethtool_ops = { + .get_settings = dpa_generic_get_settings, + .set_settings = dpa_generic_set_settings, +@@ -105,4 +279,7 @@ const struct ethtool_ops dpa_generic_ethtool_ops = { + .set_msglevel = dpa_generic_set_msglevel, + .nway_reset = dpa_generic_nway_reset, + .get_link = ethtool_op_get_link, ++ .get_sset_count = dpa_generic_get_sset_count, ++ .get_ethtool_stats = dpa_generic_get_ethtool_stats, ++ .get_strings = dpa_generic_get_strings, + }; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0050-dpaa_eth-Add-counter-for-Scatter-Gather-frames-on-RX.patch b/target/linux/layerscape-64b/patches-4.1/0050-dpaa_eth-Add-counter-for-Scatter-Gather-frames-on-RX.patch new file mode 100644 index 0000000..aa4402e --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0050-dpaa_eth-Add-counter-for-Scatter-Gather-frames-on-RX.patch @@ -0,0 +1,104 @@ +From d66ad3faa2ec2b1b68ae275dcb5079138f2d32c4 Mon Sep 17 00:00:00 2001 +From: Ioana Ciornei +Date: Thu, 11 Feb 2016 15:35:36 +0200 +Subject: [PATCH 050/151] dpaa_eth: Add counter for Scatter-Gather frames on RX + side + +Signed-off-by: Ioana Ciornei +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h | 3 +++ + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 4 +++- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c | 4 ++++ + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c | 1 + + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_macsec_ethtool.c | 4 ++++ + 5 files changed, 15 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +index f3b6ddd..db52ede 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +@@ -324,6 +324,9 @@ struct dpa_percpu_priv_s { + u64 tx_confirm; + /* fragmented (non-linear) skbuffs received from the stack */ + u64 tx_frag_skbuffs; ++ /* number of S/G frames received */ ++ u64 rx_sg; ++ + struct rtnl_link_stats64 stats; + struct dpa_rx_errors rx_errors; + struct dpa_ern_cnt ern_cnt; +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +index 3e4c652..92d0f06 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +@@ -571,8 +571,10 @@ void __hot _dpa_rx(struct net_device *net_dev, + } + #endif + skb = contig_fd_to_skb(priv, fd, &use_gro); +- } else ++ } else { + skb = sg_fd_to_skb(priv, fd, &use_gro, count_ptr); ++ percpu_priv->rx_sg++; ++ } + + /* Account for either the contig buffer or the SGT buffer (depending on + * which case we were in) having been removed from the pool. +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c +index c346d8a..4b78466 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_ethtool.c +@@ -51,6 +51,7 @@ static const char dpa_stats_percpu[][ETH_GSTRING_LEN] = { + "tx recycled", + "tx confirm", + "tx S/G", ++ "rx S/G", + "tx error", + "rx error", + "bp count" +@@ -412,6 +413,9 @@ static void copy_stats(struct dpa_percpu_priv_s *percpu_priv, int num_cpus, + data[crr_stat * num_stat_values + crr_cpu] = percpu_priv->tx_frag_skbuffs; + data[crr_stat++ * num_stat_values + num_cpus] += percpu_priv->tx_frag_skbuffs; + ++ data[crr_stat * num_stat_values + crr_cpu] = percpu_priv->rx_sg; ++ data[crr_stat++ * num_stat_values + num_cpus] += percpu_priv->rx_sg; ++ + data[crr_stat * num_stat_values + crr_cpu] = percpu_priv->stats.tx_errors; + data[crr_stat++ * num_stat_values + num_cpus] += percpu_priv->stats.tx_errors; + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c +index e152d69..10864f2 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_generic_ethtool.c +@@ -51,6 +51,7 @@ static const char dpa_stats_percpu[][ETH_GSTRING_LEN] = { + "tx recycled", + "tx confirm", + "tx S/G", ++ "rx S/G (N/A)", + "tx error", + "rx error", + "bp count", +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_macsec_ethtool.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_macsec_ethtool.c +index 6673996..14d4d73 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_macsec_ethtool.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_macsec_ethtool.c +@@ -41,6 +41,7 @@ static const char dpa_macsec_stats_percpu[][ETH_GSTRING_LEN] = { + "tx recycled", + "tx confirm", + "tx S/G", ++ "rx S/G", + "tx error", + "rx error", + "bp count", +@@ -101,6 +102,9 @@ static void copy_stats(struct dpa_percpu_priv_s *percpu_priv, int num_cpus, + data[crr * num_values + crr_cpu] = percpu_priv->tx_frag_skbuffs; + data[crr++ * num_values + num_cpus] += percpu_priv->tx_frag_skbuffs; + ++ data[crr * num_values + crr_cpu] = percpu_priv->rx_sg; ++ data[crr++ * num_values + num_cpus] += percpu_priv->rx_sg; ++ + data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_errors; + data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_errors; + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0051-Add-APIs-to-setup-HugeTLB-mappings-for-USDPAA.patch b/target/linux/layerscape-64b/patches-4.1/0051-Add-APIs-to-setup-HugeTLB-mappings-for-USDPAA.patch new file mode 100644 index 0000000..aceb881 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0051-Add-APIs-to-setup-HugeTLB-mappings-for-USDPAA.patch @@ -0,0 +1,62 @@ +From 2122797c9440c23878c9a05cf82a799578aeeaec Mon Sep 17 00:00:00 2001 +From: Roy Pledge +Date: Tue, 12 Jan 2016 13:40:26 -0500 +Subject: [PATCH 051/151] Add APIs to setup HugeTLB mappings for USDPAA + +--- + arch/powerpc/mm/fsl_booke_mmu.c | 14 +++++++++++++- + arch/powerpc/mm/mmu_decl.h | 6 ++++++ + 2 files changed, 19 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c +index 9c90e66..4394647 100644 +--- a/arch/powerpc/mm/fsl_booke_mmu.c ++++ b/arch/powerpc/mm/fsl_booke_mmu.c +@@ -105,7 +105,7 @@ unsigned long p_mapped_by_tlbcam(phys_addr_t pa) + * an unsigned long (for example, 32-bit implementations cannot support a 4GB + * size). + */ +-static void settlbcam(int index, unsigned long virt, phys_addr_t phys, ++void settlbcam(int index, unsigned long virt, phys_addr_t phys, + unsigned long size, unsigned long flags, unsigned int pid) + { + unsigned int tsize; +@@ -145,6 +145,18 @@ static void settlbcam(int index, unsigned long virt, phys_addr_t phys, + loadcam_entry(index); + } + ++void cleartlbcam(unsigned long virt, unsigned int pid) ++{ ++ int i = 0; ++ for (i = 0; i < NUM_TLBCAMS; i++) { ++ if (tlbcam_addrs[i].start == virt) { ++ TLBCAM[i].MAS1 = 0; ++ loadcam_entry(i); ++ return; ++ } ++ } ++} ++ + unsigned long calc_cam_sz(unsigned long ram, unsigned long virt, + phys_addr_t phys) + { +diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h +index 085b66b..afe3d98 100644 +--- a/arch/powerpc/mm/mmu_decl.h ++++ b/arch/powerpc/mm/mmu_decl.h +@@ -91,6 +91,12 @@ extern void _tlbia(void); + + #endif /* CONFIG_PPC_MMU_NOHASH */ + ++void settlbcam(int index, unsigned long virt, phys_addr_t phys, ++ unsigned long size, unsigned long flags, unsigned int pid); ++ ++void cleartlbcam(unsigned long virt, unsigned int pid); ++ ++ + #ifdef CONFIG_PPC32 + + extern void mapin_ram(void); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0052-Port-QBMan-Code-from-SDK-1.9.patch b/target/linux/layerscape-64b/patches-4.1/0052-Port-QBMan-Code-from-SDK-1.9.patch new file mode 100644 index 0000000..fcfa727 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0052-Port-QBMan-Code-from-SDK-1.9.patch @@ -0,0 +1,23605 @@ +From c26e2237b3f830e0ef0316228fd6c95eb97ab6a4 Mon Sep 17 00:00:00 2001 +From: Roy Pledge +Date: Tue, 19 Apr 2016 13:57:27 +0800 +Subject: [PATCH 052/151] Port QBMan Code from SDK 1.9 + +commit 5cc3c466026f5d3d597d34fe732e3fe987f4f623 +[context adjustment] + +Integrated-by: Zhao Qiang +--- + arch/powerpc/Kconfig | 9 +- + drivers/misc/Kconfig | 17 + + drivers/staging/Kconfig | 2 + + drivers/staging/Makefile | 1 + + drivers/staging/fsl_qbman/Kconfig | 209 + + drivers/staging/fsl_qbman/Makefile | 26 + + drivers/staging/fsl_qbman/bman_config.c | 747 ++++ + drivers/staging/fsl_qbman/bman_debugfs.c | 119 + + drivers/staging/fsl_qbman/bman_driver.c | 556 +++ + drivers/staging/fsl_qbman/bman_high.c | 1112 +++++ + drivers/staging/fsl_qbman/bman_low.h | 524 +++ + drivers/staging/fsl_qbman/bman_private.h | 165 + + drivers/staging/fsl_qbman/bman_test.c | 56 + + drivers/staging/fsl_qbman/bman_test.h | 44 + + drivers/staging/fsl_qbman/bman_test_high.c | 183 + + drivers/staging/fsl_qbman/bman_test_thresh.c | 196 + + drivers/staging/fsl_qbman/dpa_alloc.c | 706 +++ + drivers/staging/fsl_qbman/dpa_sys.h | 301 ++ + drivers/staging/fsl_qbman/fsl_usdpaa.c | 1939 +++++++++ + drivers/staging/fsl_qbman/fsl_usdpaa_irq.c | 284 ++ + drivers/staging/fsl_qbman/qbman_driver.c | 86 + + drivers/staging/fsl_qbman/qman_config.c | 1174 +++++ + drivers/staging/fsl_qbman/qman_debugfs.c | 1595 +++++++ + drivers/staging/fsl_qbman/qman_driver.c | 963 +++++ + drivers/staging/fsl_qbman/qman_high.c | 5245 +++++++++++++++++++++++ + drivers/staging/fsl_qbman/qman_low.h | 1346 ++++++ + drivers/staging/fsl_qbman/qman_private.h | 386 ++ + drivers/staging/fsl_qbman/qman_test.c | 57 + + drivers/staging/fsl_qbman/qman_test.h | 44 + + drivers/staging/fsl_qbman/qman_test_high.c | 213 + + drivers/staging/fsl_qbman/qman_test_hotpotato.c | 497 +++ + drivers/staging/fsl_qbman/qman_utility.c | 129 + + include/linux/fsl_bman.h | 519 +++ + include/linux/fsl_qman.h | 3464 +++++++++++++++ + include/linux/fsl_usdpaa.h | 372 ++ + 35 files changed, 23284 insertions(+), 2 deletions(-) + create mode 100644 drivers/staging/fsl_qbman/Kconfig + create mode 100644 drivers/staging/fsl_qbman/Makefile + create mode 100644 drivers/staging/fsl_qbman/bman_config.c + create mode 100644 drivers/staging/fsl_qbman/bman_debugfs.c + create mode 100644 drivers/staging/fsl_qbman/bman_driver.c + create mode 100644 drivers/staging/fsl_qbman/bman_high.c + create mode 100644 drivers/staging/fsl_qbman/bman_low.h + create mode 100644 drivers/staging/fsl_qbman/bman_private.h + create mode 100644 drivers/staging/fsl_qbman/bman_test.c + create mode 100644 drivers/staging/fsl_qbman/bman_test.h + create mode 100644 drivers/staging/fsl_qbman/bman_test_high.c + create mode 100644 drivers/staging/fsl_qbman/bman_test_thresh.c + create mode 100644 drivers/staging/fsl_qbman/dpa_alloc.c + create mode 100644 drivers/staging/fsl_qbman/dpa_sys.h + create mode 100644 drivers/staging/fsl_qbman/fsl_usdpaa.c + create mode 100644 drivers/staging/fsl_qbman/fsl_usdpaa_irq.c + create mode 100644 drivers/staging/fsl_qbman/qbman_driver.c + create mode 100644 drivers/staging/fsl_qbman/qman_config.c + create mode 100644 drivers/staging/fsl_qbman/qman_debugfs.c + create mode 100644 drivers/staging/fsl_qbman/qman_driver.c + create mode 100644 drivers/staging/fsl_qbman/qman_high.c + create mode 100644 drivers/staging/fsl_qbman/qman_low.h + create mode 100644 drivers/staging/fsl_qbman/qman_private.h + create mode 100644 drivers/staging/fsl_qbman/qman_test.c + create mode 100644 drivers/staging/fsl_qbman/qman_test.h + create mode 100644 drivers/staging/fsl_qbman/qman_test_high.c + create mode 100644 drivers/staging/fsl_qbman/qman_test_hotpotato.c + create mode 100644 drivers/staging/fsl_qbman/qman_utility.c + create mode 100644 include/linux/fsl_bman.h + create mode 100644 include/linux/fsl_qman.h + create mode 100644 include/linux/fsl_usdpaa.h + +diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig +index 190cc48..ab0eb71 100644 +--- a/arch/powerpc/Kconfig ++++ b/arch/powerpc/Kconfig +@@ -783,6 +783,11 @@ config FSL_GTM + help + Freescale General-purpose Timers support + ++config HAS_FSL_QBMAN ++ bool "Datapath Acceleration Queue and Buffer management" ++ help ++ Datapath Acceleration Queue and Buffer management ++ + # Yes MCA RS/6000s exist but Linux-PPC does not currently support any + config MCA + bool +@@ -915,14 +920,14 @@ config DYNAMIC_MEMSTART + select NONSTATIC_KERNEL + help + This option enables the kernel to be loaded at any page aligned +- physical address. The kernel creates a mapping from KERNELBASE to ++ physical address. The kernel creates a mapping from KERNELBASE to + the address where the kernel is loaded. The page size here implies + the TLB page size of the mapping for kernel on the particular platform. + Please refer to the init code for finding the TLB page size. + + DYNAMIC_MEMSTART is an easy way of implementing pseudo-RELOCATABLE + kernel image, where the only restriction is the page aligned kernel +- load address. When this option is enabled, the compile time physical ++ load address. When this option is enabled, the compile time physical + address CONFIG_PHYSICAL_START is ignored. + + This option is overridden by CONFIG_RELOCATABLE +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index 006242c..29c3018 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -224,6 +224,23 @@ config SGI_XP + this feature will allow for direct communication between SSIs + based on a network adapter and DMA messaging. + ++config FSL_USDPAA ++ bool "Freescale USDPAA process driver" ++ depends on FSL_DPA ++ default y ++ help ++ This driver provides user-space access to kernel-managed ++ resource interfaces for USDPAA applications, on the assumption ++ that each process will open this device once. Specifically, this ++ device exposes functionality that would be awkward if exposed ++ via the portal devices - ie. this device exposes functionality ++ that is inherently process-wide rather than portal-specific. ++ This device is necessary for obtaining access to DMA memory and ++ for allocation of Qman and Bman resources. In short, if you wish ++ to use USDPAA applications, you need this. ++ ++ If unsure, say Y. ++ + config CS5535_MFGPT + tristate "CS5535/CS5536 Geode Multi-Function General Purpose Timer (MFGPT) support" + depends on MFD_CS5535 +diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig +index bfacf69..32c6857 100644 +--- a/drivers/staging/Kconfig ++++ b/drivers/staging/Kconfig +@@ -112,4 +112,6 @@ source "drivers/staging/i2o/Kconfig" + + source "drivers/staging/fsl-mc/Kconfig" + ++source "drivers/staging/fsl_qbman/Kconfig" ++ + endif # STAGING +diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile +index 2bbd1bf..ab89684 100644 +--- a/drivers/staging/Makefile ++++ b/drivers/staging/Makefile +@@ -48,3 +48,4 @@ obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ + obj-$(CONFIG_FB_TFT) += fbtft/ + obj-$(CONFIG_I2O) += i2o/ + obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/ ++obj-$(CONFIG_FSL_DPA) += fsl_qbman/ +diff --git a/drivers/staging/fsl_qbman/Kconfig b/drivers/staging/fsl_qbman/Kconfig +new file mode 100644 +index 0000000..c857514 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/Kconfig +@@ -0,0 +1,209 @@ ++config FSL_DPA ++ bool "Freescale Datapath Queue and Buffer management" ++ depends on HAS_FSL_QBMAN ++ default y ++ select FSL_QMAN_FQ_LOOKUP if PPC64 ++ ++menu "Freescale Datapath QMan/BMan options" ++ depends on FSL_DPA ++ ++config FSL_DPA_CHECKING ++ bool "additional driver checking" ++ default n ++ ---help--- ++ Compiles in additional checks to sanity-check the drivers and any ++ use of it by other code. Not recommended for performance. ++ ++config FSL_DPA_CAN_WAIT ++ bool ++ default y ++ ++config FSL_DPA_CAN_WAIT_SYNC ++ bool ++ default y ++ ++config FSL_DPA_PIRQ_FAST ++ bool ++ default y ++ ++config FSL_DPA_PIRQ_SLOW ++ bool ++ default y ++ ++config FSL_DPA_PORTAL_SHARE ++ bool ++ default y ++ ++config FSL_BMAN ++ bool "Freescale Buffer Manager (BMan) support" ++ default y ++ ++if FSL_BMAN ++ ++config FSL_BMAN_CONFIG ++ bool "BMan device management" ++ default y ++ ---help--- ++ If this linux image is running natively, you need this option. If this ++ linux image is running as a guest OS under the hypervisor, only one ++ guest OS ("the control plane") needs this option. ++ ++config FSL_BMAN_TEST ++ tristate "BMan self-tests" ++ default n ++ ---help--- ++ This option compiles self-test code for BMan. ++ ++config FSL_BMAN_TEST_HIGH ++ bool "BMan high-level self-test" ++ depends on FSL_BMAN_TEST ++ default y ++ ---help--- ++ This requires the presence of cpu-affine portals, and performs ++ high-level API testing with them (whichever portal(s) are affine to ++ the cpu(s) the test executes on). ++ ++config FSL_BMAN_TEST_THRESH ++ bool "BMan threshold test" ++ depends on FSL_BMAN_TEST ++ default y ++ ---help--- ++ Multi-threaded (SMP) test of BMan pool depletion. A pool is seeded ++ before multiple threads (one per cpu) create pool objects to track ++ depletion state changes. The pool is then drained to empty by a ++ "drainer" thread, and the other threads that they observe exactly ++ the depletion state changes that are expected. ++ ++config FSL_BMAN_DEBUGFS ++ tristate "BMan debugfs interface" ++ depends on DEBUG_FS ++ default y ++ ---help--- ++ This option compiles debugfs code for BMan. ++ ++endif # FSL_BMAN ++ ++config FSL_QMAN ++ bool "Freescale Queue Manager (QMan) support" ++ default y ++ ++if FSL_QMAN ++ ++config FSL_QMAN_POLL_LIMIT ++ int ++ default 32 ++ ++config FSL_QMAN_CONFIG ++ bool "QMan device management" ++ default y ++ ---help--- ++ If this linux image is running natively, you need this option. If this ++ linux image is running as a guest OS under the hypervisor, only one ++ guest OS ("the control plane") needs this option. ++ ++config FSL_QMAN_TEST ++ tristate "QMan self-tests" ++ default n ++ ---help--- ++ This option compiles self-test code for QMan. ++ ++config FSL_QMAN_TEST_STASH_POTATO ++ bool "QMan 'hot potato' data-stashing self-test" ++ depends on FSL_QMAN_TEST ++ default y ++ ---help--- ++ This performs a "hot potato" style test enqueuing/dequeuing a frame ++ across a series of FQs scheduled to different portals (and cpus), with ++ DQRR, data and context stashing always on. ++ ++config FSL_QMAN_TEST_HIGH ++ bool "QMan high-level self-test" ++ depends on FSL_QMAN_TEST ++ default y ++ ---help--- ++ This requires the presence of cpu-affine portals, and performs ++ high-level API testing with them (whichever portal(s) are affine to ++ the cpu(s) the test executes on). ++ ++config FSL_QMAN_DEBUGFS ++ tristate "QMan debugfs interface" ++ depends on DEBUG_FS ++ default y ++ ---help--- ++ This option compiles debugfs code for QMan. ++ ++# H/w settings that can be hard-coded for now. ++config FSL_QMAN_FQD_SZ ++ int "size of Frame Queue Descriptor region" ++ default 10 ++ ---help--- ++ This is the size of the FQD region defined as: PAGE_SIZE * (2^value) ++ ex: 10 => PAGE_SIZE * (2^10) ++ Note: Default device-trees now require minimum Kconfig setting of 10. ++ ++config FSL_QMAN_PFDR_SZ ++ int "size of the PFDR pool" ++ default 13 ++ ---help--- ++ This is the size of the PFDR pool defined as: PAGE_SIZE * (2^value) ++ ex: 13 => PAGE_SIZE * (2^13) ++ ++# Corenet initiator settings. Stash request queues are 4-deep to match cores' ++# ability to snart. Stash priority is 3, other priorities are 2. ++config FSL_QMAN_CI_SCHED_CFG_SRCCIV ++ int ++ depends on FSL_QMAN_CONFIG ++ default 4 ++config FSL_QMAN_CI_SCHED_CFG_SRQ_W ++ int ++ depends on FSL_QMAN_CONFIG ++ default 3 ++config FSL_QMAN_CI_SCHED_CFG_RW_W ++ int ++ depends on FSL_QMAN_CONFIG ++ default 2 ++config FSL_QMAN_CI_SCHED_CFG_BMAN_W ++ int ++ depends on FSL_QMAN_CONFIG ++ default 2 ++ ++# portal interrupt settings ++config FSL_QMAN_PIRQ_DQRR_ITHRESH ++ int ++ default 12 ++config FSL_QMAN_PIRQ_MR_ITHRESH ++ int ++ default 4 ++config FSL_QMAN_PIRQ_IPERIOD ++ int ++ default 100 ++ ++# 64 bit kernel support ++config FSL_QMAN_FQ_LOOKUP ++ bool ++ default n ++ ++config QMAN_CEETM_UPDATE_PERIOD ++ int "Token update period for shaping, in nanoseconds" ++ default 1000 ++ ---help--- ++ Traffic shaping works by performing token calculations (using ++ credits) on shaper instances periodically. This update period ++ sets the granularity for how often those token rate credit ++ updates are performed, and thus determines the accuracy and ++ range of traffic rates that can be configured by users. The ++ reference manual recommends a 1 microsecond period as providing ++ a good balance between granularity and range. ++ ++ Unless you know what you are doing, leave this value at its default. ++ ++config FSL_QMAN_INIT_TIMEOUT ++ int "timeout for qman init stage, in seconds" ++ default 10 ++ ---help--- ++ The timeout setting to quit the initialization loop for non-control ++ partition in case the control partition fails to boot-up. ++ ++endif # FSL_QMAN ++ ++endmenu +diff --git a/drivers/staging/fsl_qbman/Makefile b/drivers/staging/fsl_qbman/Makefile +new file mode 100644 +index 0000000..0e38610 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/Makefile +@@ -0,0 +1,26 @@ ++# Common ++obj-$(CONFIG_FSL_DPA) += dpa_alloc.o ++obj-$(CONFIG_HAS_FSL_QBMAN) += qbman_driver.o ++ ++# Bman ++obj-$(CONFIG_FSL_BMAN) += bman_high.o ++obj-$(CONFIG_FSL_BMAN_CONFIG) += bman_config.o bman_driver.o ++obj-$(CONFIG_FSL_BMAN_TEST) += bman_tester.o ++obj-$(CONFIG_FSL_BMAN_DEBUGFS) += bman_debugfs_interface.o ++bman_tester-y = bman_test.o ++bman_tester-$(CONFIG_FSL_BMAN_TEST_HIGH) += bman_test_high.o ++bman_tester-$(CONFIG_FSL_BMAN_TEST_THRESH) += bman_test_thresh.o ++bman_debugfs_interface-y = bman_debugfs.o ++ ++# Qman ++obj-$(CONFIG_FSL_QMAN) += qman_high.o qman_utility.o ++obj-$(CONFIG_FSL_QMAN_CONFIG) += qman_config.o qman_driver.o ++obj-$(CONFIG_FSL_QMAN_TEST) += qman_tester.o ++qman_tester-y = qman_test.o ++qman_tester-$(CONFIG_FSL_QMAN_TEST_STASH_POTATO) += qman_test_hotpotato.o ++qman_tester-$(CONFIG_FSL_QMAN_TEST_HIGH) += qman_test_high.o ++obj-$(CONFIG_FSL_QMAN_DEBUGFS) += qman_debugfs_interface.o ++qman_debugfs_interface-y = qman_debugfs.o ++ ++# USDPAA ++obj-$(CONFIG_FSL_USDPAA) += fsl_usdpaa.o fsl_usdpaa_irq.o +diff --git a/drivers/staging/fsl_qbman/bman_config.c b/drivers/staging/fsl_qbman/bman_config.c +new file mode 100644 +index 0000000..136e22d +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_config.c +@@ -0,0 +1,747 @@ ++/* Copyright (c) 2009-2012 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 ++#include "bman_private.h" ++ ++/* Last updated for v00.79 of the BG */ ++ ++struct bman; ++ ++/* Register offsets */ ++#define REG_POOL_SWDET(n) (0x0000 + ((n) * 0x04)) ++#define REG_POOL_HWDET(n) (0x0100 + ((n) * 0x04)) ++#define REG_POOL_SWDXT(n) (0x0200 + ((n) * 0x04)) ++#define REG_POOL_HWDXT(n) (0x0300 + ((n) * 0x04)) ++#define REG_POOL_CONTENT(n) (0x0600 + ((n) * 0x04)) ++#define REG_FBPR_FPC 0x0800 ++#define REG_STATE_IDLE 0x960 ++#define REG_STATE_STOP 0x964 ++#define REG_ECSR 0x0a00 ++#define REG_ECIR 0x0a04 ++#define REG_EADR 0x0a08 ++#define REG_EDATA(n) (0x0a10 + ((n) * 0x04)) ++#define REG_SBEC(n) (0x0a80 + ((n) * 0x04)) ++#define REG_IP_REV_1 0x0bf8 ++#define REG_IP_REV_2 0x0bfc ++#define REG_FBPR_BARE 0x0c00 ++#define REG_FBPR_BAR 0x0c04 ++#define REG_FBPR_AR 0x0c10 ++#define REG_SRCIDR 0x0d04 ++#define REG_LIODNR 0x0d08 ++#define REG_ERR_ISR 0x0e00 /* + "enum bm_isr_reg" */ ++ ++/* Used by all error interrupt registers except 'inhibit' */ ++#define BM_EIRQ_IVCI 0x00000010 /* Invalid Command Verb */ ++#define BM_EIRQ_FLWI 0x00000008 /* FBPR Low Watermark */ ++#define BM_EIRQ_MBEI 0x00000004 /* Multi-bit ECC Error */ ++#define BM_EIRQ_SBEI 0x00000002 /* Single-bit ECC Error */ ++#define BM_EIRQ_BSCN 0x00000001 /* pool State Change Notification */ ++ ++/* BMAN_ECIR valid error bit */ ++#define PORTAL_ECSR_ERR (BM_EIRQ_IVCI) ++ ++union bman_ecir { ++ u32 ecir_raw; ++ struct { ++ u32 __reserved1:4; ++ u32 portal_num:4; ++ u32 __reserved2:12; ++ u32 numb:4; ++ u32 __reserved3:2; ++ u32 pid:6; ++ } __packed info; ++}; ++ ++union bman_eadr { ++ u32 eadr_raw; ++ struct { ++ u32 __reserved1:5; ++ u32 memid:3; ++ u32 __reserved2:14; ++ u32 eadr:10; ++ } __packed info; ++}; ++ ++struct bman_hwerr_txt { ++ u32 mask; ++ const char *txt; ++}; ++ ++#define BMAN_HWE_TXT(a, b) { .mask = BM_EIRQ_##a, .txt = b } ++ ++static const struct bman_hwerr_txt bman_hwerr_txts[] = { ++ BMAN_HWE_TXT(IVCI, "Invalid Command Verb"), ++ BMAN_HWE_TXT(FLWI, "FBPR Low Watermark"), ++ BMAN_HWE_TXT(MBEI, "Multi-bit ECC Error"), ++ BMAN_HWE_TXT(SBEI, "Single-bit ECC Error"), ++ BMAN_HWE_TXT(BSCN, "Pool State Change Notification"), ++}; ++#define BMAN_HWE_COUNT (sizeof(bman_hwerr_txts)/sizeof(struct bman_hwerr_txt)) ++ ++struct bman_error_info_mdata { ++ u16 addr_mask; ++ u16 bits; ++ const char *txt; ++}; ++ ++#define BMAN_ERR_MDATA(a, b, c) { .addr_mask = a, .bits = b, .txt = c} ++static const struct bman_error_info_mdata error_mdata[] = { ++ BMAN_ERR_MDATA(0x03FF, 192, "Stockpile memory"), ++ BMAN_ERR_MDATA(0x00FF, 256, "SW portal ring memory port 1"), ++ BMAN_ERR_MDATA(0x00FF, 256, "SW portal ring memory port 2"), ++}; ++#define BMAN_ERR_MDATA_COUNT \ ++ (sizeof(error_mdata)/sizeof(struct bman_error_info_mdata)) ++ ++/* Add this in Kconfig */ ++#define BMAN_ERRS_TO_UNENABLE (BM_EIRQ_FLWI) ++ ++/** ++ * bm_err_isr__ - Manipulate global interrupt registers ++ * @v: for accessors that write values, this is the 32-bit value ++ * ++ * Manipulates BMAN_ERR_ISR, BMAN_ERR_IER, BMAN_ERR_ISDR, BMAN_ERR_IIR. All ++ * manipulations except bm_err_isr_[un]inhibit() use 32-bit masks composed of ++ * the BM_EIRQ_*** definitions. Note that "bm_err_isr_enable_write" means ++ * "write the enable register" rather than "enable the write register"! ++ */ ++#define bm_err_isr_status_read(bm) \ ++ __bm_err_isr_read(bm, bm_isr_status) ++#define bm_err_isr_status_clear(bm, m) \ ++ __bm_err_isr_write(bm, bm_isr_status, m) ++#define bm_err_isr_enable_read(bm) \ ++ __bm_err_isr_read(bm, bm_isr_enable) ++#define bm_err_isr_enable_write(bm, v) \ ++ __bm_err_isr_write(bm, bm_isr_enable, v) ++#define bm_err_isr_disable_read(bm) \ ++ __bm_err_isr_read(bm, bm_isr_disable) ++#define bm_err_isr_disable_write(bm, v) \ ++ __bm_err_isr_write(bm, bm_isr_disable, v) ++#define bm_err_isr_inhibit(bm) \ ++ __bm_err_isr_write(bm, bm_isr_inhibit, 1) ++#define bm_err_isr_uninhibit(bm) \ ++ __bm_err_isr_write(bm, bm_isr_inhibit, 0) ++ ++/* ++ * TODO: unimplemented registers ++ * ++ * BMAN_POOLk_SDCNT, BMAN_POOLk_HDCNT, BMAN_FULT, ++ * BMAN_VLDPL, BMAN_EECC, BMAN_SBET, BMAN_EINJ ++ */ ++ ++/* Encapsulate "struct bman *" as a cast of the register space address. */ ++ ++static struct bman *bm_create(void *regs) ++{ ++ return (struct bman *)regs; ++} ++ ++static inline u32 __bm_in(struct bman *bm, u32 offset) ++{ ++ return in_be32((void *)bm + offset); ++} ++static inline void __bm_out(struct bman *bm, u32 offset, u32 val) ++{ ++ out_be32((void *)bm + offset, val); ++} ++#define bm_in(reg) __bm_in(bm, REG_##reg) ++#define bm_out(reg, val) __bm_out(bm, REG_##reg, val) ++ ++static u32 __bm_err_isr_read(struct bman *bm, enum bm_isr_reg n) ++{ ++ return __bm_in(bm, REG_ERR_ISR + (n << 2)); ++} ++ ++static void __bm_err_isr_write(struct bman *bm, enum bm_isr_reg n, u32 val) ++{ ++ __bm_out(bm, REG_ERR_ISR + (n << 2), val); ++} ++ ++static void bm_get_version(struct bman *bm, u16 *id, u8 *major, u8 *minor) ++{ ++ u32 v = bm_in(IP_REV_1); ++ *id = (v >> 16); ++ *major = (v >> 8) & 0xff; ++ *minor = v & 0xff; ++} ++ ++static u32 __generate_thresh(u32 val, int roundup) ++{ ++ u32 e = 0; /* co-efficient, exponent */ ++ int oddbit = 0; ++ while (val > 0xff) { ++ oddbit = val & 1; ++ val >>= 1; ++ e++; ++ if (roundup && oddbit) ++ val++; ++ } ++ DPA_ASSERT(e < 0x10); ++ return val | (e << 8); ++} ++ ++static void bm_set_pool(struct bman *bm, u8 pool, u32 swdet, u32 swdxt, ++ u32 hwdet, u32 hwdxt) ++{ ++ DPA_ASSERT(pool < bman_pool_max); ++ bm_out(POOL_SWDET(pool), __generate_thresh(swdet, 0)); ++ bm_out(POOL_SWDXT(pool), __generate_thresh(swdxt, 1)); ++ bm_out(POOL_HWDET(pool), __generate_thresh(hwdet, 0)); ++ bm_out(POOL_HWDXT(pool), __generate_thresh(hwdxt, 1)); ++} ++ ++static void bm_set_memory(struct bman *bm, u64 ba, int prio, u32 size) ++{ ++ u32 exp = ilog2(size); ++ /* choke if size isn't within range */ ++ DPA_ASSERT((size >= 4096) && (size <= 1073741824) && ++ is_power_of_2(size)); ++ /* choke if '[e]ba' has lower-alignment than 'size' */ ++ DPA_ASSERT(!(ba & (size - 1))); ++ bm_out(FBPR_BARE, upper_32_bits(ba)); ++ bm_out(FBPR_BAR, lower_32_bits(ba)); ++ bm_out(FBPR_AR, (prio ? 0x40000000 : 0) | (exp - 1)); ++} ++ ++/*****************/ ++/* Config driver */ ++/*****************/ ++ ++/* TODO: Kconfig these? */ ++#define DEFAULT_FBPR_SZ (PAGE_SIZE << 12) ++ ++/* We support only one of these. */ ++static struct bman *bm; ++static struct device_node *bm_node; ++ ++/* And this state belongs to 'bm'. It is set during fsl_bman_init(), but used ++ * during bman_init_ccsr(). */ ++static dma_addr_t fbpr_a; ++static size_t fbpr_sz = DEFAULT_FBPR_SZ; ++ ++/* Parse the property to extract the memory location and size and ++ * memblock_reserve() it. If it isn't supplied, memblock_alloc() the default ++ * size. Also flush this memory range from data cache so that BMAN originated ++ * transactions for this memory region could be marked non-coherent. ++ */ ++static __init int parse_mem_property(struct device_node *node, const char *name, ++ dma_addr_t *addr, size_t *sz, int zero) ++{ ++ const u32 *pint; ++ int ret; ++ unsigned long vaddr; ++ ++ pint = of_get_property(node, name, &ret); ++ if (!pint || (ret != 16)) { ++ pr_info("No %s property '%s', using memblock_alloc(%016zx)\n", ++ node->full_name, name, *sz); ++ *addr = memblock_alloc(*sz, *sz); ++ vaddr = (unsigned long)phys_to_virt(*addr); ++ if (zero) ++ memset((void *)vaddr, 0, *sz); ++ flush_dcache_range(vaddr, vaddr + *sz); ++ return 0; ++ } ++ pr_info("Using %s property '%s'\n", node->full_name, name); ++ /* If using a "zero-pma", don't try to zero it, even if you asked */ ++ if (zero && of_find_property(node, "zero-pma", &ret)) { ++ pr_info(" it's a 'zero-pma', not zeroing from s/w\n"); ++ zero = 0; ++ } ++ *addr = ((u64)pint[0] << 32) | (u64)pint[1]; ++ *sz = ((u64)pint[2] << 32) | (u64)pint[3]; ++ /* Keep things simple, it's either all in the DRAM range or it's all ++ * outside. */ ++ if (*addr < memblock_end_of_DRAM()) { ++ BUG_ON((u64)*addr + (u64)*sz > memblock_end_of_DRAM()); ++ if (memblock_reserve(*addr, *sz) < 0) { ++ pr_err("Failed to reserve %s\n", name); ++ return -ENOMEM; ++ } ++ vaddr = (unsigned long)phys_to_virt(*addr); ++ if (zero) ++ memset((void *)vaddr, 0, *sz); ++ flush_dcache_range(vaddr, vaddr + *sz); ++ } else if (zero) { ++ /* map as cacheable, non-guarded */ ++ void __iomem *tmpp = ioremap_prot(*addr, *sz, 0); ++ if (!tmpp) ++ return -ENOMEM; ++ memset_io(tmpp, 0, *sz); ++ vaddr = (unsigned long)tmpp; ++ flush_dcache_range(vaddr, vaddr + *sz); ++ iounmap(tmpp); ++ } ++ return 0; ++} ++ ++static int __init fsl_bman_init(struct device_node *node) ++{ ++ struct resource res; ++ u32 __iomem *regs; ++ const char *s; ++ int ret, standby = 0; ++ u16 id; ++ u8 major, minor; ++ ++ ret = of_address_to_resource(node, 0, &res); ++ if (ret) { ++ pr_err("Can't get %s property 'reg'\n", ++ node->full_name); ++ return ret; ++ } ++ s = of_get_property(node, "fsl,hv-claimable", &ret); ++ if (s && !strcmp(s, "standby")) ++ standby = 1; ++ if (!standby) { ++ ret = parse_mem_property(node, "fsl,bman-fbpr", ++ &fbpr_a, &fbpr_sz, 0); ++ BUG_ON(ret); ++ } ++ /* Global configuration */ ++ regs = ioremap(res.start, res.end - res.start + 1); ++ bm = bm_create(regs); ++ BUG_ON(!bm); ++ bm_node = node; ++ bm_get_version(bm, &id, &major, &minor); ++ pr_info("Bman ver:%04x,%02x,%02x\n", id, major, minor); ++ if ((major == 1) && (minor == 0)) { ++ bman_ip_rev = BMAN_REV10; ++ bman_pool_max = 64; ++ } else if ((major == 2) && (minor == 0)) { ++ bman_ip_rev = BMAN_REV20; ++ bman_pool_max = 8; ++ } else if ((major == 2) && (minor == 1)) { ++ bman_ip_rev = BMAN_REV21; ++ bman_pool_max = 64; ++ } else { ++ pr_warn("unknown Bman version, default to rev1.0\n"); ++ } ++ ++ if (standby) { ++ pr_info(" -> in standby mode\n"); ++ return 0; ++ } ++ return 0; ++} ++ ++int bman_have_ccsr(void) ++{ ++ return bm ? 1 : 0; ++} ++ ++int bm_pool_set(u32 bpid, const u32 *thresholds) ++{ ++ if (!bm) ++ return -ENODEV; ++ bm_set_pool(bm, bpid, thresholds[0], thresholds[1], ++ thresholds[2], thresholds[3]); ++ return 0; ++} ++EXPORT_SYMBOL(bm_pool_set); ++ ++__init void bman_init_early(void) ++{ ++ struct device_node *dn; ++ int ret; ++ ++ for_each_compatible_node(dn, NULL, "fsl,bman") { ++ if (bm) ++ pr_err("%s: only one 'fsl,bman' allowed\n", ++ dn->full_name); ++ else { ++ if (!of_device_is_available(dn)) ++ continue; ++ ++ ret = fsl_bman_init(dn); ++ BUG_ON(ret); ++ } ++ } ++} ++ ++static void log_edata_bits(u32 bit_count) ++{ ++ u32 i, j, mask = 0xffffffff; ++ ++ pr_warn("Bman ErrInt, EDATA:\n"); ++ i = bit_count/32; ++ if (bit_count%32) { ++ i++; ++ mask = ~(mask << bit_count%32); ++ } ++ j = 16-i; ++ pr_warn(" 0x%08x\n", bm_in(EDATA(j)) & mask); ++ j++; ++ for (; j < 16; j++) ++ pr_warn(" 0x%08x\n", bm_in(EDATA(j))); ++} ++ ++static void log_additional_error_info(u32 isr_val, u32 ecsr_val) ++{ ++ union bman_ecir ecir_val; ++ union bman_eadr eadr_val; ++ ++ ecir_val.ecir_raw = bm_in(ECIR); ++ /* Is portal info valid */ ++ if (ecsr_val & PORTAL_ECSR_ERR) { ++ pr_warn("Bman ErrInt: SWP id %d, numb %d, pid %d\n", ++ ecir_val.info.portal_num, ecir_val.info.numb, ++ ecir_val.info.pid); ++ } ++ if (ecsr_val & (BM_EIRQ_SBEI|BM_EIRQ_MBEI)) { ++ eadr_val.eadr_raw = bm_in(EADR); ++ pr_warn("Bman ErrInt: EADR Memory: %s, 0x%x\n", ++ error_mdata[eadr_val.info.memid].txt, ++ error_mdata[eadr_val.info.memid].addr_mask ++ & eadr_val.info.eadr); ++ log_edata_bits(error_mdata[eadr_val.info.memid].bits); ++ } ++} ++ ++/* Bman interrupt handler */ ++static irqreturn_t bman_isr(int irq, void *ptr) ++{ ++ u32 isr_val, ier_val, ecsr_val, isr_mask, i; ++ ++ ier_val = bm_err_isr_enable_read(bm); ++ isr_val = bm_err_isr_status_read(bm); ++ ecsr_val = bm_in(ECSR); ++ isr_mask = isr_val & ier_val; ++ ++ if (!isr_mask) ++ return IRQ_NONE; ++ for (i = 0; i < BMAN_HWE_COUNT; i++) { ++ if (bman_hwerr_txts[i].mask & isr_mask) { ++ pr_warn("Bman ErrInt: %s\n", bman_hwerr_txts[i].txt); ++ if (bman_hwerr_txts[i].mask & ecsr_val) { ++ log_additional_error_info(isr_mask, ecsr_val); ++ /* Re-arm error capture registers */ ++ bm_out(ECSR, ecsr_val); ++ } ++ if (bman_hwerr_txts[i].mask & BMAN_ERRS_TO_UNENABLE) { ++ pr_devel("Bman un-enabling error 0x%x\n", ++ bman_hwerr_txts[i].mask); ++ ier_val &= ~bman_hwerr_txts[i].mask; ++ bm_err_isr_enable_write(bm, ier_val); ++ } ++ } ++ } ++ bm_err_isr_status_clear(bm, isr_val); ++ return IRQ_HANDLED; ++} ++ ++static int __bind_irq(void) ++{ ++ int ret, err_irq; ++ ++ err_irq = of_irq_to_resource(bm_node, 0, NULL); ++ if (err_irq == NO_IRQ) { ++ pr_info("Can't get %s property '%s'\n", bm_node->full_name, ++ "interrupts"); ++ return -ENODEV; ++ } ++ ret = request_irq(err_irq, bman_isr, IRQF_SHARED, "bman-err", bm_node); ++ if (ret) { ++ pr_err("request_irq() failed %d for '%s'\n", ret, ++ bm_node->full_name); ++ return -ENODEV; ++ } ++ /* Disable Buffer Pool State Change */ ++ bm_err_isr_disable_write(bm, BM_EIRQ_BSCN); ++ /* Write-to-clear any stale bits, (eg. starvation being asserted prior ++ * to resource allocation during driver init). */ ++ bm_err_isr_status_clear(bm, 0xffffffff); ++ /* Enable Error Interrupts */ ++ bm_err_isr_enable_write(bm, 0xffffffff); ++ return 0; ++} ++ ++int bman_init_ccsr(struct device_node *node) ++{ ++ int ret; ++ if (!bman_have_ccsr()) ++ return 0; ++ if (node != bm_node) ++ return -EINVAL; ++ /* FBPR memory */ ++ bm_set_memory(bm, fbpr_a, 0, fbpr_sz); ++ ret = __bind_irq(); ++ if (ret) ++ return ret; ++ return 0; ++} ++ ++u32 bm_pool_free_buffers(u32 bpid) ++{ ++ return bm_in(POOL_CONTENT(bpid)); ++} ++ ++#ifdef CONFIG_SYSFS ++ ++#define DRV_NAME "fsl-bman" ++#define SBEC_MAX_ID 1 ++#define SBEC_MIN_ID 0 ++ ++static ssize_t show_fbpr_fpc(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%u\n", bm_in(FBPR_FPC)); ++}; ++ ++static ssize_t show_pool_count(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ u32 data; ++ int i; ++ ++ if (!sscanf(dev_attr->attr.name, "%d", &i) || (i >= bman_pool_max)) ++ return -EINVAL; ++ data = bm_in(POOL_CONTENT(i)); ++ return snprintf(buf, PAGE_SIZE, "%d\n", data); ++}; ++ ++static ssize_t show_err_isr(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "0x%08x\n", bm_in(ERR_ISR)); ++}; ++ ++static ssize_t show_sbec(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ int i; ++ ++ if (!sscanf(dev_attr->attr.name, "sbec_%d", &i)) ++ return -EINVAL; ++ if (i < SBEC_MIN_ID || i > SBEC_MAX_ID) ++ return -EINVAL; ++ return snprintf(buf, PAGE_SIZE, "%u\n", bm_in(SBEC(i))); ++}; ++ ++static DEVICE_ATTR(err_isr, S_IRUSR, show_err_isr, NULL); ++static DEVICE_ATTR(fbpr_fpc, S_IRUSR, show_fbpr_fpc, NULL); ++ ++/* Didn't use DEVICE_ATTR as 64 of this would be required. ++ * Initialize them when needed. */ ++static char *name_attrs_pool_count; /* "xx" + null-terminator */ ++static struct device_attribute *dev_attr_buffer_pool_count; ++ ++static DEVICE_ATTR(sbec_0, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_1, S_IRUSR, show_sbec, NULL); ++ ++static struct attribute *bman_dev_attributes[] = { ++ &dev_attr_fbpr_fpc.attr, ++ &dev_attr_err_isr.attr, ++ NULL ++}; ++ ++static struct attribute *bman_dev_ecr_attributes[] = { ++ &dev_attr_sbec_0.attr, ++ &dev_attr_sbec_1.attr, ++ NULL ++}; ++ ++static struct attribute **bman_dev_pool_count_attributes; ++ ++ ++/* root level */ ++static const struct attribute_group bman_dev_attr_grp = { ++ .name = NULL, ++ .attrs = bman_dev_attributes ++}; ++static const struct attribute_group bman_dev_ecr_grp = { ++ .name = "error_capture", ++ .attrs = bman_dev_ecr_attributes ++}; ++static struct attribute_group bman_dev_pool_countent_grp = { ++ .name = "pool_count", ++}; ++ ++static int of_fsl_bman_remove(struct platform_device *ofdev) ++{ ++ sysfs_remove_group(&ofdev->dev.kobj, &bman_dev_attr_grp); ++ return 0; ++}; ++ ++static int of_fsl_bman_probe(struct platform_device *ofdev) ++{ ++ int ret, i; ++ ++ ret = sysfs_create_group(&ofdev->dev.kobj, &bman_dev_attr_grp); ++ if (ret) ++ goto done; ++ ret = sysfs_create_group(&ofdev->dev.kobj, &bman_dev_ecr_grp); ++ if (ret) ++ goto del_group_0; ++ ++ name_attrs_pool_count = kmalloc(sizeof(char) * bman_pool_max * 3, ++ GFP_KERNEL); ++ if (!name_attrs_pool_count) { ++ pr_err("Can't alloc name_attrs_pool_count\n"); ++ goto del_group_1; ++ } ++ ++ dev_attr_buffer_pool_count = kmalloc(sizeof(struct device_attribute) * ++ bman_pool_max, GFP_KERNEL); ++ if (!dev_attr_buffer_pool_count) { ++ pr_err("Can't alloc dev_attr-buffer_pool_count\n"); ++ goto del_group_2; ++ } ++ ++ bman_dev_pool_count_attributes = kmalloc(sizeof(struct attribute *) * ++ (bman_pool_max + 1), GFP_KERNEL); ++ if (!bman_dev_pool_count_attributes) { ++ pr_err("can't alloc bman_dev_pool_count_attributes\n"); ++ goto del_group_3; ++ } ++ ++ for (i = 0; i < bman_pool_max; i++) { ++ ret = scnprintf((name_attrs_pool_count + i * 3), 3, "%d", i); ++ if (!ret) ++ goto del_group_4; ++ dev_attr_buffer_pool_count[i].attr.name = ++ (name_attrs_pool_count + i * 3); ++ dev_attr_buffer_pool_count[i].attr.mode = S_IRUSR; ++ dev_attr_buffer_pool_count[i].show = show_pool_count; ++ bman_dev_pool_count_attributes[i] = ++ &dev_attr_buffer_pool_count[i].attr; ++ sysfs_attr_init(bman_dev_pool_count_attributes[i]); ++ } ++ bman_dev_pool_count_attributes[bman_pool_max] = NULL; ++ ++ bman_dev_pool_countent_grp.attrs = bman_dev_pool_count_attributes; ++ ++ ret = sysfs_create_group(&ofdev->dev.kobj, &bman_dev_pool_countent_grp); ++ if (ret) ++ goto del_group_4; ++ ++ goto done; ++ ++del_group_4: ++ kfree(bman_dev_pool_count_attributes); ++del_group_3: ++ kfree(dev_attr_buffer_pool_count); ++del_group_2: ++ kfree(name_attrs_pool_count); ++del_group_1: ++ sysfs_remove_group(&ofdev->dev.kobj, &bman_dev_ecr_grp); ++del_group_0: ++ sysfs_remove_group(&ofdev->dev.kobj, &bman_dev_attr_grp); ++done: ++ if (ret) ++ dev_err(&ofdev->dev, ++ "Cannot create dev attributes ret=%d\n", ret); ++ return ret; ++}; ++ ++static struct of_device_id of_fsl_bman_ids[] = { ++ { ++ .compatible = "fsl,bman", ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, of_fsl_bman_ids); ++ ++#ifdef CONFIG_SUSPEND ++static u32 saved_isdr; ++ ++static int bman_pm_suspend_noirq(struct device *dev) ++{ ++ uint32_t idle_state; ++ ++ suspend_unused_bportal(); ++ /* save isdr, disable all, clear isr */ ++ saved_isdr = bm_err_isr_disable_read(bm); ++ bm_err_isr_disable_write(bm, 0xffffffff); ++ bm_err_isr_status_clear(bm, 0xffffffff); ++ ++ if (bman_ip_rev < BMAN_REV21) { ++#ifdef CONFIG_PM_DEBUG ++ pr_info("Bman version doesn't have STATE_IDLE\n"); ++#endif ++ return 0; ++ } ++ idle_state = bm_in(STATE_IDLE); ++ if (!(idle_state & 0x1)) { ++ pr_err("Bman not idle 0x%x aborting\n", idle_state); ++ bm_err_isr_disable_write(bm, saved_isdr); ++ resume_unused_bportal(); ++ return -EBUSY; ++ } ++#ifdef CONFIG_PM_DEBUG ++ pr_info("Bman suspend code, IDLE_STAT = 0x%x\n", idle_state); ++#endif ++ return 0; ++} ++ ++static int bman_pm_resume_noirq(struct device *dev) ++{ ++ /* restore isdr */ ++ bm_err_isr_disable_write(bm, saved_isdr); ++ resume_unused_bportal(); ++ return 0; ++} ++#else ++#define bman_pm_suspend_noirq NULL ++#define bman_pm_resume_noirq NULL ++#endif ++ ++static const struct dev_pm_ops bman_pm_ops = { ++ .suspend_noirq = bman_pm_suspend_noirq, ++ .resume_noirq = bman_pm_resume_noirq, ++}; ++ ++static struct platform_driver of_fsl_bman_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = DRV_NAME, ++ .of_match_table = of_fsl_bman_ids, ++ .pm = &bman_pm_ops, ++ }, ++ .probe = of_fsl_bman_probe, ++ .remove = of_fsl_bman_remove, ++}; ++ ++static int bman_ctrl_init(void) ++{ ++ return platform_driver_register(&of_fsl_bman_driver); ++} ++ ++static void bman_ctrl_exit(void) ++{ ++ platform_driver_unregister(&of_fsl_bman_driver); ++} ++ ++module_init(bman_ctrl_init); ++module_exit(bman_ctrl_exit); ++ ++#endif /* CONFIG_SYSFS */ +diff --git a/drivers/staging/fsl_qbman/bman_debugfs.c b/drivers/staging/fsl_qbman/bman_debugfs.c +new file mode 100644 +index 0000000..9690934 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_debugfs.c +@@ -0,0 +1,119 @@ ++/* Copyright 2010-2011 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 ++#include ++#include ++#include ++#include ++ ++static struct dentry *dfs_root; /* debugfs root directory */ ++ ++/******************************************************************************* ++ * Query Buffer Pool State ++ ******************************************************************************/ ++static int query_bp_state_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct bm_pool_state state; ++ int i, j; ++ u32 mask; ++ ++ memset(&state, 0, sizeof(struct bm_pool_state)); ++ ret = bman_query_pools(&state); ++ if (ret) { ++ seq_printf(file, "Error %d\n", ret); ++ return 0; ++ } ++ seq_puts(file, "bp_id free_buffers_avail bp_depleted\n"); ++ for (i = 0; i < 2; i++) { ++ mask = 0x80000000; ++ for (j = 0; j < 32; j++) { ++ seq_printf(file, ++ " %-2u %-3s %-3s\n", ++ (i*32)+j, ++ (state.as.state.__state[i] & mask) ? "no" : "yes", ++ (state.ds.state.__state[i] & mask) ? "yes" : "no"); ++ mask >>= 1; ++ } ++ } ++ return 0; ++} ++ ++static int query_bp_state_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, query_bp_state_show, NULL); ++} ++ ++static const struct file_operations query_bp_state_fops = { ++ .owner = THIS_MODULE, ++ .open = query_bp_state_open, ++ .read = seq_read, ++ .release = single_release, ++}; ++ ++static int __init bman_debugfs_module_init(void) ++{ ++ int ret = 0; ++ struct dentry *d; ++ ++ dfs_root = debugfs_create_dir("bman", NULL); ++ ++ if (dfs_root == NULL) { ++ ret = -ENOMEM; ++ pr_err("Cannot create bman debugfs dir\n"); ++ goto _return; ++ } ++ d = debugfs_create_file("query_bp_state", ++ S_IRUGO, ++ dfs_root, ++ NULL, ++ &query_bp_state_fops); ++ if (d == NULL) { ++ ret = -ENOMEM; ++ pr_err("Cannot create query_bp_state\n"); ++ goto _return; ++ } ++ return 0; ++ ++_return: ++ debugfs_remove_recursive(dfs_root); ++ return ret; ++} ++ ++static void __exit bman_debugfs_module_exit(void) ++{ ++ debugfs_remove_recursive(dfs_root); ++} ++ ++ ++module_init(bman_debugfs_module_init); ++module_exit(bman_debugfs_module_exit); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/staging/fsl_qbman/bman_driver.c b/drivers/staging/fsl_qbman/bman_driver.c +new file mode 100644 +index 0000000..980a7d3 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_driver.c +@@ -0,0 +1,556 @@ ++/* Copyright 2008-2012 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 "bman_private.h" ++#ifdef CONFIG_HOTPLUG_CPU ++#include ++#endif ++/* ++ * Global variables of the max portal/pool number this bman version supported ++ */ ++u16 bman_ip_rev; ++EXPORT_SYMBOL(bman_ip_rev); ++u16 bman_pool_max; ++EXPORT_SYMBOL(bman_pool_max); ++static u16 bman_portal_max; ++ ++/* After initialising cpus that own shared portal configs, we cache the ++ * resulting portals (ie. not just the configs) in this array. Then we ++ * initialise slave cpus that don't have their own portals, redirecting them to ++ * portals from this cache in a round-robin assignment. */ ++static struct bman_portal *shared_portals[NR_CPUS]; ++static int num_shared_portals; ++static int shared_portals_idx; ++static LIST_HEAD(unused_pcfgs); ++static DEFINE_SPINLOCK(unused_pcfgs_lock); ++static void *affine_bportals[NR_CPUS]; ++ ++static int __init fsl_bpool_init(struct device_node *node) ++{ ++ int ret; ++ u32 *thresh, *bpid = (u32 *)of_get_property(node, "fsl,bpid", &ret); ++ if (!bpid || (ret != 4)) { ++ pr_err("Can't get %s property 'fsl,bpid'\n", node->full_name); ++ return -ENODEV; ++ } ++ thresh = (u32 *)of_get_property(node, "fsl,bpool-thresholds", &ret); ++ if (thresh) { ++ if (ret != 16) { ++ pr_err("Invalid %s property '%s'\n", ++ node->full_name, "fsl,bpool-thresholds"); ++ return -ENODEV; ++ } ++ } ++ if (thresh) { ++#ifdef CONFIG_FSL_BMAN_CONFIG ++ ret = bm_pool_set(*bpid, thresh); ++ if (ret) ++ pr_err("No CCSR node for %s property '%s'\n", ++ node->full_name, "fsl,bpool-thresholds"); ++ return ret; ++#else ++ pr_err("Ignoring %s property '%s', no CCSR support\n", ++ node->full_name, "fsl,bpool-thresholds"); ++#endif ++ } ++ return 0; ++} ++ ++static int __init fsl_bpid_range_init(struct device_node *node) ++{ ++ int ret; ++ u32 *range = (u32 *)of_get_property(node, "fsl,bpid-range", &ret); ++ if (!range) { ++ pr_err("No 'fsl,bpid-range' property in node %s\n", ++ node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err("'fsl,bpid-range' is not a 2-cell range in node %s\n", ++ node->full_name); ++ return -EINVAL; ++ } ++ bman_seed_bpid_range(range[0], range[1]); ++ pr_info("Bman: BPID allocator includes range %d:%d\n", ++ range[0], range[1]); ++ return 0; ++} ++ ++static struct bm_portal_config * __init parse_pcfg(struct device_node *node) ++{ ++ struct bm_portal_config *pcfg; ++ const u32 *index; ++ int irq, ret; ++ resource_size_t len; ++ ++ pcfg = kmalloc(sizeof(*pcfg), GFP_KERNEL); ++ if (!pcfg) { ++ pr_err("can't allocate portal config"); ++ return NULL; ++ } ++ ++ if (of_device_is_compatible(node, "fsl,bman-portal-1.0") || ++ of_device_is_compatible(node, "fsl,bman-portal-1.0.0")) { ++ bman_ip_rev = BMAN_REV10; ++ bman_pool_max = 64; ++ bman_portal_max = 10; ++ } else if (of_device_is_compatible(node, "fsl,bman-portal-2.0") || ++ of_device_is_compatible(node, "fsl,bman-portal-2.0.8")) { ++ bman_ip_rev = BMAN_REV20; ++ bman_pool_max = 8; ++ bman_portal_max = 3; ++ } else if (of_device_is_compatible(node, "fsl,bman-portal-2.1.0")) { ++ bman_ip_rev = BMAN_REV21; ++ bman_pool_max = 64; ++ bman_portal_max = 50; ++ } else if (of_device_is_compatible(node, "fsl,bman-portal-2.1.1")) { ++ bman_ip_rev = BMAN_REV21; ++ bman_pool_max = 64; ++ bman_portal_max = 25; ++ } else if (of_device_is_compatible(node, "fsl,bman-portal-2.1.2")) { ++ bman_ip_rev = BMAN_REV21; ++ bman_pool_max = 64; ++ bman_portal_max = 18; ++ } else if (of_device_is_compatible(node, "fsl,bman-portal-2.1.3")) { ++ bman_ip_rev = BMAN_REV21; ++ bman_pool_max = 64; ++ bman_portal_max = 10; ++ } ++ ++ ret = of_address_to_resource(node, DPA_PORTAL_CE, ++ &pcfg->addr_phys[DPA_PORTAL_CE]); ++ if (ret) { ++ pr_err("Can't get %s property 'reg::CE'\n", node->full_name); ++ goto err; ++ } ++ ret = of_address_to_resource(node, DPA_PORTAL_CI, ++ &pcfg->addr_phys[DPA_PORTAL_CI]); ++ if (ret) { ++ pr_err("Can't get %s property 'reg::CI'\n", node->full_name); ++ goto err; ++ } ++ ++ index = of_get_property(node, "cell-index", &ret); ++ if (!index || (ret != 4)) { ++ pr_err("Can't get %s property '%s'\n", node->full_name, ++ "cell-index"); ++ goto err; ++ } ++ if (*index >= bman_portal_max) ++ goto err; ++ ++ pcfg->public_cfg.cpu = -1; ++ ++ irq = irq_of_parse_and_map(node, 0); ++ if (irq == NO_IRQ) { ++ pr_err("Can't get %s property 'interrupts'\n", node->full_name); ++ goto err; ++ } ++ pcfg->public_cfg.irq = irq; ++ pcfg->public_cfg.index = *index; ++ bman_depletion_fill(&pcfg->public_cfg.mask); ++ ++ len = resource_size(&pcfg->addr_phys[DPA_PORTAL_CE]); ++ if (len != (unsigned long)len) ++ goto err; ++ ++ pcfg->addr_virt[DPA_PORTAL_CE] = ioremap_prot( ++ pcfg->addr_phys[DPA_PORTAL_CE].start, ++ (unsigned long)len, ++ 0); ++ pcfg->addr_virt[DPA_PORTAL_CI] = ioremap_prot( ++ pcfg->addr_phys[DPA_PORTAL_CI].start, ++ resource_size(&pcfg->addr_phys[DPA_PORTAL_CI]), ++ _PAGE_GUARDED | _PAGE_NO_CACHE); ++ ++ /* disable bp depletion */ ++ __raw_writel(0x0, pcfg->addr_virt[DPA_PORTAL_CI] + 0x200); ++ __raw_writel(0x0, pcfg->addr_virt[DPA_PORTAL_CI] + 0x204); ++ return pcfg; ++err: ++ kfree(pcfg); ++ return NULL; ++} ++ ++static struct bm_portal_config *get_pcfg(struct list_head *list) ++{ ++ struct bm_portal_config *pcfg; ++ if (list_empty(list)) ++ return NULL; ++ pcfg = list_entry(list->prev, struct bm_portal_config, list); ++ list_del(&pcfg->list); ++ return pcfg; ++} ++ ++static struct bm_portal_config *get_pcfg_idx(struct list_head *list, ++ uint32_t idx) ++{ ++ struct bm_portal_config *pcfg; ++ if (list_empty(list)) ++ return NULL; ++ list_for_each_entry(pcfg, list, list) { ++ if (pcfg->public_cfg.index == idx) { ++ list_del(&pcfg->list); ++ return pcfg; ++ } ++ } ++ return NULL; ++} ++ ++struct bm_portal_config *bm_get_unused_portal(void) ++{ ++ return bm_get_unused_portal_idx(QBMAN_ANY_PORTAL_IDX); ++} ++ ++struct bm_portal_config *bm_get_unused_portal_idx(uint32_t idx) ++{ ++ struct bm_portal_config *ret; ++ spin_lock(&unused_pcfgs_lock); ++ if (idx == QBMAN_ANY_PORTAL_IDX) ++ ret = get_pcfg(&unused_pcfgs); ++ else ++ ret = get_pcfg_idx(&unused_pcfgs, idx); ++ spin_unlock(&unused_pcfgs_lock); ++ return ret; ++} ++ ++void bm_put_unused_portal(struct bm_portal_config *pcfg) ++{ ++ spin_lock(&unused_pcfgs_lock); ++ list_add(&pcfg->list, &unused_pcfgs); ++ spin_unlock(&unused_pcfgs_lock); ++} ++ ++static struct bman_portal *init_pcfg(struct bm_portal_config *pcfg) ++{ ++ struct bman_portal *p; ++ p = bman_create_affine_portal(pcfg); ++ if (p) { ++#ifdef CONFIG_FSL_DPA_PIRQ_SLOW ++ bman_p_irqsource_add(p, BM_PIRQ_RCRI | BM_PIRQ_BSCN); ++#endif ++ pr_info("Bman portal %sinitialised, cpu %d\n", ++ pcfg->public_cfg.is_shared ? "(shared) " : "", ++ pcfg->public_cfg.cpu); ++ affine_bportals[pcfg->public_cfg.cpu] = p; ++ } else ++ pr_crit("Bman portal failure on cpu %d\n", ++ pcfg->public_cfg.cpu); ++ return p; ++} ++ ++static void init_slave(int cpu) ++{ ++ struct bman_portal *p; ++ p = bman_create_affine_slave(shared_portals[shared_portals_idx++], cpu); ++ if (!p) ++ pr_err("Bman slave portal failure on cpu %d\n", cpu); ++ else ++ pr_info("Bman portal %sinitialised, cpu %d\n", "(slave) ", cpu); ++ if (shared_portals_idx >= num_shared_portals) ++ shared_portals_idx = 0; ++ affine_bportals[cpu] = p; ++} ++ ++/* Bootarg "bportals=[...]" has the same syntax as "qportals=", and so the ++ * parsing is in dpa_sys.h. The syntax is a comma-separated list of indexes ++ * and/or ranges of indexes, with each being optionally prefixed by "s" to ++ * explicitly mark it or them for sharing. ++ * Eg; ++ * bportals=s0,1-3,s4 ++ * means that cpus 1,2,3 get "unshared" portals, cpus 0 and 4 get "shared" ++ * portals, and any remaining cpus share the portals that are assigned to cpus 0 ++ * or 4, selected in a round-robin fashion. (In this example, cpu 5 would share ++ * cpu 0's portal, cpu 6 would share cpu4's portal, and cpu 7 would share cpu ++ * 0's portal.) */ ++static struct cpumask want_unshared __initdata; /* cpus requested without "s" */ ++static struct cpumask want_shared __initdata; /* cpus requested with "s" */ ++ ++static int __init parse_bportals(char *str) ++{ ++ return parse_portals_bootarg(str, &want_shared, &want_unshared, ++ "bportals"); ++} ++__setup("bportals=", parse_bportals); ++ ++static void bman_offline_cpu(unsigned int cpu) ++{ ++ struct bman_portal *p; ++ const struct bm_portal_config *pcfg; ++ p = (struct bman_portal *)affine_bportals[cpu]; ++ if (p) { ++ pcfg = bman_get_bm_portal_config(p); ++ if (pcfg) ++ irq_set_affinity(pcfg->public_cfg.irq, cpumask_of(0)); ++ } ++} ++ ++#ifdef CONFIG_HOTPLUG_CPU ++static void bman_online_cpu(unsigned int cpu) ++{ ++ struct bman_portal *p; ++ const struct bm_portal_config *pcfg; ++ p = (struct bman_portal *)affine_bportals[cpu]; ++ if (p) { ++ pcfg = bman_get_bm_portal_config(p); ++ if (pcfg) ++ irq_set_affinity(pcfg->public_cfg.irq, cpumask_of(cpu)); ++ } ++} ++ ++static int __cpuinit bman_hotplug_cpu_callback(struct notifier_block *nfb, ++ unsigned long action, void *hcpu) ++{ ++ unsigned int cpu = (unsigned long)hcpu; ++ ++ switch (action) { ++ case CPU_ONLINE: ++ case CPU_ONLINE_FROZEN: ++ bman_online_cpu(cpu); ++ break; ++ case CPU_DOWN_PREPARE: ++ case CPU_DOWN_PREPARE_FROZEN: ++ bman_offline_cpu(cpu); ++ default: ++ break; ++ } ++ return NOTIFY_OK; ++} ++ ++static struct notifier_block bman_hotplug_cpu_notifier = { ++ .notifier_call = bman_hotplug_cpu_callback, ++}; ++#endif /* CONFIG_HOTPLUG_CPU */ ++ ++/* Initialise the Bman driver. The meat of this function deals with portals. The ++ * following describes the flow of portal-handling, the code "steps" refer to ++ * this description; ++ * 1. Portal configs are parsed from the device-tree into 'unused_pcfgs', with ++ * ::cpu==-1. Regions and interrupts are mapped (but interrupts are not ++ * bound). ++ * 2. The "want_shared" and "want_unshared" lists (as filled by the ++ * "bportals=[...]" bootarg) are processed, allocating portals and assigning ++ * them to cpus, placing them in the relevant list and setting ::cpu as ++ * appropriate. If no "bportals" bootarg was present, the defaut is to try to ++ * assign portals to all online cpus at the time of driver initialisation. ++ * Any failure to allocate portals (when parsing the "want" lists or when ++ * using default behaviour) will be silently tolerated (the "fixup" logic in ++ * step 3 will determine what happens in this case). ++ * 3. Do fixups relative to cpu_online_mask(). If no portals are marked for ++ * sharing and sharing is required (because not all cpus have been assigned ++ * portals), then one portal will marked for sharing. Conversely if no ++ * sharing is required, any portals marked for sharing will not be shared. It ++ * may be that sharing occurs when it wasn't expected, if portal allocation ++ * failed to honour all the requested assignments (including the default ++ * assignments if no bootarg is present). ++ * 4. Unshared portals are initialised on their respective cpus. ++ * 5. Shared portals are initialised on their respective cpus. ++ * 6. Each remaining cpu is initialised to slave to one of the shared portals, ++ * which are selected in a round-robin fashion. ++ * Any portal configs left unused are available for USDPAA allocation. ++ */ ++__init int bman_init(void) ++{ ++ struct cpumask slave_cpus; ++ struct cpumask unshared_cpus = *cpu_none_mask; ++ struct cpumask shared_cpus = *cpu_none_mask; ++ LIST_HEAD(unshared_pcfgs); ++ LIST_HEAD(shared_pcfgs); ++ struct device_node *dn; ++ struct bm_portal_config *pcfg; ++ struct bman_portal *p; ++ int cpu, ret; ++ struct cpumask offline_cpus; ++ ++ /* Initialise the Bman (CCSR) device */ ++ for_each_compatible_node(dn, NULL, "fsl,bman") { ++ if (!bman_init_ccsr(dn)) ++ pr_info("Bman err interrupt handler present\n"); ++ else ++ pr_err("Bman CCSR setup failed\n"); ++ } ++ /* Initialise any declared buffer pools */ ++ for_each_compatible_node(dn, NULL, "fsl,bpool") { ++ ret = fsl_bpool_init(dn); ++ if (ret) ++ return ret; ++ } ++ /* Step 1. See comments at the beginning of the file. */ ++ for_each_compatible_node(dn, NULL, "fsl,bman-portal") { ++ if (!of_device_is_available(dn)) ++ continue; ++ pcfg = parse_pcfg(dn); ++ if (pcfg) ++ list_add_tail(&pcfg->list, &unused_pcfgs); ++ } ++ /* Step 2. */ ++ for_each_possible_cpu(cpu) { ++ if (cpumask_test_cpu(cpu, &want_shared)) { ++ pcfg = get_pcfg(&unused_pcfgs); ++ if (!pcfg) ++ break; ++ pcfg->public_cfg.cpu = cpu; ++ list_add_tail(&pcfg->list, &shared_pcfgs); ++ cpumask_set_cpu(cpu, &shared_cpus); ++ } ++ if (cpumask_test_cpu(cpu, &want_unshared)) { ++ if (cpumask_test_cpu(cpu, &shared_cpus)) ++ continue; ++ pcfg = get_pcfg(&unused_pcfgs); ++ if (!pcfg) ++ break; ++ pcfg->public_cfg.cpu = cpu; ++ list_add_tail(&pcfg->list, &unshared_pcfgs); ++ cpumask_set_cpu(cpu, &unshared_cpus); ++ } ++ } ++ if (list_empty(&shared_pcfgs) && list_empty(&unshared_pcfgs)) { ++ /* Default, give an unshared portal to each online cpu */ ++ for_each_possible_cpu(cpu) { ++ pcfg = get_pcfg(&unused_pcfgs); ++ if (!pcfg) ++ break; ++ pcfg->public_cfg.cpu = cpu; ++ list_add_tail(&pcfg->list, &unshared_pcfgs); ++ cpumask_set_cpu(cpu, &unshared_cpus); ++ } ++ } ++ /* Step 3. */ ++ cpumask_andnot(&slave_cpus, cpu_possible_mask, &shared_cpus); ++ cpumask_andnot(&slave_cpus, &slave_cpus, &unshared_cpus); ++ if (cpumask_empty(&slave_cpus)) { ++ /* No sharing required */ ++ if (!list_empty(&shared_pcfgs)) { ++ /* Migrate "shared" to "unshared" */ ++ cpumask_or(&unshared_cpus, &unshared_cpus, ++ &shared_cpus); ++ cpumask_clear(&shared_cpus); ++ list_splice_tail(&shared_pcfgs, &unshared_pcfgs); ++ INIT_LIST_HEAD(&shared_pcfgs); ++ } ++ } else { ++ /* Sharing required */ ++ if (list_empty(&shared_pcfgs)) { ++ /* Migrate one "unshared" to "shared" */ ++ pcfg = get_pcfg(&unshared_pcfgs); ++ if (!pcfg) { ++ pr_crit("No BMan portals available!\n"); ++ return 0; ++ } ++ cpumask_clear_cpu(pcfg->public_cfg.cpu, &unshared_cpus); ++ cpumask_set_cpu(pcfg->public_cfg.cpu, &shared_cpus); ++ list_add_tail(&pcfg->list, &shared_pcfgs); ++ } ++ } ++ /* Step 4. */ ++ list_for_each_entry(pcfg, &unshared_pcfgs, list) { ++ pcfg->public_cfg.is_shared = 0; ++ p = init_pcfg(pcfg); ++ if (!p) { ++ pr_crit("Unable to initialize bman portal\n"); ++ return 0; ++ } ++ } ++ /* Step 5. */ ++ list_for_each_entry(pcfg, &shared_pcfgs, list) { ++ pcfg->public_cfg.is_shared = 1; ++ p = init_pcfg(pcfg); ++ if (p) ++ shared_portals[num_shared_portals++] = p; ++ } ++ /* Step 6. */ ++ if (!cpumask_empty(&slave_cpus)) ++ for_each_cpu(cpu, &slave_cpus) ++ init_slave(cpu); ++ pr_info("Bman portals initialised\n"); ++ cpumask_andnot(&offline_cpus, cpu_possible_mask, cpu_online_mask); ++ for_each_cpu(cpu, &offline_cpus) ++ bman_offline_cpu(cpu); ++#ifdef CONFIG_HOTPLUG_CPU ++ register_hotcpu_notifier(&bman_hotplug_cpu_notifier); ++#endif ++ return 0; ++} ++ ++__init int bman_resource_init(void) ++{ ++ struct device_node *dn; ++ int ret; ++ ++ /* Initialise BPID allocation ranges */ ++ for_each_compatible_node(dn, NULL, "fsl,bpid-range") { ++ ret = fsl_bpid_range_init(dn); ++ if (ret) ++ return ret; ++ } ++ return 0; ++} ++ ++#ifdef CONFIG_SUSPEND ++void suspend_unused_bportal(void) ++{ ++ struct bm_portal_config *pcfg; ++ ++ if (list_empty(&unused_pcfgs)) ++ return; ++ ++ list_for_each_entry(pcfg, &unused_pcfgs, list) { ++#ifdef CONFIG_PM_DEBUG ++ pr_info("Need to save bportal %d\n", pcfg->public_cfg.index); ++#endif ++ /* save isdr, disable all via isdr, clear isr */ ++ pcfg->saved_isdr = ++ __raw_readl(pcfg->addr_virt[DPA_PORTAL_CI] + 0xe08); ++ __raw_writel(0xffffffff, pcfg->addr_virt[DPA_PORTAL_CI] + ++ 0xe08); ++ __raw_writel(0xffffffff, pcfg->addr_virt[DPA_PORTAL_CI] + ++ 0xe00); ++ } ++ return; ++} ++ ++void resume_unused_bportal(void) ++{ ++ struct bm_portal_config *pcfg; ++ ++ if (list_empty(&unused_pcfgs)) ++ return; ++ ++ list_for_each_entry(pcfg, &unused_pcfgs, list) { ++#ifdef CONFIG_PM_DEBUG ++ pr_info("Need to resume bportal %d\n", pcfg->public_cfg.index); ++#endif ++ /* restore isdr */ ++ __raw_writel(pcfg->saved_isdr, ++ pcfg->addr_virt[DPA_PORTAL_CI] + 0xe08); ++ } ++ return; ++} ++#endif +diff --git a/drivers/staging/fsl_qbman/bman_high.c b/drivers/staging/fsl_qbman/bman_high.c +new file mode 100644 +index 0000000..9986120 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_high.c +@@ -0,0 +1,1112 @@ ++/* Copyright 2008-2012 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 "bman_low.h" ++ ++/* Compilation constants */ ++#define RCR_THRESH 2 /* reread h/w CI when running out of space */ ++#define IRQNAME "BMan portal %d" ++#define MAX_IRQNAME 16 /* big enough for "BMan portal %d" */ ++ ++struct bman_portal { ++ struct bm_portal p; ++ /* 2-element array. pools[0] is mask, pools[1] is snapshot. */ ++ struct bman_depletion *pools; ++ int thresh_set; ++ unsigned long irq_sources; ++ u32 slowpoll; /* only used when interrupts are off */ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ struct bman_pool *rcri_owned; /* only 1 release WAIT_SYNC at a time */ ++#endif ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ raw_spinlock_t sharing_lock; /* only used if is_shared */ ++ int is_shared; ++ struct bman_portal *sharing_redirect; ++#endif ++ /* When the cpu-affine portal is activated, this is non-NULL */ ++ const struct bm_portal_config *config; ++ /* This is needed for power management */ ++ struct platform_device *pdev; ++ /* 64-entry hash-table of pool objects that are tracking depletion ++ * entry/exit (ie. BMAN_POOL_FLAG_DEPLETION). This isn't fast-path, so ++ * we're not fussy about cache-misses and so forth - whereas the above ++ * members should all fit in one cacheline. ++ * BTW, with 64 entries in the hash table and 64 buffer pools to track, ++ * you'll never guess the hash-function ... */ ++ struct bman_pool *cb[64]; ++ char irqname[MAX_IRQNAME]; ++ /* Track if the portal was alloced by the driver */ ++ u8 alloced; ++ /* power management data */ ++ u32 save_isdr; ++}; ++ ++/* For an explanation of the locking, redirection, or affine-portal logic, ++ * please consult the Qman driver for details. This is the same, only simpler ++ * (no fiddly Qman-specific bits.) */ ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++#define PORTAL_IRQ_LOCK(p, irqflags) \ ++ do { \ ++ if ((p)->is_shared) \ ++ raw_spin_lock_irqsave(&(p)->sharing_lock, irqflags); \ ++ else \ ++ local_irq_save(irqflags); \ ++ } while (0) ++#define PORTAL_IRQ_UNLOCK(p, irqflags) \ ++ do { \ ++ if ((p)->is_shared) \ ++ raw_spin_unlock_irqrestore(&(p)->sharing_lock, \ ++ irqflags); \ ++ else \ ++ local_irq_restore(irqflags); \ ++ } while (0) ++#else ++#define PORTAL_IRQ_LOCK(p, irqflags) local_irq_save(irqflags) ++#define PORTAL_IRQ_UNLOCK(p, irqflags) local_irq_restore(irqflags) ++#endif ++ ++static cpumask_t affine_mask; ++static DEFINE_SPINLOCK(affine_mask_lock); ++static DEFINE_PER_CPU(struct bman_portal, bman_affine_portal); ++static inline struct bman_portal *get_raw_affine_portal(void) ++{ ++ return &get_cpu_var(bman_affine_portal); ++} ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++static inline struct bman_portal *get_affine_portal(void) ++{ ++ struct bman_portal *p = get_raw_affine_portal(); ++ if (p->sharing_redirect) ++ return p->sharing_redirect; ++ return p; ++} ++#else ++#define get_affine_portal() get_raw_affine_portal() ++#endif ++static inline void put_affine_portal(void) ++{ ++ put_cpu_var(bman_affine_portal); ++} ++static inline struct bman_portal *get_poll_portal(void) ++{ ++ return &get_cpu_var(bman_affine_portal); ++} ++#define put_poll_portal() ++ ++/* GOTCHA: this object type refers to a pool, it isn't *the* pool. There may be ++ * more than one such object per Bman buffer pool, eg. if different users of the ++ * pool are operating via different portals. */ ++struct bman_pool { ++ struct bman_pool_params params; ++ /* Used for hash-table admin when using depletion notifications. */ ++ struct bman_portal *portal; ++ struct bman_pool *next; ++ /* stockpile state - NULL unless BMAN_POOL_FLAG_STOCKPILE is set */ ++ struct bm_buffer *sp; ++ unsigned int sp_fill; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ atomic_t in_use; ++#endif ++}; ++ ++/* (De)Registration of depletion notification callbacks */ ++static void depletion_link(struct bman_portal *portal, struct bman_pool *pool) ++{ ++ __maybe_unused unsigned long irqflags; ++ pool->portal = portal; ++ PORTAL_IRQ_LOCK(portal, irqflags); ++ pool->next = portal->cb[pool->params.bpid]; ++ portal->cb[pool->params.bpid] = pool; ++ if (!pool->next) ++ /* First object for that bpid on this portal, enable the BSCN ++ * mask bit. */ ++ bm_isr_bscn_mask(&portal->p, pool->params.bpid, 1); ++ PORTAL_IRQ_UNLOCK(portal, irqflags); ++} ++static void depletion_unlink(struct bman_pool *pool) ++{ ++ struct bman_pool *it, *last = NULL; ++ struct bman_pool **base = &pool->portal->cb[pool->params.bpid]; ++ __maybe_unused unsigned long irqflags; ++ PORTAL_IRQ_LOCK(pool->portal, irqflags); ++ it = *base; /* <-- gotcha, don't do this prior to the irq_save */ ++ while (it != pool) { ++ last = it; ++ it = it->next; ++ } ++ if (!last) ++ *base = pool->next; ++ else ++ last->next = pool->next; ++ if (!last && !pool->next) { ++ /* Last object for that bpid on this portal, disable the BSCN ++ * mask bit. */ ++ bm_isr_bscn_mask(&pool->portal->p, pool->params.bpid, 0); ++ /* And "forget" that we last saw this pool as depleted */ ++ bman_depletion_unset(&pool->portal->pools[1], ++ pool->params.bpid); ++ } ++ PORTAL_IRQ_UNLOCK(pool->portal, irqflags); ++} ++ ++/* In the case that the application's core loop calls qman_poll() and ++ * bman_poll(), we ought to balance how often we incur the overheads of the ++ * slow-path poll. We'll use two decrementer sources. The idle decrementer ++ * constant is used when the last slow-poll detected no work to do, and the busy ++ * decrementer constant when the last slow-poll had work to do. */ ++#define SLOW_POLL_IDLE 1000 ++#define SLOW_POLL_BUSY 10 ++static u32 __poll_portal_slow(struct bman_portal *p, u32 is); ++ ++/* Portal interrupt handler */ ++static irqreturn_t portal_isr(__always_unused int irq, void *ptr) ++{ ++ struct bman_portal *p = ptr; ++ u32 clear = p->irq_sources; ++ u32 is = bm_isr_status_read(&p->p) & p->irq_sources; ++ clear |= __poll_portal_slow(p, is); ++ bm_isr_status_clear(&p->p, clear); ++ return IRQ_HANDLED; ++} ++ ++#ifdef CONFIG_SUSPEND ++static int _bman_portal_suspend_noirq(struct device *dev) ++{ ++ struct bman_portal *p = (struct bman_portal *)dev->platform_data; ++#ifdef CONFIG_PM_DEBUG ++ struct platform_device *pdev = to_platform_device(dev); ++#endif ++ p->save_isdr = bm_isr_disable_read(&p->p); ++ bm_isr_disable_write(&p->p, 0xffffffff); ++ bm_isr_status_clear(&p->p, 0xffffffff); ++#ifdef CONFIG_PM_DEBUG ++ pr_info("Suspend for %s\n", pdev->name); ++#endif ++ return 0; ++} ++ ++static int _bman_portal_resume_noirq(struct device *dev) ++{ ++ struct bman_portal *p = (struct bman_portal *)dev->platform_data; ++ ++ /* restore isdr */ ++ bm_isr_disable_write(&p->p, p->save_isdr); ++ return 0; ++} ++#else ++#define _bman_portal_suspend_noirq NULL ++#define _bman_portal_resume_noirq NULL ++#endif ++ ++struct dev_pm_domain bman_portal_device_pm_domain = { ++ .ops = { ++ USE_PLATFORM_PM_SLEEP_OPS ++ .suspend_noirq = _bman_portal_suspend_noirq, ++ .resume_noirq = _bman_portal_resume_noirq, ++ } ++}; ++ ++struct bman_portal *bman_create_portal( ++ struct bman_portal *portal, ++ const struct bm_portal_config *config) ++{ ++ struct bm_portal *__p; ++ const struct bman_depletion *pools = &config->public_cfg.mask; ++ int ret; ++ u8 bpid = 0; ++ char buf[16]; ++ ++ if (!portal) { ++ portal = kmalloc(sizeof(*portal), GFP_KERNEL); ++ if (!portal) ++ return portal; ++ portal->alloced = 1; ++ } else ++ portal->alloced = 0; ++ ++ __p = &portal->p; ++ ++ /* prep the low-level portal struct with the mapped addresses from the ++ * config, everything that follows depends on it and "config" is more ++ * for (de)reference... */ ++ __p->addr.addr_ce = config->addr_virt[DPA_PORTAL_CE]; ++ __p->addr.addr_ci = config->addr_virt[DPA_PORTAL_CI]; ++ if (bm_rcr_init(__p, bm_rcr_pvb, bm_rcr_cce)) { ++ pr_err("Bman RCR initialisation failed\n"); ++ goto fail_rcr; ++ } ++ if (bm_mc_init(__p)) { ++ pr_err("Bman MC initialisation failed\n"); ++ goto fail_mc; ++ } ++ if (bm_isr_init(__p)) { ++ pr_err("Bman ISR initialisation failed\n"); ++ goto fail_isr; ++ } ++ portal->pools = kmalloc(2 * sizeof(*pools), GFP_KERNEL); ++ if (!portal->pools) ++ goto fail_pools; ++ portal->pools[0] = *pools; ++ bman_depletion_init(portal->pools + 1); ++ while (bpid < bman_pool_max) { ++ /* Default to all BPIDs disabled, we enable as required at ++ * run-time. */ ++ bm_isr_bscn_mask(__p, bpid, 0); ++ bpid++; ++ } ++ portal->slowpoll = 0; ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ portal->rcri_owned = NULL; ++#endif ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ raw_spin_lock_init(&portal->sharing_lock); ++ portal->is_shared = config->public_cfg.is_shared; ++ portal->sharing_redirect = NULL; ++#endif ++ sprintf(buf, "bportal-%u", config->public_cfg.index); ++ portal->pdev = platform_device_alloc(buf, -1); ++ if (!portal->pdev) ++ goto fail_devalloc; ++ portal->pdev->dev.pm_domain = &bman_portal_device_pm_domain; ++ portal->pdev->dev.platform_data = portal; ++ ret = platform_device_add(portal->pdev); ++ if (ret) ++ goto fail_devadd; ++ memset(&portal->cb, 0, sizeof(portal->cb)); ++ /* Write-to-clear any stale interrupt status bits */ ++ bm_isr_disable_write(__p, 0xffffffff); ++ portal->irq_sources = 0; ++ bm_isr_enable_write(__p, portal->irq_sources); ++ bm_isr_status_clear(__p, 0xffffffff); ++ snprintf(portal->irqname, MAX_IRQNAME, IRQNAME, config->public_cfg.cpu); ++ if (request_irq(config->public_cfg.irq, portal_isr, 0, portal->irqname, ++ portal)) { ++ pr_err("request_irq() failed\n"); ++ goto fail_irq; ++ } ++ if ((config->public_cfg.cpu != -1) && ++ irq_can_set_affinity(config->public_cfg.irq) && ++ irq_set_affinity(config->public_cfg.irq, ++ cpumask_of(config->public_cfg.cpu))) { ++ pr_err("irq_set_affinity() failed\n"); ++ goto fail_affinity; ++ } ++ ++ /* Need RCR to be empty before continuing */ ++ ret = bm_rcr_get_fill(__p); ++ if (ret) { ++ pr_err("Bman RCR unclean\n"); ++ goto fail_rcr_empty; ++ } ++ /* Success */ ++ portal->config = config; ++ ++ bm_isr_disable_write(__p, 0); ++ bm_isr_uninhibit(__p); ++ return portal; ++fail_rcr_empty: ++fail_affinity: ++ free_irq(config->public_cfg.irq, portal); ++fail_irq: ++ platform_device_del(portal->pdev); ++fail_devadd: ++ platform_device_put(portal->pdev); ++fail_devalloc: ++ kfree(portal->pools); ++fail_pools: ++ bm_isr_finish(__p); ++fail_isr: ++ bm_mc_finish(__p); ++fail_mc: ++ bm_rcr_finish(__p); ++fail_rcr: ++ if (portal->alloced) ++ kfree(portal); ++ return NULL; ++} ++ ++struct bman_portal *bman_create_affine_portal( ++ const struct bm_portal_config *config) ++{ ++ struct bman_portal *portal; ++ ++ portal = &per_cpu(bman_affine_portal, config->public_cfg.cpu); ++ portal = bman_create_portal(portal, config); ++ if (portal) { ++ spin_lock(&affine_mask_lock); ++ cpumask_set_cpu(config->public_cfg.cpu, &affine_mask); ++ spin_unlock(&affine_mask_lock); ++ } ++ return portal; ++} ++ ++ ++struct bman_portal *bman_create_affine_slave(struct bman_portal *redirect, ++ int cpu) ++{ ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ struct bman_portal *p; ++ p = &per_cpu(bman_affine_portal, cpu); ++ BUG_ON(p->config); ++ BUG_ON(p->is_shared); ++ BUG_ON(!redirect->config->public_cfg.is_shared); ++ p->irq_sources = 0; ++ p->sharing_redirect = redirect; ++ return p; ++#else ++ BUG(); ++ return NULL; ++#endif ++} ++ ++void bman_destroy_portal(struct bman_portal *bm) ++{ ++ const struct bm_portal_config *pcfg; ++ pcfg = bm->config; ++ bm_rcr_cce_update(&bm->p); ++ bm_rcr_cce_update(&bm->p); ++ ++ free_irq(pcfg->public_cfg.irq, bm); ++ ++ kfree(bm->pools); ++ bm_isr_finish(&bm->p); ++ bm_mc_finish(&bm->p); ++ bm_rcr_finish(&bm->p); ++ bm->config = NULL; ++ if (bm->alloced) ++ kfree(bm); ++} ++ ++const struct bm_portal_config *bman_destroy_affine_portal(void) ++{ ++ struct bman_portal *bm = get_raw_affine_portal(); ++ const struct bm_portal_config *pcfg; ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (bm->sharing_redirect) { ++ bm->sharing_redirect = NULL; ++ put_affine_portal(); ++ return NULL; ++ } ++ bm->is_shared = 0; ++#endif ++ pcfg = bm->config; ++ bman_destroy_portal(bm); ++ spin_lock(&affine_mask_lock); ++ cpumask_clear_cpu(pcfg->public_cfg.cpu, &affine_mask); ++ spin_unlock(&affine_mask_lock); ++ put_affine_portal(); ++ return pcfg; ++} ++ ++/* When release logic waits on available RCR space, we need a global waitqueue ++ * in the case of "affine" use (as the waits wake on different cpus which means ++ * different portals - so we can't wait on any per-portal waitqueue). */ ++static DECLARE_WAIT_QUEUE_HEAD(affine_queue); ++ ++static u32 __poll_portal_slow(struct bman_portal *p, u32 is) ++{ ++ struct bman_depletion tmp; ++ u32 ret = is; ++ ++ /* There is a gotcha to be aware of. If we do the query before clearing ++ * the status register, we may miss state changes that occur between the ++ * two. If we write to clear the status register before the query, the ++ * cache-enabled query command may overtake the status register write ++ * unless we use a heavyweight sync (which we don't want). Instead, we ++ * write-to-clear the status register then *read it back* before doing ++ * the query, hence the odd while loop with the 'is' accumulation. */ ++ if (is & BM_PIRQ_BSCN) { ++ struct bm_mc_result *mcr; ++ __maybe_unused unsigned long irqflags; ++ unsigned int i, j; ++ u32 __is; ++ bm_isr_status_clear(&p->p, BM_PIRQ_BSCN); ++ while ((__is = bm_isr_status_read(&p->p)) & BM_PIRQ_BSCN) { ++ is |= __is; ++ bm_isr_status_clear(&p->p, BM_PIRQ_BSCN); ++ } ++ is &= ~BM_PIRQ_BSCN; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ bm_mc_start(&p->p); ++ bm_mc_commit(&p->p, BM_MCC_VERB_CMD_QUERY); ++ while (!(mcr = bm_mc_result(&p->p))) ++ cpu_relax(); ++ tmp = mcr->query.ds.state; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ for (i = 0; i < 2; i++) { ++ int idx = i * 32; ++ /* tmp is a mask of currently-depleted pools. ++ * pools[0] is mask of those we care about. ++ * pools[1] is our previous view (we only want to ++ * be told about changes). */ ++ tmp.__state[i] &= p->pools[0].__state[i]; ++ if (tmp.__state[i] == p->pools[1].__state[i]) ++ /* fast-path, nothing to see, move along */ ++ continue; ++ for (j = 0; j <= 31; j++, idx++) { ++ struct bman_pool *pool = p->cb[idx]; ++ int b4 = bman_depletion_get(&p->pools[1], idx); ++ int af = bman_depletion_get(&tmp, idx); ++ if (b4 == af) ++ continue; ++ while (pool) { ++ pool->params.cb(p, pool, ++ pool->params.cb_ctx, af); ++ pool = pool->next; ++ } ++ } ++ } ++ p->pools[1] = tmp; ++ } ++ ++ if (is & BM_PIRQ_RCRI) { ++ __maybe_unused unsigned long irqflags; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ bm_rcr_cce_update(&p->p); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ /* If waiting for sync, we only cancel the interrupt threshold ++ * when the ring utilisation hits zero. */ ++ if (p->rcri_owned) { ++ if (!bm_rcr_get_fill(&p->p)) { ++ p->rcri_owned = NULL; ++ bm_rcr_set_ithresh(&p->p, 0); ++ } ++ } else ++#endif ++ bm_rcr_set_ithresh(&p->p, 0); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ wake_up(&affine_queue); ++ bm_isr_status_clear(&p->p, BM_PIRQ_RCRI); ++ is &= ~BM_PIRQ_RCRI; ++ } ++ ++ /* There should be no status register bits left undefined */ ++ DPA_ASSERT(!is); ++ return ret; ++} ++ ++const struct bman_portal_config *bman_get_portal_config(void) ++{ ++ struct bman_portal *p = get_affine_portal(); ++ const struct bman_portal_config *ret = &p->config->public_cfg; ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(bman_get_portal_config); ++ ++u32 bman_irqsource_get(void) ++{ ++ struct bman_portal *p = get_raw_affine_portal(); ++ u32 ret = p->irq_sources & BM_PIRQ_VISIBLE; ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(bman_irqsource_get); ++ ++int bman_p_irqsource_add(struct bman_portal *p, __maybe_unused u32 bits) ++{ ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (p->sharing_redirect) ++ return -EINVAL; ++ else ++#endif ++ { ++ __maybe_unused unsigned long irqflags; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ set_bits(bits & BM_PIRQ_VISIBLE, &p->irq_sources); ++ bm_isr_enable_write(&p->p, p->irq_sources); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ } ++ return 0; ++} ++EXPORT_SYMBOL(bman_p_irqsource_add); ++ ++int bman_irqsource_add(__maybe_unused u32 bits) ++{ ++ struct bman_portal *p = get_raw_affine_portal(); ++ int ret = 0; ++ ret = bman_p_irqsource_add(p, bits); ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(bman_irqsource_add); ++ ++int bman_irqsource_remove(u32 bits) ++{ ++ struct bman_portal *p = get_raw_affine_portal(); ++ __maybe_unused unsigned long irqflags; ++ u32 ier; ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (p->sharing_redirect) { ++ put_affine_portal(); ++ return -EINVAL; ++ } ++#endif ++ /* Our interrupt handler only processes+clears status register bits that ++ * are in p->irq_sources. As we're trimming that mask, if one of them ++ * were to assert in the status register just before we remove it from ++ * the enable register, there would be an interrupt-storm when we ++ * release the IRQ lock. So we wait for the enable register update to ++ * take effect in h/w (by reading it back) and then clear all other bits ++ * in the status register. Ie. we clear them from ISR once it's certain ++ * IER won't allow them to reassert. */ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ bits &= BM_PIRQ_VISIBLE; ++ clear_bits(bits, &p->irq_sources); ++ bm_isr_enable_write(&p->p, p->irq_sources); ++ ier = bm_isr_enable_read(&p->p); ++ /* Using "~ier" (rather than "bits" or "~p->irq_sources") creates a ++ * data-dependency, ie. to protect against re-ordering. */ ++ bm_isr_status_clear(&p->p, ~ier); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return 0; ++} ++EXPORT_SYMBOL(bman_irqsource_remove); ++ ++const cpumask_t *bman_affine_cpus(void) ++{ ++ return &affine_mask; ++} ++EXPORT_SYMBOL(bman_affine_cpus); ++ ++u32 bman_poll_slow(void) ++{ ++ struct bman_portal *p = get_poll_portal(); ++ u32 ret; ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (unlikely(p->sharing_redirect)) ++ ret = (u32)-1; ++ else ++#endif ++ { ++ u32 is = bm_isr_status_read(&p->p) & ~p->irq_sources; ++ ret = __poll_portal_slow(p, is); ++ bm_isr_status_clear(&p->p, ret); ++ } ++ put_poll_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(bman_poll_slow); ++ ++/* Legacy wrapper */ ++void bman_poll(void) ++{ ++ struct bman_portal *p = get_poll_portal(); ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (unlikely(p->sharing_redirect)) ++ goto done; ++#endif ++ if (!(p->slowpoll--)) { ++ u32 is = bm_isr_status_read(&p->p) & ~p->irq_sources; ++ u32 active = __poll_portal_slow(p, is); ++ if (active) ++ p->slowpoll = SLOW_POLL_BUSY; ++ else ++ p->slowpoll = SLOW_POLL_IDLE; ++ } ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++done: ++#endif ++ put_poll_portal(); ++} ++EXPORT_SYMBOL(bman_poll); ++ ++static const u32 zero_thresholds[4] = {0, 0, 0, 0}; ++ ++struct bman_pool *bman_new_pool(const struct bman_pool_params *params) ++{ ++ struct bman_pool *pool = NULL; ++ u32 bpid; ++ ++ if (params->flags & BMAN_POOL_FLAG_DYNAMIC_BPID) { ++ int ret = bman_alloc_bpid(&bpid); ++ if (ret) ++ return NULL; ++ } else { ++ if (params->bpid >= bman_pool_max) ++ return NULL; ++ bpid = params->bpid; ++ } ++#ifdef CONFIG_FSL_BMAN_CONFIG ++ if (params->flags & BMAN_POOL_FLAG_THRESH) { ++ int ret = bm_pool_set(bpid, params->thresholds); ++ if (ret) ++ goto err; ++ } ++#else ++ if (params->flags & BMAN_POOL_FLAG_THRESH) ++ goto err; ++#endif ++ pool = kmalloc(sizeof(*pool), GFP_KERNEL); ++ if (!pool) ++ goto err; ++ pool->sp = NULL; ++ pool->sp_fill = 0; ++ pool->params = *params; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ atomic_set(&pool->in_use, 1); ++#endif ++ if (params->flags & BMAN_POOL_FLAG_DYNAMIC_BPID) ++ pool->params.bpid = bpid; ++ if (params->flags & BMAN_POOL_FLAG_STOCKPILE) { ++ pool->sp = kmalloc(sizeof(struct bm_buffer) * BMAN_STOCKPILE_SZ, ++ GFP_KERNEL); ++ if (!pool->sp) ++ goto err; ++ } ++ if (pool->params.flags & BMAN_POOL_FLAG_DEPLETION) { ++ struct bman_portal *p = get_affine_portal(); ++ if (!p->pools || !bman_depletion_get(&p->pools[0], bpid)) { ++ pr_err("Depletion events disabled for bpid %d\n", bpid); ++ goto err; ++ } ++ depletion_link(p, pool); ++ put_affine_portal(); ++ } ++ return pool; ++err: ++#ifdef CONFIG_FSL_BMAN_CONFIG ++ if (params->flags & BMAN_POOL_FLAG_THRESH) ++ bm_pool_set(bpid, zero_thresholds); ++#endif ++ if (params->flags & BMAN_POOL_FLAG_DYNAMIC_BPID) ++ bman_release_bpid(bpid); ++ if (pool) { ++ kfree(pool->sp); ++ kfree(pool); ++ } ++ return NULL; ++} ++EXPORT_SYMBOL(bman_new_pool); ++ ++void bman_free_pool(struct bman_pool *pool) ++{ ++#ifdef CONFIG_FSL_BMAN_CONFIG ++ if (pool->params.flags & BMAN_POOL_FLAG_THRESH) ++ bm_pool_set(pool->params.bpid, zero_thresholds); ++#endif ++ if (pool->params.flags & BMAN_POOL_FLAG_DEPLETION) ++ depletion_unlink(pool); ++ if (pool->params.flags & BMAN_POOL_FLAG_STOCKPILE) { ++ if (pool->sp_fill) ++ pr_err("Stockpile not flushed, has %u in bpid %u.\n", ++ pool->sp_fill, pool->params.bpid); ++ kfree(pool->sp); ++ pool->sp = NULL; ++ pool->params.flags ^= BMAN_POOL_FLAG_STOCKPILE; ++ } ++ if (pool->params.flags & BMAN_POOL_FLAG_DYNAMIC_BPID) ++ bman_release_bpid(pool->params.bpid); ++ kfree(pool); ++} ++EXPORT_SYMBOL(bman_free_pool); ++ ++const struct bman_pool_params *bman_get_params(const struct bman_pool *pool) ++{ ++ return &pool->params; ++} ++EXPORT_SYMBOL(bman_get_params); ++ ++static noinline void update_rcr_ci(struct bman_portal *p, u8 avail) ++{ ++ if (avail) ++ bm_rcr_cce_prefetch(&p->p); ++ else ++ bm_rcr_cce_update(&p->p); ++} ++ ++int bman_rcr_is_empty(void) ++{ ++ __maybe_unused unsigned long irqflags; ++ struct bman_portal *p = get_affine_portal(); ++ u8 avail; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ update_rcr_ci(p, 0); ++ avail = bm_rcr_get_fill(&p->p); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return avail == 0; ++} ++EXPORT_SYMBOL(bman_rcr_is_empty); ++ ++static inline struct bm_rcr_entry *try_rel_start(struct bman_portal **p, ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ __maybe_unused struct bman_pool *pool, ++#endif ++ __maybe_unused unsigned long *irqflags, ++ __maybe_unused u32 flags) ++{ ++ struct bm_rcr_entry *r; ++ u8 avail; ++ ++ *p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(*p, (*irqflags)); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & BMAN_RELEASE_FLAG_WAIT) && ++ (flags & BMAN_RELEASE_FLAG_WAIT_SYNC))) { ++ if ((*p)->rcri_owned) { ++ PORTAL_IRQ_UNLOCK(*p, (*irqflags)); ++ put_affine_portal(); ++ return NULL; ++ } ++ (*p)->rcri_owned = pool; ++ } ++#endif ++ avail = bm_rcr_get_avail(&(*p)->p); ++ if (avail < 2) ++ update_rcr_ci(*p, avail); ++ r = bm_rcr_start(&(*p)->p); ++ if (unlikely(!r)) { ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & BMAN_RELEASE_FLAG_WAIT) && ++ (flags & BMAN_RELEASE_FLAG_WAIT_SYNC))) ++ (*p)->rcri_owned = NULL; ++#endif ++ PORTAL_IRQ_UNLOCK(*p, (*irqflags)); ++ put_affine_portal(); ++ } ++ return r; ++} ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++static noinline struct bm_rcr_entry *__wait_rel_start(struct bman_portal **p, ++ struct bman_pool *pool, ++ __maybe_unused unsigned long *irqflags, ++ u32 flags) ++{ ++ struct bm_rcr_entry *rcr = try_rel_start(p, pool, irqflags, flags); ++ if (!rcr) ++ bm_rcr_set_ithresh(&(*p)->p, 1); ++ return rcr; ++} ++ ++static noinline struct bm_rcr_entry *wait_rel_start(struct bman_portal **p, ++ struct bman_pool *pool, ++ __maybe_unused unsigned long *irqflags, ++ u32 flags) ++{ ++ struct bm_rcr_entry *rcr; ++#ifndef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ pool = NULL; ++#endif ++ if (flags & BMAN_RELEASE_FLAG_WAIT_INT) ++ /* NB: return NULL if signal occurs before completion. Signal ++ * can occur during return. Caller must check for signal */ ++ wait_event_interruptible(affine_queue, ++ (rcr = __wait_rel_start(p, pool, irqflags, flags))); ++ else ++ wait_event(affine_queue, ++ (rcr = __wait_rel_start(p, pool, irqflags, flags))); ++ return rcr; ++} ++#endif ++ ++/* to facilitate better copying of bufs into the ring without either (a) copying ++ * noise into the first byte (prematurely triggering the command), nor (b) being ++ * very inefficient by copying small fields using read-modify-write */ ++struct overlay_bm_buffer { ++ u32 first; ++ u32 second; ++}; ++ ++static inline int __bman_release(struct bman_pool *pool, ++ const struct bm_buffer *bufs, u8 num, u32 flags) ++{ ++ struct bman_portal *p; ++ struct bm_rcr_entry *r; ++ struct overlay_bm_buffer *o_dest; ++ struct overlay_bm_buffer *o_src = (struct overlay_bm_buffer *)&bufs[0]; ++ __maybe_unused unsigned long irqflags; ++ u32 i = num - 1; ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & BMAN_RELEASE_FLAG_WAIT) ++ r = wait_rel_start(&p, pool, &irqflags, flags); ++ else ++ r = try_rel_start(&p, pool, &irqflags, flags); ++#else ++ r = try_rel_start(&p, &irqflags, flags); ++#endif ++ if (!r) ++ return -EBUSY; ++ /* We can copy all but the first entry, as this can trigger badness ++ * with the valid-bit. Use the overlay to mask the verb byte. */ ++ o_dest = (struct overlay_bm_buffer *)&r->bufs[0]; ++ o_dest->first = (o_src->first & 0x0000ffff) | ++ (((u32)pool->params.bpid << 16) & 0x00ff0000); ++ o_dest->second = o_src->second; ++ if (i) ++ copy_words(&r->bufs[1], &bufs[1], i * sizeof(bufs[0])); ++ bm_rcr_pvb_commit(&p->p, BM_RCR_VERB_CMD_BPID_SINGLE | ++ (num & BM_RCR_VERB_BUFCOUNT_MASK)); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ /* if we wish to sync we need to set the threshold after h/w sees the ++ * new ring entry. As we're mixing cache-enabled and cache-inhibited ++ * accesses, this requires a heavy-weight sync. */ ++ if (unlikely((flags & BMAN_RELEASE_FLAG_WAIT) && ++ (flags & BMAN_RELEASE_FLAG_WAIT_SYNC))) { ++ hwsync(); ++ bm_rcr_set_ithresh(&p->p, 1); ++ } ++#endif ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & BMAN_RELEASE_FLAG_WAIT) && ++ (flags & BMAN_RELEASE_FLAG_WAIT_SYNC))) { ++ if (flags & BMAN_RELEASE_FLAG_WAIT_INT) ++ /* NB: return success even if signal occurs before ++ * condition is true. pvb_commit guarantees success */ ++ wait_event_interruptible(affine_queue, ++ (p->rcri_owned != pool)); ++ else ++ wait_event(affine_queue, (p->rcri_owned != pool)); ++ } ++#endif ++ return 0; ++} ++ ++int bman_release(struct bman_pool *pool, const struct bm_buffer *bufs, u8 num, ++ u32 flags) ++{ ++ int ret = 0; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (!num || (num > 8)) ++ return -EINVAL; ++ if (pool->params.flags & BMAN_POOL_FLAG_NO_RELEASE) ++ return -EINVAL; ++#endif ++ /* Without stockpile, this API is a pass-through to the h/w operation */ ++ if (!(pool->params.flags & BMAN_POOL_FLAG_STOCKPILE)) ++ return __bman_release(pool, bufs, num, flags); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (!atomic_dec_and_test(&pool->in_use)) { ++ pr_crit("Parallel attempts to enter bman_released() detected."); ++ panic("only one instance of bman_released/acquired allowed"); ++ } ++#endif ++ /* This needs some explanation. Adding the given buffers may take the ++ * stockpile over the threshold, but in fact the stockpile may already ++ * *be* over the threshold if a previous release-to-hw attempt had ++ * failed. So we have 3 cases to cover; ++ * 1. we add to the stockpile and don't hit the threshold, ++ * 2. we add to the stockpile, hit the threshold and release-to-hw, ++ * 3. we have to release-to-hw before adding to the stockpile ++ * (not enough room in the stockpile for case 2). ++ * Our constraints on thresholds guarantee that in case 3, there must be ++ * at least 8 bufs already in the stockpile, so all release-to-hw ops ++ * are for 8 bufs. Despite all this, the API must indicate whether the ++ * given buffers were taken off the caller's hands, irrespective of ++ * whether a release-to-hw was attempted. */ ++ while (num) { ++ /* Add buffers to stockpile if they fit */ ++ if ((pool->sp_fill + num) < BMAN_STOCKPILE_SZ) { ++ copy_words(pool->sp + pool->sp_fill, bufs, ++ sizeof(struct bm_buffer) * num); ++ pool->sp_fill += num; ++ num = 0; /* --> will return success no matter what */ ++ } ++ /* Do hw op if hitting the high-water threshold */ ++ if ((pool->sp_fill + num) >= BMAN_STOCKPILE_HIGH) { ++ ret = __bman_release(pool, ++ pool->sp + (pool->sp_fill - 8), 8, flags); ++ if (ret) { ++ ret = (num ? ret : 0); ++ goto release_done; ++ } ++ pool->sp_fill -= 8; ++ } ++ } ++release_done: ++#ifdef CONFIG_FSL_DPA_CHECKING ++ atomic_inc(&pool->in_use); ++#endif ++ return ret; ++} ++EXPORT_SYMBOL(bman_release); ++ ++static inline int __bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, ++ u8 num) ++{ ++ struct bman_portal *p = get_affine_portal(); ++ struct bm_mc_command *mcc; ++ struct bm_mc_result *mcr; ++ __maybe_unused unsigned long irqflags; ++ int ret; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ mcc = bm_mc_start(&p->p); ++ mcc->acquire.bpid = pool->params.bpid; ++ bm_mc_commit(&p->p, BM_MCC_VERB_CMD_ACQUIRE | ++ (num & BM_MCC_VERB_ACQUIRE_BUFCOUNT)); ++ while (!(mcr = bm_mc_result(&p->p))) ++ cpu_relax(); ++ ret = mcr->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT; ++ if (bufs) ++ copy_words(&bufs[0], &mcr->acquire.bufs[0], ++ num * sizeof(bufs[0])); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (ret != num) ++ ret = -ENOMEM; ++ return ret; ++} ++ ++int bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, u8 num, ++ u32 flags) ++{ ++ int ret = 0; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (!num || (num > 8)) ++ return -EINVAL; ++ if (pool->params.flags & BMAN_POOL_FLAG_ONLY_RELEASE) ++ return -EINVAL; ++#endif ++ /* Without stockpile, this API is a pass-through to the h/w operation */ ++ if (!(pool->params.flags & BMAN_POOL_FLAG_STOCKPILE)) ++ return __bman_acquire(pool, bufs, num); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (!atomic_dec_and_test(&pool->in_use)) { ++ pr_crit("Parallel attempts to enter bman_acquire() detected."); ++ panic("only one instance of bman_released/acquired allowed"); ++ } ++#endif ++ /* Only need a h/w op if we'll hit the low-water thresh */ ++ if (!(flags & BMAN_ACQUIRE_FLAG_STOCKPILE) && ++ (pool->sp_fill <= (BMAN_STOCKPILE_LOW + num))) { ++ /* refill stockpile with max amount, but if max amount ++ * isn't available, try amount the user wants */ ++ int bufcount = 8; ++ ret = __bman_acquire(pool, pool->sp + pool->sp_fill, bufcount); ++ if (ret < 0 && bufcount != num) { ++ bufcount = num; ++ /* Maybe buffer pool has less than 8 */ ++ ret = __bman_acquire(pool, pool->sp + pool->sp_fill, ++ bufcount); ++ } ++ if (ret < 0) ++ goto hw_starved; ++ DPA_ASSERT(ret == bufcount); ++ pool->sp_fill += bufcount; ++ } else { ++hw_starved: ++ if (pool->sp_fill < num) { ++ ret = -ENOMEM; ++ goto acquire_done; ++ } ++ } ++ copy_words(bufs, pool->sp + (pool->sp_fill - num), ++ sizeof(struct bm_buffer) * num); ++ pool->sp_fill -= num; ++ ret = num; ++acquire_done: ++#ifdef CONFIG_FSL_DPA_CHECKING ++ atomic_inc(&pool->in_use); ++#endif ++ return ret; ++} ++EXPORT_SYMBOL(bman_acquire); ++ ++int bman_flush_stockpile(struct bman_pool *pool, u32 flags) ++{ ++ u8 num; ++ int ret; ++ ++ while (pool->sp_fill) { ++ num = ((pool->sp_fill > 8) ? 8 : pool->sp_fill); ++ ret = __bman_release(pool, pool->sp + (pool->sp_fill - num), ++ num, flags); ++ if (ret) ++ return ret; ++ pool->sp_fill -= num; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(bman_flush_stockpile); ++ ++int bman_query_pools(struct bm_pool_state *state) ++{ ++ struct bman_portal *p = get_affine_portal(); ++ struct bm_mc_result *mcr; ++ __maybe_unused unsigned long irqflags; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ bm_mc_start(&p->p); ++ bm_mc_commit(&p->p, BM_MCC_VERB_CMD_QUERY); ++ while (!(mcr = bm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & BM_MCR_VERB_CMD_MASK) == BM_MCR_VERB_CMD_QUERY); ++ *state = mcr->query; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return 0; ++} ++EXPORT_SYMBOL(bman_query_pools); ++ ++#ifdef CONFIG_FSL_BMAN_CONFIG ++u32 bman_query_free_buffers(struct bman_pool *pool) ++{ ++ return bm_pool_free_buffers(pool->params.bpid); ++} ++EXPORT_SYMBOL(bman_query_free_buffers); ++ ++int bman_update_pool_thresholds(struct bman_pool *pool, const u32 *thresholds) ++{ ++ u32 bpid; ++ ++ bpid = bman_get_params(pool)->bpid; ++ ++ return bm_pool_set(bpid, thresholds); ++} ++EXPORT_SYMBOL(bman_update_pool_thresholds); ++#endif ++ ++int bman_shutdown_pool(u32 bpid) ++{ ++ struct bman_portal *p = get_affine_portal(); ++ __maybe_unused unsigned long irqflags; ++ int ret; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ret = bm_shutdown_pool(&p->p, bpid); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(bman_shutdown_pool); ++ ++const struct bm_portal_config *bman_get_bm_portal_config( ++ struct bman_portal *portal) ++{ ++ return portal->sharing_redirect ? NULL : portal->config; ++} +diff --git a/drivers/staging/fsl_qbman/bman_low.h b/drivers/staging/fsl_qbman/bman_low.h +new file mode 100644 +index 0000000..e4ab771 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_low.h +@@ -0,0 +1,524 @@ ++/* Copyright 2008-2011 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 "bman_private.h" ++ ++/***************************/ ++/* Portal register assists */ ++/***************************/ ++ ++/* Cache-inhibited register offsets */ ++#define BM_REG_RCR_PI_CINH 0x0000 ++#define BM_REG_RCR_CI_CINH 0x0004 ++#define BM_REG_RCR_ITR 0x0008 ++#define BM_REG_CFG 0x0100 ++#define BM_REG_SCN(n) (0x0200 + ((n) << 2)) ++#define BM_REG_ISR 0x0e00 ++#define BM_REG_IIR 0x0e0c ++ ++/* Cache-enabled register offsets */ ++#define BM_CL_CR 0x0000 ++#define BM_CL_RR0 0x0100 ++#define BM_CL_RR1 0x0140 ++#define BM_CL_RCR 0x1000 ++#define BM_CL_RCR_PI_CENA 0x3000 ++#define BM_CL_RCR_CI_CENA 0x3100 ++ ++/* BTW, the drivers (and h/w programming model) already obtain the required ++ * synchronisation for portal accesses via lwsync(), hwsync(), and ++ * data-dependencies. Use of barrier()s or other order-preserving primitives ++ * simply degrade performance. Hence the use of the __raw_*() interfaces, which ++ * simply ensure that the compiler treats the portal registers as volatile (ie. ++ * non-coherent). */ ++ ++/* Cache-inhibited register access. */ ++#define __bm_in(bm, o) __raw_readl((bm)->addr_ci + (o)) ++#define __bm_out(bm, o, val) __raw_writel((val), (bm)->addr_ci + (o)) ++#define bm_in(reg) __bm_in(&portal->addr, BM_REG_##reg) ++#define bm_out(reg, val) __bm_out(&portal->addr, BM_REG_##reg, val) ++ ++/* Cache-enabled (index) register access */ ++#define __bm_cl_touch_ro(bm, o) dcbt_ro((bm)->addr_ce + (o)) ++#define __bm_cl_touch_rw(bm, o) dcbt_rw((bm)->addr_ce + (o)) ++#define __bm_cl_in(bm, o) __raw_readl((bm)->addr_ce + (o)) ++#define __bm_cl_out(bm, o, val) \ ++ do { \ ++ u32 *__tmpclout = (bm)->addr_ce + (o); \ ++ __raw_writel((val), __tmpclout); \ ++ dcbf(__tmpclout); \ ++ } while (0) ++#define __bm_cl_invalidate(bm, o) dcbi((bm)->addr_ce + (o)) ++#define bm_cl_touch_ro(reg) __bm_cl_touch_ro(&portal->addr, BM_CL_##reg##_CENA) ++#define bm_cl_touch_rw(reg) __bm_cl_touch_rw(&portal->addr, BM_CL_##reg##_CENA) ++#define bm_cl_in(reg) __bm_cl_in(&portal->addr, BM_CL_##reg##_CENA) ++#define bm_cl_out(reg, val) __bm_cl_out(&portal->addr, BM_CL_##reg##_CENA, val) ++#define bm_cl_invalidate(reg)\ ++ __bm_cl_invalidate(&portal->addr, BM_CL_##reg##_CENA) ++ ++/* Cyclic helper for rings. FIXME: once we are able to do fine-grain perf ++ * analysis, look at using the "extra" bit in the ring index registers to avoid ++ * cyclic issues. */ ++static inline u8 bm_cyc_diff(u8 ringsize, u8 first, u8 last) ++{ ++ /* 'first' is included, 'last' is excluded */ ++ if (first <= last) ++ return last - first; ++ return ringsize + last - first; ++} ++ ++/* Portal modes. ++ * Enum types; ++ * pmode == production mode ++ * cmode == consumption mode, ++ * Enum values use 3 letter codes. First letter matches the portal mode, ++ * remaining two letters indicate; ++ * ci == cache-inhibited portal register ++ * ce == cache-enabled portal register ++ * vb == in-band valid-bit (cache-enabled) ++ */ ++enum bm_rcr_pmode { /* matches BCSP_CFG::RPM */ ++ bm_rcr_pci = 0, /* PI index, cache-inhibited */ ++ bm_rcr_pce = 1, /* PI index, cache-enabled */ ++ bm_rcr_pvb = 2 /* valid-bit */ ++}; ++enum bm_rcr_cmode { /* s/w-only */ ++ bm_rcr_cci, /* CI index, cache-inhibited */ ++ bm_rcr_cce /* CI index, cache-enabled */ ++}; ++ ++ ++/* ------------------------- */ ++/* --- Portal structures --- */ ++ ++#define BM_RCR_SIZE 8 ++ ++struct bm_rcr { ++ struct bm_rcr_entry *ring, *cursor; ++ u8 ci, available, ithresh, vbit; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ u32 busy; ++ enum bm_rcr_pmode pmode; ++ enum bm_rcr_cmode cmode; ++#endif ++}; ++ ++struct bm_mc { ++ struct bm_mc_command *cr; ++ struct bm_mc_result *rr; ++ u8 rridx, vbit; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ enum { ++ /* Can only be _mc_start()ed */ ++ mc_idle, ++ /* Can only be _mc_commit()ed or _mc_abort()ed */ ++ mc_user, ++ /* Can only be _mc_retry()ed */ ++ mc_hw ++ } state; ++#endif ++}; ++ ++struct bm_addr { ++ void __iomem *addr_ce; /* cache-enabled */ ++ void __iomem *addr_ci; /* cache-inhibited */ ++}; ++ ++struct bm_portal { ++ struct bm_addr addr; ++ struct bm_rcr rcr; ++ struct bm_mc mc; ++ struct bm_portal_config config; ++} ____cacheline_aligned; ++ ++ ++/* --------------- */ ++/* --- RCR API --- */ ++ ++/* Bit-wise logic to wrap a ring pointer by clearing the "carry bit" */ ++#define RCR_CARRYCLEAR(p) \ ++ (void *)((unsigned long)(p) & (~(unsigned long)(BM_RCR_SIZE << 6))) ++ ++/* Bit-wise logic to convert a ring pointer to a ring index */ ++static inline u8 RCR_PTR2IDX(struct bm_rcr_entry *e) ++{ ++ return ((uintptr_t)e >> 6) & (BM_RCR_SIZE - 1); ++} ++ ++/* Increment the 'cursor' ring pointer, taking 'vbit' into account */ ++static inline void RCR_INC(struct bm_rcr *rcr) ++{ ++ /* NB: this is odd-looking, but experiments show that it generates ++ * fast code with essentially no branching overheads. We increment to ++ * the next RCR pointer and handle overflow and 'vbit'. */ ++ struct bm_rcr_entry *partial = rcr->cursor + 1; ++ rcr->cursor = RCR_CARRYCLEAR(partial); ++ if (partial != rcr->cursor) ++ rcr->vbit ^= BM_RCR_VERB_VBIT; ++} ++ ++static inline int bm_rcr_init(struct bm_portal *portal, enum bm_rcr_pmode pmode, ++ __maybe_unused enum bm_rcr_cmode cmode) ++{ ++ /* This use of 'register', as well as all other occurrences, is because ++ * it has been observed to generate much faster code with gcc than is ++ * otherwise the case. */ ++ register struct bm_rcr *rcr = &portal->rcr; ++ u32 cfg; ++ u8 pi; ++ ++ rcr->ring = portal->addr.addr_ce + BM_CL_RCR; ++ rcr->ci = bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1); ++ pi = bm_in(RCR_PI_CINH) & (BM_RCR_SIZE - 1); ++ rcr->cursor = rcr->ring + pi; ++ rcr->vbit = (bm_in(RCR_PI_CINH) & BM_RCR_SIZE) ? BM_RCR_VERB_VBIT : 0; ++ rcr->available = BM_RCR_SIZE - 1 ++ - bm_cyc_diff(BM_RCR_SIZE, rcr->ci, pi); ++ rcr->ithresh = bm_in(RCR_ITR); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ rcr->busy = 0; ++ rcr->pmode = pmode; ++ rcr->cmode = cmode; ++#endif ++ cfg = (bm_in(CFG) & 0xffffffe0) | (pmode & 0x3); /* BCSP_CFG::RPM */ ++ bm_out(CFG, cfg); ++ return 0; ++} ++ ++static inline void bm_rcr_finish(struct bm_portal *portal) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ u8 pi = bm_in(RCR_PI_CINH) & (BM_RCR_SIZE - 1); ++ u8 ci = bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1); ++ DPA_ASSERT(!rcr->busy); ++ if (pi != RCR_PTR2IDX(rcr->cursor)) ++ pr_crit("losing uncommited RCR entries\n"); ++ if (ci != rcr->ci) ++ pr_crit("missing existing RCR completions\n"); ++ if (rcr->ci != RCR_PTR2IDX(rcr->cursor)) ++ pr_crit("RCR destroyed unquiesced\n"); ++} ++ ++static inline struct bm_rcr_entry *bm_rcr_start(struct bm_portal *portal) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ DPA_ASSERT(!rcr->busy); ++ if (!rcr->available) ++ return NULL; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ rcr->busy = 1; ++#endif ++ dcbz_64(rcr->cursor); ++ return rcr->cursor; ++} ++ ++static inline void bm_rcr_abort(struct bm_portal *portal) ++{ ++ __maybe_unused register struct bm_rcr *rcr = &portal->rcr; ++ DPA_ASSERT(rcr->busy); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ rcr->busy = 0; ++#endif ++} ++ ++static inline struct bm_rcr_entry *bm_rcr_pend_and_next( ++ struct bm_portal *portal, u8 myverb) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ DPA_ASSERT(rcr->busy); ++ DPA_ASSERT(rcr->pmode != bm_rcr_pvb); ++ if (rcr->available == 1) ++ return NULL; ++ rcr->cursor->__dont_write_directly__verb = myverb | rcr->vbit; ++ dcbf_64(rcr->cursor); ++ RCR_INC(rcr); ++ rcr->available--; ++ dcbz_64(rcr->cursor); ++ return rcr->cursor; ++} ++ ++static inline void bm_rcr_pci_commit(struct bm_portal *portal, u8 myverb) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ DPA_ASSERT(rcr->busy); ++ DPA_ASSERT(rcr->pmode == bm_rcr_pci); ++ rcr->cursor->__dont_write_directly__verb = myverb | rcr->vbit; ++ RCR_INC(rcr); ++ rcr->available--; ++ hwsync(); ++ bm_out(RCR_PI_CINH, RCR_PTR2IDX(rcr->cursor)); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ rcr->busy = 0; ++#endif ++} ++ ++static inline void bm_rcr_pce_prefetch(struct bm_portal *portal) ++{ ++ __maybe_unused register struct bm_rcr *rcr = &portal->rcr; ++ DPA_ASSERT(rcr->pmode == bm_rcr_pce); ++ bm_cl_invalidate(RCR_PI); ++ bm_cl_touch_rw(RCR_PI); ++} ++ ++static inline void bm_rcr_pce_commit(struct bm_portal *portal, u8 myverb) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ DPA_ASSERT(rcr->busy); ++ DPA_ASSERT(rcr->pmode == bm_rcr_pce); ++ rcr->cursor->__dont_write_directly__verb = myverb | rcr->vbit; ++ RCR_INC(rcr); ++ rcr->available--; ++ lwsync(); ++ bm_cl_out(RCR_PI, RCR_PTR2IDX(rcr->cursor)); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ rcr->busy = 0; ++#endif ++} ++ ++static inline void bm_rcr_pvb_commit(struct bm_portal *portal, u8 myverb) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ struct bm_rcr_entry *rcursor; ++ DPA_ASSERT(rcr->busy); ++ DPA_ASSERT(rcr->pmode == bm_rcr_pvb); ++ lwsync(); ++ rcursor = rcr->cursor; ++ rcursor->__dont_write_directly__verb = myverb | rcr->vbit; ++ dcbf_64(rcursor); ++ RCR_INC(rcr); ++ rcr->available--; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ rcr->busy = 0; ++#endif ++} ++ ++static inline u8 bm_rcr_cci_update(struct bm_portal *portal) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ u8 diff, old_ci = rcr->ci; ++ DPA_ASSERT(rcr->cmode == bm_rcr_cci); ++ rcr->ci = bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1); ++ diff = bm_cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci); ++ rcr->available += diff; ++ return diff; ++} ++ ++static inline void bm_rcr_cce_prefetch(struct bm_portal *portal) ++{ ++ __maybe_unused register struct bm_rcr *rcr = &portal->rcr; ++ DPA_ASSERT(rcr->cmode == bm_rcr_cce); ++ bm_cl_touch_ro(RCR_CI); ++} ++ ++static inline u8 bm_rcr_cce_update(struct bm_portal *portal) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ u8 diff, old_ci = rcr->ci; ++ DPA_ASSERT(rcr->cmode == bm_rcr_cce); ++ rcr->ci = bm_cl_in(RCR_CI) & (BM_RCR_SIZE - 1); ++ bm_cl_invalidate(RCR_CI); ++ diff = bm_cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci); ++ rcr->available += diff; ++ return diff; ++} ++ ++static inline u8 bm_rcr_get_ithresh(struct bm_portal *portal) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ return rcr->ithresh; ++} ++ ++static inline void bm_rcr_set_ithresh(struct bm_portal *portal, u8 ithresh) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ rcr->ithresh = ithresh; ++ bm_out(RCR_ITR, ithresh); ++} ++ ++static inline u8 bm_rcr_get_avail(struct bm_portal *portal) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ return rcr->available; ++} ++ ++static inline u8 bm_rcr_get_fill(struct bm_portal *portal) ++{ ++ register struct bm_rcr *rcr = &portal->rcr; ++ return BM_RCR_SIZE - 1 - rcr->available; ++} ++ ++ ++/* ------------------------------ */ ++/* --- Management command API --- */ ++ ++static inline int bm_mc_init(struct bm_portal *portal) ++{ ++ register struct bm_mc *mc = &portal->mc; ++ mc->cr = portal->addr.addr_ce + BM_CL_CR; ++ mc->rr = portal->addr.addr_ce + BM_CL_RR0; ++ mc->rridx = (__raw_readb(&mc->cr->__dont_write_directly__verb) & ++ BM_MCC_VERB_VBIT) ? 0 : 1; ++ mc->vbit = mc->rridx ? BM_MCC_VERB_VBIT : 0; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_idle; ++#endif ++ return 0; ++} ++ ++static inline void bm_mc_finish(struct bm_portal *portal) ++{ ++ __maybe_unused register struct bm_mc *mc = &portal->mc; ++ DPA_ASSERT(mc->state == mc_idle); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (mc->state != mc_idle) ++ pr_crit("Losing incomplete MC command\n"); ++#endif ++} ++ ++static inline struct bm_mc_command *bm_mc_start(struct bm_portal *portal) ++{ ++ register struct bm_mc *mc = &portal->mc; ++ DPA_ASSERT(mc->state == mc_idle); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_user; ++#endif ++ dcbz_64(mc->cr); ++ return mc->cr; ++} ++ ++static inline void bm_mc_abort(struct bm_portal *portal) ++{ ++ __maybe_unused register struct bm_mc *mc = &portal->mc; ++ DPA_ASSERT(mc->state == mc_user); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_idle; ++#endif ++} ++ ++static inline void bm_mc_commit(struct bm_portal *portal, u8 myverb) ++{ ++ register struct bm_mc *mc = &portal->mc; ++ struct bm_mc_result *rr = mc->rr + mc->rridx; ++ DPA_ASSERT(mc->state == mc_user); ++ lwsync(); ++ mc->cr->__dont_write_directly__verb = myverb | mc->vbit; ++ dcbf(mc->cr); ++ dcbit_ro(rr); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_hw; ++#endif ++} ++ ++static inline struct bm_mc_result *bm_mc_result(struct bm_portal *portal) ++{ ++ register struct bm_mc *mc = &portal->mc; ++ struct bm_mc_result *rr = mc->rr + mc->rridx; ++ DPA_ASSERT(mc->state == mc_hw); ++ /* The inactive response register's verb byte always returns zero until ++ * its command is submitted and completed. This includes the valid-bit, ++ * in case you were wondering... */ ++ if (!__raw_readb(&rr->verb)) { ++ dcbit_ro(rr); ++ return NULL; ++ } ++ mc->rridx ^= 1; ++ mc->vbit ^= BM_MCC_VERB_VBIT; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = mc_idle; ++#endif ++ return rr; ++} ++ ++ ++/* ------------------------------------- */ ++/* --- Portal interrupt register API --- */ ++ ++static inline int bm_isr_init(__always_unused struct bm_portal *portal) ++{ ++ return 0; ++} ++ ++static inline void bm_isr_finish(__always_unused struct bm_portal *portal) ++{ ++} ++ ++#define SCN_REG(bpid) BM_REG_SCN((bpid) / 32) ++#define SCN_BIT(bpid) (0x80000000 >> (bpid & 31)) ++static inline void bm_isr_bscn_mask(struct bm_portal *portal, u8 bpid, ++ int enable) ++{ ++ u32 val; ++ DPA_ASSERT(bpid < bman_pool_max); ++ /* REG_SCN for bpid=0..31, REG_SCN+4 for bpid=32..63 */ ++ val = __bm_in(&portal->addr, SCN_REG(bpid)); ++ if (enable) ++ val |= SCN_BIT(bpid); ++ else ++ val &= ~SCN_BIT(bpid); ++ __bm_out(&portal->addr, SCN_REG(bpid), val); ++} ++ ++static inline u32 __bm_isr_read(struct bm_portal *portal, enum bm_isr_reg n) ++{ ++ return __bm_in(&portal->addr, BM_REG_ISR + (n << 2)); ++} ++ ++static inline void __bm_isr_write(struct bm_portal *portal, enum bm_isr_reg n, ++ u32 val) ++{ ++ __bm_out(&portal->addr, BM_REG_ISR + (n << 2), val); ++} ++ ++/* Buffer Pool Cleanup */ ++static inline int bm_shutdown_pool(struct bm_portal *p, u32 bpid) ++{ ++ struct bm_mc_command *bm_cmd; ++ struct bm_mc_result *bm_res; ++ ++ int aq_count = 0; ++ bool stop = false; ++ while (!stop) { ++ /* Acquire buffers until empty */ ++ bm_cmd = bm_mc_start(p); ++ bm_cmd->acquire.bpid = bpid; ++ bm_mc_commit(p, BM_MCC_VERB_CMD_ACQUIRE | 1); ++ while (!(bm_res = bm_mc_result(p))) ++ cpu_relax(); ++ if (!(bm_res->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT)) { ++ /* Pool is empty */ ++ /* TBD : Should we do a few extra iterations in ++ case some other some blocks keep buffers 'on deck', ++ which may also be problematic */ ++ stop = true; ++ } else ++ ++aq_count; ++ } ++ return 0; ++} +diff --git a/drivers/staging/fsl_qbman/bman_private.h b/drivers/staging/fsl_qbman/bman_private.h +new file mode 100644 +index 0000000..34e4127 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_private.h +@@ -0,0 +1,165 @@ ++/* Copyright 2008-2012 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 "dpa_sys.h" ++#include ++ ++/* Revision info (for errata and feature handling) */ ++#define BMAN_REV10 0x0100 ++#define BMAN_REV20 0x0200 ++#define BMAN_REV21 0x0201 ++extern u16 bman_ip_rev; /* 0 if uninitialised, otherwise QMAN_REVx */ ++ ++/* ++ * Global variables of the max portal/pool number this bman version supported ++ */ ++extern u16 bman_pool_max; ++ ++/* used by CCSR and portal interrupt code */ ++enum bm_isr_reg { ++ bm_isr_status = 0, ++ bm_isr_enable = 1, ++ bm_isr_disable = 2, ++ bm_isr_inhibit = 3 ++}; ++ ++struct bm_portal_config { ++ /* Corenet portal addresses; ++ * [0]==cache-enabled, [1]==cache-inhibited. */ ++ __iomem void *addr_virt[2]; ++ struct resource addr_phys[2]; ++ /* Allow these to be joined in lists */ ++ struct list_head list; ++ /* User-visible portal configuration settings */ ++ struct bman_portal_config public_cfg; ++ /* power management saved data */ ++ u32 saved_isdr; ++}; ++ ++#ifdef CONFIG_FSL_BMAN_CONFIG ++/* Hooks from bman_driver.c to bman_config.c */ ++int bman_init_ccsr(struct device_node *node); ++#endif ++ ++/* Hooks from bman_driver.c in to bman_high.c */ ++struct bman_portal *bman_create_portal( ++ struct bman_portal *portal, ++ const struct bm_portal_config *config); ++struct bman_portal *bman_create_affine_portal( ++ const struct bm_portal_config *config); ++struct bman_portal *bman_create_affine_slave(struct bman_portal *redirect, ++ int cpu); ++void bman_destroy_portal(struct bman_portal *bm); ++ ++const struct bm_portal_config *bman_destroy_affine_portal(void); ++ ++/* Hooks from fsl_usdpaa.c to bman_driver.c */ ++struct bm_portal_config *bm_get_unused_portal(void); ++struct bm_portal_config *bm_get_unused_portal_idx(uint32_t idx); ++void bm_put_unused_portal(struct bm_portal_config *pcfg); ++void bm_set_liodns(struct bm_portal_config *pcfg); ++ ++/* Pool logic in the portal driver, during initialisation, needs to know if ++ * there's access to CCSR or not (if not, it'll cripple the pool allocator). */ ++#ifdef CONFIG_FSL_BMAN_CONFIG ++int bman_have_ccsr(void); ++#else ++#define bman_have_ccsr() 0 ++#endif ++ ++/* Stockpile build constants. The _LOW value: when bman_acquire() is called and ++ * the stockpile fill-level is <= _LOW, an acquire is attempted from h/w but it ++ * might fail (if the buffer pool is depleted). So this value provides some ++ * "stagger" in that the bman_acquire() function will only fail if lots of bufs ++ * are requested at once or if h/w has been tested a couple of times without ++ * luck. The _HIGH value: when bman_release() is called and the stockpile ++ * fill-level is >= _HIGH, a release is attempted to h/w but it might fail (if ++ * the release ring is full). So this value provides some "stagger" so that ++ * ring-access is retried a couple of times prior to the API returning a ++ * failure. The following *must* be true; ++ * BMAN_STOCKPILE_HIGH-BMAN_STOCKPILE_LOW > 8 ++ * (to avoid thrashing) ++ * BMAN_STOCKPILE_SZ >= 16 ++ * (as the release logic expects to either send 8 buffers to hw prior to ++ * adding the given buffers to the stockpile or add the buffers to the ++ * stockpile before sending 8 to hw, as the API must be an all-or-nothing ++ * success/fail.) ++ */ ++#define BMAN_STOCKPILE_SZ 16u /* number of bufs in per-pool cache */ ++#define BMAN_STOCKPILE_LOW 2u /* when fill is <= this, acquire from hw */ ++#define BMAN_STOCKPILE_HIGH 14u /* when fill is >= this, release to hw */ ++ ++/*************************************************/ ++/* BMan s/w corenet portal, low-level i/face */ ++/*************************************************/ ++ ++/* Used by all portal interrupt registers except 'inhibit' ++ * This mask contains all the "irqsource" bits visible to API users ++ */ ++#define BM_PIRQ_VISIBLE (BM_PIRQ_RCRI | BM_PIRQ_BSCN) ++ ++/* These are bm__(). So for example, bm_disable_write() means "write ++ * the disable register" rather than "disable the ability to write". */ ++#define bm_isr_status_read(bm) __bm_isr_read(bm, bm_isr_status) ++#define bm_isr_status_clear(bm, m) __bm_isr_write(bm, bm_isr_status, m) ++#define bm_isr_enable_read(bm) __bm_isr_read(bm, bm_isr_enable) ++#define bm_isr_enable_write(bm, v) __bm_isr_write(bm, bm_isr_enable, v) ++#define bm_isr_disable_read(bm) __bm_isr_read(bm, bm_isr_disable) ++#define bm_isr_disable_write(bm, v) __bm_isr_write(bm, bm_isr_disable, v) ++#define bm_isr_inhibit(bm) __bm_isr_write(bm, bm_isr_inhibit, 1) ++#define bm_isr_uninhibit(bm) __bm_isr_write(bm, bm_isr_inhibit, 0) ++ ++#ifdef CONFIG_FSL_BMAN_CONFIG ++/* Set depletion thresholds associated with a buffer pool. Requires that the ++ * operating system have access to Bman CCSR (ie. compiled in support and ++ * run-time access courtesy of the device-tree). */ ++int bm_pool_set(u32 bpid, const u32 *thresholds); ++#define BM_POOL_THRESH_SW_ENTER 0 ++#define BM_POOL_THRESH_SW_EXIT 1 ++#define BM_POOL_THRESH_HW_ENTER 2 ++#define BM_POOL_THRESH_HW_EXIT 3 ++ ++/* Read the free buffer count for a given buffer */ ++u32 bm_pool_free_buffers(u32 bpid); ++ ++__init int bman_init(void); ++__init int bman_resource_init(void); ++ ++const struct bm_portal_config *bman_get_bm_portal_config( ++ struct bman_portal *portal); ++ ++/* power management */ ++#ifdef CONFIG_SUSPEND ++void suspend_unused_bportal(void); ++void resume_unused_bportal(void); ++#endif ++ ++#endif /* CONFIG_FSL_BMAN_CONFIG */ +diff --git a/drivers/staging/fsl_qbman/bman_test.c b/drivers/staging/fsl_qbman/bman_test.c +new file mode 100644 +index 0000000..db5b7fd +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_test.c +@@ -0,0 +1,56 @@ ++/* Copyright 2008-2011 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 "bman_test.h" ++ ++MODULE_AUTHOR("Geoff Thorpe"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("Bman testing"); ++ ++static int test_init(void) ++{ ++#ifdef CONFIG_FSL_BMAN_TEST_HIGH ++ int loop = 1; ++ while (loop--) ++ bman_test_high(); ++#endif ++#ifdef CONFIG_FSL_BMAN_TEST_THRESH ++ bman_test_thresh(); ++#endif ++ return 0; ++} ++ ++static void test_exit(void) ++{ ++} ++ ++module_init(test_init); ++module_exit(test_exit); +diff --git a/drivers/staging/fsl_qbman/bman_test.h b/drivers/staging/fsl_qbman/bman_test.h +new file mode 100644 +index 0000000..fcd6505 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_test.h +@@ -0,0 +1,44 @@ ++/* Copyright 2008-2011 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++void bman_test_high(void); ++void bman_test_thresh(void); +diff --git a/drivers/staging/fsl_qbman/bman_test_high.c b/drivers/staging/fsl_qbman/bman_test_high.c +new file mode 100644 +index 0000000..4676fb0 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_test_high.c +@@ -0,0 +1,183 @@ ++/* Copyright 2008-2011 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 "bman_test.h" ++#include "bman_private.h" ++ ++/*************/ ++/* constants */ ++/*************/ ++ ++#define PORTAL_OPAQUE ((void *)0xf00dbeef) ++#define POOL_OPAQUE ((void *)0xdeadabba) ++#define NUM_BUFS 93 ++#define LOOPS 3 ++#define BMAN_TOKEN_MASK 0x00FFFFFFFFFFLLU ++ ++/***************/ ++/* global vars */ ++/***************/ ++ ++static struct bman_pool *pool; ++static int depleted; ++static struct bm_buffer bufs_in[NUM_BUFS] ____cacheline_aligned; ++static struct bm_buffer bufs_out[NUM_BUFS] ____cacheline_aligned; ++static int bufs_received; ++ ++/* Predeclare the callback so we can instantiate pool parameters */ ++static void depletion_cb(struct bman_portal *, struct bman_pool *, void *, int); ++ ++/**********************/ ++/* internal functions */ ++/**********************/ ++ ++static void bufs_init(void) ++{ ++ int i; ++ for (i = 0; i < NUM_BUFS; i++) ++ bm_buffer_set64(&bufs_in[i], 0xfedc01234567LLU * i); ++ bufs_received = 0; ++} ++ ++static inline int bufs_cmp(const struct bm_buffer *a, const struct bm_buffer *b) ++{ ++ if ((bman_ip_rev == BMAN_REV20) || (bman_ip_rev == BMAN_REV21)) { ++ ++ /* On SoCs with Bman revison 2.0, Bman only respects the 40 ++ * LS-bits of buffer addresses, masking off the upper 8-bits on ++ * release commands. The API provides for 48-bit addresses ++ * because some SoCs support all 48-bits. When generating ++ * garbage addresses for testing, we either need to zero the ++ * upper 8-bits when releasing to Bman (otherwise we'll be ++ * disappointed when the buffers we acquire back from Bman ++ * don't match), or we need to mask the upper 8-bits off when ++ * comparing. We do the latter. ++ */ ++ if ((bm_buffer_get64(a) & BMAN_TOKEN_MASK) ++ < (bm_buffer_get64(b) & BMAN_TOKEN_MASK)) ++ return -1; ++ if ((bm_buffer_get64(a) & BMAN_TOKEN_MASK) ++ > (bm_buffer_get64(b) & BMAN_TOKEN_MASK)) ++ return 1; ++ } else { ++ if (bm_buffer_get64(a) < bm_buffer_get64(b)) ++ return -1; ++ if (bm_buffer_get64(a) > bm_buffer_get64(b)) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void bufs_confirm(void) ++{ ++ int i, j; ++ for (i = 0; i < NUM_BUFS; i++) { ++ int matches = 0; ++ for (j = 0; j < NUM_BUFS; j++) ++ if (!bufs_cmp(&bufs_in[i], &bufs_out[j])) ++ matches++; ++ BUG_ON(matches != 1); ++ } ++} ++ ++/********/ ++/* test */ ++/********/ ++ ++static void depletion_cb(struct bman_portal *__portal, struct bman_pool *__pool, ++ void *pool_ctx, int __depleted) ++{ ++ BUG_ON(__pool != pool); ++ BUG_ON(pool_ctx != POOL_OPAQUE); ++ depleted = __depleted; ++} ++ ++void bman_test_high(void) ++{ ++ struct bman_pool_params pparams = { ++ .flags = BMAN_POOL_FLAG_DEPLETION | BMAN_POOL_FLAG_DYNAMIC_BPID, ++ .cb = depletion_cb, ++ .cb_ctx = POOL_OPAQUE, ++ }; ++ int i, loops = LOOPS; ++ ++ bufs_init(); ++ ++ pr_info("BMAN: --- starting high-level test ---\n"); ++ ++ pool = bman_new_pool(&pparams); ++ BUG_ON(!pool); ++ ++ /*******************/ ++ /* Release buffers */ ++ /*******************/ ++do_loop: ++ i = 0; ++ while (i < NUM_BUFS) { ++ u32 flags = BMAN_RELEASE_FLAG_WAIT; ++ int num = 8; ++ if ((i + num) > NUM_BUFS) ++ num = NUM_BUFS - i; ++ if ((i + num) == NUM_BUFS) ++ flags |= BMAN_RELEASE_FLAG_WAIT_SYNC; ++ if (bman_release(pool, bufs_in + i, num, flags)) ++ panic("bman_release() failed\n"); ++ i += num; ++ } ++ ++ /*******************/ ++ /* Acquire buffers */ ++ /*******************/ ++ while (i > 0) { ++ int tmp, num = 8; ++ if (num > i) ++ num = i; ++ tmp = bman_acquire(pool, bufs_out + i - num, num, 0); ++ BUG_ON(tmp != num); ++ i -= num; ++ } ++ ++ struct bm_buffer tmp_buf; ++ i = bman_acquire(pool, &tmp_buf, 1, 0); ++ BUG_ON(i > 0); ++ ++ bufs_confirm(); ++ ++ if (--loops) ++ goto do_loop; ++ ++ /************/ ++ /* Clean up */ ++ /************/ ++ bman_free_pool(pool); ++ pr_info("BMAN: --- finished high-level test ---\n"); ++} +diff --git a/drivers/staging/fsl_qbman/bman_test_thresh.c b/drivers/staging/fsl_qbman/bman_test_thresh.c +new file mode 100644 +index 0000000..6709369 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/bman_test_thresh.c +@@ -0,0 +1,196 @@ ++/* Copyright 2010-2011 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 "bman_test.h" ++ ++/* Test constants */ ++#define TEST_NUMBUFS 129728 ++#define TEST_EXIT 129536 ++#define TEST_ENTRY 129024 ++ ++struct affine_test_data { ++ struct task_struct *t; ++ int cpu; ++ int expect_affinity; ++ int drain; ++ int num_enter; ++ int num_exit; ++ struct list_head node; ++ struct completion wakethread; ++ struct completion wakeparent; ++}; ++ ++static void cb_depletion(struct bman_portal *portal, ++ struct bman_pool *pool, ++ void *opaque, ++ int depleted) ++{ ++ struct affine_test_data *data = opaque; ++ int c = smp_processor_id(); ++ pr_info("cb_depletion: bpid=%d, depleted=%d, cpu=%d, original=%d\n", ++ bman_get_params(pool)->bpid, !!depleted, c, data->cpu); ++ /* We should be executing on the CPU of the thread that owns the pool if ++ * and that CPU has an affine portal (ie. it isn't slaved). */ ++ BUG_ON((c != data->cpu) && data->expect_affinity); ++ BUG_ON((c == data->cpu) && !data->expect_affinity); ++ if (depleted) ++ data->num_enter++; ++ else ++ data->num_exit++; ++} ++ ++/* Params used to set up a pool, this also dynamically allocates a BPID */ ++static const struct bman_pool_params params_nocb = { ++ .flags = BMAN_POOL_FLAG_DYNAMIC_BPID | BMAN_POOL_FLAG_THRESH, ++ .thresholds = { TEST_ENTRY, TEST_EXIT, 0, 0 } ++}; ++ ++/* Params used to set up each cpu's pool with callbacks enabled */ ++static struct bman_pool_params params_cb = { ++ .bpid = 0, /* will be replaced to match pool_nocb */ ++ .flags = BMAN_POOL_FLAG_DEPLETION, ++ .cb = cb_depletion ++}; ++ ++static struct bman_pool *pool_nocb; ++static LIST_HEAD(threads); ++ ++static int affine_test(void *__data) ++{ ++ struct bman_pool *pool; ++ struct affine_test_data *data = __data; ++ struct bman_pool_params my_params = params_cb; ++ ++ pr_info("thread %d: starting\n", data->cpu); ++ /* create the pool */ ++ my_params.cb_ctx = data; ++ pool = bman_new_pool(&my_params); ++ BUG_ON(!pool); ++ complete(&data->wakeparent); ++ wait_for_completion(&data->wakethread); ++ init_completion(&data->wakethread); ++ ++ /* if we're the drainer, we get signalled for that */ ++ if (data->drain) { ++ struct bm_buffer buf; ++ int ret; ++ pr_info("thread %d: draining...\n", data->cpu); ++ do { ++ ret = bman_acquire(pool, &buf, 1, 0); ++ } while (ret > 0); ++ pr_info("thread %d: draining done.\n", data->cpu); ++ complete(&data->wakeparent); ++ wait_for_completion(&data->wakethread); ++ init_completion(&data->wakethread); ++ } ++ ++ /* cleanup */ ++ bman_free_pool(pool); ++ while (!kthread_should_stop()) ++ cpu_relax(); ++ pr_info("thread %d: exiting\n", data->cpu); ++ return 0; ++} ++ ++static struct affine_test_data *start_affine_test(int cpu, int drain) ++{ ++ struct affine_test_data *data = kmalloc(sizeof(*data), GFP_KERNEL); ++ ++ if (!data) ++ return NULL; ++ data->cpu = cpu; ++ data->expect_affinity = cpumask_test_cpu(cpu, bman_affine_cpus()); ++ data->drain = drain; ++ data->num_enter = 0; ++ data->num_exit = 0; ++ init_completion(&data->wakethread); ++ init_completion(&data->wakeparent); ++ list_add_tail(&data->node, &threads); ++ data->t = kthread_create(affine_test, data, "threshtest%d", cpu); ++ BUG_ON(IS_ERR(data->t)); ++ kthread_bind(data->t, cpu); ++ wake_up_process(data->t); ++ return data; ++} ++ ++void bman_test_thresh(void) ++{ ++ int loop = TEST_NUMBUFS; ++ int ret, num_cpus = 0; ++ struct affine_test_data *data, *drainer = NULL; ++ ++ pr_info("bman_test_thresh: start\n"); ++ ++ /* allocate a BPID and seed it */ ++ pool_nocb = bman_new_pool(¶ms_nocb); ++ BUG_ON(!pool_nocb); ++ while (loop--) { ++ struct bm_buffer buf; ++ bm_buffer_set64(&buf, 0x0badbeef + loop); ++ ret = bman_release(pool_nocb, &buf, 1, ++ BMAN_RELEASE_FLAG_WAIT); ++ BUG_ON(ret); ++ } ++ while (!bman_rcr_is_empty()) ++ cpu_relax(); ++ pr_info("bman_test_thresh: buffers are in\n"); ++ ++ /* create threads and wait for them to create pools */ ++ params_cb.bpid = bman_get_params(pool_nocb)->bpid; ++ for_each_cpu(loop, cpu_online_mask) { ++ data = start_affine_test(loop, drainer ? 0 : 1); ++ BUG_ON(!data); ++ if (!drainer) ++ drainer = data; ++ num_cpus++; ++ wait_for_completion(&data->wakeparent); ++ } ++ ++ /* signal the drainer to start draining */ ++ complete(&drainer->wakethread); ++ wait_for_completion(&drainer->wakeparent); ++ init_completion(&drainer->wakeparent); ++ ++ /* tear down */ ++ list_for_each_entry_safe(data, drainer, &threads, node) { ++ complete(&data->wakethread); ++ ret = kthread_stop(data->t); ++ BUG_ON(ret); ++ list_del(&data->node); ++ /* check that we get the expected callbacks (and no others) */ ++ BUG_ON(data->num_enter != 1); ++ BUG_ON(data->num_exit != 0); ++ kfree(data); ++ } ++ bman_free_pool(pool_nocb); ++ ++ pr_info("bman_test_thresh: done\n"); ++} +diff --git a/drivers/staging/fsl_qbman/dpa_alloc.c b/drivers/staging/fsl_qbman/dpa_alloc.c +new file mode 100644 +index 0000000..44db3e1 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/dpa_alloc.c +@@ -0,0 +1,706 @@ ++/* Copyright 2009-2012 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 "dpa_sys.h" ++#include ++#include ++ ++/* Qman and Bman APIs are front-ends to the common code; */ ++ ++static DECLARE_DPA_ALLOC(bpalloc); /* BPID allocator */ ++static DECLARE_DPA_ALLOC(fqalloc); /* FQID allocator */ ++static DECLARE_DPA_ALLOC(qpalloc); /* pool-channel allocator */ ++static DECLARE_DPA_ALLOC(cgralloc); /* CGR ID allocator */ ++static DECLARE_DPA_ALLOC(ceetm0_challoc); /* CEETM Channel ID allocator */ ++static DECLARE_DPA_ALLOC(ceetm0_lfqidalloc); /* CEETM LFQID allocator */ ++static DECLARE_DPA_ALLOC(ceetm1_challoc); /* CEETM Channel ID allocator */ ++static DECLARE_DPA_ALLOC(ceetm1_lfqidalloc); /* CEETM LFQID allocator */ ++ ++/* This is a sort-of-conditional dpa_alloc_free() routine. Eg. when releasing ++ * FQIDs (probably from user-space), it can filter out those that aren't in the ++ * OOS state (better to leak a h/w resource than to crash). This function ++ * returns the number of invalid IDs that were not released. */ ++static u32 release_id_range(struct dpa_alloc *alloc, u32 id, u32 count, ++ int (*is_valid)(u32 id)) ++{ ++ int valid_mode = 0; ++ u32 loop = id, total_invalid = 0; ++ while (loop < (id + count)) { ++ int isvalid = is_valid ? is_valid(loop) : 1; ++ if (!valid_mode) { ++ /* We're looking for a valid ID to terminate an invalid ++ * range */ ++ if (isvalid) { ++ /* We finished a range of invalid IDs, a valid ++ * range is now underway */ ++ valid_mode = 1; ++ count -= (loop - id); ++ id = loop; ++ } else ++ total_invalid++; ++ } else { ++ /* We're looking for an invalid ID to terminate a ++ * valid range */ ++ if (!isvalid) { ++ /* Release the range of valid IDs, an unvalid ++ * range is now underway */ ++ if (loop > id) ++ dpa_alloc_free(alloc, id, loop - id); ++ valid_mode = 0; ++ } ++ } ++ loop++; ++ } ++ /* Release any unterminated range of valid IDs */ ++ if (valid_mode && count) ++ dpa_alloc_free(alloc, id, count); ++ return total_invalid; ++} ++ ++/* BPID allocator front-end */ ++ ++int bman_alloc_bpid_range(u32 *result, u32 count, u32 align, int partial) ++{ ++ return dpa_alloc_new(&bpalloc, result, count, align, partial); ++} ++EXPORT_SYMBOL(bman_alloc_bpid_range); ++ ++static int bp_cleanup(u32 bpid) ++{ ++ return bman_shutdown_pool(bpid) == 0; ++} ++void bman_release_bpid_range(u32 bpid, u32 count) ++{ ++ u32 total_invalid = release_id_range(&bpalloc, bpid, count, bp_cleanup); ++ if (total_invalid) ++ pr_err("BPID range [%d..%d] (%d) had %d leaks\n", ++ bpid, bpid + count - 1, count, total_invalid); ++} ++EXPORT_SYMBOL(bman_release_bpid_range); ++ ++void bman_seed_bpid_range(u32 bpid, u32 count) ++{ ++ dpa_alloc_seed(&bpalloc, bpid, count); ++} ++EXPORT_SYMBOL(bman_seed_bpid_range); ++ ++int bman_reserve_bpid_range(u32 bpid, u32 count) ++{ ++ return dpa_alloc_reserve(&bpalloc, bpid, count); ++} ++EXPORT_SYMBOL(bman_reserve_bpid_range); ++ ++ ++/* FQID allocator front-end */ ++ ++int qman_alloc_fqid_range(u32 *result, u32 count, u32 align, int partial) ++{ ++ return dpa_alloc_new(&fqalloc, result, count, align, partial); ++} ++EXPORT_SYMBOL(qman_alloc_fqid_range); ++ ++static int fq_cleanup(u32 fqid) ++{ ++ return qman_shutdown_fq(fqid) == 0; ++} ++void qman_release_fqid_range(u32 fqid, u32 count) ++{ ++ u32 total_invalid = release_id_range(&fqalloc, fqid, count, fq_cleanup); ++ if (total_invalid) ++ pr_err("FQID range [%d..%d] (%d) had %d leaks\n", ++ fqid, fqid + count - 1, count, total_invalid); ++} ++EXPORT_SYMBOL(qman_release_fqid_range); ++ ++int qman_reserve_fqid_range(u32 fqid, u32 count) ++{ ++ return dpa_alloc_reserve(&fqalloc, fqid, count); ++} ++EXPORT_SYMBOL(qman_reserve_fqid_range); ++ ++void qman_seed_fqid_range(u32 fqid, u32 count) ++{ ++ dpa_alloc_seed(&fqalloc, fqid, count); ++} ++EXPORT_SYMBOL(qman_seed_fqid_range); ++ ++/* Pool-channel allocator front-end */ ++ ++int qman_alloc_pool_range(u32 *result, u32 count, u32 align, int partial) ++{ ++ return dpa_alloc_new(&qpalloc, result, count, align, partial); ++} ++EXPORT_SYMBOL(qman_alloc_pool_range); ++ ++static int qpool_cleanup(u32 qp) ++{ ++ /* We query all FQDs starting from ++ * FQID 1 until we get an "invalid FQID" error, looking for non-OOS FQDs ++ * whose destination channel is the pool-channel being released. ++ * When a non-OOS FQD is found we attempt to clean it up */ ++ struct qman_fq fq = { ++ .fqid = 1 ++ }; ++ int err; ++ do { ++ struct qm_mcr_queryfq_np np; ++ err = qman_query_fq_np(&fq, &np); ++ if (err) ++ /* FQID range exceeded, found no problems */ ++ return 1; ++ if ((np.state & QM_MCR_NP_STATE_MASK) != QM_MCR_NP_STATE_OOS) { ++ struct qm_fqd fqd; ++ err = qman_query_fq(&fq, &fqd); ++ BUG_ON(err); ++ if (fqd.dest.channel == qp) { ++ /* The channel is the FQ's target, clean it */ ++ if (qman_shutdown_fq(fq.fqid) != 0) ++ /* Couldn't shut down the FQ ++ so the pool must be leaked */ ++ return 0; ++ } ++ } ++ /* Move to the next FQID */ ++ fq.fqid++; ++ } while (1); ++} ++void qman_release_pool_range(u32 qp, u32 count) ++{ ++ u32 total_invalid = release_id_range(&qpalloc, qp, ++ count, qpool_cleanup); ++ if (total_invalid) { ++ /* Pool channels are almost always used individually */ ++ if (count == 1) ++ pr_err("Pool channel 0x%x had %d leaks\n", ++ qp, total_invalid); ++ else ++ pr_err("Pool channels [%d..%d] (%d) had %d leaks\n", ++ qp, qp + count - 1, count, total_invalid); ++ } ++} ++EXPORT_SYMBOL(qman_release_pool_range); ++ ++ ++void qman_seed_pool_range(u32 poolid, u32 count) ++{ ++ dpa_alloc_seed(&qpalloc, poolid, count); ++ ++} ++EXPORT_SYMBOL(qman_seed_pool_range); ++ ++int qman_reserve_pool_range(u32 poolid, u32 count) ++{ ++ return dpa_alloc_reserve(&qpalloc, poolid, count); ++} ++EXPORT_SYMBOL(qman_reserve_pool_range); ++ ++ ++/* CGR ID allocator front-end */ ++ ++int qman_alloc_cgrid_range(u32 *result, u32 count, u32 align, int partial) ++{ ++ return dpa_alloc_new(&cgralloc, result, count, align, partial); ++} ++EXPORT_SYMBOL(qman_alloc_cgrid_range); ++ ++static int cqr_cleanup(u32 cgrid) ++{ ++ /* We query all FQDs starting from ++ * FQID 1 until we get an "invalid FQID" error, looking for non-OOS FQDs ++ * whose CGR is the CGR being released. ++ */ ++ struct qman_fq fq = { ++ .fqid = 1 ++ }; ++ int err; ++ do { ++ struct qm_mcr_queryfq_np np; ++ err = qman_query_fq_np(&fq, &np); ++ if (err) ++ /* FQID range exceeded, found no problems */ ++ return 1; ++ if ((np.state & QM_MCR_NP_STATE_MASK) != QM_MCR_NP_STATE_OOS) { ++ struct qm_fqd fqd; ++ err = qman_query_fq(&fq, &fqd); ++ BUG_ON(err); ++ if ((fqd.fq_ctrl & QM_FQCTRL_CGE) && ++ (fqd.cgid == cgrid)) { ++ pr_err("CRGID 0x%x is being used by FQID 0x%x," ++ " CGR will be leaked\n", ++ cgrid, fq.fqid); ++ return 1; ++ } ++ } ++ /* Move to the next FQID */ ++ fq.fqid++; ++ } while (1); ++} ++ ++void qman_release_cgrid_range(u32 cgrid, u32 count) ++{ ++ u32 total_invalid = release_id_range(&cgralloc, cgrid, ++ count, cqr_cleanup); ++ if (total_invalid) ++ pr_err("CGRID range [%d..%d] (%d) had %d leaks\n", ++ cgrid, cgrid + count - 1, count, total_invalid); ++} ++EXPORT_SYMBOL(qman_release_cgrid_range); ++ ++void qman_seed_cgrid_range(u32 cgrid, u32 count) ++{ ++ dpa_alloc_seed(&cgralloc, cgrid, count); ++ ++} ++EXPORT_SYMBOL(qman_seed_cgrid_range); ++ ++/* CEETM CHANNEL ID allocator front-end */ ++int qman_alloc_ceetm0_channel_range(u32 *result, u32 count, u32 align, ++ int partial) ++{ ++ return dpa_alloc_new(&ceetm0_challoc, result, count, align, partial); ++} ++EXPORT_SYMBOL(qman_alloc_ceetm0_channel_range); ++ ++int qman_alloc_ceetm1_channel_range(u32 *result, u32 count, u32 align, ++ int partial) ++{ ++ return dpa_alloc_new(&ceetm1_challoc, result, count, align, partial); ++} ++EXPORT_SYMBOL(qman_alloc_ceetm1_channel_range); ++ ++void qman_release_ceetm0_channel_range(u32 channelid, u32 count) ++{ ++ u32 total_invalid; ++ ++ total_invalid = release_id_range(&ceetm0_challoc, channelid, count, ++ NULL); ++ if (total_invalid) ++ pr_err("CEETM channel range [%d..%d] (%d) had %d leaks\n", ++ channelid, channelid + count - 1, count, total_invalid); ++} ++EXPORT_SYMBOL(qman_release_ceetm0_channel_range); ++ ++void qman_seed_ceetm0_channel_range(u32 channelid, u32 count) ++{ ++ dpa_alloc_seed(&ceetm0_challoc, channelid, count); ++ ++} ++EXPORT_SYMBOL(qman_seed_ceetm0_channel_range); ++ ++void qman_release_ceetm1_channel_range(u32 channelid, u32 count) ++{ ++ u32 total_invalid; ++ total_invalid = release_id_range(&ceetm1_challoc, channelid, count, ++ NULL); ++ if (total_invalid) ++ pr_err("CEETM channel range [%d..%d] (%d) had %d leaks\n", ++ channelid, channelid + count - 1, count, total_invalid); ++} ++EXPORT_SYMBOL(qman_release_ceetm1_channel_range); ++ ++void qman_seed_ceetm1_channel_range(u32 channelid, u32 count) ++{ ++ dpa_alloc_seed(&ceetm1_challoc, channelid, count); ++ ++} ++EXPORT_SYMBOL(qman_seed_ceetm1_channel_range); ++ ++/* CEETM LFQID allocator front-end */ ++int qman_alloc_ceetm0_lfqid_range(u32 *result, u32 count, u32 align, ++ int partial) ++{ ++ return dpa_alloc_new(&ceetm0_lfqidalloc, result, count, align, partial); ++} ++EXPORT_SYMBOL(qman_alloc_ceetm0_lfqid_range); ++ ++int qman_alloc_ceetm1_lfqid_range(u32 *result, u32 count, u32 align, ++ int partial) ++{ ++ return dpa_alloc_new(&ceetm1_lfqidalloc, result, count, align, partial); ++} ++EXPORT_SYMBOL(qman_alloc_ceetm1_lfqid_range); ++ ++void qman_release_ceetm0_lfqid_range(u32 lfqid, u32 count) ++{ ++ u32 total_invalid; ++ ++ total_invalid = release_id_range(&ceetm0_lfqidalloc, lfqid, count, ++ NULL); ++ if (total_invalid) ++ pr_err("CEETM LFQID range [0x%x..0x%x] (%d) had %d leaks\n", ++ lfqid, lfqid + count - 1, count, total_invalid); ++} ++EXPORT_SYMBOL(qman_release_ceetm0_lfqid_range); ++ ++void qman_seed_ceetm0_lfqid_range(u32 lfqid, u32 count) ++{ ++ dpa_alloc_seed(&ceetm0_lfqidalloc, lfqid, count); ++ ++} ++EXPORT_SYMBOL(qman_seed_ceetm0_lfqid_range); ++ ++void qman_release_ceetm1_lfqid_range(u32 lfqid, u32 count) ++{ ++ u32 total_invalid; ++ ++ total_invalid = release_id_range(&ceetm1_lfqidalloc, lfqid, count, ++ NULL); ++ if (total_invalid) ++ pr_err("CEETM LFQID range [0x%x..0x%x] (%d) had %d leaks\n", ++ lfqid, lfqid + count - 1, count, total_invalid); ++} ++EXPORT_SYMBOL(qman_release_ceetm1_lfqid_range); ++ ++void qman_seed_ceetm1_lfqid_range(u32 lfqid, u32 count) ++{ ++ dpa_alloc_seed(&ceetm1_lfqidalloc, lfqid, count); ++ ++} ++EXPORT_SYMBOL(qman_seed_ceetm1_lfqid_range); ++ ++ ++/* Everything else is the common backend to all the allocators */ ++ ++/* The allocator is a (possibly-empty) list of these; */ ++struct alloc_node { ++ struct list_head list; ++ u32 base; ++ u32 num; ++ /* refcount and is_alloced are only set ++ when the node is in the used list */ ++ unsigned int refcount; ++ int is_alloced; ++}; ++ ++/* #define DPA_ALLOC_DEBUG */ ++ ++#ifdef DPA_ALLOC_DEBUG ++#define DPRINT pr_info ++static void DUMP(struct dpa_alloc *alloc) ++{ ++ int off = 0; ++ char buf[256]; ++ struct alloc_node *p; ++ pr_info("Free Nodes\n"); ++ list_for_each_entry(p, &alloc->free, list) { ++ if (off < 255) ++ off += snprintf(buf + off, 255-off, "{%d,%d}", ++ p->base, p->base + p->num - 1); ++ } ++ pr_info("%s\n", buf); ++ ++ off = 0; ++ pr_info("Used Nodes\n"); ++ list_for_each_entry(p, &alloc->used, list) { ++ if (off < 255) ++ off += snprintf(buf + off, 255-off, "{%d,%d}", ++ p->base, p->base + p->num - 1); ++ } ++ pr_info("%s\n", buf); ++ ++ ++ ++} ++#else ++#define DPRINT(x...) ++#define DUMP(a) ++#endif ++ ++int dpa_alloc_new(struct dpa_alloc *alloc, u32 *result, u32 count, u32 align, ++ int partial) ++{ ++ struct alloc_node *i = NULL, *next_best = NULL, *used_node = NULL; ++ u32 base, next_best_base = 0, num = 0, next_best_num = 0; ++ struct alloc_node *margin_left, *margin_right; ++ ++ *result = (u32)-1; ++ DPRINT("alloc_range(%d,%d,%d)\n", count, align, partial); ++ DUMP(alloc); ++ /* If 'align' is 0, it should behave as though it was 1 */ ++ if (!align) ++ align = 1; ++ margin_left = kmalloc(sizeof(*margin_left), GFP_KERNEL); ++ if (!margin_left) ++ goto err; ++ margin_right = kmalloc(sizeof(*margin_right), GFP_KERNEL); ++ if (!margin_right) { ++ kfree(margin_left); ++ goto err; ++ } ++ spin_lock_irq(&alloc->lock); ++ list_for_each_entry(i, &alloc->free, list) { ++ base = (i->base + align - 1) / align; ++ base *= align; ++ if ((base - i->base) >= i->num) ++ /* alignment is impossible, regardless of count */ ++ continue; ++ num = i->num - (base - i->base); ++ if (num >= count) { ++ /* this one will do nicely */ ++ num = count; ++ goto done; ++ } ++ if (num > next_best_num) { ++ next_best = i; ++ next_best_base = base; ++ next_best_num = num; ++ } ++ } ++ if (partial && next_best) { ++ i = next_best; ++ base = next_best_base; ++ num = next_best_num; ++ } else ++ i = NULL; ++done: ++ if (i) { ++ if (base != i->base) { ++ margin_left->base = i->base; ++ margin_left->num = base - i->base; ++ list_add_tail(&margin_left->list, &i->list); ++ } else ++ kfree(margin_left); ++ if ((base + num) < (i->base + i->num)) { ++ margin_right->base = base + num; ++ margin_right->num = (i->base + i->num) - ++ (base + num); ++ list_add(&margin_right->list, &i->list); ++ } else ++ kfree(margin_right); ++ list_del(&i->list); ++ kfree(i); ++ *result = base; ++ } else { ++ spin_unlock_irq(&alloc->lock); ++ kfree(margin_left); ++ kfree(margin_right); ++ } ++ ++err: ++ DPRINT("returning %d\n", i ? num : -ENOMEM); ++ DUMP(alloc); ++ if (!i) ++ return -ENOMEM; ++ ++ /* Add the allocation to the used list with a refcount of 1 */ ++ used_node = kmalloc(sizeof(*used_node), GFP_KERNEL); ++ if (!used_node) { ++ spin_unlock_irq(&alloc->lock); ++ return -ENOMEM; ++ } ++ used_node->base = *result; ++ used_node->num = num; ++ used_node->refcount = 1; ++ used_node->is_alloced = 1; ++ list_add_tail(&used_node->list, &alloc->used); ++ spin_unlock_irq(&alloc->lock); ++ return (int)num; ++} ++ ++/* Allocate the list node using GFP_ATOMIC, because we *really* want to avoid ++ * forcing error-handling on to users in the deallocation path. */ ++static void _dpa_alloc_free(struct dpa_alloc *alloc, u32 base_id, u32 count) ++{ ++ struct alloc_node *i, *node = kmalloc(sizeof(*node), GFP_ATOMIC); ++ BUG_ON(!node); ++ DPRINT("release_range(%d,%d)\n", base_id, count); ++ DUMP(alloc); ++ BUG_ON(!count); ++ spin_lock_irq(&alloc->lock); ++ ++ ++ node->base = base_id; ++ node->num = count; ++ list_for_each_entry(i, &alloc->free, list) { ++ if (i->base >= node->base) { ++ /* BUG_ON(any overlapping) */ ++ BUG_ON(i->base < (node->base + node->num)); ++ list_add_tail(&node->list, &i->list); ++ goto done; ++ } ++ } ++ list_add_tail(&node->list, &alloc->free); ++done: ++ /* Merge to the left */ ++ i = list_entry(node->list.prev, struct alloc_node, list); ++ if (node->list.prev != &alloc->free) { ++ BUG_ON((i->base + i->num) > node->base); ++ if ((i->base + i->num) == node->base) { ++ node->base = i->base; ++ node->num += i->num; ++ list_del(&i->list); ++ kfree(i); ++ } ++ } ++ /* Merge to the right */ ++ i = list_entry(node->list.next, struct alloc_node, list); ++ if (node->list.next != &alloc->free) { ++ BUG_ON((node->base + node->num) > i->base); ++ if ((node->base + node->num) == i->base) { ++ node->num += i->num; ++ list_del(&i->list); ++ kfree(i); ++ } ++ } ++ spin_unlock_irq(&alloc->lock); ++ DUMP(alloc); ++} ++ ++ ++void dpa_alloc_free(struct dpa_alloc *alloc, u32 base_id, u32 count) ++{ ++ struct alloc_node *i = NULL; ++ spin_lock_irq(&alloc->lock); ++ ++ /* First find the node in the used list and decrement its ref count */ ++ list_for_each_entry(i, &alloc->used, list) { ++ if (i->base == base_id && i->num == count) { ++ --i->refcount; ++ if (i->refcount == 0) { ++ list_del(&i->list); ++ spin_unlock_irq(&alloc->lock); ++ if (i->is_alloced) ++ _dpa_alloc_free(alloc, base_id, count); ++ kfree(i); ++ return; ++ } ++ spin_unlock_irq(&alloc->lock); ++ return; ++ } ++ } ++ /* Couldn't find the allocation */ ++ pr_err("Attempt to free ID 0x%x COUNT %d that wasn't alloc'd or reserved\n", ++ base_id, count); ++ spin_unlock_irq(&alloc->lock); ++} ++ ++void dpa_alloc_seed(struct dpa_alloc *alloc, u32 base_id, u32 count) ++{ ++ /* Same as free but no previous allocation checking is needed */ ++ _dpa_alloc_free(alloc, base_id, count); ++} ++ ++ ++int dpa_alloc_reserve(struct dpa_alloc *alloc, u32 base, u32 num) ++{ ++ struct alloc_node *i = NULL, *used_node; ++ ++ DPRINT("alloc_reserve(%d,%d)\n", base, num); ++ DUMP(alloc); ++ ++ spin_lock_irq(&alloc->lock); ++ ++ /* Check for the node in the used list. ++ If found, increase it's refcount */ ++ list_for_each_entry(i, &alloc->used, list) { ++ if ((i->base == base) && (i->num == num)) { ++ ++i->refcount; ++ spin_unlock_irq(&alloc->lock); ++ return 0; ++ } ++ if ((base >= i->base) && (base < (i->base + i->num))) { ++ /* This is an attempt to reserve a region that was ++ already reserved or alloced with a different ++ base or num */ ++ pr_err("Cannot reserve %d - %d, it overlaps with" ++ " existing reservation from %d - %d\n", ++ base, base + num - 1, i->base, ++ i->base + i->num - 1); ++ spin_unlock_irq(&alloc->lock); ++ return -1; ++ } ++ } ++ /* Check to make sure this ID isn't in the free list */ ++ list_for_each_entry(i, &alloc->free, list) { ++ if ((base >= i->base) && (base < (i->base + i->num))) { ++ /* yep, the reservation is within this node */ ++ pr_err("Cannot reserve %d - %d, it overlaps with" ++ " free range %d - %d and must be alloced\n", ++ base, base + num - 1, ++ i->base, i->base + i->num - 1); ++ spin_unlock_irq(&alloc->lock); ++ return -1; ++ } ++ } ++ /* Add the allocation to the used list with a refcount of 1 */ ++ used_node = kmalloc(sizeof(*used_node), GFP_KERNEL); ++ if (!used_node) { ++ spin_unlock_irq(&alloc->lock); ++ return -ENOMEM; ++ ++ } ++ used_node->base = base; ++ used_node->num = num; ++ used_node->refcount = 1; ++ used_node->is_alloced = 0; ++ list_add_tail(&used_node->list, &alloc->used); ++ spin_unlock_irq(&alloc->lock); ++ return 0; ++} ++ ++ ++int dpa_alloc_pop(struct dpa_alloc *alloc, u32 *result, u32 *count) ++{ ++ struct alloc_node *i = NULL; ++ DPRINT("alloc_pop()\n"); ++ DUMP(alloc); ++ spin_lock_irq(&alloc->lock); ++ if (!list_empty(&alloc->free)) { ++ i = list_entry(alloc->free.next, struct alloc_node, list); ++ list_del(&i->list); ++ } ++ spin_unlock_irq(&alloc->lock); ++ DPRINT("returning %d\n", i ? 0 : -ENOMEM); ++ DUMP(alloc); ++ if (!i) ++ return -ENOMEM; ++ *result = i->base; ++ *count = i->num; ++ kfree(i); ++ return 0; ++} ++ ++int dpa_alloc_check(struct dpa_alloc *list_head, u32 item) ++{ ++ struct alloc_node *i = NULL; ++ int res = 0; ++ DPRINT("alloc_check()\n"); ++ spin_lock_irq(&list_head->lock); ++ ++ list_for_each_entry(i, &list_head->free, list) { ++ if ((item >= i->base) && (item < (i->base + i->num))) { ++ res = 1; ++ break; ++ } ++ } ++ spin_unlock_irq(&list_head->lock); ++ return res; ++} +diff --git a/drivers/staging/fsl_qbman/dpa_sys.h b/drivers/staging/fsl_qbman/dpa_sys.h +new file mode 100644 +index 0000000..7dd0640 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/dpa_sys.h +@@ -0,0 +1,301 @@ ++/* Copyright 2008-2012 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 DPA_SYS_H ++#define DPA_SYS_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* When copying aligned words or shorts, try to avoid memcpy() */ ++#define CONFIG_TRY_BETTER_MEMCPY ++ ++/* For 2-element tables related to cache-inhibited and cache-enabled mappings */ ++#define DPA_PORTAL_CE 0 ++#define DPA_PORTAL_CI 1 ++ ++/***********************/ ++/* Misc inline assists */ ++/***********************/ ++ ++/* TODO: NB, we currently assume that hwsync() and lwsync() imply compiler ++ * barriers and that dcb*() won't fall victim to compiler or execution ++ * reordering with respect to other code/instructions that manipulate the same ++ * cacheline. */ ++#define hwsync() __asm__ __volatile__ ("sync" : : : "memory") ++#define lwsync()__asm__ __volatile__ (stringify_in_c(LWSYNC) : : : "memory") ++#define dcbf(p) __asm__ __volatile__ ("dcbf 0,%0" : : "r" (p) : "memory") ++#define dcbt_ro(p) __asm__ __volatile__ ("dcbt 0,%0" : : "r" (p)) ++#define dcbt_rw(p) __asm__ __volatile__ ("dcbtst 0,%0" : : "r" (p)) ++#define dcbi(p) dcbf(p) ++#ifdef CONFIG_PPC_E500MC ++#define dcbzl(p) __asm__ __volatile__ ("dcbzl 0,%0" : : "r" (p)) ++#define dcbz_64(p) dcbzl(p) ++#define dcbf_64(p) dcbf(p) ++/* Commonly used combo */ ++#define dcbit_ro(p) \ ++ do { \ ++ dcbi(p); \ ++ dcbt_ro(p); \ ++ } while (0) ++#else ++#define dcbz(p)__asm__ __volatile__ ("dcbz 0,%0" : : "r" (p)) ++#define dcbz_64(p) \ ++ do { \ ++ dcbz((u32)p + 32); \ ++ dcbz(p); \ ++ } while (0) ++#define dcbf_64(p) \ ++ do { \ ++ dcbf((u32)p + 32); \ ++ dcbf(p); \ ++ } while (0) ++/* Commonly used combo */ ++#define dcbit_ro(p) \ ++ do { \ ++ dcbi(p); \ ++ dcbi((u32)p + 32); \ ++ dcbt_ro(p); \ ++ dcbt_ro((u32)p + 32); \ ++ } while (0) ++#endif /* CONFIG_PPC_E500MC */ ++ ++static inline u64 mfatb(void) ++{ ++ u32 hi, lo, chk; ++ do { ++ hi = mfspr(SPRN_ATBU); ++ lo = mfspr(SPRN_ATBL); ++ chk = mfspr(SPRN_ATBU); ++ } while (unlikely(hi != chk)); ++ return ((u64)hi << 32) | (u64)lo; ++} ++ ++#ifdef CONFIG_FSL_DPA_CHECKING ++#define DPA_ASSERT(x) \ ++ do { \ ++ if (!(x)) { \ ++ pr_crit("ASSERT: (%s:%d) %s\n", __FILE__, __LINE__, \ ++ __stringify_1(x)); \ ++ dump_stack(); \ ++ panic("assertion failure"); \ ++ } \ ++ } while (0) ++#else ++#define DPA_ASSERT(x) ++#endif ++ ++/* memcpy() stuff - when you know alignments in advance */ ++#ifdef CONFIG_TRY_BETTER_MEMCPY ++static inline void copy_words(void *dest, const void *src, size_t sz) ++{ ++ u32 *__dest = dest; ++ const u32 *__src = src; ++ size_t __sz = sz >> 2; ++ BUG_ON((unsigned long)dest & 0x3); ++ BUG_ON((unsigned long)src & 0x3); ++ BUG_ON(sz & 0x3); ++ while (__sz--) ++ *(__dest++) = *(__src++); ++} ++static inline void copy_shorts(void *dest, const void *src, size_t sz) ++{ ++ u16 *__dest = dest; ++ const u16 *__src = src; ++ size_t __sz = sz >> 1; ++ BUG_ON((unsigned long)dest & 0x1); ++ BUG_ON((unsigned long)src & 0x1); ++ BUG_ON(sz & 0x1); ++ while (__sz--) ++ *(__dest++) = *(__src++); ++} ++static inline void copy_bytes(void *dest, const void *src, size_t sz) ++{ ++ u8 *__dest = dest; ++ const u8 *__src = src; ++ while (sz--) ++ *(__dest++) = *(__src++); ++} ++#else ++#define copy_words memcpy ++#define copy_shorts memcpy ++#define copy_bytes memcpy ++#endif ++ ++/************/ ++/* RB-trees */ ++/************/ ++ ++/* We encapsulate RB-trees so that its easier to use non-linux forms in ++ * non-linux systems. This also encapsulates the extra plumbing that linux code ++ * usually provides when using RB-trees. This encapsulation assumes that the ++ * data type held by the tree is u32. */ ++ ++struct dpa_rbtree { ++ struct rb_root root; ++}; ++#define DPA_RBTREE { .root = RB_ROOT } ++ ++static inline void dpa_rbtree_init(struct dpa_rbtree *tree) ++{ ++ tree->root = RB_ROOT; ++} ++ ++#define IMPLEMENT_DPA_RBTREE(name, type, node_field, val_field) \ ++static inline int name##_push(struct dpa_rbtree *tree, type *obj) \ ++{ \ ++ struct rb_node *parent = NULL, **p = &tree->root.rb_node; \ ++ while (*p) { \ ++ u32 item; \ ++ parent = *p; \ ++ item = rb_entry(parent, type, node_field)->val_field; \ ++ if (obj->val_field < item) \ ++ p = &parent->rb_left; \ ++ else if (obj->val_field > item) \ ++ p = &parent->rb_right; \ ++ else \ ++ return -EBUSY; \ ++ } \ ++ rb_link_node(&obj->node_field, parent, p); \ ++ rb_insert_color(&obj->node_field, &tree->root); \ ++ return 0; \ ++} \ ++static inline void name##_del(struct dpa_rbtree *tree, type *obj) \ ++{ \ ++ rb_erase(&obj->node_field, &tree->root); \ ++} \ ++static inline type *name##_find(struct dpa_rbtree *tree, u32 val) \ ++{ \ ++ type *ret; \ ++ struct rb_node *p = tree->root.rb_node; \ ++ while (p) { \ ++ ret = rb_entry(p, type, node_field); \ ++ if (val < ret->val_field) \ ++ p = p->rb_left; \ ++ else if (val > ret->val_field) \ ++ p = p->rb_right; \ ++ else \ ++ return ret; \ ++ } \ ++ return NULL; \ ++} ++ ++/************/ ++/* Bootargs */ ++/************/ ++ ++/* Qman has "qportals=" and Bman has "bportals=", they use the same syntax ++ * though; a comma-separated list of items, each item being a cpu index and/or a ++ * range of cpu indices, and each item optionally be prefixed by "s" to indicate ++ * that the portal associated with that cpu should be shared. See bman_driver.c ++ * for more specifics. */ ++static int __parse_portals_cpu(const char **s, unsigned int *cpu) ++{ ++ *cpu = 0; ++ if (!isdigit(**s)) ++ return -EINVAL; ++ while (isdigit(**s)) ++ *cpu = *cpu * 10 + (*((*s)++) - '0'); ++ return 0; ++} ++static inline int parse_portals_bootarg(char *str, struct cpumask *want_shared, ++ struct cpumask *want_unshared, ++ const char *argname) ++{ ++ const char *s = str; ++ unsigned int shared, cpu1, cpu2, loop; ++ ++keep_going: ++ if (*s == 's') { ++ shared = 1; ++ s++; ++ } else ++ shared = 0; ++ if (__parse_portals_cpu(&s, &cpu1)) ++ goto err; ++ if (*s == '-') { ++ s++; ++ if (__parse_portals_cpu(&s, &cpu2)) ++ goto err; ++ if (cpu2 < cpu1) ++ goto err; ++ } else ++ cpu2 = cpu1; ++ for (loop = cpu1; loop <= cpu2; loop++) ++ cpumask_set_cpu(loop, shared ? want_shared : want_unshared); ++ if (*s == ',') { ++ s++; ++ goto keep_going; ++ } else if ((*s == '\0') || isspace(*s)) ++ return 0; ++err: ++ pr_crit("Malformed %s argument: %s, offset: %lu\n", argname, str, ++ (unsigned long)s - (unsigned long)str); ++ return -EINVAL; ++} ++ ++/* Hooks from fsl_usdpaa_irq.c to fsl_usdpaa.c */ ++int usdpaa_get_portal_config(struct file *filp, void *cinh, ++ enum usdpaa_portal_type ptype, unsigned int *irq, ++ void **iir_reg); ++ ++#endif /* DPA_SYS_H */ +diff --git a/drivers/staging/fsl_qbman/fsl_usdpaa.c b/drivers/staging/fsl_qbman/fsl_usdpaa.c +new file mode 100644 +index 0000000..955b345 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/fsl_usdpaa.c +@@ -0,0 +1,1939 @@ ++/* Copyright (C) 2008-2012 Freescale Semiconductor, Inc. ++ * Authors: Andy Fleming ++ * Timur Tabi ++ * Geoff Thorpe ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include ++#include "bman_low.h" ++#include "qman_low.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Physical address range of the memory reservation, exported for mm/mem.c */ ++static u64 phys_start; ++static u64 phys_size; ++/* PFN versions of the above */ ++static unsigned long pfn_start; ++static unsigned long pfn_size; ++ ++/* Memory reservations are manipulated under this spinlock (which is why 'refs' ++ * isn't atomic_t). */ ++static DEFINE_SPINLOCK(mem_lock); ++ ++/* The range of TLB1 indices */ ++static unsigned int first_tlb; ++static unsigned int num_tlb; ++static unsigned int current_tlb; /* loops around for fault handling */ ++ ++/* Memory reservation is represented as a list of 'mem_fragment's, some of which ++ * may be mapped. Unmapped fragments are always merged where possible. */ ++static LIST_HEAD(mem_list); ++ ++struct mem_mapping; ++ ++/* Memory fragments are in 'mem_list'. */ ++struct mem_fragment { ++ u64 base; ++ u64 len; ++ unsigned long pfn_base; /* PFN version of 'base' */ ++ unsigned long pfn_len; /* PFN version of 'len' */ ++ unsigned int refs; /* zero if unmapped */ ++ u64 root_len; /* Size of the orignal fragment */ ++ unsigned long root_pfn; /* PFN of the orignal fragment */ ++ struct list_head list; ++ /* if mapped, flags+name captured at creation time */ ++ u32 flags; ++ char name[USDPAA_DMA_NAME_MAX]; ++ u64 map_len; ++ /* support multi-process locks per-memory-fragment. */ ++ int has_locking; ++ wait_queue_head_t wq; ++ struct mem_mapping *owner; ++}; ++ ++/* Mappings of memory fragments in 'struct ctx'. These are created from ++ * ioctl(USDPAA_IOCTL_DMA_MAP), though the actual mapping then happens via a ++ * mmap(). */ ++struct mem_mapping { ++ struct mem_fragment *root_frag; ++ u32 frag_count; ++ u64 total_size; ++ struct list_head list; ++ int refs; ++ void *virt_addr; ++}; ++ ++struct portal_mapping { ++ struct usdpaa_ioctl_portal_map user; ++ union { ++ struct qm_portal_config *qportal; ++ struct bm_portal_config *bportal; ++ }; ++ /* Declare space for the portals in case the process ++ exits unexpectedly and needs to be cleaned by the kernel */ ++ union { ++ struct qm_portal qman_portal_low; ++ struct bm_portal bman_portal_low; ++ }; ++ struct list_head list; ++ struct resource *phys; ++ struct iommu_domain *iommu_domain; ++}; ++ ++/* Track the DPAA resources the process is using */ ++struct active_resource { ++ struct list_head list; ++ u32 id; ++ u32 num; ++ unsigned int refcount; ++}; ++ ++/* Per-FD state (which should also be per-process but we don't enforce that) */ ++struct ctx { ++ /* Lock to protect the context */ ++ spinlock_t lock; ++ /* Allocated resources get put here for accounting */ ++ struct list_head resources[usdpaa_id_max]; ++ /* list of DMA maps */ ++ struct list_head maps; ++ /* list of portal maps */ ++ struct list_head portals; ++}; ++ ++/* Different resource classes */ ++static const struct alloc_backend { ++ enum usdpaa_id_type id_type; ++ int (*alloc)(u32 *, u32, u32, int); ++ void (*release)(u32 base, unsigned int count); ++ int (*reserve)(u32 base, unsigned int count); ++ const char *acronym; ++} alloc_backends[] = { ++ { ++ .id_type = usdpaa_id_fqid, ++ .alloc = qman_alloc_fqid_range, ++ .release = qman_release_fqid_range, ++ .reserve = qman_reserve_fqid_range, ++ .acronym = "FQID" ++ }, ++ { ++ .id_type = usdpaa_id_bpid, ++ .alloc = bman_alloc_bpid_range, ++ .release = bman_release_bpid_range, ++ .reserve = bman_reserve_bpid_range, ++ .acronym = "BPID" ++ }, ++ { ++ .id_type = usdpaa_id_qpool, ++ .alloc = qman_alloc_pool_range, ++ .release = qman_release_pool_range, ++ .reserve = qman_reserve_pool_range, ++ .acronym = "QPOOL" ++ }, ++ { ++ .id_type = usdpaa_id_cgrid, ++ .alloc = qman_alloc_cgrid_range, ++ .release = qman_release_cgrid_range, ++ .acronym = "CGRID" ++ }, ++ { ++ .id_type = usdpaa_id_ceetm0_lfqid, ++ .alloc = qman_alloc_ceetm0_lfqid_range, ++ .release = qman_release_ceetm0_lfqid_range, ++ .acronym = "CEETM0_LFQID" ++ }, ++ { ++ .id_type = usdpaa_id_ceetm0_channelid, ++ .alloc = qman_alloc_ceetm0_channel_range, ++ .release = qman_release_ceetm0_channel_range, ++ .acronym = "CEETM0_LFQID" ++ }, ++ { ++ .id_type = usdpaa_id_ceetm1_lfqid, ++ .alloc = qman_alloc_ceetm1_lfqid_range, ++ .release = qman_release_ceetm1_lfqid_range, ++ .acronym = "CEETM1_LFQID" ++ }, ++ { ++ .id_type = usdpaa_id_ceetm1_channelid, ++ .alloc = qman_alloc_ceetm1_channel_range, ++ .release = qman_release_ceetm1_channel_range, ++ .acronym = "CEETM1_LFQID" ++ }, ++ { ++ /* This terminates the array */ ++ .id_type = usdpaa_id_max ++ } ++}; ++ ++/* Determines the largest acceptable page size for a given size ++ The sizes are determined by what the TLB1 acceptable page sizes are */ ++static u32 largest_page_size(u32 size) ++{ ++ int shift = 30; /* Start at 1G size */ ++ if (size < 4096) ++ return 0; ++ do { ++ if (size >= (1<= 12); /* Up to 4k */ ++ return 0; ++} ++ ++/* Determine if value is power of 4 */ ++static inline bool is_power_of_4(u64 x) ++{ ++ if (x == 0 || ((x & (x - 1)) != 0)) ++ return false; ++ return !!(x & 0x5555555555555555ull); ++} ++ ++/* Helper for ioctl_dma_map() when we have a larger fragment than we need. This ++ * splits the fragment into 4 and returns the upper-most. (The caller can loop ++ * until it has a suitable fragment size.) */ ++static struct mem_fragment *split_frag(struct mem_fragment *frag) ++{ ++ struct mem_fragment *x[3]; ++ ++ x[0] = kmalloc(sizeof(struct mem_fragment), GFP_ATOMIC); ++ x[1] = kmalloc(sizeof(struct mem_fragment), GFP_ATOMIC); ++ x[2] = kmalloc(sizeof(struct mem_fragment), GFP_ATOMIC); ++ if (!x[0] || !x[1] || !x[2]) { ++ kfree(x[0]); ++ kfree(x[1]); ++ kfree(x[2]); ++ return NULL; ++ } ++ BUG_ON(frag->refs); ++ frag->len >>= 2; ++ frag->pfn_len >>= 2; ++ x[0]->base = frag->base + frag->len; ++ x[1]->base = x[0]->base + frag->len; ++ x[2]->base = x[1]->base + frag->len; ++ x[0]->len = x[1]->len = x[2]->len = frag->len; ++ x[0]->pfn_base = frag->pfn_base + frag->pfn_len; ++ x[1]->pfn_base = x[0]->pfn_base + frag->pfn_len; ++ x[2]->pfn_base = x[1]->pfn_base + frag->pfn_len; ++ x[0]->pfn_len = x[1]->pfn_len = x[2]->pfn_len = frag->pfn_len; ++ x[0]->refs = x[1]->refs = x[2]->refs = 0; ++ x[0]->root_len = x[1]->root_len = x[2]->root_len = frag->root_len; ++ x[0]->root_pfn = x[1]->root_pfn = x[2]->root_pfn = frag->root_pfn; ++ x[0]->name[0] = x[1]->name[0] = x[2]->name[0] = 0; ++ list_add_tail(&x[0]->list, &frag->list); ++ list_add_tail(&x[1]->list, &x[0]->list); ++ list_add_tail(&x[2]->list, &x[1]->list); ++ return x[2]; ++} ++ ++static __maybe_unused void dump_frags(void) ++{ ++ struct mem_fragment *frag; ++ int i = 0; ++ list_for_each_entry(frag, &mem_list, list) { ++ pr_info("FRAG %d: base 0x%llx pfn_base 0x%lx len 0x%llx root_len 0x%llx root_pfn 0x%lx refs %d name %s\n", ++ i, frag->base, frag->pfn_base, ++ frag->len, frag->root_len, frag->root_pfn, ++ frag->refs, frag->name); ++ ++i; ++ } ++} ++ ++/* Walk the list of fragments and adjoin neighbouring segments if possible */ ++static void compress_frags(void) ++{ ++ /* Walk the fragment list and combine fragments */ ++ struct mem_fragment *frag, *nxtfrag; ++ u64 len = 0; ++ ++ int i, numfrags; ++ ++ ++ frag = list_entry(mem_list.next, struct mem_fragment, list); ++ ++ while (&frag->list != &mem_list) { ++ /* Must combine consecutive fragemenst with ++ same root_pfn such that they are power of 4 */ ++ if (frag->refs != 0) { ++ frag = list_entry(frag->list.next, ++ struct mem_fragment, list); ++ continue; /* Not this window */ ++ } ++ len = frag->len; ++ numfrags = 0; ++ nxtfrag = list_entry(frag->list.next, ++ struct mem_fragment, list); ++ while (true) { ++ if (&nxtfrag->list == &mem_list) { ++ numfrags = 0; ++ break; /* End of list */ ++ } ++ if (nxtfrag->refs) { ++ numfrags = 0; ++ break; /* In use still */ ++ } ++ if (nxtfrag->root_pfn != frag->root_pfn) { ++ numfrags = 0; ++ break; /* Crosses root fragment boundary */ ++ } ++ len += nxtfrag->len; ++ numfrags++; ++ if (is_power_of_4(len)) { ++ /* These fragments can be combined */ ++ break; ++ } ++ nxtfrag = list_entry(nxtfrag->list.next, ++ struct mem_fragment, list); ++ } ++ if (numfrags == 0) { ++ frag = list_entry(frag->list.next, ++ struct mem_fragment, list); ++ continue; /* try the next window */ ++ } ++ for (i = 0; i < numfrags; i++) { ++ struct mem_fragment *todel = ++ list_entry(nxtfrag->list.prev, ++ struct mem_fragment, list); ++ nxtfrag->len += todel->len; ++ nxtfrag->pfn_len += todel->pfn_len; ++ list_del(&todel->list); ++ } ++ /* Re evaluate the list, things may merge now */ ++ frag = list_entry(mem_list.next, struct mem_fragment, list); ++ } ++} ++ ++/* Hook from arch/powerpc/mm/mem.c */ ++int usdpaa_test_fault(unsigned long pfn, u64 *phys_addr, u64 *size) ++{ ++ struct mem_fragment *frag; ++ int idx = -1; ++ if ((pfn < pfn_start) || (pfn >= (pfn_start + pfn_size))) ++ return -1; ++ /* It's in-range, we need to find the fragment */ ++ spin_lock(&mem_lock); ++ list_for_each_entry(frag, &mem_list, list) { ++ if ((pfn >= frag->pfn_base) && (pfn < (frag->pfn_base + ++ frag->pfn_len))) { ++ *phys_addr = frag->base; ++ *size = frag->len; ++ idx = current_tlb++; ++ if (current_tlb >= (first_tlb + num_tlb)) ++ current_tlb = first_tlb; ++ break; ++ } ++ } ++ spin_unlock(&mem_lock); ++ return idx; ++} ++ ++static int usdpaa_open(struct inode *inode, struct file *filp) ++{ ++ const struct alloc_backend *backend = &alloc_backends[0]; ++ struct ctx *ctx = kmalloc(sizeof(struct ctx), GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ filp->private_data = ctx; ++ ++ while (backend->id_type != usdpaa_id_max) { ++ INIT_LIST_HEAD(&ctx->resources[backend->id_type]); ++ backend++; ++ } ++ ++ INIT_LIST_HEAD(&ctx->maps); ++ INIT_LIST_HEAD(&ctx->portals); ++ spin_lock_init(&ctx->lock); ++ ++ //filp->f_mapping->backing_dev_info = &directly_mappable_cdev_bdi; ++ ++ return 0; ++} ++ ++#define DQRR_MAXFILL 15 ++ ++/* Reset a QMan portal to its default state */ ++static int init_qm_portal(struct qm_portal_config *config, ++ struct qm_portal *portal) ++{ ++ portal->addr.addr_ce = config->addr_virt[DPA_PORTAL_CE]; ++ portal->addr.addr_ci = config->addr_virt[DPA_PORTAL_CI]; ++ ++ /* Make sure interrupts are inhibited */ ++ qm_out(IIR, 1); ++ ++ /* Initialize the DQRR. This will stop any dequeue ++ commands that are in progress */ ++ if (qm_dqrr_init(portal, config, qm_dqrr_dpush, qm_dqrr_pvb, ++ qm_dqrr_cdc, DQRR_MAXFILL)) { ++ pr_err("qm_dqrr_init() failed when trying to" ++ " recover portal, portal will be leaked\n"); ++ return 1; ++ } ++ ++ /* Initialize the EQCR */ ++ if (qm_eqcr_init(portal, qm_eqcr_pvb, ++ qm_eqcr_get_ci_stashing(portal), 1)) { ++ pr_err("Qman EQCR initialisation failed\n"); ++ return 1; ++ } ++ /* initialize the MR */ ++ if (qm_mr_init(portal, qm_mr_pvb, qm_mr_cci)) { ++ pr_err("Qman MR initialisation failed\n"); ++ return 1; ++ } ++ qm_mr_pvb_update(portal); ++ while (qm_mr_current(portal)) { ++ qm_mr_next(portal); ++ qm_mr_cci_consume_to_current(portal); ++ qm_mr_pvb_update(portal); ++ } ++ ++ if (qm_mc_init(portal)) { ++ pr_err("Qman MC initialisation failed\n"); ++ return 1; ++ } ++ return 0; ++} ++ ++static int init_bm_portal(struct bm_portal_config *config, ++ struct bm_portal *portal) ++{ ++ portal->addr.addr_ce = config->addr_virt[DPA_PORTAL_CE]; ++ portal->addr.addr_ci = config->addr_virt[DPA_PORTAL_CI]; ++ ++ if (bm_rcr_init(portal, bm_rcr_pvb, bm_rcr_cce)) { ++ pr_err("Bman RCR initialisation failed\n"); ++ return 1; ++ } ++ if (bm_mc_init(portal)) { ++ pr_err("Bman MC initialisation failed\n"); ++ return 1; ++ } ++ return 0; ++} ++ ++/* Function that will scan all FQ's in the system. For each FQ that is not ++ OOS it will call the check_channel helper to determine if the FQ should ++ be torn down. If the check_channel helper returns true the FQ will be ++ transitioned to the OOS state */ ++static int qm_check_and_destroy_fqs(struct qm_portal *portal, void *ctx, ++ bool (*check_channel)(void*, u32)) ++{ ++ u32 fq_id = 0; ++ while (1) { ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ u8 state; ++ u32 channel; ++ ++ /* Determine the channel for the FQID */ ++ mcc = qm_mc_start(portal); ++ mcc->queryfq.fqid = fq_id; ++ qm_mc_commit(portal, QM_MCC_VERB_QUERYFQ); ++ while (!(mcr = qm_mc_result(portal))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ++ == QM_MCR_VERB_QUERYFQ); ++ if (mcr->result != QM_MCR_RESULT_OK) ++ break; /* End of valid FQIDs */ ++ ++ channel = mcr->queryfq.fqd.dest.channel; ++ /* Determine the state of the FQID */ ++ mcc = qm_mc_start(portal); ++ mcc->queryfq_np.fqid = fq_id; ++ qm_mc_commit(portal, QM_MCC_VERB_QUERYFQ_NP); ++ while (!(mcr = qm_mc_result(portal))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ++ == QM_MCR_VERB_QUERYFQ_NP); ++ state = mcr->queryfq_np.state & QM_MCR_NP_STATE_MASK; ++ if (state == QM_MCR_NP_STATE_OOS) ++ /* Already OOS, no need to do anymore checks */ ++ goto next; ++ ++ if (check_channel(ctx, channel)) ++ qm_shutdown_fq(&portal, 1, fq_id); ++ next: ++ ++fq_id; ++ } ++ return 0; ++} ++ ++static bool check_channel_device(void *_ctx, u32 channel) ++{ ++ struct ctx *ctx = _ctx; ++ struct portal_mapping *portal, *tmpportal; ++ struct active_resource *res; ++ ++ /* See if the FQ is destined for one of the portals we're cleaning up */ ++ list_for_each_entry_safe(portal, tmpportal, &ctx->portals, list) { ++ if (portal->user.type == usdpaa_portal_qman) { ++ if (portal->qportal->public_cfg.channel == channel) { ++ /* This FQs destination is a portal ++ we're cleaning, send a retire */ ++ return true; ++ } ++ } ++ } ++ ++ /* Check the pool channels that will be released as well */ ++ list_for_each_entry(res, &ctx->resources[usdpaa_id_qpool], list) { ++ if ((res->id >= channel) && ++ ((res->id + res->num - 1) <= channel)) ++ return true; ++ } ++ return false; ++} ++ ++static bool check_portal_channel(void *ctx, u32 channel) ++{ ++ u32 portal_channel = *(u32 *)ctx; ++ if (portal_channel == channel) { ++ /* This FQs destination is a portal ++ we're cleaning, send a retire */ ++ return true; ++ } ++ return false; ++} ++ ++ ++ ++ ++static int usdpaa_release(struct inode *inode, struct file *filp) ++{ ++ struct ctx *ctx = filp->private_data; ++ struct mem_mapping *map, *tmpmap; ++ struct portal_mapping *portal, *tmpportal; ++ const struct alloc_backend *backend = &alloc_backends[0]; ++ struct active_resource *res; ++ struct qm_portal *qm_cleanup_portal = NULL; ++ struct bm_portal *bm_cleanup_portal = NULL; ++ struct qm_portal_config *qm_alloced_portal = NULL; ++ struct bm_portal_config *bm_alloced_portal = NULL; ++ ++ struct qm_portal *portal_array[qman_portal_max]; ++ int portal_count = 0; ++ ++ /* Ensure the release operation cannot be migrated to another ++ CPU as CPU specific variables may be needed during cleanup */ ++#ifdef CONFIG_PREEMPT_RT_FULL ++ migrate_disable(); ++#endif ++ /* The following logic is used to recover resources that were not ++ correctly released by the process that is closing the FD. ++ Step 1: syncronize the HW with the qm_portal/bm_portal structures ++ in the kernel ++ */ ++ ++ list_for_each_entry_safe(portal, tmpportal, &ctx->portals, list) { ++ /* Try to recover any portals that weren't shut down */ ++ if (portal->user.type == usdpaa_portal_qman) { ++ portal_array[portal_count] = &portal->qman_portal_low; ++ ++portal_count; ++ init_qm_portal(portal->qportal, ++ &portal->qman_portal_low); ++ if (!qm_cleanup_portal) { ++ qm_cleanup_portal = &portal->qman_portal_low; ++ } else { ++ /* Clean FQs on the dedicated channel */ ++ u32 chan = portal->qportal->public_cfg.channel; ++ qm_check_and_destroy_fqs( ++ &portal->qman_portal_low, &chan, ++ check_portal_channel); ++ } ++ } else { ++ /* BMAN */ ++ init_bm_portal(portal->bportal, ++ &portal->bman_portal_low); ++ if (!bm_cleanup_portal) ++ bm_cleanup_portal = &portal->bman_portal_low; ++ } ++ } ++ /* If no portal was found, allocate one for cleanup */ ++ if (!qm_cleanup_portal) { ++ qm_alloced_portal = qm_get_unused_portal(); ++ if (!qm_alloced_portal) { ++ pr_crit("No QMan portal avalaible for cleanup\n"); ++#ifdef CONFIG_PREEMPT_RT_FULL ++ migrate_enable(); ++#endif ++ return -1; ++ } ++ qm_cleanup_portal = kmalloc(sizeof(struct qm_portal), ++ GFP_KERNEL); ++ if (!qm_cleanup_portal) { ++#ifdef CONFIG_PREEMPT_RT_FULL ++ migrate_enable(); ++#endif ++ return -ENOMEM; ++ } ++ init_qm_portal(qm_alloced_portal, qm_cleanup_portal); ++ portal_array[portal_count] = qm_cleanup_portal; ++ ++portal_count; ++ } ++ if (!bm_cleanup_portal) { ++ bm_alloced_portal = bm_get_unused_portal(); ++ if (!bm_alloced_portal) { ++ pr_crit("No BMan portal avalaible for cleanup\n"); ++#ifdef CONFIG_PREEMPT_RT_FULL ++ migrate_enable(); ++#endif ++ return -1; ++ } ++ bm_cleanup_portal = kmalloc(sizeof(struct bm_portal), ++ GFP_KERNEL); ++ if (!bm_cleanup_portal) { ++#ifdef CONFIG_PREEMPT_RT_FULL ++ migrate_enable(); ++#endif ++ return -ENOMEM; ++ } ++ init_bm_portal(bm_alloced_portal, bm_cleanup_portal); ++ } ++ ++ /* OOS the FQs associated with this process */ ++ qm_check_and_destroy_fqs(qm_cleanup_portal, ctx, check_channel_device); ++ ++ while (backend->id_type != usdpaa_id_max) { ++ int leaks = 0; ++ list_for_each_entry(res, &ctx->resources[backend->id_type], ++ list) { ++ if (backend->id_type == usdpaa_id_fqid) { ++ int i = 0; ++ for (; i < res->num; i++) { ++ /* Clean FQs with the cleanup portal */ ++ qm_shutdown_fq(portal_array, ++ portal_count, ++ res->id + i); ++ } ++ } ++ leaks += res->num; ++ backend->release(res->id, res->num); ++ } ++ if (leaks) ++ pr_crit("USDPAA process leaking %d %s%s\n", leaks, ++ backend->acronym, (leaks > 1) ? "s" : ""); ++ backend++; ++ } ++ /* Release any DMA regions */ ++ spin_lock(&mem_lock); ++ list_for_each_entry_safe(map, tmpmap, &ctx->maps, list) { ++ struct mem_fragment *current_frag = map->root_frag; ++ int i; ++ if (map->root_frag->has_locking && ++ (map->root_frag->owner == map)) { ++ map->root_frag->owner = NULL; ++ wake_up(&map->root_frag->wq); ++ } ++ /* Check each fragment and merge if the ref count is 0 */ ++ for (i = 0; i < map->frag_count; i++) { ++ --current_frag->refs; ++ current_frag = list_entry(current_frag->list.prev, ++ struct mem_fragment, list); ++ } ++ ++ compress_frags(); ++ list_del(&map->list); ++ kfree(map); ++ } ++ spin_unlock(&mem_lock); ++ ++ /* Return portals */ ++ list_for_each_entry_safe(portal, tmpportal, &ctx->portals, list) { ++ if (portal->user.type == usdpaa_portal_qman) { ++ /* Give the portal back to the allocator */ ++ init_qm_portal(portal->qportal, ++ &portal->qman_portal_low); ++ qm_put_unused_portal(portal->qportal); ++ } else { ++ init_bm_portal(portal->bportal, ++ &portal->bman_portal_low); ++ bm_put_unused_portal(portal->bportal); ++ } ++ list_del(&portal->list); ++ kfree(portal); ++ } ++ if (qm_alloced_portal) { ++ qm_put_unused_portal(qm_alloced_portal); ++ kfree(qm_cleanup_portal); ++ } ++ if (bm_alloced_portal) { ++ bm_put_unused_portal(bm_alloced_portal); ++ kfree(bm_cleanup_portal); ++ } ++ ++ kfree(ctx); ++#ifdef CONFIG_PREEMPT_RT_FULL ++ migrate_enable(); ++#endif ++ return 0; ++} ++ ++static int check_mmap_dma(struct ctx *ctx, struct vm_area_struct *vma, ++ int *match, unsigned long *pfn) ++{ ++ struct mem_mapping *map; ++ ++ list_for_each_entry(map, &ctx->maps, list) { ++ int i; ++ struct mem_fragment *frag = map->root_frag; ++ ++ for (i = 0; i < map->frag_count; i++) { ++ if (frag->pfn_base == vma->vm_pgoff) { ++ *match = 1; ++ *pfn = frag->pfn_base; ++ return 0; ++ } ++ frag = list_entry(frag->list.next, struct mem_fragment, ++ list); ++ } ++ } ++ *match = 0; ++ return 0; ++} ++ ++static int check_mmap_resource(struct resource *res, struct vm_area_struct *vma, ++ int *match, unsigned long *pfn) ++{ ++ *pfn = res->start >> PAGE_SHIFT; ++ if (*pfn == vma->vm_pgoff) { ++ *match = 1; ++ if ((vma->vm_end - vma->vm_start) != resource_size(res)) ++ return -EINVAL; ++ } else ++ *match = 0; ++ return 0; ++} ++ ++static int check_mmap_portal(struct ctx *ctx, struct vm_area_struct *vma, ++ int *match, unsigned long *pfn) ++{ ++ struct portal_mapping *portal; ++ int ret; ++ ++ list_for_each_entry(portal, &ctx->portals, list) { ++ ret = check_mmap_resource(&portal->phys[DPA_PORTAL_CE], vma, ++ match, pfn); ++ if (*match) { ++ vma->vm_page_prot = ++ pgprot_cached_noncoherent(vma->vm_page_prot); ++ return ret; ++ } ++ ret = check_mmap_resource(&portal->phys[DPA_PORTAL_CI], vma, ++ match, pfn); ++ if (*match) { ++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); ++ return ret; ++ } ++ } ++ *match = 0; ++ return 0; ++} ++ ++static int usdpaa_mmap(struct file *filp, struct vm_area_struct *vma) ++{ ++ struct ctx *ctx = filp->private_data; ++ unsigned long pfn = 0; ++ int match, ret; ++ ++ spin_lock(&mem_lock); ++ ret = check_mmap_dma(ctx, vma, &match, &pfn); ++ if (!match) ++ ret = check_mmap_portal(ctx, vma, &match, &pfn); ++ spin_unlock(&mem_lock); ++ if (!match) ++ return -EINVAL; ++ if (!ret) ++ ret = remap_pfn_range(vma, vma->vm_start, pfn, ++ vma->vm_end - vma->vm_start, ++ vma->vm_page_prot); ++ return ret; ++} ++ ++/* Return the nearest rounded-up address >= 'addr' that is 'sz'-aligned. 'sz' ++ * must be a power of 2, but both 'addr' and 'sz' can be expressions. */ ++#define USDPAA_MEM_ROUNDUP(addr, sz) \ ++ ({ \ ++ unsigned long foo_align = (sz) - 1; \ ++ ((addr) + foo_align) & ~foo_align; \ ++ }) ++/* Searching for a size-aligned virtual address range starting from 'addr' */ ++static unsigned long usdpaa_get_unmapped_area(struct file *file, ++ unsigned long addr, ++ unsigned long len, ++ unsigned long pgoff, ++ unsigned long flags) ++{ ++ struct vm_area_struct *vma; ++ ++ if (len % PAGE_SIZE) ++ return -EINVAL; ++ if (!len) ++ return -EINVAL; ++ ++ /* Need to align the address to the largest pagesize of the mapping ++ * because the MMU requires the virtual address to have the same ++ * alignment as the physical address */ ++ addr = USDPAA_MEM_ROUNDUP(addr, largest_page_size(len)); ++ vma = find_vma(current->mm, addr); ++ /* Keep searching until we reach the end of currently-used virtual ++ * address-space or we find a big enough gap. */ ++ while (vma) { ++ if ((addr + len) < vma->vm_start) ++ return addr; ++ ++ addr = USDPAA_MEM_ROUNDUP(vma->vm_end, largest_page_size(len)); ++ vma = vma->vm_next; ++ } ++ if ((TASK_SIZE - len) < addr) ++ return -ENOMEM; ++ return addr; ++} ++ ++static long ioctl_id_alloc(struct ctx *ctx, void __user *arg) ++{ ++ struct usdpaa_ioctl_id_alloc i; ++ const struct alloc_backend *backend; ++ struct active_resource *res; ++ int ret = copy_from_user(&i, arg, sizeof(i)); ++ if (ret) ++ return ret; ++ if ((i.id_type >= usdpaa_id_max) || !i.num) ++ return -EINVAL; ++ backend = &alloc_backends[i.id_type]; ++ /* Allocate the required resource type */ ++ ret = backend->alloc(&i.base, i.num, i.align, i.partial); ++ if (ret < 0) ++ return ret; ++ i.num = ret; ++ /* Copy the result to user-space */ ++ ret = copy_to_user(arg, &i, sizeof(i)); ++ if (ret) { ++ backend->release(i.base, i.num); ++ return ret; ++ } ++ /* Assign the allocated range to the FD accounting */ ++ res = kmalloc(sizeof(*res), GFP_KERNEL); ++ if (!res) { ++ backend->release(i.base, i.num); ++ return -ENOMEM; ++ } ++ spin_lock(&ctx->lock); ++ res->id = i.base; ++ res->num = i.num; ++ res->refcount = 1; ++ list_add(&res->list, &ctx->resources[i.id_type]); ++ spin_unlock(&ctx->lock); ++ return 0; ++} ++ ++static long ioctl_id_release(struct ctx *ctx, void __user *arg) ++{ ++ struct usdpaa_ioctl_id_release i; ++ const struct alloc_backend *backend; ++ struct active_resource *tmp, *pos; ++ ++ int ret = copy_from_user(&i, arg, sizeof(i)); ++ if (ret) ++ return ret; ++ if ((i.id_type >= usdpaa_id_max) || !i.num) ++ return -EINVAL; ++ backend = &alloc_backends[i.id_type]; ++ /* Pull the range out of the FD accounting - the range is valid iff this ++ * succeeds. */ ++ spin_lock(&ctx->lock); ++ list_for_each_entry_safe(pos, tmp, &ctx->resources[i.id_type], list) { ++ if (pos->id == i.base && pos->num == i.num) { ++ pos->refcount--; ++ if (pos->refcount) { ++ spin_unlock(&ctx->lock); ++ return 0; /* Still being used */ ++ } ++ list_del(&pos->list); ++ kfree(pos); ++ spin_unlock(&ctx->lock); ++ goto found; ++ } ++ } ++ /* Failed to find the resource */ ++ spin_unlock(&ctx->lock); ++ pr_err("Couldn't find resource type %d base 0x%x num %d\n", ++ i.id_type, i.base, i.num); ++ return -EINVAL; ++found: ++ /* Release the resource to the backend */ ++ backend->release(i.base, i.num); ++ return 0; ++} ++ ++static long ioctl_id_reserve(struct ctx *ctx, void __user *arg) ++{ ++ struct usdpaa_ioctl_id_reserve i; ++ const struct alloc_backend *backend; ++ struct active_resource *tmp, *pos; ++ ++ int ret = copy_from_user(&i, arg, sizeof(i)); ++ if (ret) ++ return ret; ++ if ((i.id_type >= usdpaa_id_max) || !i.num) ++ return -EINVAL; ++ backend = &alloc_backends[i.id_type]; ++ if (!backend->reserve) ++ return -EINVAL; ++ /* Pull the range out of the FD accounting - the range is valid iff this ++ * succeeds. */ ++ spin_lock(&ctx->lock); ++ list_for_each_entry_safe(pos, tmp, &ctx->resources[i.id_type], list) { ++ if (pos->id == i.base && pos->num == i.num) { ++ pos->refcount++; ++ spin_unlock(&ctx->lock); ++ return 0; ++ } ++ } ++ ++ /* Failed to find the resource */ ++ spin_unlock(&ctx->lock); ++ ++ /* Reserve the resource in the backend */ ++ ret = backend->reserve(i.base, i.num); ++ if (ret) ++ return ret; ++ /* Assign the reserved range to the FD accounting */ ++ pos = kmalloc(sizeof(*pos), GFP_KERNEL); ++ if (!pos) { ++ backend->release(i.base, i.num); ++ return -ENOMEM; ++ } ++ spin_lock(&ctx->lock); ++ pos->id = i.base; ++ pos->num = i.num; ++ pos->refcount = 1; ++ list_add(&pos->list, &ctx->resources[i.id_type]); ++ spin_unlock(&ctx->lock); ++ return 0; ++} ++ ++static long ioctl_dma_map(struct file *fp, struct ctx *ctx, ++ struct usdpaa_ioctl_dma_map *i) ++{ ++ struct mem_fragment *frag, *start_frag, *next_frag; ++ struct mem_mapping *map, *tmp; ++ int ret = 0; ++ u32 largest_page, so_far = 0; ++ int frag_count = 0; ++ unsigned long next_addr = PAGE_SIZE, populate; ++ ++ /* error checking to ensure values copied from user space are valid */ ++ if (i->len % PAGE_SIZE) ++ return -EINVAL; ++ ++ map = kmalloc(sizeof(*map), GFP_KERNEL); ++ if (!map) ++ return -ENOMEM; ++ ++ spin_lock(&mem_lock); ++ if (i->flags & USDPAA_DMA_FLAG_SHARE) { ++ list_for_each_entry(frag, &mem_list, list) { ++ if (frag->refs && (frag->flags & ++ USDPAA_DMA_FLAG_SHARE) && ++ !strncmp(i->name, frag->name, ++ USDPAA_DMA_NAME_MAX)) { ++ /* Matching entry */ ++ if ((i->flags & USDPAA_DMA_FLAG_CREATE) && ++ !(i->flags & USDPAA_DMA_FLAG_LAZY)) { ++ ret = -EBUSY; ++ goto out; ++ } ++ ++ /* Check to ensure size matches record */ ++ if (i->len != frag->map_len && i->len) { ++ pr_err("ioctl_dma_map() Size requested does not match %s and is none zero. This usage will be disallowed in future release\n", ++ frag->name); ++ } ++ ++ /* Check if this has already been mapped ++ to this process */ ++ list_for_each_entry(tmp, &ctx->maps, list) ++ if (tmp->root_frag == frag) { ++ /* Already mapped, just need to ++ inc ref count */ ++ tmp->refs++; ++ kfree(map); ++ i->did_create = 0; ++ i->len = tmp->total_size; ++ i->phys_addr = frag->base; ++ i->ptr = tmp->virt_addr; ++ spin_unlock(&mem_lock); ++ return 0; ++ } ++ /* Matching entry - just need to map */ ++ i->has_locking = frag->has_locking; ++ i->did_create = 0; ++ i->len = frag->map_len; ++ start_frag = frag; ++ goto do_map; ++ } ++ } ++ /* No matching entry */ ++ if (!(i->flags & USDPAA_DMA_FLAG_CREATE)) { ++ pr_err("ioctl_dma_map() No matching entry\n"); ++ ret = -ENOMEM; ++ goto out; ++ } ++ } ++ /* New fragment required, size must be provided. */ ++ if (!i->len) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ /* Find one of more contiguous fragments that satisfy the total length ++ trying to minimize the number of fragments ++ compute the largest page size that the allocation could use */ ++ largest_page = largest_page_size(i->len); ++ start_frag = NULL; ++ while (largest_page && ++ largest_page <= largest_page_size(phys_size) && ++ start_frag == NULL) { ++ /* Search the list for a frag of that size */ ++ list_for_each_entry(frag, &mem_list, list) { ++ if (!frag->refs && (frag->len == largest_page)) { ++ /* See if the next x fragments are free ++ and can accomidate the size */ ++ u32 found_size = largest_page; ++ next_frag = list_entry(frag->list.prev, ++ struct mem_fragment, ++ list); ++ /* If the fragement is too small check ++ if the neighbours cab support it */ ++ while (found_size < i->len) { ++ if (&mem_list == &next_frag->list) ++ break; /* End of list */ ++ if (next_frag->refs != 0 || ++ next_frag->len == 0) ++ break; /* not enough space */ ++ found_size += next_frag->len; ++ next_frag = list_entry( ++ next_frag->list.prev, ++ struct mem_fragment, ++ list); ++ } ++ if (found_size >= i->len) { ++ /* Success! there is enough contigous ++ free space */ ++ start_frag = frag; ++ break; ++ } ++ } ++ } /* next frag loop */ ++ /* Couldn't statisfy the request with this ++ largest page size, try a smaller one */ ++ largest_page <<= 2; ++ } ++ if (start_frag == NULL) { ++ /* Couldn't find proper amount of space */ ++ ret = -ENOMEM; ++ goto out; ++ } ++ i->did_create = 1; ++do_map: ++ /* Verify there is sufficient space to do the mapping */ ++ down_write(¤t->mm->mmap_sem); ++ next_addr = usdpaa_get_unmapped_area(fp, next_addr, i->len, 0, 0); ++ up_write(¤t->mm->mmap_sem); ++ ++ if (next_addr & ~PAGE_MASK) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ /* We may need to divide the final fragment to accomidate the mapping */ ++ next_frag = start_frag; ++ while (so_far != i->len) { ++ BUG_ON(next_frag->len == 0); ++ while ((next_frag->len + so_far) > i->len) { ++ /* Split frag until they match */ ++ split_frag(next_frag); ++ } ++ so_far += next_frag->len; ++ next_frag->refs++; ++ ++frag_count; ++ next_frag = list_entry(next_frag->list.prev, ++ struct mem_fragment, list); ++ } ++ if (i->did_create) { ++ size_t name_len = 0; ++ start_frag->flags = i->flags; ++ strncpy(start_frag->name, i->name, USDPAA_DMA_NAME_MAX); ++ name_len = strnlen(start_frag->name, USDPAA_DMA_NAME_MAX); ++ if (name_len >= USDPAA_DMA_NAME_MAX) { ++ ret = -EFAULT; ++ goto out; ++ } ++ start_frag->map_len = i->len; ++ start_frag->has_locking = i->has_locking; ++ init_waitqueue_head(&start_frag->wq); ++ start_frag->owner = NULL; ++ } ++ ++ /* Setup the map entry */ ++ map->root_frag = start_frag; ++ map->total_size = i->len; ++ map->frag_count = frag_count; ++ map->refs = 1; ++ list_add(&map->list, &ctx->maps); ++ i->phys_addr = start_frag->base; ++out: ++ spin_unlock(&mem_lock); ++ ++ if (!ret) { ++ unsigned long longret; ++ down_write(¤t->mm->mmap_sem); ++ longret = do_mmap_pgoff(fp, next_addr, map->total_size, ++ PROT_READ | ++ (i->flags & ++ USDPAA_DMA_FLAG_RDONLY ? 0 ++ : PROT_WRITE), ++ MAP_SHARED, ++ start_frag->pfn_base, ++ &populate); ++ up_write(¤t->mm->mmap_sem); ++ if (longret & ~PAGE_MASK) { ++ ret = (int)longret; ++ } else { ++ i->ptr = (void *)longret; ++ map->virt_addr = i->ptr; ++ } ++ } else ++ kfree(map); ++ return ret; ++} ++ ++static long ioctl_dma_unmap(struct ctx *ctx, void __user *arg) ++{ ++ struct mem_mapping *map; ++ struct vm_area_struct *vma; ++ int ret, i; ++ struct mem_fragment *current_frag; ++ size_t sz; ++ unsigned long base; ++ unsigned long vaddr; ++ ++ down_write(¤t->mm->mmap_sem); ++ vma = find_vma(current->mm, (unsigned long)arg); ++ if (!vma || (vma->vm_start > (unsigned long)arg)) { ++ up_write(¤t->mm->mmap_sem); ++ return -EFAULT; ++ } ++ spin_lock(&mem_lock); ++ list_for_each_entry(map, &ctx->maps, list) { ++ if (map->root_frag->pfn_base == vma->vm_pgoff) { ++ /* Drop the map lock if we hold it */ ++ if (map->root_frag->has_locking && ++ (map->root_frag->owner == map)) { ++ map->root_frag->owner = NULL; ++ wake_up(&map->root_frag->wq); ++ } ++ goto map_match; ++ } ++ } ++ /* Failed to find a matching mapping for this process */ ++ ret = -EFAULT; ++ spin_unlock(&mem_lock); ++ goto out; ++map_match: ++ map->refs--; ++ if (map->refs != 0) { ++ /* Another call the dma_map is referencing this */ ++ ret = 0; ++ spin_unlock(&mem_lock); ++ goto out; ++ } ++ ++ current_frag = map->root_frag; ++ vaddr = (unsigned long) map->virt_addr; ++ for (i = 0; i < map->frag_count; i++) { ++ DPA_ASSERT(current_frag->refs > 0); ++ --current_frag->refs; ++ /* ++ * Make sure we invalidate the TLB entry for ++ * this fragment, otherwise a remap of a different ++ * page to this vaddr would give acces to an ++ * incorrect piece of memory ++ */ ++ cleartlbcam(vaddr, mfspr(SPRN_PID)); ++ ++ vaddr += current_frag->len; ++ current_frag = list_entry(current_frag->list.prev, ++ struct mem_fragment, list); ++ } ++ map->root_frag->name[0] = 0; ++ list_del(&map->list); ++ compress_frags(); ++ spin_unlock(&mem_lock); ++ ++ base = vma->vm_start; ++ sz = vma->vm_end - vma->vm_start; ++ do_munmap(current->mm, base, sz); ++ ret = 0; ++ out: ++ up_write(¤t->mm->mmap_sem); ++ return ret; ++} ++ ++static long ioctl_dma_stats(struct ctx *ctx, void __user *arg) ++{ ++ struct mem_fragment *frag; ++ struct usdpaa_ioctl_dma_used result; ++ ++ result.free_bytes = 0; ++ result.total_bytes = phys_size; ++ ++ list_for_each_entry(frag, &mem_list, list) { ++ if (frag->refs == 0) ++ result.free_bytes += frag->len; ++ } ++ ++ return copy_to_user(arg, &result, sizeof(result)); } ++ ++static int test_lock(struct mem_mapping *map) ++{ ++ int ret = 0; ++ spin_lock(&mem_lock); ++ if (!map->root_frag->owner) { ++ map->root_frag->owner = map; ++ ret = 1; ++ } ++ spin_unlock(&mem_lock); ++ return ret; ++} ++ ++static long ioctl_dma_lock(struct ctx *ctx, void __user *arg) ++{ ++ struct mem_mapping *map; ++ struct vm_area_struct *vma; ++ ++ down_read(¤t->mm->mmap_sem); ++ vma = find_vma(current->mm, (unsigned long)arg); ++ if (!vma || (vma->vm_start > (unsigned long)arg)) { ++ up_read(¤t->mm->mmap_sem); ++ return -EFAULT; ++ } ++ spin_lock(&mem_lock); ++ list_for_each_entry(map, &ctx->maps, list) { ++ if (map->root_frag->pfn_base == vma->vm_pgoff) ++ goto map_match; ++ } ++ map = NULL; ++map_match: ++ spin_unlock(&mem_lock); ++ up_read(¤t->mm->mmap_sem); ++ ++ if (!map) ++ return -EFAULT; ++ if (!map->root_frag->has_locking) ++ return -ENODEV; ++ return wait_event_interruptible(map->root_frag->wq, test_lock(map)); ++} ++ ++static long ioctl_dma_unlock(struct ctx *ctx, void __user *arg) ++{ ++ struct mem_mapping *map; ++ struct vm_area_struct *vma; ++ int ret; ++ ++ down_read(¤t->mm->mmap_sem); ++ vma = find_vma(current->mm, (unsigned long)arg); ++ if (!vma || (vma->vm_start > (unsigned long)arg)) ++ ret = -EFAULT; ++ else { ++ spin_lock(&mem_lock); ++ list_for_each_entry(map, &ctx->maps, list) { ++ if (map->root_frag->pfn_base == vma->vm_pgoff) { ++ if (!map->root_frag->has_locking) ++ ret = -ENODEV; ++ else if (map->root_frag->owner == map) { ++ map->root_frag->owner = NULL; ++ wake_up(&map->root_frag->wq); ++ ret = 0; ++ } else ++ ret = -EBUSY; ++ goto map_match; ++ } ++ } ++ ret = -EINVAL; ++map_match: ++ spin_unlock(&mem_lock); ++ } ++ up_read(¤t->mm->mmap_sem); ++ return ret; ++} ++ ++static int portal_mmap(struct file *fp, struct resource *res, void **ptr) ++{ ++ unsigned long longret = 0, populate; ++ resource_size_t len; ++ ++ down_write(¤t->mm->mmap_sem); ++ len = resource_size(res); ++ if (len != (unsigned long)len) ++ return -EINVAL; ++ longret = do_mmap_pgoff(fp, PAGE_SIZE, (unsigned long)len, ++ PROT_READ | PROT_WRITE, MAP_SHARED, ++ res->start >> PAGE_SHIFT, &populate); ++ up_write(¤t->mm->mmap_sem); ++ ++ if (longret & ~PAGE_MASK) ++ return (int)longret; ++ ++ *ptr = (void *) longret; ++ return 0; ++} ++ ++static void portal_munmap(struct resource *res, void *ptr) ++{ ++ down_write(¤t->mm->mmap_sem); ++ do_munmap(current->mm, (unsigned long)ptr, resource_size(res)); ++ up_write(¤t->mm->mmap_sem); ++} ++ ++static long ioctl_portal_map(struct file *fp, struct ctx *ctx, ++ struct usdpaa_ioctl_portal_map *arg) ++{ ++ struct portal_mapping *mapping = kmalloc(sizeof(*mapping), GFP_KERNEL); ++ int ret; ++ ++ if (!mapping) ++ return -ENOMEM; ++ ++ mapping->user = *arg; ++ mapping->iommu_domain = NULL; ++ ++ if (mapping->user.type == usdpaa_portal_qman) { ++ mapping->qportal = ++ qm_get_unused_portal_idx(mapping->user.index); ++ if (!mapping->qportal) { ++ ret = -ENODEV; ++ goto err_get_portal; ++ } ++ mapping->phys = &mapping->qportal->addr_phys[0]; ++ mapping->user.channel = mapping->qportal->public_cfg.channel; ++ mapping->user.pools = mapping->qportal->public_cfg.pools; ++ mapping->user.index = mapping->qportal->public_cfg.index; ++ } else if (mapping->user.type == usdpaa_portal_bman) { ++ mapping->bportal = ++ bm_get_unused_portal_idx(mapping->user.index); ++ if (!mapping->bportal) { ++ ret = -ENODEV; ++ goto err_get_portal; ++ } ++ mapping->phys = &mapping->bportal->addr_phys[0]; ++ mapping->user.index = mapping->bportal->public_cfg.index; ++ } else { ++ ret = -EINVAL; ++ goto err_copy_from_user; ++ } ++ /* Need to put pcfg in ctx's list before the mmaps because the mmap ++ * handlers look it up. */ ++ spin_lock(&mem_lock); ++ list_add(&mapping->list, &ctx->portals); ++ spin_unlock(&mem_lock); ++ ret = portal_mmap(fp, &mapping->phys[DPA_PORTAL_CE], ++ &mapping->user.addr.cena); ++ if (ret) ++ goto err_mmap_cena; ++ ret = portal_mmap(fp, &mapping->phys[DPA_PORTAL_CI], ++ &mapping->user.addr.cinh); ++ if (ret) ++ goto err_mmap_cinh; ++ *arg = mapping->user; ++ return ret; ++ ++err_mmap_cinh: ++ portal_munmap(&mapping->phys[DPA_PORTAL_CE], mapping->user.addr.cena); ++err_mmap_cena: ++ if ((mapping->user.type == usdpaa_portal_qman) && mapping->qportal) ++ qm_put_unused_portal(mapping->qportal); ++ else if ((mapping->user.type == usdpaa_portal_bman) && mapping->bportal) ++ bm_put_unused_portal(mapping->bportal); ++ spin_lock(&mem_lock); ++ list_del(&mapping->list); ++ spin_unlock(&mem_lock); ++err_get_portal: ++err_copy_from_user: ++ kfree(mapping); ++ return ret; ++} ++ ++static long ioctl_portal_unmap(struct ctx *ctx, struct usdpaa_portal_map *i) ++{ ++ struct portal_mapping *mapping; ++ struct vm_area_struct *vma; ++ unsigned long pfn; ++ u32 channel; ++ ++ /* Get the PFN corresponding to one of the virt addresses */ ++ down_read(¤t->mm->mmap_sem); ++ vma = find_vma(current->mm, (unsigned long)i->cinh); ++ if (!vma || (vma->vm_start > (unsigned long)i->cinh)) { ++ up_read(¤t->mm->mmap_sem); ++ return -EFAULT; ++ } ++ pfn = vma->vm_pgoff; ++ up_read(¤t->mm->mmap_sem); ++ ++ /* Find the corresponding portal */ ++ spin_lock(&mem_lock); ++ list_for_each_entry(mapping, &ctx->portals, list) { ++ if (pfn == (mapping->phys[DPA_PORTAL_CI].start >> PAGE_SHIFT)) ++ goto found; ++ } ++ mapping = NULL; ++found: ++ if (mapping) ++ list_del(&mapping->list); ++ spin_unlock(&mem_lock); ++ if (!mapping) ++ return -ENODEV; ++ portal_munmap(&mapping->phys[DPA_PORTAL_CI], mapping->user.addr.cinh); ++ portal_munmap(&mapping->phys[DPA_PORTAL_CE], mapping->user.addr.cena); ++ if (mapping->user.type == usdpaa_portal_qman) { ++ init_qm_portal(mapping->qportal, ++ &mapping->qman_portal_low); ++ ++ /* Tear down any FQs this portal is referencing */ ++ channel = mapping->qportal->public_cfg.channel; ++ qm_check_and_destroy_fqs(&mapping->qman_portal_low, ++ &channel, ++ check_portal_channel); ++ qm_put_unused_portal(mapping->qportal); ++ } else if (mapping->user.type == usdpaa_portal_bman) { ++ init_bm_portal(mapping->bportal, ++ &mapping->bman_portal_low); ++ bm_put_unused_portal(mapping->bportal); ++ } ++ kfree(mapping); ++ return 0; ++} ++ ++static void portal_config_pamu(struct qm_portal_config *pcfg, uint8_t sdest, ++ uint32_t cpu, uint32_t cache, uint32_t window) ++{ ++#ifdef CONFIG_FSL_PAMU ++ int ret; ++ int window_count = 1; ++ struct iommu_domain_geometry geom_attr; ++ struct pamu_stash_attribute stash_attr; ++ ++ pcfg->iommu_domain = iommu_domain_alloc(&platform_bus_type); ++ if (!pcfg->iommu_domain) { ++ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_alloc() failed", ++ __func__); ++ goto _no_iommu; ++ } ++ geom_attr.aperture_start = 0; ++ geom_attr.aperture_end = ++ ((dma_addr_t)1 << min(8 * sizeof(dma_addr_t), (size_t)36)) - 1; ++ geom_attr.force_aperture = true; ++ ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_GEOMETRY, ++ &geom_attr); ++ if (ret < 0) { ++ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d", ++ __func__, ret); ++ goto _iommu_domain_free; ++ } ++ ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_WINDOWS, ++ &window_count); ++ if (ret < 0) { ++ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d", ++ __func__, ret); ++ goto _iommu_domain_free; ++ } ++ stash_attr.cpu = cpu; ++ stash_attr.cache = cache; ++ /* set stash information for the window */ ++ stash_attr.window = 0; ++ ++ ret = iommu_domain_set_attr(pcfg->iommu_domain, ++ DOMAIN_ATTR_FSL_PAMU_STASH, ++ &stash_attr); ++ if (ret < 0) { ++ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d", ++ __func__, ret); ++ goto _iommu_domain_free; ++ } ++ ret = iommu_domain_window_enable(pcfg->iommu_domain, 0, 0, 1ULL << 36, ++ IOMMU_READ | IOMMU_WRITE); ++ if (ret < 0) { ++ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_window_enable() = %d", ++ __func__, ret); ++ goto _iommu_domain_free; ++ } ++ ret = iommu_attach_device(pcfg->iommu_domain, &pcfg->dev); ++ if (ret < 0) { ++ pr_err(KBUILD_MODNAME ":%s(): iommu_device_attach() = %d", ++ __func__, ret); ++ goto _iommu_domain_free; ++ } ++ ret = iommu_domain_set_attr(pcfg->iommu_domain, ++ DOMAIN_ATTR_FSL_PAMU_ENABLE, ++ &window_count); ++ if (ret < 0) { ++ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d", ++ __func__, ret); ++ goto _iommu_detach_device; ++ } ++_no_iommu: ++#endif ++ ++#ifdef CONFIG_FSL_QMAN_CONFIG ++ if (qman_set_sdest(pcfg->public_cfg.channel, sdest)) ++#endif ++ pr_warn("Failed to set QMan portal's stash request queue\n"); ++ ++ return; ++ ++#ifdef CONFIG_FSL_PAMU ++_iommu_detach_device: ++ iommu_detach_device(pcfg->iommu_domain, NULL); ++_iommu_domain_free: ++ iommu_domain_free(pcfg->iommu_domain); ++#endif ++} ++ ++static long ioctl_allocate_raw_portal(struct file *fp, struct ctx *ctx, ++ struct usdpaa_ioctl_raw_portal *arg) ++{ ++ struct portal_mapping *mapping = kmalloc(sizeof(*mapping), GFP_KERNEL); ++ int ret; ++ ++ if (!mapping) ++ return -ENOMEM; ++ ++ mapping->user.type = arg->type; ++ mapping->iommu_domain = NULL; ++ if (arg->type == usdpaa_portal_qman) { ++ mapping->qportal = qm_get_unused_portal_idx(arg->index); ++ if (!mapping->qportal) { ++ ret = -ENODEV; ++ goto err; ++ } ++ mapping->phys = &mapping->qportal->addr_phys[0]; ++ arg->index = mapping->qportal->public_cfg.index; ++ arg->cinh = mapping->qportal->addr_phys[DPA_PORTAL_CI].start; ++ arg->cena = mapping->qportal->addr_phys[DPA_PORTAL_CE].start; ++ if (arg->enable_stash) { ++ /* Setup the PAMU with the supplied parameters */ ++ portal_config_pamu(mapping->qportal, arg->sdest, ++ arg->cpu, arg->cache, arg->window); ++ } ++ } else if (mapping->user.type == usdpaa_portal_bman) { ++ mapping->bportal = ++ bm_get_unused_portal_idx(arg->index); ++ if (!mapping->bportal) { ++ ret = -ENODEV; ++ goto err; ++ } ++ mapping->phys = &mapping->bportal->addr_phys[0]; ++ arg->index = mapping->bportal->public_cfg.index; ++ arg->cinh = mapping->bportal->addr_phys[DPA_PORTAL_CI].start; ++ arg->cena = mapping->bportal->addr_phys[DPA_PORTAL_CE].start; ++ } else { ++ ret = -EINVAL; ++ goto err; ++ } ++ /* Need to put pcfg in ctx's list before the mmaps because the mmap ++ * handlers look it up. */ ++ spin_lock(&mem_lock); ++ list_add(&mapping->list, &ctx->portals); ++ spin_unlock(&mem_lock); ++ return 0; ++err: ++ kfree(mapping); ++ return ret; ++} ++ ++static long ioctl_free_raw_portal(struct file *fp, struct ctx *ctx, ++ struct usdpaa_ioctl_raw_portal *arg) ++{ ++ struct portal_mapping *mapping; ++ u32 channel; ++ ++ /* Find the corresponding portal */ ++ spin_lock(&mem_lock); ++ list_for_each_entry(mapping, &ctx->portals, list) { ++ if (mapping->phys[DPA_PORTAL_CI].start == arg->cinh) ++ goto found; ++ } ++ mapping = NULL; ++found: ++ if (mapping) ++ list_del(&mapping->list); ++ spin_unlock(&mem_lock); ++ if (!mapping) ++ return -ENODEV; ++ if (mapping->user.type == usdpaa_portal_qman) { ++ init_qm_portal(mapping->qportal, ++ &mapping->qman_portal_low); ++ ++ /* Tear down any FQs this portal is referencing */ ++ channel = mapping->qportal->public_cfg.channel; ++ qm_check_and_destroy_fqs(&mapping->qman_portal_low, ++ &channel, ++ check_portal_channel); ++ qm_put_unused_portal(mapping->qportal); ++ } else if (mapping->user.type == usdpaa_portal_bman) { ++ init_bm_portal(mapping->bportal, ++ &mapping->bman_portal_low); ++ bm_put_unused_portal(mapping->bportal); ++ } ++ kfree(mapping); ++ return 0; ++} ++ ++static long usdpaa_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) ++{ ++ struct ctx *ctx = fp->private_data; ++ void __user *a = (void __user *)arg; ++ switch (cmd) { ++ case USDPAA_IOCTL_ID_ALLOC: ++ return ioctl_id_alloc(ctx, a); ++ case USDPAA_IOCTL_ID_RELEASE: ++ return ioctl_id_release(ctx, a); ++ case USDPAA_IOCTL_ID_RESERVE: ++ return ioctl_id_reserve(ctx, a); ++ case USDPAA_IOCTL_DMA_MAP: ++ { ++ struct usdpaa_ioctl_dma_map input; ++ int ret; ++ if (copy_from_user(&input, a, sizeof(input))) ++ return -EFAULT; ++ ret = ioctl_dma_map(fp, ctx, &input); ++ if (copy_to_user(a, &input, sizeof(input))) ++ return -EFAULT; ++ return ret; ++ } ++ case USDPAA_IOCTL_DMA_UNMAP: ++ return ioctl_dma_unmap(ctx, a); ++ case USDPAA_IOCTL_DMA_LOCK: ++ return ioctl_dma_lock(ctx, a); ++ case USDPAA_IOCTL_DMA_UNLOCK: ++ return ioctl_dma_unlock(ctx, a); ++ case USDPAA_IOCTL_PORTAL_MAP: ++ { ++ struct usdpaa_ioctl_portal_map input; ++ int ret; ++ if (copy_from_user(&input, a, sizeof(input))) ++ return -EFAULT; ++ ret = ioctl_portal_map(fp, ctx, &input); ++ if (copy_to_user(a, &input, sizeof(input))) ++ return -EFAULT; ++ return ret; ++ } ++ case USDPAA_IOCTL_PORTAL_UNMAP: ++ { ++ struct usdpaa_portal_map input; ++ if (copy_from_user(&input, a, sizeof(input))) ++ return -EFAULT; ++ return ioctl_portal_unmap(ctx, &input); ++ } ++ case USDPAA_IOCTL_DMA_USED: ++ return ioctl_dma_stats(ctx, a); ++ case USDPAA_IOCTL_ALLOC_RAW_PORTAL: ++ { ++ struct usdpaa_ioctl_raw_portal input; ++ int ret; ++ if (copy_from_user(&input, a, sizeof(input))) ++ return -EFAULT; ++ ret = ioctl_allocate_raw_portal(fp, ctx, &input); ++ if (copy_to_user(a, &input, sizeof(input))) ++ return -EFAULT; ++ return ret; ++ } ++ case USDPAA_IOCTL_FREE_RAW_PORTAL: ++ { ++ struct usdpaa_ioctl_raw_portal input; ++ if (copy_from_user(&input, a, sizeof(input))) ++ return -EFAULT; ++ return ioctl_free_raw_portal(fp, ctx, &input); ++ } ++ } ++ return -EINVAL; ++} ++ ++static long usdpaa_ioctl_compat(struct file *fp, unsigned int cmd, ++ unsigned long arg) ++{ ++#ifdef CONFIG_COMPAT ++ struct ctx *ctx = fp->private_data; ++ void __user *a = (void __user *)arg; ++#endif ++ switch (cmd) { ++#ifdef CONFIG_COMPAT ++ case USDPAA_IOCTL_DMA_MAP_COMPAT: ++ { ++ int ret; ++ struct usdpaa_ioctl_dma_map_compat input; ++ struct usdpaa_ioctl_dma_map converted; ++ ++ if (copy_from_user(&input, a, sizeof(input))) ++ return -EFAULT; ++ ++ converted.ptr = compat_ptr(input.ptr); ++ converted.phys_addr = input.phys_addr; ++ converted.len = input.len; ++ converted.flags = input.flags; ++ strncpy(converted.name, input.name, USDPAA_DMA_NAME_MAX); ++ converted.has_locking = input.has_locking; ++ converted.did_create = input.did_create; ++ ++ ret = ioctl_dma_map(fp, ctx, &converted); ++ input.ptr = ptr_to_compat(converted.ptr); ++ input.phys_addr = converted.phys_addr; ++ input.len = converted.len; ++ input.flags = converted.flags; ++ strncpy(input.name, converted.name, USDPAA_DMA_NAME_MAX); ++ input.has_locking = converted.has_locking; ++ input.did_create = converted.did_create; ++ if (copy_to_user(a, &input, sizeof(input))) ++ return -EFAULT; ++ return ret; ++ } ++ case USDPAA_IOCTL_PORTAL_MAP_COMPAT: ++ { ++ int ret; ++ struct compat_usdpaa_ioctl_portal_map input; ++ struct usdpaa_ioctl_portal_map converted; ++ if (copy_from_user(&input, a, sizeof(input))) ++ return -EFAULT; ++ converted.type = input.type; ++ converted.index = input.index; ++ ret = ioctl_portal_map(fp, ctx, &converted); ++ input.addr.cinh = ptr_to_compat(converted.addr.cinh); ++ input.addr.cena = ptr_to_compat(converted.addr.cena); ++ input.channel = converted.channel; ++ input.pools = converted.pools; ++ input.index = converted.index; ++ if (copy_to_user(a, &input, sizeof(input))) ++ return -EFAULT; ++ return ret; ++ } ++ case USDPAA_IOCTL_PORTAL_UNMAP_COMPAT: ++ { ++ struct usdpaa_portal_map_compat input; ++ struct usdpaa_portal_map converted; ++ ++ if (copy_from_user(&input, a, sizeof(input))) ++ return -EFAULT; ++ converted.cinh = compat_ptr(input.cinh); ++ converted.cena = compat_ptr(input.cena); ++ return ioctl_portal_unmap(ctx, &converted); ++ } ++ case USDPAA_IOCTL_ALLOC_RAW_PORTAL_COMPAT: ++ { ++ int ret; ++ struct usdpaa_ioctl_raw_portal converted; ++ struct compat_ioctl_raw_portal input; ++ if (copy_from_user(&input, a, sizeof(input))) ++ return -EFAULT; ++ converted.type = input.type; ++ converted.index = input.index; ++ converted.enable_stash = input.enable_stash; ++ converted.cpu = input.cpu; ++ converted.cache = input.cache; ++ converted.window = input.window; ++ converted.sdest = input.sdest; ++ ret = ioctl_allocate_raw_portal(fp, ctx, &converted); ++ ++ input.cinh = converted.cinh; ++ input.cena = converted.cena; ++ input.index = converted.index; ++ ++ if (copy_to_user(a, &input, sizeof(input))) ++ return -EFAULT; ++ return ret; ++ } ++ case USDPAA_IOCTL_FREE_RAW_PORTAL_COMPAT: ++ { ++ struct usdpaa_ioctl_raw_portal converted; ++ struct compat_ioctl_raw_portal input; ++ if (copy_from_user(&input, a, sizeof(input))) ++ return -EFAULT; ++ converted.type = input.type; ++ converted.index = input.index; ++ converted.cinh = input.cinh; ++ converted.cena = input.cena; ++ return ioctl_free_raw_portal(fp, ctx, &converted); ++ } ++#endif ++ default: ++ return usdpaa_ioctl(fp, cmd, arg); ++ } ++ return -EINVAL; ++} ++ ++int usdpaa_get_portal_config(struct file *filp, void *cinh, ++ enum usdpaa_portal_type ptype, unsigned int *irq, ++ void **iir_reg) ++{ ++ /* Walk the list of portals for filp and return the config ++ for the portal that matches the hint */ ++ struct ctx *context; ++ struct portal_mapping *portal; ++ ++ /* First sanitize the filp */ ++ if (filp->f_op->open != usdpaa_open) ++ return -ENODEV; ++ context = filp->private_data; ++ spin_lock(&context->lock); ++ list_for_each_entry(portal, &context->portals, list) { ++ if (portal->user.type == ptype && ++ portal->user.addr.cinh == cinh) { ++ if (ptype == usdpaa_portal_qman) { ++ *irq = portal->qportal->public_cfg.irq; ++ *iir_reg = portal->qportal->addr_virt[1] + ++ QM_REG_IIR; ++ } else { ++ *irq = portal->bportal->public_cfg.irq; ++ *iir_reg = portal->bportal->addr_virt[1] + ++ BM_REG_IIR; ++ } ++ spin_unlock(&context->lock); ++ return 0; ++ } ++ } ++ spin_unlock(&context->lock); ++ return -EINVAL; ++} ++ ++static const struct file_operations usdpaa_fops = { ++ .open = usdpaa_open, ++ .release = usdpaa_release, ++ .mmap = usdpaa_mmap, ++ .get_unmapped_area = usdpaa_get_unmapped_area, ++ .unlocked_ioctl = usdpaa_ioctl, ++ .compat_ioctl = usdpaa_ioctl_compat ++}; ++ ++static struct miscdevice usdpaa_miscdev = { ++ .name = "fsl-usdpaa", ++ .fops = &usdpaa_fops, ++ .minor = MISC_DYNAMIC_MINOR, ++}; ++ ++/* Early-boot memory allocation. The boot-arg "usdpaa_mem=" is used to ++ * indicate how much memory (if any) to allocate during early boot. If the ++ * format "usdpaa_mem=," is used, then will be interpreted as the ++ * number of TLB1 entries to reserve (default is 1). If there are more mappings ++ * than there are TLB1 entries, fault-handling will occur. */ ++static __init int usdpaa_mem(char *arg) ++{ ++ phys_size = memparse(arg, &arg); ++ num_tlb = 1; ++ if (*arg == ',') { ++ unsigned long ul; ++ int err = kstrtoul(arg + 1, 0, &ul); ++ if (err < 0) { ++ num_tlb = 1; ++ pr_warn("ERROR, usdpaa_mem arg is invalid\n"); ++ } else ++ num_tlb = (unsigned int)ul; ++ } ++ return 0; ++} ++early_param("usdpaa_mem", usdpaa_mem); ++ ++__init void fsl_usdpaa_init_early(void) ++{ ++ if (!phys_size) { ++ pr_info("No USDPAA memory, no 'usdpaa_mem' bootarg\n"); ++ return; ++ } ++ if (phys_size % PAGE_SIZE) { ++ pr_err("'usdpaa_mem' bootarg must be a multiple of page size\n"); ++ phys_size = 0; ++ return; ++ } ++ phys_start = __memblock_alloc_base(phys_size, ++ largest_page_size(phys_size), ++ MEMBLOCK_ALLOC_ACCESSIBLE); ++ if (!phys_start) { ++ pr_err("Failed to reserve USDPAA region (sz:%llx)\n", ++ phys_size); ++ return; ++ } ++ pfn_start = phys_start >> PAGE_SHIFT; ++ pfn_size = phys_size >> PAGE_SHIFT; ++ first_tlb = current_tlb = tlbcam_index; ++ tlbcam_index += num_tlb; ++ pr_info("USDPAA region at %llx:%llx(%lx:%lx), %d TLB1 entries)\n", ++ phys_start, phys_size, pfn_start, pfn_size, num_tlb); ++} ++ ++static int __init usdpaa_init(void) ++{ ++ struct mem_fragment *frag; ++ int ret; ++ u64 tmp_size = phys_size; ++ u64 tmp_start = phys_start; ++ u64 tmp_pfn_size = pfn_size; ++ u64 tmp_pfn_start = pfn_start; ++ ++ pr_info("Freescale USDPAA process driver\n"); ++ if (!phys_start) { ++ pr_warn("fsl-usdpaa: no region found\n"); ++ return 0; ++ } ++ ++ while (tmp_size != 0) { ++ u32 frag_size = largest_page_size(tmp_size); ++ frag = kmalloc(sizeof(*frag), GFP_KERNEL); ++ if (!frag) { ++ pr_err("Failed to setup USDPAA memory accounting\n"); ++ return -ENOMEM; ++ } ++ frag->base = tmp_start; ++ frag->len = frag->root_len = frag_size; ++ frag->root_pfn = tmp_pfn_start; ++ frag->pfn_base = tmp_pfn_start; ++ frag->pfn_len = frag_size / PAGE_SIZE; ++ frag->refs = 0; ++ init_waitqueue_head(&frag->wq); ++ frag->owner = NULL; ++ list_add(&frag->list, &mem_list); ++ ++ /* Adjust for this frag */ ++ tmp_start += frag_size; ++ tmp_size -= frag_size; ++ tmp_pfn_start += frag_size / PAGE_SIZE; ++ tmp_pfn_size -= frag_size / PAGE_SIZE; ++ } ++ ret = misc_register(&usdpaa_miscdev); ++ if (ret) ++ pr_err("fsl-usdpaa: failed to register misc device\n"); ++ return ret; ++} ++ ++static void __exit usdpaa_exit(void) ++{ ++ misc_deregister(&usdpaa_miscdev); ++} ++ ++module_init(usdpaa_init); ++module_exit(usdpaa_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Freescale Semiconductor"); ++MODULE_DESCRIPTION("Freescale USDPAA process driver"); +diff --git a/drivers/staging/fsl_qbman/fsl_usdpaa_irq.c b/drivers/staging/fsl_qbman/fsl_usdpaa_irq.c +new file mode 100644 +index 0000000..1f8260b +--- /dev/null ++++ b/drivers/staging/fsl_qbman/fsl_usdpaa_irq.c +@@ -0,0 +1,284 @@ ++/* Copyright (c) 2013 Freescale Semiconductor, Inc. ++ * All rights reserved. ++ * ++ * 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. ++ */ ++ ++/* define a device that allows USPDAA processes to open a file ++ descriptor and specify which IRQ it wants to montior using an ioctl() ++ When an IRQ is received, the device becomes readable so that a process ++ can use read() or select() type calls to monitor for IRQs */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "qman_low.h" ++#include "bman_low.h" ++ ++struct usdpaa_irq_ctx { ++ int irq_set; /* Set to true once the irq is set via ioctl */ ++ unsigned int irq_num; ++ u32 last_irq_count; /* Last value returned from read */ ++ u32 irq_count; /* Number of irqs since last read */ ++ wait_queue_head_t wait_queue; /* Waiting processes */ ++ spinlock_t lock; ++ void *inhibit_addr; /* inhibit register address */ ++ struct file *usdpaa_filp; ++}; ++ ++static int usdpaa_irq_open(struct inode *inode, struct file *filp) ++{ ++ struct usdpaa_irq_ctx *ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); ++ if (!ctx) ++ return -ENOMEM; ++ ctx->irq_set = 0; ++ ctx->irq_count = 0; ++ ctx->last_irq_count = 0; ++ init_waitqueue_head(&ctx->wait_queue); ++ spin_lock_init(&ctx->lock); ++ filp->private_data = ctx; ++ return 0; ++} ++ ++static int usdpaa_irq_release(struct inode *inode, struct file *filp) ++{ ++ struct usdpaa_irq_ctx *ctx = filp->private_data; ++ if (ctx->irq_set) { ++ /* Inhibit the IRQ */ ++ out_be32(ctx->inhibit_addr, 0x1); ++ irq_set_affinity_hint(ctx->irq_num, NULL); ++ free_irq(ctx->irq_num, ctx); ++ ctx->irq_set = 0; ++ fput(ctx->usdpaa_filp); ++ } ++ kfree(filp->private_data); ++ return 0; ++} ++ ++static irqreturn_t usdpaa_irq_handler(int irq, void *_ctx) ++{ ++ unsigned long flags; ++ struct usdpaa_irq_ctx *ctx = _ctx; ++ spin_lock_irqsave(&ctx->lock, flags); ++ ++ctx->irq_count; ++ spin_unlock_irqrestore(&ctx->lock, flags); ++ wake_up_all(&ctx->wait_queue); ++ /* Set the inhibit register. This will be reenabled ++ once the USDPAA code handles the IRQ */ ++ out_be32(ctx->inhibit_addr, 0x1); ++ return IRQ_HANDLED; ++} ++ ++static int map_irq(struct file *fp, struct usdpaa_ioctl_irq_map *irq_map) ++{ ++ struct usdpaa_irq_ctx *ctx = fp->private_data; ++ int ret; ++ ++ if (ctx->irq_set) { ++ pr_debug("Setting USDPAA IRQ when it was already set!\n"); ++ return -EBUSY; ++ } ++ ++ ctx->usdpaa_filp = fget(irq_map->fd); ++ if (!ctx->usdpaa_filp) { ++ pr_debug("USDPAA fget(%d) returned NULL\n", irq_map->fd); ++ return -EINVAL; ++ } ++ ++ ret = usdpaa_get_portal_config(ctx->usdpaa_filp, irq_map->portal_cinh, ++ irq_map->type, &ctx->irq_num, ++ &ctx->inhibit_addr); ++ if (ret) { ++ pr_debug("USDPAA IRQ couldn't identify portal\n"); ++ fput(ctx->usdpaa_filp); ++ return ret; ++ } ++ ++ ctx->irq_set = 1; ++ ++ ret = request_irq(ctx->irq_num, usdpaa_irq_handler, 0, ++ "usdpaa_irq", ctx); ++ if (ret) { ++ pr_err("USDPAA request_irq(%d) failed, ret= %d\n", ++ ctx->irq_num, ret); ++ ctx->irq_set = 0; ++ fput(ctx->usdpaa_filp); ++ return ret; ++ } ++ ret = irq_set_affinity(ctx->irq_num, tsk_cpus_allowed(current)); ++ if (ret) ++ pr_err("USDPAA irq_set_affinity() failed, ret= %d\n", ret); ++ ++ ret = irq_set_affinity_hint(ctx->irq_num, tsk_cpus_allowed(current)); ++ if (ret) ++ pr_err("USDPAA irq_set_affinity_hint() failed, ret= %d\n", ret); ++ ++ return 0; ++} ++ ++static long usdpaa_irq_ioctl(struct file *fp, unsigned int cmd, ++ unsigned long arg) ++{ ++ int ret; ++ struct usdpaa_ioctl_irq_map irq_map; ++ ++ if (cmd != USDPAA_IOCTL_PORTAL_IRQ_MAP) { ++ pr_debug("USDPAA IRQ unknown command 0x%x\n", cmd); ++ return -EINVAL; ++ } ++ ++ ret = copy_from_user(&irq_map, (void __user *)arg, ++ sizeof(irq_map)); ++ if (ret) ++ return ret; ++ return map_irq(fp, &irq_map); ++} ++ ++static ssize_t usdpaa_irq_read(struct file *filp, char __user *buff, ++ size_t count, loff_t *offp) ++{ ++ struct usdpaa_irq_ctx *ctx = filp->private_data; ++ int ret; ++ ++ if (!ctx->irq_set) { ++ pr_debug("Reading USDPAA IRQ before it was set\n"); ++ return -EINVAL; ++ } ++ ++ if (count < sizeof(ctx->irq_count)) { ++ pr_debug("USDPAA IRQ Read too small\n"); ++ return -EINVAL; ++ } ++ if (ctx->irq_count == ctx->last_irq_count) { ++ if (filp->f_flags & O_NONBLOCK) ++ return -EAGAIN; ++ ++ ret = wait_event_interruptible(ctx->wait_queue, ++ ctx->irq_count != ctx->last_irq_count); ++ if (ret == -ERESTARTSYS) ++ return ret; ++ } ++ ++ ctx->last_irq_count = ctx->irq_count; ++ ++ if (copy_to_user(buff, &ctx->last_irq_count, ++ sizeof(ctx->last_irq_count))) ++ return -EFAULT; ++ return sizeof(ctx->irq_count); ++} ++ ++static unsigned int usdpaa_irq_poll(struct file *filp, poll_table *wait) ++{ ++ struct usdpaa_irq_ctx *ctx = filp->private_data; ++ unsigned int ret = 0; ++ unsigned long flags; ++ ++ if (!ctx->irq_set) ++ return POLLHUP; ++ ++ poll_wait(filp, &ctx->wait_queue, wait); ++ ++ spin_lock_irqsave(&ctx->lock, flags); ++ if (ctx->irq_count != ctx->last_irq_count) ++ ret |= POLLIN | POLLRDNORM; ++ spin_unlock_irqrestore(&ctx->lock, flags); ++ return ret; ++} ++ ++static long usdpaa_irq_ioctl_compat(struct file *fp, unsigned int cmd, ++ unsigned long arg) ++{ ++#ifdef CONFIG_COMPAT ++ void __user *a = (void __user *)arg; ++#endif ++ switch (cmd) { ++#ifdef CONFIG_COMPAT ++ case USDPAA_IOCTL_PORTAL_IRQ_MAP_COMPAT: ++ { ++ struct compat_ioctl_irq_map input; ++ struct usdpaa_ioctl_irq_map converted; ++ if (copy_from_user(&input, a, sizeof(input))) ++ return -EFAULT; ++ converted.type = input.type; ++ converted.fd = input.fd; ++ converted.portal_cinh = compat_ptr(input.portal_cinh); ++ return map_irq(fp, &converted); ++ } ++#endif ++ default: ++ return usdpaa_irq_ioctl(fp, cmd, arg); ++ } ++} ++ ++static const struct file_operations usdpaa_irq_fops = { ++ .open = usdpaa_irq_open, ++ .release = usdpaa_irq_release, ++ .unlocked_ioctl = usdpaa_irq_ioctl, ++ .compat_ioctl = usdpaa_irq_ioctl_compat, ++ .read = usdpaa_irq_read, ++ .poll = usdpaa_irq_poll ++}; ++ ++static struct miscdevice usdpaa_miscdev = { ++ .name = "fsl-usdpaa-irq", ++ .fops = &usdpaa_irq_fops, ++ .minor = MISC_DYNAMIC_MINOR, ++}; ++ ++static int __init usdpaa_irq_init(void) ++{ ++ int ret; ++ ++ pr_info("Freescale USDPAA process IRQ driver\n"); ++ ret = misc_register(&usdpaa_miscdev); ++ if (ret) ++ pr_err("fsl-usdpaa-irq: failed to register misc device\n"); ++ return ret; ++} ++ ++static void __exit usdpaa_irq_exit(void) ++{ ++ misc_deregister(&usdpaa_miscdev); ++} ++ ++module_init(usdpaa_irq_init); ++module_exit(usdpaa_irq_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Freescale Semiconductor"); ++MODULE_DESCRIPTION("Freescale USDPAA process IRQ driver"); +diff --git a/drivers/staging/fsl_qbman/qbman_driver.c b/drivers/staging/fsl_qbman/qbman_driver.c +new file mode 100644 +index 0000000..a2904bd +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qbman_driver.c +@@ -0,0 +1,86 @@ ++/* Copyright 2013 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 ++#include "qman_private.h" ++#include "bman_private.h" ++ ++static __init int qbman_init(void) ++{ ++ struct device_node *dn; ++ u32 is_portal_available; ++ ++ bman_init(); ++ qman_init(); ++ ++ is_portal_available = 0; ++ for_each_compatible_node(dn, NULL, "fsl,qman-portal") { ++ if (!of_device_is_available(dn)) ++ continue; ++ else ++ is_portal_available = 1; ++ } ++ ++ if (!qman_have_ccsr() && is_portal_available) { ++ struct qman_fq fq = { ++ .fqid = 1 ++ }; ++ struct qm_mcr_queryfq_np np; ++ int err, retry = CONFIG_FSL_QMAN_INIT_TIMEOUT; ++ struct timespec nowts, diffts, startts = current_kernel_time(); ++ /* Loop while querying given fqid succeeds or time out */ ++ while (1) { ++ err = qman_query_fq_np(&fq, &np); ++ if (!err) { ++ /* success, control-plane has configured QMan */ ++ break; ++ } else if (err != -ERANGE) { ++ pr_err("QMan: I/O error, continuing anyway\n"); ++ break; ++ } ++ nowts = current_kernel_time(); ++ diffts = timespec_sub(nowts, startts); ++ if (diffts.tv_sec > 0) { ++ if (!retry--) { ++ pr_err("QMan: time out, control-plane" ++ " dead?\n"); ++ break; ++ } ++ pr_warn("QMan: polling for the control-plane" ++ " (%d)\n", retry); ++ } ++ } ++ } ++ bman_resource_init(); ++ qman_resource_init(); ++ return 0; ++} ++subsys_initcall(qbman_init); +diff --git a/drivers/staging/fsl_qbman/qman_config.c b/drivers/staging/fsl_qbman/qman_config.c +new file mode 100644 +index 0000000..6a6225e +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_config.c +@@ -0,0 +1,1174 @@ ++/* Copyright 2008-2012 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 ++#include "qman_private.h" ++ ++/* Last updated for v00.800 of the BG */ ++ ++/* Register offsets */ ++#define REG_QCSP_LIO_CFG(n) (0x0000 + ((n) * 0x10)) ++#define REG_QCSP_IO_CFG(n) (0x0004 + ((n) * 0x10)) ++#define REG_QCSP_DD_CFG(n) (0x000c + ((n) * 0x10)) ++#define REG_DD_CFG 0x0200 ++#define REG_DCP_CFG(n) (0x0300 + ((n) * 0x10)) ++#define REG_DCP_DD_CFG(n) (0x0304 + ((n) * 0x10)) ++#define REG_DCP_DLM_AVG(n) (0x030c + ((n) * 0x10)) ++#define REG_PFDR_FPC 0x0400 ++#define REG_PFDR_FP_HEAD 0x0404 ++#define REG_PFDR_FP_TAIL 0x0408 ++#define REG_PFDR_FP_LWIT 0x0410 ++#define REG_PFDR_CFG 0x0414 ++#define REG_SFDR_CFG 0x0500 ++#define REG_SFDR_IN_USE 0x0504 ++#define REG_WQ_CS_CFG(n) (0x0600 + ((n) * 0x04)) ++#define REG_WQ_DEF_ENC_WQID 0x0630 ++#define REG_WQ_SC_DD_CFG(n) (0x640 + ((n) * 0x04)) ++#define REG_WQ_PC_DD_CFG(n) (0x680 + ((n) * 0x04)) ++#define REG_WQ_DC0_DD_CFG(n) (0x6c0 + ((n) * 0x04)) ++#define REG_WQ_DC1_DD_CFG(n) (0x700 + ((n) * 0x04)) ++#define REG_WQ_DCn_DD_CFG(n) (0x6c0 + ((n) * 0x40)) /* n=2,3 */ ++#define REG_CM_CFG 0x0800 ++#define REG_ECSR 0x0a00 ++#define REG_ECIR 0x0a04 ++#define REG_EADR 0x0a08 ++#define REG_ECIR2 0x0a0c ++#define REG_EDATA(n) (0x0a10 + ((n) * 0x04)) ++#define REG_SBEC(n) (0x0a80 + ((n) * 0x04)) ++#define REG_MCR 0x0b00 ++#define REG_MCP(n) (0x0b04 + ((n) * 0x04)) ++#define REG_MISC_CFG 0x0be0 ++#define REG_HID_CFG 0x0bf0 ++#define REG_IDLE_STAT 0x0bf4 ++#define REG_IP_REV_1 0x0bf8 ++#define REG_IP_REV_2 0x0bfc ++#define REG_FQD_BARE 0x0c00 ++#define REG_PFDR_BARE 0x0c20 ++#define REG_offset_BAR 0x0004 /* relative to REG_[FQD|PFDR]_BARE */ ++#define REG_offset_AR 0x0010 /* relative to REG_[FQD|PFDR]_BARE */ ++#define REG_QCSP_BARE 0x0c80 ++#define REG_QCSP_BAR 0x0c84 ++#define REG_CI_SCHED_CFG 0x0d00 ++#define REG_SRCIDR 0x0d04 ++#define REG_LIODNR 0x0d08 ++#define REG_CI_RLM_AVG 0x0d14 ++#define REG_ERR_ISR 0x0e00 /* + "enum qm_isr_reg" */ ++#define REG_REV3_QCSP_LIO_CFG(n) (0x1000 + ((n) * 0x10)) ++#define REG_REV3_QCSP_IO_CFG(n) (0x1004 + ((n) * 0x10)) ++#define REG_REV3_QCSP_DD_CFG(n) (0x100c + ((n) * 0x10)) ++#define REG_CEETM_CFG_IDX 0x900 ++#define REG_CEETM_CFG_PRES 0x904 ++#define REG_CEETM_XSFDR_IN_USE 0x908 ++ ++/* Assists for QMAN_MCR */ ++#define MCR_INIT_PFDR 0x01000000 ++#define MCR_get_rslt(v) (u8)((v) >> 24) ++#define MCR_rslt_idle(r) (!rslt || (rslt >= 0xf0)) ++#define MCR_rslt_ok(r) (rslt == 0xf0) ++#define MCR_rslt_eaccess(r) (rslt == 0xf8) ++#define MCR_rslt_inval(r) (rslt == 0xff) ++ ++struct qman; ++ ++/* Follows WQ_CS_CFG0-5 */ ++enum qm_wq_class { ++ qm_wq_portal = 0, ++ qm_wq_pool = 1, ++ qm_wq_fman0 = 2, ++ qm_wq_fman1 = 3, ++ qm_wq_caam = 4, ++ qm_wq_pme = 5, ++ qm_wq_first = qm_wq_portal, ++ qm_wq_last = qm_wq_pme ++}; ++ ++/* Follows FQD_[BARE|BAR|AR] and PFDR_[BARE|BAR|AR] */ ++enum qm_memory { ++ qm_memory_fqd, ++ qm_memory_pfdr ++}; ++ ++/* Used by all error interrupt registers except 'inhibit' */ ++#define QM_EIRQ_CIDE 0x20000000 /* Corenet Initiator Data Error */ ++#define QM_EIRQ_CTDE 0x10000000 /* Corenet Target Data Error */ ++#define QM_EIRQ_CITT 0x08000000 /* Corenet Invalid Target Transaction */ ++#define QM_EIRQ_PLWI 0x04000000 /* PFDR Low Watermark */ ++#define QM_EIRQ_MBEI 0x02000000 /* Multi-bit ECC Error */ ++#define QM_EIRQ_SBEI 0x01000000 /* Single-bit ECC Error */ ++#define QM_EIRQ_PEBI 0x00800000 /* PFDR Enqueues Blocked Interrupt */ ++#define QM_EIRQ_IFSI 0x00020000 /* Invalid FQ Flow Control State */ ++#define QM_EIRQ_ICVI 0x00010000 /* Invalid Command Verb */ ++#define QM_EIRQ_IDDI 0x00000800 /* Invalid Dequeue (Direct-connect) */ ++#define QM_EIRQ_IDFI 0x00000400 /* Invalid Dequeue FQ */ ++#define QM_EIRQ_IDSI 0x00000200 /* Invalid Dequeue Source */ ++#define QM_EIRQ_IDQI 0x00000100 /* Invalid Dequeue Queue */ ++#define QM_EIRQ_IECE 0x00000010 /* Invalid Enqueue Configuration */ ++#define QM_EIRQ_IEOI 0x00000008 /* Invalid Enqueue Overflow */ ++#define QM_EIRQ_IESI 0x00000004 /* Invalid Enqueue State */ ++#define QM_EIRQ_IECI 0x00000002 /* Invalid Enqueue Channel */ ++#define QM_EIRQ_IEQI 0x00000001 /* Invalid Enqueue Queue */ ++ ++/* QMAN_ECIR valid error bit */ ++#define PORTAL_ECSR_ERR (QM_EIRQ_IEQI | QM_EIRQ_IESI | QM_EIRQ_IEOI | \ ++ QM_EIRQ_IDQI | QM_EIRQ_IDSI | QM_EIRQ_IDFI | \ ++ QM_EIRQ_IDDI | QM_EIRQ_ICVI | QM_EIRQ_IFSI) ++#define FQID_ECSR_ERR (QM_EIRQ_IEQI | QM_EIRQ_IECI | QM_EIRQ_IESI | \ ++ QM_EIRQ_IEOI | QM_EIRQ_IDQI | QM_EIRQ_IDFI | \ ++ QM_EIRQ_IFSI) ++ ++union qman_ecir { ++ u32 ecir_raw; ++ struct { ++ u32 __reserved:2; ++ u32 portal_type:1; ++ u32 portal_num:5; ++ u32 fqid:24; ++ } __packed info; ++}; ++ ++union qman_ecir2 { ++ u32 ecir2_raw; ++ struct { ++ u32 portal_type:1; ++ u32 __reserved:21; ++ u32 portal_num:10; ++ } __packed info; ++}; ++ ++union qman_eadr { ++ u32 eadr_raw; ++ struct { ++ u32 __reserved1:4; ++ u32 memid:4; ++ u32 __reserved2:12; ++ u32 eadr:12; ++ } __packed info; ++ struct { ++ u32 __reserved1:3; ++ u32 memid:5; ++ u32 __reserved:8; ++ u32 eadr:16; ++ } __packed info_rev3; ++}; ++ ++struct qman_hwerr_txt { ++ u32 mask; ++ const char *txt; ++}; ++ ++#define QMAN_HWE_TXT(a, b) { .mask = QM_EIRQ_##a, .txt = b } ++ ++static const struct qman_hwerr_txt qman_hwerr_txts[] = { ++ QMAN_HWE_TXT(CIDE, "Corenet Initiator Data Error"), ++ QMAN_HWE_TXT(CTDE, "Corenet Target Data Error"), ++ QMAN_HWE_TXT(CITT, "Corenet Invalid Target Transaction"), ++ QMAN_HWE_TXT(PLWI, "PFDR Low Watermark"), ++ QMAN_HWE_TXT(MBEI, "Multi-bit ECC Error"), ++ QMAN_HWE_TXT(SBEI, "Single-bit ECC Error"), ++ QMAN_HWE_TXT(PEBI, "PFDR Enqueues Blocked Interrupt"), ++ QMAN_HWE_TXT(ICVI, "Invalid Command Verb"), ++ QMAN_HWE_TXT(IFSI, "Invalid Flow Control State"), ++ QMAN_HWE_TXT(IDDI, "Invalid Dequeue (Direct-connect)"), ++ QMAN_HWE_TXT(IDFI, "Invalid Dequeue FQ"), ++ QMAN_HWE_TXT(IDSI, "Invalid Dequeue Source"), ++ QMAN_HWE_TXT(IDQI, "Invalid Dequeue Queue"), ++ QMAN_HWE_TXT(IECE, "Invalid Enqueue Configuration"), ++ QMAN_HWE_TXT(IEOI, "Invalid Enqueue Overflow"), ++ QMAN_HWE_TXT(IESI, "Invalid Enqueue State"), ++ QMAN_HWE_TXT(IECI, "Invalid Enqueue Channel"), ++ QMAN_HWE_TXT(IEQI, "Invalid Enqueue Queue") ++}; ++#define QMAN_HWE_COUNT (sizeof(qman_hwerr_txts)/sizeof(struct qman_hwerr_txt)) ++ ++struct qman_error_info_mdata { ++ u16 addr_mask; ++ u16 bits; ++ const char *txt; ++}; ++ ++#define QMAN_ERR_MDATA(a, b, c) { .addr_mask = a, .bits = b, .txt = c} ++static const struct qman_error_info_mdata error_mdata[] = { ++ QMAN_ERR_MDATA(0x01FF, 24, "FQD cache tag memory 0"), ++ QMAN_ERR_MDATA(0x01FF, 24, "FQD cache tag memory 1"), ++ QMAN_ERR_MDATA(0x01FF, 24, "FQD cache tag memory 2"), ++ QMAN_ERR_MDATA(0x01FF, 24, "FQD cache tag memory 3"), ++ QMAN_ERR_MDATA(0x0FFF, 512, "FQD cache memory"), ++ QMAN_ERR_MDATA(0x07FF, 128, "SFDR memory"), ++ QMAN_ERR_MDATA(0x01FF, 72, "WQ context memory"), ++ QMAN_ERR_MDATA(0x00FF, 240, "CGR memory"), ++ QMAN_ERR_MDATA(0x00FF, 302, "Internal Order Restoration List memory"), ++ QMAN_ERR_MDATA(0x01FF, 256, "SW portal ring memory"), ++ QMAN_ERR_MDATA(0x07FF, 181, "CEETM class queue descriptor memory"), ++ QMAN_ERR_MDATA(0x0FFF, 140, "CEETM extended SFDR memory"), ++ QMAN_ERR_MDATA(0x0FFF, 25, "CEETM logical FQ mapping memory"), ++ QMAN_ERR_MDATA(0x0FFF, 96, "CEETM dequeue context memory"), ++ QMAN_ERR_MDATA(0x07FF, 396, "CEETM ccgr memory"), ++ QMAN_ERR_MDATA(0x00FF, 146, "CEETM CQ channel shaping memory"), ++ QMAN_ERR_MDATA(0x007F, 256, "CEETM CQ channel scheduling memory"), ++ QMAN_ERR_MDATA(0x01FF, 88, "CEETM dequeue statistics memory"), ++}; ++#define QMAN_ERR_MDATA_COUNT \ ++ (sizeof(error_mdata)/sizeof(struct qman_error_info_mdata)) ++ ++/* Add this in Kconfig */ ++#define QMAN_ERRS_TO_UNENABLE (QM_EIRQ_PLWI | QM_EIRQ_PEBI) ++ ++/** ++ * qm_err_isr__ - Manipulate global interrupt registers ++ * @v: for accessors that write values, this is the 32-bit value ++ * ++ * Manipulates QMAN_ERR_ISR, QMAN_ERR_IER, QMAN_ERR_ISDR, QMAN_ERR_IIR. All ++ * manipulations except qm_err_isr_[un]inhibit() use 32-bit masks composed of ++ * the QM_EIRQ_*** definitions. Note that "qm_err_isr_enable_write" means ++ * "write the enable register" rather than "enable the write register"! ++ */ ++#define qm_err_isr_status_read(qm) \ ++ __qm_err_isr_read(qm, qm_isr_status) ++#define qm_err_isr_status_clear(qm, m) \ ++ __qm_err_isr_write(qm, qm_isr_status, m) ++#define qm_err_isr_enable_read(qm) \ ++ __qm_err_isr_read(qm, qm_isr_enable) ++#define qm_err_isr_enable_write(qm, v) \ ++ __qm_err_isr_write(qm, qm_isr_enable, v) ++#define qm_err_isr_disable_read(qm) \ ++ __qm_err_isr_read(qm, qm_isr_disable) ++#define qm_err_isr_disable_write(qm, v) \ ++ __qm_err_isr_write(qm, qm_isr_disable, v) ++#define qm_err_isr_inhibit(qm) \ ++ __qm_err_isr_write(qm, qm_isr_inhibit, 1) ++#define qm_err_isr_uninhibit(qm) \ ++ __qm_err_isr_write(qm, qm_isr_inhibit, 0) ++ ++/* ++ * TODO: unimplemented registers ++ * ++ * Keeping a list here of Qman registers I have not yet covered; ++ * QCSP_DD_IHRSR, QCSP_DD_IHRFR, QCSP_DD_HASR, ++ * DCP_DD_IHRSR, DCP_DD_IHRFR, DCP_DD_HASR, CM_CFG, ++ * QMAN_EECC, QMAN_SBET, QMAN_EINJ, QMAN_SBEC0-12 ++ */ ++ ++/* Encapsulate "struct qman *" as a cast of the register space address. */ ++ ++static struct qman *qm_create(void *regs) ++{ ++ return (struct qman *)regs; ++} ++ ++static inline u32 __qm_in(struct qman *qm, u32 offset) ++{ ++ return in_be32((void *)qm + offset); ++} ++static inline void __qm_out(struct qman *qm, u32 offset, u32 val) ++{ ++ out_be32((void *)qm + offset, val); ++} ++#define qm_in(reg) __qm_in(qm, REG_##reg) ++#define qm_out(reg, val) __qm_out(qm, REG_##reg, val) ++ ++static u32 __qm_err_isr_read(struct qman *qm, enum qm_isr_reg n) ++{ ++ return __qm_in(qm, REG_ERR_ISR + (n << 2)); ++} ++ ++static void __qm_err_isr_write(struct qman *qm, enum qm_isr_reg n, u32 val) ++{ ++ __qm_out(qm, REG_ERR_ISR + (n << 2), val); ++} ++ ++static void qm_set_dc(struct qman *qm, enum qm_dc_portal portal, ++ int ed, u8 sernd) ++{ ++ DPA_ASSERT(!ed || (portal == qm_dc_portal_fman0) || ++ (portal == qm_dc_portal_fman1)); ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) ++ qm_out(DCP_CFG(portal), (ed ? 0x1000 : 0) | (sernd & 0x3ff)); ++ else ++ qm_out(DCP_CFG(portal), (ed ? 0x100 : 0) | (sernd & 0x1f)); ++} ++ ++static void qm_set_wq_scheduling(struct qman *qm, enum qm_wq_class wq_class, ++ u8 cs_elev, u8 csw2, u8 csw3, u8 csw4, u8 csw5, ++ u8 csw6, u8 csw7) ++{ ++ qm_out(WQ_CS_CFG(wq_class), ((cs_elev & 0xff) << 24) | ++ ((csw2 & 0x7) << 20) | ((csw3 & 0x7) << 16) | ++ ((csw4 & 0x7) << 12) | ((csw5 & 0x7) << 8) | ++ ((csw6 & 0x7) << 4) | (csw7 & 0x7)); ++} ++ ++static void qm_set_hid(struct qman *qm) ++{ ++ qm_out(HID_CFG, 0); ++} ++ ++static void qm_set_corenet_initiator(struct qman *qm) ++{ ++ qm_out(CI_SCHED_CFG, ++ 0x80000000 | /* write srcciv enable */ ++ (CONFIG_FSL_QMAN_CI_SCHED_CFG_SRCCIV << 24) | ++ (CONFIG_FSL_QMAN_CI_SCHED_CFG_SRQ_W << 8) | ++ (CONFIG_FSL_QMAN_CI_SCHED_CFG_RW_W << 4) | ++ CONFIG_FSL_QMAN_CI_SCHED_CFG_BMAN_W); ++} ++ ++static void qm_get_version(struct qman *qm, u16 *id, u8 *major, u8 *minor, ++ u8 *cfg) ++{ ++ u32 v = qm_in(IP_REV_1); ++ u32 v2 = qm_in(IP_REV_2); ++ *id = (v >> 16); ++ *major = (v >> 8) & 0xff; ++ *minor = v & 0xff; ++ *cfg = v2 & 0xff; ++} ++ ++static void qm_set_memory(struct qman *qm, enum qm_memory memory, u64 ba, ++ int enable, int prio, int stash, u32 size) ++{ ++ u32 offset = (memory == qm_memory_fqd) ? REG_FQD_BARE : REG_PFDR_BARE; ++ u32 exp = ilog2(size); ++ /* choke if size isn't within range */ ++ DPA_ASSERT((size >= 4096) && (size <= 1073741824) && ++ is_power_of_2(size)); ++ /* choke if 'ba' has lower-alignment than 'size' */ ++ DPA_ASSERT(!(ba & (size - 1))); ++ __qm_out(qm, offset, upper_32_bits(ba)); ++ __qm_out(qm, offset + REG_offset_BAR, lower_32_bits(ba)); ++ __qm_out(qm, offset + REG_offset_AR, ++ (enable ? 0x80000000 : 0) | ++ (prio ? 0x40000000 : 0) | ++ (stash ? 0x20000000 : 0) | ++ (exp - 1)); ++} ++ ++static void qm_set_pfdr_threshold(struct qman *qm, u32 th, u8 k) ++{ ++ qm_out(PFDR_FP_LWIT, th & 0xffffff); ++ qm_out(PFDR_CFG, k); ++} ++ ++static void qm_set_sfdr_threshold(struct qman *qm, u16 th) ++{ ++ qm_out(SFDR_CFG, th & 0x3ff); ++} ++ ++static int qm_init_pfdr(struct qman *qm, u32 pfdr_start, u32 num) ++{ ++ u8 rslt = MCR_get_rslt(qm_in(MCR)); ++ ++ DPA_ASSERT(pfdr_start && !(pfdr_start & 7) && !(num & 7) && num); ++ /* Make sure the command interface is 'idle' */ ++ if (!MCR_rslt_idle(rslt)) ++ panic("QMAN_MCR isn't idle"); ++ ++ /* Write the MCR command params then the verb */ ++ qm_out(MCP(0), pfdr_start); ++ /* TODO: remove this - it's a workaround for a model bug that is ++ * corrected in more recent versions. We use the workaround until ++ * everyone has upgraded. */ ++ qm_out(MCP(1), (pfdr_start + num - 16)); ++ lwsync(); ++ qm_out(MCR, MCR_INIT_PFDR); ++ /* Poll for the result */ ++ do { ++ rslt = MCR_get_rslt(qm_in(MCR)); ++ } while (!MCR_rslt_idle(rslt)); ++ if (MCR_rslt_ok(rslt)) ++ return 0; ++ if (MCR_rslt_eaccess(rslt)) ++ return -EACCES; ++ if (MCR_rslt_inval(rslt)) ++ return -EINVAL; ++ pr_crit("Unexpected result from MCR_INIT_PFDR: %02x\n", rslt); ++ return -ENOSYS; ++} ++ ++/*****************/ ++/* Config driver */ ++/*****************/ ++ ++#define DEFAULT_FQD_SZ (PAGE_SIZE << CONFIG_FSL_QMAN_FQD_SZ) ++#define DEFAULT_PFDR_SZ (PAGE_SIZE << CONFIG_FSL_QMAN_PFDR_SZ) ++ ++/* We support only one of these */ ++static struct qman *qm; ++static struct device_node *qm_node; ++ ++/* And this state belongs to 'qm'. It is set during fsl_qman_init(), but used ++ * during qman_init_ccsr(). */ ++static dma_addr_t fqd_a, pfdr_a; ++static size_t fqd_sz = DEFAULT_FQD_SZ, pfdr_sz = DEFAULT_PFDR_SZ; ++ ++/* Parse the property to extract the memory location and size and ++ * memblock_reserve() it. If it isn't supplied, memblock_alloc() the default ++ * size. Also flush this memory range from data cache so that QMAN originated ++ * transactions for this memory region could be marked non-coherent. ++ */ ++static __init int parse_mem_property(struct device_node *node, const char *name, ++ dma_addr_t *addr, size_t *sz, int zero) ++{ ++ const u32 *pint; ++ int ret; ++ unsigned long vaddr; ++ ++ pint = of_get_property(node, name, &ret); ++ if (!pint || (ret != 16)) { ++ pr_info("No %s property '%s', using memblock_alloc(%016zx)\n", ++ node->full_name, name, *sz); ++ *addr = memblock_alloc(*sz, *sz); ++ vaddr = (unsigned long)phys_to_virt(*addr); ++ if (zero) ++ memset((void *)vaddr, 0, *sz); ++ flush_dcache_range(vaddr, vaddr + *sz); ++ return 0; ++ } ++ pr_info("Using %s property '%s'\n", node->full_name, name); ++ /* If using a "zero-pma", don't try to zero it, even if you asked */ ++ if (zero && of_find_property(node, "zero-pma", &ret)) { ++ pr_info(" it's a 'zero-pma', not zeroing from s/w\n"); ++ zero = 0; ++ } ++ *addr = ((u64)pint[0] << 32) | (u64)pint[1]; ++ *sz = ((u64)pint[2] << 32) | (u64)pint[3]; ++ /* Keep things simple, it's either all in the DRAM range or it's all ++ * outside. */ ++ if (*addr < memblock_end_of_DRAM()) { ++ BUG_ON((u64)*addr + (u64)*sz > memblock_end_of_DRAM()); ++ if (memblock_reserve(*addr, *sz) < 0) { ++ pr_err("Failed to reserve %s\n", name); ++ return -ENOMEM; ++ } ++ vaddr = (unsigned long)phys_to_virt(*addr); ++ if (zero) ++ memset(phys_to_virt(*addr), 0, *sz); ++ flush_dcache_range(vaddr, vaddr + *sz); ++ } else if (zero) { ++ /* map as cacheable, non-guarded */ ++ void __iomem *tmpp = ioremap_prot(*addr, *sz, 0); ++ if (!tmpp) ++ return -ENOMEM; ++ memset_io(tmpp, 0, *sz); ++ vaddr = (unsigned long)tmpp; ++ flush_dcache_range(vaddr, vaddr + *sz); ++ iounmap(tmpp); ++ } ++ return 0; ++} ++ ++/* TODO: ++ * - there is obviously no handling of errors, ++ * - the calls to qm_set_memory() hard-code the priority and CPC-stashing for ++ * both memory resources to zero. ++ */ ++static int __init fsl_qman_init(struct device_node *node) ++{ ++ struct resource res; ++ resource_size_t len; ++ u32 __iomem *regs; ++ const char *s; ++ int ret, standby = 0; ++ u16 id; ++ u8 major, minor, cfg; ++ ret = of_address_to_resource(node, 0, &res); ++ if (ret) { ++ pr_err("Can't get %s property '%s'\n", node->full_name, "reg"); ++ return ret; ++ } ++ s = of_get_property(node, "fsl,hv-claimable", &ret); ++ if (s && !strcmp(s, "standby")) ++ standby = 1; ++ if (!standby) { ++ ret = parse_mem_property(node, "fsl,qman-fqd", ++ &fqd_a, &fqd_sz, 1); ++ BUG_ON(ret); ++ ret = parse_mem_property(node, "fsl,qman-pfdr", ++ &pfdr_a, &pfdr_sz, 0); ++ BUG_ON(ret); ++ } ++ /* Global configuration */ ++ len = resource_size(&res); ++ if (len != (unsigned long)len) ++ return -EINVAL; ++ regs = ioremap(res.start, (unsigned long)len); ++ qm = qm_create(regs); ++ qm_node = node; ++ qm_get_version(qm, &id, &major, &minor, &cfg); ++ pr_info("Qman ver:%04x,%02x,%02x,%02x\n", id, major, minor, cfg); ++ if (!qman_ip_rev) { ++ if ((major == 1) && (minor == 0)) { ++ pr_err("QMAN rev1.0 on P4080 rev1 is not supported!\n"); ++ iounmap(regs); ++ return -ENODEV; ++ } else if ((major == 1) && (minor == 1)) ++ qman_ip_rev = QMAN_REV11; ++ else if ((major == 1) && (minor == 2)) ++ qman_ip_rev = QMAN_REV12; ++ else if ((major == 2) && (minor == 0)) ++ qman_ip_rev = QMAN_REV20; ++ else if ((major == 3) && (minor == 0)) ++ qman_ip_rev = QMAN_REV30; ++ else if ((major == 3) && (minor == 1)) ++ qman_ip_rev = QMAN_REV31; ++ else { ++ pr_warn("unknown Qman version, default to rev1.1\n"); ++ qman_ip_rev = QMAN_REV11; ++ } ++ qman_ip_cfg = cfg; ++ } ++ ++ if (standby) { ++ pr_info(" -> in standby mode\n"); ++ return 0; ++ } ++ return 0; ++} ++ ++int qman_have_ccsr(void) ++{ ++ return qm ? 1 : 0; ++} ++ ++__init void qman_init_early(void) ++{ ++ struct device_node *dn; ++ int ret; ++ ++ for_each_compatible_node(dn, NULL, "fsl,qman") { ++ if (qm) ++ pr_err("%s: only one 'fsl,qman' allowed\n", ++ dn->full_name); ++ else { ++ if (!of_device_is_available(dn)) ++ continue; ++ ++ ret = fsl_qman_init(dn); ++ BUG_ON(ret); ++ } ++ } ++} ++ ++static void log_edata_bits(u32 bit_count) ++{ ++ u32 i, j, mask = 0xffffffff; ++ ++ pr_warn("Qman ErrInt, EDATA:\n"); ++ i = bit_count/32; ++ if (bit_count%32) { ++ i++; ++ mask = ~(mask << bit_count%32); ++ } ++ j = 16-i; ++ pr_warn(" 0x%08x\n", qm_in(EDATA(j)) & mask); ++ j++; ++ for (; j < 16; j++) ++ pr_warn(" 0x%08x\n", qm_in(EDATA(j))); ++} ++ ++static void log_additional_error_info(u32 isr_val, u32 ecsr_val) ++{ ++ union qman_ecir ecir_val; ++ union qman_eadr eadr_val; ++ ++ ecir_val.ecir_raw = qm_in(ECIR); ++ /* Is portal info valid */ ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) { ++ union qman_ecir2 ecir2_val; ++ ecir2_val.ecir2_raw = qm_in(ECIR2); ++ if (ecsr_val & PORTAL_ECSR_ERR) { ++ pr_warn("Qman ErrInt: %s id %d\n", ++ (ecir2_val.info.portal_type) ? ++ "DCP" : "SWP", ecir2_val.info.portal_num); ++ } ++ if (ecsr_val & (FQID_ECSR_ERR | QM_EIRQ_IECE)) { ++ pr_warn("Qman ErrInt: ecir.fqid 0x%x\n", ++ ecir_val.info.fqid); ++ } ++ if (ecsr_val & (QM_EIRQ_SBEI|QM_EIRQ_MBEI)) { ++ eadr_val.eadr_raw = qm_in(EADR); ++ pr_warn("Qman ErrInt: EADR Memory: %s, 0x%x\n", ++ error_mdata[eadr_val.info_rev3.memid].txt, ++ error_mdata[eadr_val.info_rev3.memid].addr_mask ++ & eadr_val.info_rev3.eadr); ++ log_edata_bits( ++ error_mdata[eadr_val.info_rev3.memid].bits); ++ } ++ } else { ++ if (ecsr_val & PORTAL_ECSR_ERR) { ++ pr_warn("Qman ErrInt: %s id %d\n", ++ (ecir_val.info.portal_type) ? ++ "DCP" : "SWP", ecir_val.info.portal_num); ++ } ++ if (ecsr_val & FQID_ECSR_ERR) { ++ pr_warn("Qman ErrInt: ecir.fqid 0x%x\n", ++ ecir_val.info.fqid); ++ } ++ if (ecsr_val & (QM_EIRQ_SBEI|QM_EIRQ_MBEI)) { ++ eadr_val.eadr_raw = qm_in(EADR); ++ pr_warn("Qman ErrInt: EADR Memory: %s, 0x%x\n", ++ error_mdata[eadr_val.info.memid].txt, ++ error_mdata[eadr_val.info.memid].addr_mask ++ & eadr_val.info.eadr); ++ log_edata_bits(error_mdata[eadr_val.info.memid].bits); ++ } ++ } ++} ++ ++/* Qman interrupt handler */ ++static irqreturn_t qman_isr(int irq, void *ptr) ++{ ++ u32 isr_val, ier_val, ecsr_val, isr_mask, i; ++ ++ ier_val = qm_err_isr_enable_read(qm); ++ isr_val = qm_err_isr_status_read(qm); ++ ecsr_val = qm_in(ECSR); ++ isr_mask = isr_val & ier_val; ++ ++ if (!isr_mask) ++ return IRQ_NONE; ++ for (i = 0; i < QMAN_HWE_COUNT; i++) { ++ if (qman_hwerr_txts[i].mask & isr_mask) { ++ pr_warn("Qman ErrInt: %s\n", qman_hwerr_txts[i].txt); ++ if (qman_hwerr_txts[i].mask & ecsr_val) { ++ log_additional_error_info(isr_mask, ecsr_val); ++ /* Re-arm error capture registers */ ++ qm_out(ECSR, ecsr_val); ++ } ++ if (qman_hwerr_txts[i].mask & QMAN_ERRS_TO_UNENABLE) { ++ pr_devel("Qman un-enabling error 0x%x\n", ++ qman_hwerr_txts[i].mask); ++ ier_val &= ~qman_hwerr_txts[i].mask; ++ qm_err_isr_enable_write(qm, ier_val); ++ } ++ } ++ } ++ qm_err_isr_status_clear(qm, isr_val); ++ return IRQ_HANDLED; ++} ++ ++static int __bind_irq(void) ++{ ++ int ret, err_irq; ++ ++ err_irq = of_irq_to_resource(qm_node, 0, NULL); ++ if (err_irq == NO_IRQ) { ++ pr_info("Can't get %s property '%s'\n", qm_node->full_name, ++ "interrupts"); ++ return -ENODEV; ++ } ++ ret = request_irq(err_irq, qman_isr, IRQF_SHARED, "qman-err", qm_node); ++ if (ret) { ++ pr_err("request_irq() failed %d for '%s'\n", ret, ++ qm_node->full_name); ++ return -ENODEV; ++ } ++ /* Write-to-clear any stale bits, (eg. starvation being asserted prior ++ * to resource allocation during driver init). */ ++ qm_err_isr_status_clear(qm, 0xffffffff); ++ /* Enable Error Interrupts */ ++ qm_err_isr_enable_write(qm, 0xffffffff); ++ return 0; ++} ++ ++int qman_init_ccsr(struct device_node *node) ++{ ++ int ret; ++ if (!qman_have_ccsr()) ++ return 0; ++ if (node != qm_node) ++ return -EINVAL; ++ /* FQD memory */ ++ qm_set_memory(qm, qm_memory_fqd, fqd_a, 1, 0, 0, fqd_sz); ++ /* PFDR memory */ ++ qm_set_memory(qm, qm_memory_pfdr, pfdr_a, 1, 0, 0, pfdr_sz); ++ qm_init_pfdr(qm, 8, pfdr_sz / 64 - 8); ++ /* thresholds */ ++ qm_set_pfdr_threshold(qm, 512, 64); ++ qm_set_sfdr_threshold(qm, 128); ++ /* clear stale PEBI bit from interrupt status register */ ++ qm_err_isr_status_clear(qm, QM_EIRQ_PEBI); ++ /* corenet initiator settings */ ++ qm_set_corenet_initiator(qm); ++ /* HID settings */ ++ qm_set_hid(qm); ++ /* Set scheduling weights to defaults */ ++ for (ret = qm_wq_first; ret <= qm_wq_last; ret++) ++ qm_set_wq_scheduling(qm, ret, 0, 0, 0, 0, 0, 0, 0); ++ /* We are not prepared to accept ERNs for hardware enqueues */ ++ qm_set_dc(qm, qm_dc_portal_fman0, 1, 0); ++ qm_set_dc(qm, qm_dc_portal_fman1, 1, 0); ++ /* Initialise Error Interrupt Handler */ ++ ret = __bind_irq(); ++ if (ret) ++ return ret; ++ return 0; ++} ++ ++#define LIO_CFG_LIODN_MASK 0x0fff0000 ++void qman_liodn_fixup(u16 channel) ++{ ++ static int done; ++ static u32 liodn_offset; ++ u32 before, after; ++ int idx = channel - QM_CHANNEL_SWPORTAL0; ++ ++ if (!qman_have_ccsr()) ++ return; ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) ++ before = qm_in(REV3_QCSP_LIO_CFG(idx)); ++ else ++ before = qm_in(QCSP_LIO_CFG(idx)); ++ if (!done) { ++ liodn_offset = before & LIO_CFG_LIODN_MASK; ++ done = 1; ++ return; ++ } ++ after = (before & (~LIO_CFG_LIODN_MASK)) | liodn_offset; ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) ++ qm_out(REV3_QCSP_LIO_CFG(idx), after); ++ else ++ qm_out(QCSP_LIO_CFG(idx), after); ++} ++ ++#define IO_CFG_SDEST_MASK 0x00ff0000 ++int qman_set_sdest(u16 channel, unsigned int cpu_idx) ++{ ++ int idx = channel - QM_CHANNEL_SWPORTAL0; ++ u32 before, after; ++ ++ if (!qman_have_ccsr()) ++ return -ENODEV; ++ ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) { ++ before = qm_in(REV3_QCSP_IO_CFG(idx)); ++ /* Each pair of vcpu share the same SRQ(SDEST) */ ++ cpu_idx /= 2; ++ after = (before & (~IO_CFG_SDEST_MASK)) | (cpu_idx << 16); ++ qm_out(REV3_QCSP_IO_CFG(idx), after); ++ } else { ++ before = qm_in(QCSP_IO_CFG(idx)); ++ after = (before & (~IO_CFG_SDEST_MASK)) | (cpu_idx << 16); ++ qm_out(QCSP_IO_CFG(idx), after); ++ } ++ return 0; ++} ++ ++#define MISC_CFG_WPM_MASK 0x00000002 ++int qm_set_wpm(int wpm) ++{ ++ u32 before; ++ u32 after; ++ ++ if (!qman_have_ccsr()) ++ return -ENODEV; ++ ++ before = qm_in(MISC_CFG); ++ after = (before & (~MISC_CFG_WPM_MASK)) | (wpm << 1); ++ qm_out(MISC_CFG, after); ++ return 0; ++} ++ ++int qm_get_wpm(int *wpm) ++{ ++ u32 before; ++ ++ if (!qman_have_ccsr()) ++ return -ENODEV; ++ ++ before = qm_in(MISC_CFG); ++ *wpm = (before & MISC_CFG_WPM_MASK) >> 1; ++ return 0; ++} ++ ++/* CEETM_CFG_PRES register has PRES field which is calculated by: ++ * PRES = (2^22 / credit update reference period) * QMan clock period ++ * = (2^22 * 10^9)/ CONFIG_QMAN_CEETM_UPDATE_PERIOD) / qman_clk ++ */ ++ ++int qman_ceetm_set_prescaler(enum qm_dc_portal portal) ++{ ++ u64 temp; ++ u16 pres; ++ ++ if (!qman_have_ccsr()) ++ return -ENODEV; ++ ++ temp = 0x400000 * 100; ++ do_div(temp, CONFIG_QMAN_CEETM_UPDATE_PERIOD); ++ temp *= 10000000; ++ pres = (u16)(temp / qman_clk); ++ ++ qm_out(CEETM_CFG_IDX, portal); ++ qm_out(CEETM_CFG_PRES, pres); ++ return 0; ++} ++ ++int qman_ceetm_get_prescaler(u16 *pres) ++{ ++ if (!qman_have_ccsr()) ++ return -ENODEV; ++ *pres = (u16)qm_in(CEETM_CFG_PRES); ++ return 0; ++} ++ ++#define DCP_CFG_CEETME_MASK 0xFFFF0000 ++#define QM_SP_ENABLE_CEETM(n) (0x80000000 >> (n)) ++int qman_sp_enable_ceetm_mode(enum qm_dc_portal portal, u16 sub_portal) ++{ ++ u32 dcp_cfg; ++ ++ if (!qman_have_ccsr()) ++ return -ENODEV; ++ ++ dcp_cfg = qm_in(DCP_CFG(portal)); ++ dcp_cfg |= QM_SP_ENABLE_CEETM(sub_portal); ++ qm_out(DCP_CFG(portal), dcp_cfg); ++ return 0; ++} ++ ++int qman_sp_disable_ceetm_mode(enum qm_dc_portal portal, u16 sub_portal) ++{ ++ u32 dcp_cfg; ++ ++ if (!qman_have_ccsr()) ++ return -ENODEV; ++ dcp_cfg = qm_in(DCP_CFG(portal)); ++ dcp_cfg &= ~(QM_SP_ENABLE_CEETM(sub_portal)); ++ qm_out(DCP_CFG(portal), dcp_cfg); ++ return 0; ++} ++ ++int qman_ceetm_get_xsfdr(enum qm_dc_portal portal, unsigned int *num) ++{ ++ if (!qman_have_ccsr()) ++ return -ENODEV; ++ *num = qm_in(CEETM_XSFDR_IN_USE); ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_get_xsfdr); ++ ++#ifdef CONFIG_SYSFS ++ ++#define DRV_NAME "fsl-qman" ++#define DCP_MAX_ID 3 ++#define DCP_MIN_ID 0 ++ ++static ssize_t show_pfdr_fpc(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%u\n", qm_in(PFDR_FPC)); ++}; ++ ++static ssize_t show_dlm_avg(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ u32 data; ++ int i; ++ ++ if (!sscanf(dev_attr->attr.name, "dcp%d_dlm_avg", &i)) ++ return -EINVAL; ++ if (i < DCP_MIN_ID || i > DCP_MAX_ID) ++ return -EINVAL; ++ data = qm_in(DCP_DLM_AVG(i)); ++ return snprintf(buf, PAGE_SIZE, "%d.%08d\n", data>>8, ++ (data & 0x000000ff)*390625); ++}; ++ ++static ssize_t set_dlm_avg(struct device *dev, ++ struct device_attribute *dev_attr, const char *buf, size_t count) ++{ ++ unsigned long val; ++ int i; ++ ++ if (!sscanf(dev_attr->attr.name, "dcp%d_dlm_avg", &i)) ++ return -EINVAL; ++ if (i < DCP_MIN_ID || i > DCP_MAX_ID) ++ return -EINVAL; ++ if (kstrtoul(buf, 0, &val)) { ++ dev_dbg(dev, "invalid input %s\n", buf); ++ return -EINVAL; ++ } ++ qm_out(DCP_DLM_AVG(i), val); ++ return count; ++}; ++ ++static ssize_t show_pfdr_cfg(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%u\n", qm_in(PFDR_CFG)); ++}; ++ ++static ssize_t set_pfdr_cfg(struct device *dev, ++ struct device_attribute *dev_attr, const char *buf, size_t count) ++{ ++ unsigned long val; ++ ++ if (kstrtoul(buf, 0, &val)) { ++ dev_dbg(dev, "invalid input %s\n", buf); ++ return -EINVAL; ++ } ++ qm_out(PFDR_CFG, val); ++ return count; ++}; ++ ++static ssize_t show_sfdr_in_use(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%u\n", qm_in(SFDR_IN_USE)); ++}; ++ ++static ssize_t show_idle_stat(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "%u\n", qm_in(IDLE_STAT)); ++}; ++ ++static ssize_t show_ci_rlm_avg(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ u32 data = qm_in(CI_RLM_AVG); ++ return snprintf(buf, PAGE_SIZE, "%d.%08d\n", data>>8, ++ (data & 0x000000ff)*390625); ++}; ++ ++static ssize_t set_ci_rlm_avg(struct device *dev, ++ struct device_attribute *dev_attr, const char *buf, size_t count) ++{ ++ unsigned long val; ++ ++ if (kstrtoul(buf, 0, &val)) { ++ dev_dbg(dev, "invalid input %s\n", buf); ++ return -EINVAL; ++ } ++ qm_out(CI_RLM_AVG, val); ++ return count; ++}; ++ ++static ssize_t show_err_isr(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ return snprintf(buf, PAGE_SIZE, "0x%08x\n", qm_in(ERR_ISR)); ++}; ++ ++#define SBEC_MAX_ID 14 ++#define SBEC_MIN_ID 0 ++ ++static ssize_t show_sbec(struct device *dev, ++ struct device_attribute *dev_attr, char *buf) ++{ ++ int i; ++ ++ if (!sscanf(dev_attr->attr.name, "sbec_%d", &i)) ++ return -EINVAL; ++ if (i < SBEC_MIN_ID || i > SBEC_MAX_ID) ++ return -EINVAL; ++ return snprintf(buf, PAGE_SIZE, "%u\n", qm_in(SBEC(i))); ++}; ++ ++static DEVICE_ATTR(pfdr_fpc, S_IRUSR, show_pfdr_fpc, NULL); ++static DEVICE_ATTR(pfdr_cfg, S_IRUSR, show_pfdr_cfg, set_pfdr_cfg); ++static DEVICE_ATTR(idle_stat, S_IRUSR, show_idle_stat, NULL); ++static DEVICE_ATTR(ci_rlm_avg, (S_IRUSR|S_IWUSR), ++ show_ci_rlm_avg, set_ci_rlm_avg); ++static DEVICE_ATTR(err_isr, S_IRUSR, show_err_isr, NULL); ++static DEVICE_ATTR(sfdr_in_use, S_IRUSR, show_sfdr_in_use, NULL); ++ ++static DEVICE_ATTR(dcp0_dlm_avg, (S_IRUSR|S_IWUSR), show_dlm_avg, set_dlm_avg); ++static DEVICE_ATTR(dcp1_dlm_avg, (S_IRUSR|S_IWUSR), show_dlm_avg, set_dlm_avg); ++static DEVICE_ATTR(dcp2_dlm_avg, (S_IRUSR|S_IWUSR), show_dlm_avg, set_dlm_avg); ++static DEVICE_ATTR(dcp3_dlm_avg, (S_IRUSR|S_IWUSR), show_dlm_avg, set_dlm_avg); ++ ++static DEVICE_ATTR(sbec_0, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_1, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_2, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_3, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_4, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_5, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_6, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_7, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_8, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_9, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_10, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_11, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_12, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_13, S_IRUSR, show_sbec, NULL); ++static DEVICE_ATTR(sbec_14, S_IRUSR, show_sbec, NULL); ++ ++static struct attribute *qman_dev_attributes[] = { ++ &dev_attr_pfdr_fpc.attr, ++ &dev_attr_pfdr_cfg.attr, ++ &dev_attr_idle_stat.attr, ++ &dev_attr_ci_rlm_avg.attr, ++ &dev_attr_err_isr.attr, ++ &dev_attr_dcp0_dlm_avg.attr, ++ &dev_attr_dcp1_dlm_avg.attr, ++ &dev_attr_dcp2_dlm_avg.attr, ++ &dev_attr_dcp3_dlm_avg.attr, ++ /* sfdr_in_use will be added if necessary */ ++ NULL ++}; ++ ++static struct attribute *qman_dev_ecr_attributes[] = { ++ &dev_attr_sbec_0.attr, ++ &dev_attr_sbec_1.attr, ++ &dev_attr_sbec_2.attr, ++ &dev_attr_sbec_3.attr, ++ &dev_attr_sbec_4.attr, ++ &dev_attr_sbec_5.attr, ++ &dev_attr_sbec_6.attr, ++ &dev_attr_sbec_7.attr, ++ &dev_attr_sbec_8.attr, ++ &dev_attr_sbec_9.attr, ++ &dev_attr_sbec_10.attr, ++ &dev_attr_sbec_11.attr, ++ &dev_attr_sbec_12.attr, ++ &dev_attr_sbec_13.attr, ++ &dev_attr_sbec_14.attr, ++ NULL ++}; ++ ++/* root level */ ++static const struct attribute_group qman_dev_attr_grp = { ++ .name = NULL, ++ .attrs = qman_dev_attributes ++}; ++static const struct attribute_group qman_dev_ecr_grp = { ++ .name = "error_capture", ++ .attrs = qman_dev_ecr_attributes ++}; ++ ++static int of_fsl_qman_remove(struct platform_device *ofdev) ++{ ++ sysfs_remove_group(&ofdev->dev.kobj, &qman_dev_attr_grp); ++ return 0; ++}; ++ ++static int of_fsl_qman_probe(struct platform_device *ofdev) ++{ ++ int ret; ++ ++ ret = sysfs_create_group(&ofdev->dev.kobj, &qman_dev_attr_grp); ++ if (ret) ++ goto done; ++ ret = sysfs_add_file_to_group(&ofdev->dev.kobj, ++ &dev_attr_sfdr_in_use.attr, qman_dev_attr_grp.name); ++ if (ret) ++ goto del_group_0; ++ ret = sysfs_create_group(&ofdev->dev.kobj, &qman_dev_ecr_grp); ++ if (ret) ++ goto del_group_0; ++ ++ goto done; ++ ++del_group_0: ++ sysfs_remove_group(&ofdev->dev.kobj, &qman_dev_attr_grp); ++done: ++ if (ret) ++ dev_err(&ofdev->dev, ++ "Cannot create dev attributes ret=%d\n", ret); ++ return ret; ++}; ++ ++static struct of_device_id of_fsl_qman_ids[] = { ++ { ++ .compatible = "fsl,qman", ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, of_fsl_qman_ids); ++ ++#ifdef CONFIG_PM ++ ++static u32 saved_isdr; ++static int qman_pm_suspend_noirq(struct device *dev) ++{ ++ uint32_t idle_state; ++ ++ suspend_unused_qportal(); ++ /* save isdr, disable all, clear isr */ ++ saved_isdr = qm_err_isr_disable_read(qm); ++ qm_err_isr_disable_write(qm, 0xffffffff); ++ qm_err_isr_status_clear(qm, 0xffffffff); ++ idle_state = qm_in(IDLE_STAT); ++ if (!(idle_state & 0x1)) { ++ pr_err("Qman not idle 0x%x aborting\n", idle_state); ++ qm_err_isr_disable_write(qm, saved_isdr); ++ resume_unused_qportal(); ++ return -EBUSY; ++ } ++#ifdef CONFIG_PM_DEBUG ++ pr_info("Qman suspend code, IDLE_STAT = 0x%x\n", idle_state); ++#endif ++ return 0; ++} ++ ++static int qman_pm_resume_noirq(struct device *dev) ++{ ++ /* restore isdr */ ++ qm_err_isr_disable_write(qm, saved_isdr); ++ resume_unused_qportal(); ++ return 0; ++} ++#else ++#define qman_pm_suspend_noirq NULL ++#define qman_pm_resume_noirq NULL ++#endif ++ ++static const struct dev_pm_ops qman_pm_ops = { ++ .suspend_noirq = qman_pm_suspend_noirq, ++ .resume_noirq = qman_pm_resume_noirq, ++}; ++ ++static struct platform_driver of_fsl_qman_driver = { ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = DRV_NAME, ++ .of_match_table = of_fsl_qman_ids, ++ .pm = &qman_pm_ops, ++ }, ++ .probe = of_fsl_qman_probe, ++ .remove = of_fsl_qman_remove, ++}; ++ ++static int qman_ctrl_init(void) ++{ ++ return platform_driver_register(&of_fsl_qman_driver); ++} ++ ++static void qman_ctrl_exit(void) ++{ ++ platform_driver_unregister(&of_fsl_qman_driver); ++} ++ ++module_init(qman_ctrl_init); ++module_exit(qman_ctrl_exit); ++ ++#endif /* CONFIG_SYSFS */ +diff --git a/drivers/staging/fsl_qbman/qman_debugfs.c b/drivers/staging/fsl_qbman/qman_debugfs.c +new file mode 100644 +index 0000000..06e52b1 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_debugfs.c +@@ -0,0 +1,1595 @@ ++/* Copyright 2010-2011 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 "qman_private.h" ++ ++#define MAX_FQID (0x00ffffff) ++#define QM_FQD_BLOCK_SIZE 64 ++#define QM_FQD_AR (0xC10) ++ ++static u32 fqid_max; ++static u64 qman_ccsr_start; ++static u64 qman_ccsr_size; ++ ++static const char * const state_txt[] = { ++ "Out of Service", ++ "Retired", ++ "Tentatively Scheduled", ++ "Truly Scheduled", ++ "Parked", ++ "Active, Active Held or Held Suspended", ++ "Unknown State 6", ++ "Unknown State 7", ++ NULL, ++}; ++ ++static const u8 fqd_states[] = { ++ QM_MCR_NP_STATE_OOS, QM_MCR_NP_STATE_RETIRED, QM_MCR_NP_STATE_TEN_SCHED, ++ QM_MCR_NP_STATE_TRU_SCHED, QM_MCR_NP_STATE_PARKED, ++ QM_MCR_NP_STATE_ACTIVE}; ++ ++struct mask_to_text { ++ u16 mask; ++ const char *txt; ++}; ++ ++struct mask_filter_s { ++ u16 mask; ++ u8 filter; ++}; ++ ++static const struct mask_filter_s mask_filter[] = { ++ {QM_FQCTRL_PREFERINCACHE, 0}, ++ {QM_FQCTRL_PREFERINCACHE, 1}, ++ {QM_FQCTRL_HOLDACTIVE, 0}, ++ {QM_FQCTRL_HOLDACTIVE, 1}, ++ {QM_FQCTRL_AVOIDBLOCK, 0}, ++ {QM_FQCTRL_AVOIDBLOCK, 1}, ++ {QM_FQCTRL_FORCESFDR, 0}, ++ {QM_FQCTRL_FORCESFDR, 1}, ++ {QM_FQCTRL_CPCSTASH, 0}, ++ {QM_FQCTRL_CPCSTASH, 1}, ++ {QM_FQCTRL_CTXASTASHING, 0}, ++ {QM_FQCTRL_CTXASTASHING, 1}, ++ {QM_FQCTRL_ORP, 0}, ++ {QM_FQCTRL_ORP, 1}, ++ {QM_FQCTRL_TDE, 0}, ++ {QM_FQCTRL_TDE, 1}, ++ {QM_FQCTRL_CGE, 0}, ++ {QM_FQCTRL_CGE, 1} ++}; ++ ++static const struct mask_to_text fq_ctrl_text_list[] = { ++ { ++ .mask = QM_FQCTRL_PREFERINCACHE, ++ .txt = "Prefer in cache", ++ }, ++ { ++ .mask = QM_FQCTRL_HOLDACTIVE, ++ .txt = "Hold active in portal", ++ }, ++ { ++ .mask = QM_FQCTRL_AVOIDBLOCK, ++ .txt = "Avoid Blocking", ++ }, ++ { ++ .mask = QM_FQCTRL_FORCESFDR, ++ .txt = "High-priority SFDRs", ++ }, ++ { ++ .mask = QM_FQCTRL_CPCSTASH, ++ .txt = "CPC Stash Enable", ++ }, ++ { ++ .mask = QM_FQCTRL_CTXASTASHING, ++ .txt = "Context-A stashing", ++ }, ++ { ++ .mask = QM_FQCTRL_ORP, ++ .txt = "ORP Enable", ++ }, ++ { ++ .mask = QM_FQCTRL_TDE, ++ .txt = "Tail-Drop Enable", ++ }, ++ { ++ .mask = QM_FQCTRL_CGE, ++ .txt = "Congestion Group Enable", ++ }, ++ { ++ .mask = 0, ++ .txt = NULL, ++ } ++}; ++ ++static const char *get_fqd_ctrl_text(u16 mask) ++{ ++ int i = 0; ++ ++ while (fq_ctrl_text_list[i].txt != NULL) { ++ if (fq_ctrl_text_list[i].mask == mask) ++ return fq_ctrl_text_list[i].txt; ++ i++; ++ } ++ return NULL; ++} ++ ++static const struct mask_to_text stashing_text_list[] = { ++ { ++ .mask = QM_STASHING_EXCL_CTX, ++ .txt = "FQ Ctx Stash" ++ }, ++ { ++ .mask = QM_STASHING_EXCL_DATA, ++ .txt = "Frame Data Stash", ++ }, ++ { ++ .mask = QM_STASHING_EXCL_ANNOTATION, ++ .txt = "Frame Annotation Stash", ++ }, ++ { ++ .mask = 0, ++ .txt = NULL, ++ }, ++}; ++ ++static int user_input_convert(const char __user *user_buf, size_t count, ++ unsigned long *val) ++{ ++ char buf[12]; ++ ++ if (count > sizeof(buf) - 1) ++ return -EINVAL; ++ if (copy_from_user(buf, user_buf, count)) ++ return -EFAULT; ++ buf[count] = '\0'; ++ if (kstrtoul(buf, 0, val)) ++ return -EINVAL; ++ return 0; ++} ++ ++struct line_buffer_fq { ++ u32 buf[8]; ++ u32 buf_cnt; ++ int line_cnt; ++}; ++ ++static void add_to_line_buffer(struct line_buffer_fq *line_buf, u32 fqid, ++ struct seq_file *file) ++{ ++ line_buf->buf[line_buf->buf_cnt] = fqid; ++ line_buf->buf_cnt++; ++ if (line_buf->buf_cnt == 8) { ++ /* Buffer is full, flush it */ ++ if (line_buf->line_cnt != 0) ++ seq_puts(file, ",\n"); ++ seq_printf(file, "0x%06x,0x%06x,0x%06x,0x%06x,0x%06x," ++ "0x%06x,0x%06x,0x%06x", ++ line_buf->buf[0], line_buf->buf[1], line_buf->buf[2], ++ line_buf->buf[3], line_buf->buf[4], line_buf->buf[5], ++ line_buf->buf[6], line_buf->buf[7]); ++ line_buf->buf_cnt = 0; ++ line_buf->line_cnt++; ++ } ++} ++ ++static void flush_line_buffer(struct line_buffer_fq *line_buf, ++ struct seq_file *file) ++{ ++ if (line_buf->buf_cnt) { ++ int y = 0; ++ if (line_buf->line_cnt != 0) ++ seq_puts(file, ",\n"); ++ while (y != line_buf->buf_cnt) { ++ if (y+1 == line_buf->buf_cnt) ++ seq_printf(file, "0x%06x", line_buf->buf[y]); ++ else ++ seq_printf(file, "0x%06x,", line_buf->buf[y]); ++ y++; ++ } ++ line_buf->line_cnt++; ++ } ++ if (line_buf->line_cnt) ++ seq_putc(file, '\n'); ++} ++ ++static struct dentry *dfs_root; /* debugfs root directory */ ++ ++/******************************************************************************* ++ * Query Frame Queue Non Programmable Fields ++ ******************************************************************************/ ++struct query_fq_np_fields_data_s { ++ u32 fqid; ++}; ++static struct query_fq_np_fields_data_s query_fq_np_fields_data = { ++ .fqid = 1, ++}; ++ ++static int query_fq_np_fields_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct qm_mcr_queryfq_np np; ++ struct qman_fq fq; ++ ++ fq.fqid = query_fq_np_fields_data.fqid; ++ ret = qman_query_fq_np(&fq, &np); ++ if (ret) ++ return ret; ++ /* Print state */ ++ seq_printf(file, "Query FQ Non Programmable Fields Result fqid 0x%x\n", ++ fq.fqid); ++ seq_printf(file, " force eligible pending: %s\n", ++ (np.state & QM_MCR_NP_STATE_FE) ? "yes" : "no"); ++ seq_printf(file, " retirement pending: %s\n", ++ (np.state & QM_MCR_NP_STATE_R) ? "yes" : "no"); ++ seq_printf(file, " state: %s\n", ++ state_txt[np.state & QM_MCR_NP_STATE_MASK]); ++ seq_printf(file, " fq_link: 0x%x\n", np.fqd_link); ++ seq_printf(file, " odp_seq: %u\n", np.odp_seq); ++ seq_printf(file, " orp_nesn: %u\n", np.orp_nesn); ++ seq_printf(file, " orp_ea_hseq: %u\n", np.orp_ea_hseq); ++ seq_printf(file, " orp_ea_tseq: %u\n", np.orp_ea_tseq); ++ seq_printf(file, " orp_ea_hptr: 0x%x\n", np.orp_ea_hptr); ++ seq_printf(file, " orp_ea_tptr: 0x%x\n", np.orp_ea_tptr); ++ seq_printf(file, " pfdr_hptr: 0x%x\n", np.pfdr_hptr); ++ seq_printf(file, " pfdr_tptr: 0x%x\n", np.pfdr_tptr); ++ seq_printf(file, " is: ics_surp contains a %s\n", ++ (np.is) ? "deficit" : "surplus"); ++ seq_printf(file, " ics_surp: %u\n", np.ics_surp); ++ seq_printf(file, " byte_cnt: %u\n", np.byte_cnt); ++ seq_printf(file, " frm_cnt: %u\n", np.frm_cnt); ++ seq_printf(file, " ra1_sfdr: 0x%x\n", np.ra1_sfdr); ++ seq_printf(file, " ra2_sfdr: 0x%x\n", np.ra2_sfdr); ++ seq_printf(file, " od1_sfdr: 0x%x\n", np.od1_sfdr); ++ seq_printf(file, " od2_sfdr: 0x%x\n", np.od2_sfdr); ++ seq_printf(file, " od3_sfdr: 0x%x\n", np.od3_sfdr); ++ return 0; ++} ++ ++static int query_fq_np_fields_open(struct inode *inode, ++ struct file *file) ++{ ++ return single_open(file, query_fq_np_fields_show, NULL); ++} ++ ++static ssize_t query_fq_np_fields_write(struct file *f, ++ const char __user *buf, size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ if (val > MAX_FQID) ++ return -EINVAL; ++ query_fq_np_fields_data.fqid = (u32)val; ++ return count; ++} ++ ++static const struct file_operations query_fq_np_fields_fops = { ++ .owner = THIS_MODULE, ++ .open = query_fq_np_fields_open, ++ .read = seq_read, ++ .write = query_fq_np_fields_write, ++ .release = single_release, ++}; ++ ++/******************************************************************************* ++ * Frame Queue Programmable Fields ++ ******************************************************************************/ ++struct query_fq_fields_data_s { ++ u32 fqid; ++}; ++ ++static struct query_fq_fields_data_s query_fq_fields_data = { ++ .fqid = 1, ++}; ++ ++static int query_fq_fields_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct qm_fqd fqd; ++ struct qman_fq fq; ++ int i = 0; ++ ++ memset(&fqd, 0, sizeof(struct qm_fqd)); ++ fq.fqid = query_fq_fields_data.fqid; ++ ret = qman_query_fq(&fq, &fqd); ++ if (ret) ++ return ret; ++ seq_printf(file, "Query FQ Programmable Fields Result fqid 0x%x\n", ++ fq.fqid); ++ seq_printf(file, " orprws: %u\n", fqd.orprws); ++ seq_printf(file, " oa: %u\n", fqd.oa); ++ seq_printf(file, " olws: %u\n", fqd.olws); ++ ++ seq_printf(file, " cgid: %u\n", fqd.cgid); ++ ++ if ((fqd.fq_ctrl & QM_FQCTRL_MASK) == 0) ++ seq_puts(file, " fq_ctrl: None\n"); ++ else { ++ i = 0; ++ seq_puts(file, " fq_ctrl:\n"); ++ while (fq_ctrl_text_list[i].txt != NULL) { ++ if ((fqd.fq_ctrl & QM_FQCTRL_MASK) & ++ fq_ctrl_text_list[i].mask) ++ seq_printf(file, " %s\n", ++ fq_ctrl_text_list[i].txt); ++ i++; ++ } ++ } ++ seq_printf(file, " dest_channel: %u\n", fqd.dest.channel); ++ seq_printf(file, " dest_wq: %u\n", fqd.dest.wq); ++ seq_printf(file, " ics_cred: %u\n", fqd.ics_cred); ++ seq_printf(file, " td_mant: %u\n", fqd.td.mant); ++ seq_printf(file, " td_exp: %u\n", fqd.td.exp); ++ ++ seq_printf(file, " ctx_b: 0x%x\n", fqd.context_b); ++ ++ seq_printf(file, " ctx_a: 0x%llx\n", qm_fqd_stashing_get64(&fqd)); ++ /* Any stashing configured */ ++ if ((fqd.context_a.stashing.exclusive & 0x7) == 0) ++ seq_puts(file, " ctx_a_stash_exclusive: None\n"); ++ else { ++ seq_puts(file, " ctx_a_stash_exclusive:\n"); ++ i = 0; ++ while (stashing_text_list[i].txt != NULL) { ++ if ((fqd.fq_ctrl & 0x7) & stashing_text_list[i].mask) ++ seq_printf(file, " %s\n", ++ stashing_text_list[i].txt); ++ i++; ++ } ++ } ++ seq_printf(file, " ctx_a_stash_annotation_cl: %u\n", ++ fqd.context_a.stashing.annotation_cl); ++ seq_printf(file, " ctx_a_stash_data_cl: %u\n", ++ fqd.context_a.stashing.data_cl); ++ seq_printf(file, " ctx_a_stash_context_cl: %u\n", ++ fqd.context_a.stashing.context_cl); ++ return 0; ++} ++ ++static int query_fq_fields_open(struct inode *inode, ++ struct file *file) ++{ ++ return single_open(file, query_fq_fields_show, NULL); ++} ++ ++static ssize_t query_fq_fields_write(struct file *f, ++ const char __user *buf, size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ if (val > MAX_FQID) ++ return -EINVAL; ++ query_fq_fields_data.fqid = (u32)val; ++ return count; ++} ++ ++static const struct file_operations query_fq_fields_fops = { ++ .owner = THIS_MODULE, ++ .open = query_fq_fields_open, ++ .read = seq_read, ++ .write = query_fq_fields_write, ++ .release = single_release, ++}; ++ ++/******************************************************************************* ++ * Query WQ lengths ++ ******************************************************************************/ ++struct query_wq_lengths_data_s { ++ union { ++ u16 channel_wq; /* ignores wq (3 lsbits) */ ++ struct { ++ u16 id:13; /* qm_channel */ ++ u16 __reserved:3; ++ } __packed channel; ++ }; ++}; ++static struct query_wq_lengths_data_s query_wq_lengths_data; ++static int query_wq_lengths_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct qm_mcr_querywq wq; ++ int i; ++ ++ memset(&wq, 0, sizeof(struct qm_mcr_querywq)); ++ wq.channel.id = query_wq_lengths_data.channel.id; ++ ret = qman_query_wq(0, &wq); ++ if (ret) ++ return ret; ++ seq_printf(file, "Query Result For Channel: 0x%x\n", wq.channel.id); ++ for (i = 0; i < 8; i++) ++ /* mask out upper 4 bits since they are not part of length */ ++ seq_printf(file, " wq%d_len : %u\n", i, wq.wq_len[i] & 0x0fff); ++ return 0; ++} ++ ++static int query_wq_lengths_open(struct inode *inode, ++ struct file *file) ++{ ++ return single_open(file, query_wq_lengths_show, NULL); ++} ++ ++static ssize_t query_wq_lengths_write(struct file *f, ++ const char __user *buf, size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ if (val > 0xfff8) ++ return -EINVAL; ++ query_wq_lengths_data.channel.id = (u16)val; ++ return count; ++} ++ ++static const struct file_operations query_wq_lengths_fops = { ++ .owner = THIS_MODULE, ++ .open = query_wq_lengths_open, ++ .read = seq_read, ++ .write = query_wq_lengths_write, ++ .release = single_release, ++}; ++ ++/******************************************************************************* ++ * Query CGR ++ ******************************************************************************/ ++struct query_cgr_s { ++ u8 cgid; ++}; ++static struct query_cgr_s query_cgr_data; ++ ++static int query_cgr_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct qm_mcr_querycgr cgrd; ++ struct qman_cgr cgr; ++ int i, j; ++ u32 mask; ++ ++ memset(&cgr, 0, sizeof(cgr)); ++ memset(&cgrd, 0, sizeof(cgrd)); ++ cgr.cgrid = query_cgr_data.cgid; ++ ret = qman_query_cgr(&cgr, &cgrd); ++ if (ret) ++ return ret; ++ seq_printf(file, "Query CGR id 0x%x\n", cgr.cgrid); ++ seq_printf(file, " wr_parm_g MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n", ++ cgrd.cgr.wr_parm_g.MA, cgrd.cgr.wr_parm_g.Mn, ++ cgrd.cgr.wr_parm_g.SA, cgrd.cgr.wr_parm_g.Sn, ++ cgrd.cgr.wr_parm_g.Pn); ++ ++ seq_printf(file, " wr_parm_y MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n", ++ cgrd.cgr.wr_parm_y.MA, cgrd.cgr.wr_parm_y.Mn, ++ cgrd.cgr.wr_parm_y.SA, cgrd.cgr.wr_parm_y.Sn, ++ cgrd.cgr.wr_parm_y.Pn); ++ ++ seq_printf(file, " wr_parm_r MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n", ++ cgrd.cgr.wr_parm_r.MA, cgrd.cgr.wr_parm_r.Mn, ++ cgrd.cgr.wr_parm_r.SA, cgrd.cgr.wr_parm_r.Sn, ++ cgrd.cgr.wr_parm_r.Pn); ++ ++ seq_printf(file, " wr_en_g: %u, wr_en_y: %u, we_en_r: %u\n", ++ cgrd.cgr.wr_en_g, cgrd.cgr.wr_en_y, cgrd.cgr.wr_en_r); ++ ++ seq_printf(file, " cscn_en: %u\n", cgrd.cgr.cscn_en); ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) { ++ seq_puts(file, " cscn_targ_dcp:\n"); ++ mask = 0x80000000; ++ for (i = 0; i < 32; i++) { ++ if (cgrd.cgr.cscn_targ & mask) ++ seq_printf(file, " send CSCN to dcp %u\n", ++ (31 - i)); ++ mask >>= 1; ++ } ++ ++ seq_puts(file, " cscn_targ_swp:\n"); ++ for (i = 0; i < 4; i++) { ++ mask = 0x80000000; ++ for (j = 0; j < 32; j++) { ++ if (cgrd.cscn_targ_swp[i] & mask) ++ seq_printf(file, " send CSCN to swp" ++ " %u\n", (127 - (i * 32) - j)); ++ mask >>= 1; ++ } ++ } ++ } else { ++ seq_printf(file, " cscn_targ: %u\n", cgrd.cgr.cscn_targ); ++ } ++ seq_printf(file, " cstd_en: %u\n", cgrd.cgr.cstd_en); ++ seq_printf(file, " cs: %u\n", cgrd.cgr.cs); ++ ++ seq_printf(file, " cs_thresh_TA: %u, cs_thresh_Tn: %u\n", ++ cgrd.cgr.cs_thres.TA, cgrd.cgr.cs_thres.Tn); ++ ++ seq_printf(file, " mode: %s\n", ++ (cgrd.cgr.mode & QMAN_CGR_MODE_FRAME) ? ++ "frame count" : "byte count"); ++ seq_printf(file, " i_bcnt: %llu\n", qm_mcr_querycgr_i_get64(&cgrd)); ++ seq_printf(file, " a_bcnt: %llu\n", qm_mcr_querycgr_a_get64(&cgrd)); ++ ++ return 0; ++} ++ ++static int query_cgr_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, query_cgr_show, NULL); ++} ++ ++static ssize_t query_cgr_write(struct file *f, const char __user *buf, ++ size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ if (val > 0xff) ++ return -EINVAL; ++ query_cgr_data.cgid = (u8)val; ++ return count; ++} ++ ++static const struct file_operations query_cgr_fops = { ++ .owner = THIS_MODULE, ++ .open = query_cgr_open, ++ .read = seq_read, ++ .write = query_cgr_write, ++ .release = single_release, ++}; ++ ++/******************************************************************************* ++ * Test Write CGR ++ ******************************************************************************/ ++struct test_write_cgr_s { ++ u64 i_bcnt; ++ u8 cgid; ++}; ++static struct test_write_cgr_s test_write_cgr_data; ++ ++static int testwrite_cgr_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct qm_mcr_cgrtestwrite result; ++ struct qman_cgr cgr; ++ u64 i_bcnt; ++ ++ memset(&cgr, 0, sizeof(struct qman_cgr)); ++ memset(&result, 0, sizeof(struct qm_mcr_cgrtestwrite)); ++ cgr.cgrid = test_write_cgr_data.cgid; ++ i_bcnt = test_write_cgr_data.i_bcnt; ++ ret = qman_testwrite_cgr(&cgr, i_bcnt, &result); ++ if (ret) ++ return ret; ++ seq_printf(file, "CGR Test Write CGR id 0x%x\n", cgr.cgrid); ++ seq_printf(file, " wr_parm_g MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n", ++ result.cgr.wr_parm_g.MA, result.cgr.wr_parm_g.Mn, ++ result.cgr.wr_parm_g.SA, result.cgr.wr_parm_g.Sn, ++ result.cgr.wr_parm_g.Pn); ++ seq_printf(file, " wr_parm_y MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n", ++ result.cgr.wr_parm_y.MA, result.cgr.wr_parm_y.Mn, ++ result.cgr.wr_parm_y.SA, result.cgr.wr_parm_y.Sn, ++ result.cgr.wr_parm_y.Pn); ++ seq_printf(file, " wr_parm_r MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n", ++ result.cgr.wr_parm_r.MA, result.cgr.wr_parm_r.Mn, ++ result.cgr.wr_parm_r.SA, result.cgr.wr_parm_r.Sn, ++ result.cgr.wr_parm_r.Pn); ++ seq_printf(file, " wr_en_g: %u, wr_en_y: %u, we_en_r: %u\n", ++ result.cgr.wr_en_g, result.cgr.wr_en_y, result.cgr.wr_en_r); ++ seq_printf(file, " cscn_en: %u\n", result.cgr.cscn_en); ++ seq_printf(file, " cscn_targ: %u\n", result.cgr.cscn_targ); ++ seq_printf(file, " cstd_en: %u\n", result.cgr.cstd_en); ++ seq_printf(file, " cs: %u\n", result.cgr.cs); ++ seq_printf(file, " cs_thresh_TA: %u, cs_thresh_Tn: %u\n", ++ result.cgr.cs_thres.TA, result.cgr.cs_thres.Tn); ++ ++ /* Add Mode for Si 2 */ ++ seq_printf(file, " mode: %s\n", ++ (result.cgr.mode & QMAN_CGR_MODE_FRAME) ? ++ "frame count" : "byte count"); ++ ++ seq_printf(file, " i_bcnt: %llu\n", ++ qm_mcr_cgrtestwrite_i_get64(&result)); ++ seq_printf(file, " a_bcnt: %llu\n", ++ qm_mcr_cgrtestwrite_a_get64(&result)); ++ seq_printf(file, " wr_prob_g: %u\n", result.wr_prob_g); ++ seq_printf(file, " wr_prob_y: %u\n", result.wr_prob_y); ++ seq_printf(file, " wr_prob_r: %u\n", result.wr_prob_r); ++ return 0; ++} ++ ++static int testwrite_cgr_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, testwrite_cgr_show, NULL); ++} ++ ++static const struct file_operations testwrite_cgr_fops = { ++ .owner = THIS_MODULE, ++ .open = testwrite_cgr_open, ++ .read = seq_read, ++ .release = single_release, ++}; ++ ++ ++static int testwrite_cgr_ibcnt_show(struct seq_file *file, void *offset) ++{ ++ seq_printf(file, "i_bcnt: %llu\n", test_write_cgr_data.i_bcnt); ++ return 0; ++} ++static int testwrite_cgr_ibcnt_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, testwrite_cgr_ibcnt_show, NULL); ++} ++ ++static ssize_t testwrite_cgr_ibcnt_write(struct file *f, const char __user *buf, ++ size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ test_write_cgr_data.i_bcnt = val; ++ return count; ++} ++ ++static const struct file_operations teswrite_cgr_ibcnt_fops = { ++ .owner = THIS_MODULE, ++ .open = testwrite_cgr_ibcnt_open, ++ .read = seq_read, ++ .write = testwrite_cgr_ibcnt_write, ++ .release = single_release, ++}; ++ ++static int testwrite_cgr_cgrid_show(struct seq_file *file, void *offset) ++{ ++ seq_printf(file, "cgrid: %u\n", (u32)test_write_cgr_data.cgid); ++ return 0; ++} ++static int testwrite_cgr_cgrid_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, testwrite_cgr_cgrid_show, NULL); ++} ++ ++static ssize_t testwrite_cgr_cgrid_write(struct file *f, const char __user *buf, ++ size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ if (val > 0xff) ++ return -EINVAL; ++ test_write_cgr_data.cgid = (u8)val; ++ return count; ++} ++ ++static const struct file_operations teswrite_cgr_cgrid_fops = { ++ .owner = THIS_MODULE, ++ .open = testwrite_cgr_cgrid_open, ++ .read = seq_read, ++ .write = testwrite_cgr_cgrid_write, ++ .release = single_release, ++}; ++ ++/******************************************************************************* ++ * Query Congestion State ++ ******************************************************************************/ ++static int query_congestion_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct qm_mcr_querycongestion cs; ++ int i, j, in_cong = 0; ++ u32 mask; ++ ++ memset(&cs, 0, sizeof(struct qm_mcr_querycongestion)); ++ ret = qman_query_congestion(&cs); ++ if (ret) ++ return ret; ++ seq_puts(file, "Query Congestion Result\n"); ++ for (i = 0; i < 8; i++) { ++ mask = 0x80000000; ++ for (j = 0; j < 32; j++) { ++ if (cs.state.__state[i] & mask) { ++ in_cong = 1; ++ seq_printf(file, " cg %u: %s\n", (i*32)+j, ++ "in congestion"); ++ } ++ mask >>= 1; ++ } ++ } ++ if (!in_cong) ++ seq_puts(file, " All congestion groups not congested.\n"); ++ return 0; ++} ++ ++static int query_congestion_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, query_congestion_show, NULL); ++} ++ ++static const struct file_operations query_congestion_fops = { ++ .owner = THIS_MODULE, ++ .open = query_congestion_open, ++ .read = seq_read, ++ .release = single_release, ++}; ++ ++/******************************************************************************* ++ * Query CCGR ++ ******************************************************************************/ ++struct query_ccgr_s { ++ u32 ccgid; ++}; ++static struct query_ccgr_s query_ccgr_data; ++ ++static int query_ccgr_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct qm_mcr_ceetm_ccgr_query ccgr_query; ++ struct qm_mcc_ceetm_ccgr_query query_opts; ++ int i, j; ++ u32 mask; ++ ++ memset(&ccgr_query, 0, sizeof(struct qm_mcr_ceetm_ccgr_query)); ++ memset(&query_opts, 0, sizeof(struct qm_mcc_ceetm_ccgr_query)); ++ ++ if ((qman_ip_rev & 0xFF00) < QMAN_REV30) ++ return -EINVAL; ++ ++ seq_printf(file, "Query CCGID %x\n", query_ccgr_data.ccgid); ++ query_opts.dcpid = ((query_ccgr_data.ccgid & 0xFF000000) >> 24); ++ query_opts.ccgrid = query_ccgr_data.ccgid & 0x000001FF; ++ ret = qman_ceetm_query_ccgr(&query_opts, &ccgr_query); ++ if (ret) ++ return ret; ++ seq_printf(file, "Query CCGR id %x in DCP %d\n", query_opts.ccgrid, ++ query_opts.dcpid); ++ seq_printf(file, " wr_parm_g MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n", ++ ccgr_query.cm_query.wr_parm_g.MA, ++ ccgr_query.cm_query.wr_parm_g.Mn, ++ ccgr_query.cm_query.wr_parm_g.SA, ++ ccgr_query.cm_query.wr_parm_g.Sn, ++ ccgr_query.cm_query.wr_parm_g.Pn); ++ ++ seq_printf(file, " wr_parm_y MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n", ++ ccgr_query.cm_query.wr_parm_y.MA, ++ ccgr_query.cm_query.wr_parm_y.Mn, ++ ccgr_query.cm_query.wr_parm_y.SA, ++ ccgr_query.cm_query.wr_parm_y.Sn, ++ ccgr_query.cm_query.wr_parm_y.Pn); ++ ++ seq_printf(file, " wr_parm_r MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n", ++ ccgr_query.cm_query.wr_parm_r.MA, ++ ccgr_query.cm_query.wr_parm_r.Mn, ++ ccgr_query.cm_query.wr_parm_r.SA, ++ ccgr_query.cm_query.wr_parm_r.Sn, ++ ccgr_query.cm_query.wr_parm_r.Pn); ++ ++ seq_printf(file, " wr_en_g: %u, wr_en_y: %u, we_en_r: %u\n", ++ ((ccgr_query.cm_query.ctl >> 6) & 0x1), ++ ((ccgr_query.cm_query.ctl >> 5 & 0x1)), ++ ((ccgr_query.cm_query.ctl >> 4) & 0x1)); ++ ++ seq_printf(file, " cscn_en: %u\n", ((ccgr_query.cm_query.ctl >> 1) & ++ 0x1)); ++ seq_puts(file, " cscn_targ_dcp:\n"); ++ mask = 0x80000000; ++ for (i = 0; i < 32; i++) { ++ if (ccgr_query.cm_query.cscn_targ_dcp & mask) ++ seq_printf(file, " send CSCN to dcp %u\n", (31 - i)); ++ mask >>= 1; ++ } ++ ++ seq_puts(file, " cscn_targ_swp:\n"); ++ for (i = 0; i < 4; i++) { ++ mask = 0x80000000; ++ for (j = 0; j < 32; j++) { ++ if (ccgr_query.cm_query.cscn_targ_swp[i] & mask) ++ seq_printf(file, " send CSCN to swp" ++ "%u\n", (127 - (i * 32) - j)); ++ mask >>= 1; ++ } ++ } ++ ++ seq_printf(file, " td_en: %u\n", (ccgr_query.cm_query.ctl >> 3)); ++ ++ seq_printf(file, " cs_thresh_in_TA: %u, cs_thresh_in_Tn: %u\n", ++ ccgr_query.cm_query.cs_thres.TA, ++ ccgr_query.cm_query.cs_thres.Tn); ++ ++ seq_printf(file, " cs_thresh_out_TA: %u, cs_thresh_out_Tn: %u\n", ++ ccgr_query.cm_query.cs_thres_x.TA, ++ ccgr_query.cm_query.cs_thres_x.Tn); ++ ++ seq_printf(file, " td_thresh_TA: %u, td_thresh_Tn: %u\n", ++ ccgr_query.cm_query.td_thres.TA, ++ ccgr_query.cm_query.td_thres.Tn); ++ ++ seq_printf(file, " mode: %s\n", ++ ((ccgr_query.cm_query.ctl & 0x1) & ++ QMAN_CGR_MODE_FRAME) ? ++ "frame count" : "byte count"); ++ seq_printf(file, " i_cnt: %llu\n", (u64)ccgr_query.cm_query.i_cnt); ++ seq_printf(file, " a_cnt: %llu\n", (u64)ccgr_query.cm_query.a_cnt); ++ ++ return 0; ++} ++ ++static int query_ccgr_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, query_ccgr_show, NULL); ++} ++ ++static ssize_t query_ccgr_write(struct file *f, const char __user *buf, ++ size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ query_ccgr_data.ccgid = val; ++ return count; ++} ++ ++static const struct file_operations query_ccgr_fops = { ++ .owner = THIS_MODULE, ++ .open = query_ccgr_open, ++ .read = seq_read, ++ .write = query_ccgr_write, ++ .release = single_release, ++}; ++/******************************************************************************* ++ * QMan register ++ ******************************************************************************/ ++struct qman_register_s { ++ u32 val; ++}; ++static struct qman_register_s qman_register_data; ++ ++static void init_ccsrmempeek(void) ++{ ++ struct device_node *dn; ++ const u32 *regaddr_p; ++ ++ dn = of_find_compatible_node(NULL, NULL, "fsl,qman"); ++ if (!dn) { ++ pr_info("No fsl,qman node\n"); ++ return; ++ } ++ regaddr_p = of_get_address(dn, 0, &qman_ccsr_size, NULL); ++ if (!regaddr_p) { ++ of_node_put(dn); ++ return; ++ } ++ qman_ccsr_start = of_translate_address(dn, regaddr_p); ++ of_node_put(dn); ++} ++/* This function provides access to QMan ccsr memory map */ ++static int qman_ccsrmempeek(u32 *val, u32 offset) ++{ ++ void __iomem *addr; ++ u64 phys_addr; ++ ++ if (!qman_ccsr_start) ++ return -EINVAL; ++ ++ if (offset > (qman_ccsr_size - sizeof(u32))) ++ return -EINVAL; ++ ++ phys_addr = qman_ccsr_start + offset; ++ addr = ioremap(phys_addr, sizeof(u32)); ++ if (!addr) { ++ pr_err("ccsrmempeek, ioremap failed\n"); ++ return -EINVAL; ++ } ++ *val = in_be32(addr); ++ iounmap(addr); ++ return 0; ++} ++ ++static int qman_ccsrmempeek_show(struct seq_file *file, void *offset) ++{ ++ u32 b; ++ ++ qman_ccsrmempeek(&b, qman_register_data.val); ++ seq_printf(file, "QMan register offset = 0x%x\n", ++ qman_register_data.val); ++ seq_printf(file, "value = 0x%08x\n", b); ++ ++ return 0; ++} ++ ++static int qman_ccsrmempeek_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, qman_ccsrmempeek_show, NULL); ++} ++ ++static ssize_t qman_ccsrmempeek_write(struct file *f, const char __user *buf, ++ size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ /* multiple of 4 */ ++ if (val > (qman_ccsr_size - sizeof(u32))) { ++ pr_info("Input 0x%lx > 0x%llx\n", ++ val, (qman_ccsr_size - sizeof(u32))); ++ return -EINVAL; ++ } ++ if (val & 0x3) { ++ pr_info("Input 0x%lx not multiple of 4\n", val); ++ return -EINVAL; ++ } ++ qman_register_data.val = val; ++ return count; ++} ++ ++static const struct file_operations qman_ccsrmempeek_fops = { ++ .owner = THIS_MODULE, ++ .open = qman_ccsrmempeek_open, ++ .read = seq_read, ++ .write = qman_ccsrmempeek_write, ++}; ++ ++/******************************************************************************* ++ * QMan state ++ ******************************************************************************/ ++static int qman_fqd_state_show(struct seq_file *file, void *offset) ++{ ++ struct qm_mcr_queryfq_np np; ++ struct qman_fq fq; ++ struct line_buffer_fq line_buf; ++ int ret, i; ++ u8 *state = file->private; ++ u32 qm_fq_state_cnt[ARRAY_SIZE(fqd_states)]; ++ ++ memset(qm_fq_state_cnt, 0, sizeof(qm_fq_state_cnt)); ++ memset(&line_buf, 0, sizeof(line_buf)); ++ ++ seq_printf(file, "List of fq ids in state: %s\n", state_txt[*state]); ++ ++ for (i = 1; i < fqid_max; i++) { ++ fq.fqid = i; ++ ret = qman_query_fq_np(&fq, &np); ++ if (ret) ++ return ret; ++ if (*state == (np.state & QM_MCR_NP_STATE_MASK)) ++ add_to_line_buffer(&line_buf, fq.fqid, file); ++ /* Keep a summary count of all states */ ++ if ((np.state & QM_MCR_NP_STATE_MASK) < ARRAY_SIZE(fqd_states)) ++ qm_fq_state_cnt[(np.state & QM_MCR_NP_STATE_MASK)]++; ++ } ++ flush_line_buffer(&line_buf, file); ++ ++ for (i = 0; i < ARRAY_SIZE(fqd_states); i++) { ++ seq_printf(file, "%s count = %u\n", state_txt[i], ++ qm_fq_state_cnt[i]); ++ } ++ return 0; ++} ++ ++static int qman_fqd_state_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, qman_fqd_state_show, inode->i_private); ++} ++ ++static const struct file_operations qman_fqd_state_fops = { ++ .owner = THIS_MODULE, ++ .open = qman_fqd_state_open, ++ .read = seq_read, ++}; ++ ++static int qman_fqd_ctrl_show(struct seq_file *file, void *offset) ++{ ++ struct qm_fqd fqd; ++ struct qman_fq fq; ++ u32 fq_en_cnt = 0, fq_di_cnt = 0; ++ int ret, i; ++ struct mask_filter_s *data = file->private; ++ const char *ctrl_txt = get_fqd_ctrl_text(data->mask); ++ struct line_buffer_fq line_buf; ++ ++ memset(&line_buf, 0, sizeof(line_buf)); ++ seq_printf(file, "List of fq ids with: %s :%s\n", ++ ctrl_txt, (data->filter) ? "enabled" : "disabled"); ++ for (i = 1; i < fqid_max; i++) { ++ fq.fqid = i; ++ memset(&fqd, 0, sizeof(struct qm_fqd)); ++ ret = qman_query_fq(&fq, &fqd); ++ if (ret) ++ return ret; ++ if (data->filter) { ++ if (fqd.fq_ctrl & data->mask) ++ add_to_line_buffer(&line_buf, fq.fqid, file); ++ } else { ++ if (!(fqd.fq_ctrl & data->mask)) ++ add_to_line_buffer(&line_buf, fq.fqid, file); ++ } ++ if (fqd.fq_ctrl & data->mask) ++ fq_en_cnt++; ++ else ++ fq_di_cnt++; ++ } ++ flush_line_buffer(&line_buf, file); ++ ++ seq_printf(file, "Total FQD with: %s : enabled = %u\n", ++ ctrl_txt, fq_en_cnt); ++ seq_printf(file, "Total FQD with: %s : disabled = %u\n", ++ ctrl_txt, fq_di_cnt); ++ return 0; ++} ++ ++/******************************************************************************* ++ * QMan ctrl CGE, TDE, ORP, CTX, CPC, SFDR, BLOCK, HOLD, CACHE ++ ******************************************************************************/ ++static int qman_fqd_ctrl_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, qman_fqd_ctrl_show, inode->i_private); ++} ++ ++static const struct file_operations qman_fqd_ctrl_fops = { ++ .owner = THIS_MODULE, ++ .open = qman_fqd_ctrl_open, ++ .read = seq_read, ++}; ++ ++/******************************************************************************* ++ * QMan ctrl summary ++ ******************************************************************************/ ++/******************************************************************************* ++ * QMan summary state ++ ******************************************************************************/ ++static int qman_fqd_non_prog_summary_show(struct seq_file *file, void *offset) ++{ ++ struct qm_mcr_queryfq_np np; ++ struct qman_fq fq; ++ int ret, i; ++ u32 qm_fq_state_cnt[ARRAY_SIZE(fqd_states)]; ++ ++ memset(qm_fq_state_cnt, 0, sizeof(qm_fq_state_cnt)); ++ ++ for (i = 1; i < fqid_max; i++) { ++ fq.fqid = i; ++ ret = qman_query_fq_np(&fq, &np); ++ if (ret) ++ return ret; ++ /* Keep a summary count of all states */ ++ if ((np.state & QM_MCR_NP_STATE_MASK) < ARRAY_SIZE(fqd_states)) ++ qm_fq_state_cnt[(np.state & QM_MCR_NP_STATE_MASK)]++; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(fqd_states); i++) { ++ seq_printf(file, "%s count = %u\n", state_txt[i], ++ qm_fq_state_cnt[i]); ++ } ++ return 0; ++} ++ ++static int qman_fqd_prog_summary_show(struct seq_file *file, void *offset) ++{ ++ struct qm_fqd fqd; ++ struct qman_fq fq; ++ int ret, i , j; ++ u32 qm_prog_cnt[ARRAY_SIZE(mask_filter)/2]; ++ ++ memset(qm_prog_cnt, 0, sizeof(qm_prog_cnt)); ++ ++ for (i = 1; i < fqid_max; i++) { ++ memset(&fqd, 0, sizeof(struct qm_fqd)); ++ fq.fqid = i; ++ ret = qman_query_fq(&fq, &fqd); ++ if (ret) ++ return ret; ++ /* Keep a summary count of all states */ ++ for (j = 0; j < ARRAY_SIZE(mask_filter); j += 2) ++ if ((fqd.fq_ctrl & QM_FQCTRL_MASK) & ++ mask_filter[j].mask) ++ qm_prog_cnt[j/2]++; ++ } ++ for (i = 0; i < ARRAY_SIZE(mask_filter) / 2; i++) { ++ seq_printf(file, "%s count = %u\n", ++ get_fqd_ctrl_text(mask_filter[i*2].mask), ++ qm_prog_cnt[i]); ++ } ++ return 0; ++} ++ ++static int qman_fqd_summary_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ ++ /* Display summary of non programmable fields */ ++ ret = qman_fqd_non_prog_summary_show(file, offset); ++ if (ret) ++ return ret; ++ seq_puts(file, "-----------------------------------------\n"); ++ /* Display programmable fields */ ++ ret = qman_fqd_prog_summary_show(file, offset); ++ if (ret) ++ return ret; ++ return 0; ++} ++ ++static int qman_fqd_summary_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, qman_fqd_summary_show, NULL); ++} ++ ++static const struct file_operations qman_fqd_summary_fops = { ++ .owner = THIS_MODULE, ++ .open = qman_fqd_summary_open, ++ .read = seq_read, ++}; ++ ++/******************************************************************************* ++ * QMan destination work queue ++ ******************************************************************************/ ++struct qman_dest_wq_s { ++ u16 wq_id; ++}; ++static struct qman_dest_wq_s qman_dest_wq_data = { ++ .wq_id = 0, ++}; ++ ++static int qman_fqd_dest_wq_show(struct seq_file *file, void *offset) ++{ ++ struct qm_fqd fqd; ++ struct qman_fq fq; ++ int ret, i; ++ u16 *wq, wq_id = qman_dest_wq_data.wq_id; ++ struct line_buffer_fq line_buf; ++ ++ memset(&line_buf, 0, sizeof(line_buf)); ++ /* use vmalloc : need to allocate large memory region and don't ++ * require the memory to be physically contiguous. */ ++ wq = vzalloc(sizeof(u16) * (0xFFFF+1)); ++ if (!wq) ++ return -ENOMEM; ++ ++ seq_printf(file, "List of fq ids with destination work queue id" ++ " = 0x%x\n", wq_id); ++ ++ for (i = 1; i < fqid_max; i++) { ++ fq.fqid = i; ++ memset(&fqd, 0, sizeof(struct qm_fqd)); ++ ret = qman_query_fq(&fq, &fqd); ++ if (ret) { ++ vfree(wq); ++ return ret; ++ } ++ if (wq_id == fqd.dest_wq) ++ add_to_line_buffer(&line_buf, fq.fqid, file); ++ wq[fqd.dest_wq]++; ++ } ++ flush_line_buffer(&line_buf, file); ++ ++ seq_puts(file, "Summary of all FQD destination work queue values\n"); ++ for (i = 0; i < 0xFFFF; i++) { ++ if (wq[i]) ++ seq_printf(file, "Channel: 0x%x WQ: 0x%x WQ_ID: 0x%x, " ++ "count = %u\n", i >> 3, i & 0x3, i, wq[i]); ++ } ++ vfree(wq); ++ return 0; ++} ++ ++static ssize_t qman_fqd_dest_wq_write(struct file *f, const char __user *buf, ++ size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ if (val > 0xFFFF) ++ return -EINVAL; ++ qman_dest_wq_data.wq_id = val; ++ return count; ++} ++ ++static int qman_fqd_dest_wq_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, qman_fqd_dest_wq_show, NULL); ++} ++ ++static const struct file_operations qman_fqd_dest_wq_fops = { ++ .owner = THIS_MODULE, ++ .open = qman_fqd_dest_wq_open, ++ .read = seq_read, ++ .write = qman_fqd_dest_wq_write, ++}; ++ ++/******************************************************************************* ++ * QMan Intra-Class Scheduling Credit ++ ******************************************************************************/ ++static int qman_fqd_cred_show(struct seq_file *file, void *offset) ++{ ++ struct qm_fqd fqd; ++ struct qman_fq fq; ++ int ret, i; ++ u32 fq_cnt = 0; ++ struct line_buffer_fq line_buf; ++ ++ memset(&line_buf, 0, sizeof(line_buf)); ++ seq_puts(file, "List of fq ids with Intra-Class Scheduling Credit > 0" ++ "\n"); ++ ++ for (i = 1; i < fqid_max; i++) { ++ fq.fqid = i; ++ memset(&fqd, 0, sizeof(struct qm_fqd)); ++ ret = qman_query_fq(&fq, &fqd); ++ if (ret) ++ return ret; ++ if (fqd.ics_cred > 0) { ++ add_to_line_buffer(&line_buf, fq.fqid, file); ++ fq_cnt++; ++ } ++ } ++ flush_line_buffer(&line_buf, file); ++ ++ seq_printf(file, "Total FQD with ics_cred > 0 = %d\n", fq_cnt); ++ return 0; ++} ++ ++static int qman_fqd_cred_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, qman_fqd_cred_show, NULL); ++} ++ ++static const struct file_operations qman_fqd_cred_fops = { ++ .owner = THIS_MODULE, ++ .open = qman_fqd_cred_open, ++ .read = seq_read, ++}; ++ ++/******************************************************************************* ++ * Class Queue Fields ++ ******************************************************************************/ ++struct query_cq_fields_data_s { ++ u32 cqid; ++}; ++ ++static struct query_cq_fields_data_s query_cq_fields_data = { ++ .cqid = 1, ++}; ++ ++static int query_cq_fields_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ struct qm_mcr_ceetm_cq_query query_result; ++ unsigned int cqid; ++ unsigned int portal; ++ ++ if ((qman_ip_rev & 0xFF00) < QMAN_REV30) ++ return -EINVAL; ++ ++ cqid = query_cq_fields_data.cqid & 0x00FFFFFF; ++ portal = query_cq_fields_data.cqid >> 24; ++ if (portal > qm_dc_portal_fman1) ++ return -EINVAL; ++ ++ ret = qman_ceetm_query_cq(cqid, portal, &query_result); ++ if (ret) ++ return ret; ++ seq_printf(file, "Query CQ Fields Result cqid 0x%x on DCP %d\n", ++ cqid, portal); ++ seq_printf(file, " ccgid: %u\n", query_result.ccgid); ++ seq_printf(file, " state: %u\n", query_result.state); ++ seq_printf(file, " pfdr_hptr: %u\n", query_result.pfdr_hptr); ++ seq_printf(file, " pfdr_tptr: %u\n", query_result.pfdr_tptr); ++ seq_printf(file, " od1_xsfdr: %u\n", query_result.od1_xsfdr); ++ seq_printf(file, " od2_xsfdr: %u\n", query_result.od2_xsfdr); ++ seq_printf(file, " od3_xsfdr: %u\n", query_result.od3_xsfdr); ++ seq_printf(file, " od4_xsfdr: %u\n", query_result.od4_xsfdr); ++ seq_printf(file, " od5_xsfdr: %u\n", query_result.od5_xsfdr); ++ seq_printf(file, " od6_xsfdr: %u\n", query_result.od6_xsfdr); ++ seq_printf(file, " ra1_xsfdr: %u\n", query_result.ra1_xsfdr); ++ seq_printf(file, " ra2_xsfdr: %u\n", query_result.ra2_xsfdr); ++ seq_printf(file, " frame_count: %u\n", query_result.frm_cnt); ++ ++ return 0; ++} ++ ++static int query_cq_fields_open(struct inode *inode, ++ struct file *file) ++{ ++ return single_open(file, query_cq_fields_show, NULL); ++} ++ ++static ssize_t query_cq_fields_write(struct file *f, ++ const char __user *buf, size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ query_cq_fields_data.cqid = (u32)val; ++ return count; ++} ++ ++static const struct file_operations query_cq_fields_fops = { ++ .owner = THIS_MODULE, ++ .open = query_cq_fields_open, ++ .read = seq_read, ++ .write = query_cq_fields_write, ++ .release = single_release, ++}; ++ ++/******************************************************************************* ++ * READ CEETM_XSFDR_IN_USE ++ ******************************************************************************/ ++struct query_ceetm_xsfdr_data_s { ++ enum qm_dc_portal dcp_portal; ++}; ++ ++static struct query_ceetm_xsfdr_data_s query_ceetm_xsfdr_data; ++ ++static int query_ceetm_xsfdr_show(struct seq_file *file, void *offset) ++{ ++ int ret; ++ unsigned int xsfdr_in_use; ++ enum qm_dc_portal portal; ++ ++ ++ if (qman_ip_rev < QMAN_REV31) ++ return -EINVAL; ++ ++ portal = query_ceetm_xsfdr_data.dcp_portal; ++ ret = qman_ceetm_get_xsfdr(portal, &xsfdr_in_use); ++ if (ret) { ++ seq_printf(file, "Read CEETM_XSFDR_IN_USE on DCP %d failed\n", ++ portal); ++ return ret; ++ } ++ ++ seq_printf(file, "DCP%d: CEETM_XSFDR_IN_USE number is %u\n", portal, ++ (xsfdr_in_use & 0x1FFF)); ++ return 0; ++} ++ ++static int query_ceetm_xsfdr_open(struct inode *inode, ++ struct file *file) ++{ ++ return single_open(file, query_ceetm_xsfdr_show, NULL); ++} ++ ++static ssize_t query_ceetm_xsfdr_write(struct file *f, ++ const char __user *buf, size_t count, loff_t *off) ++{ ++ int ret; ++ unsigned long val; ++ ++ ret = user_input_convert(buf, count, &val); ++ if (ret) ++ return ret; ++ if (val > qm_dc_portal_fman1) ++ return -EINVAL; ++ query_ceetm_xsfdr_data.dcp_portal = (u32)val; ++ return count; ++} ++ ++static const struct file_operations query_ceetm_xsfdr_fops = { ++ .owner = THIS_MODULE, ++ .open = query_ceetm_xsfdr_open, ++ .read = seq_read, ++ .write = query_ceetm_xsfdr_write, ++ .release = single_release, ++}; ++ ++/* helper macros used in qman_debugfs_module_init */ ++#define QMAN_DBGFS_ENTRY(name, mode, parent, data, fops) \ ++ do { \ ++ d = debugfs_create_file(name, \ ++ mode, parent, \ ++ data, \ ++ fops); \ ++ if (d == NULL) { \ ++ ret = -ENOMEM; \ ++ goto _return; \ ++ } \ ++ } while (0) ++ ++/* dfs_root as parent */ ++#define QMAN_DBGFS_ENTRY_ROOT(name, mode, data, fops) \ ++ QMAN_DBGFS_ENTRY(name, mode, dfs_root, data, fops) ++ ++/* fqd_root as parent */ ++#define QMAN_DBGFS_ENTRY_FQDROOT(name, mode, data, fops) \ ++ QMAN_DBGFS_ENTRY(name, mode, fqd_root, data, fops) ++ ++/* fqd state */ ++#define QMAN_DBGFS_ENTRY_FQDSTATE(name, index) \ ++ QMAN_DBGFS_ENTRY_FQDROOT(name, S_IRUGO, \ ++ (void *)&mask_filter[index], &qman_fqd_ctrl_fops) ++ ++static int __init qman_debugfs_module_init(void) ++{ ++ int ret = 0; ++ struct dentry *d, *fqd_root; ++ u32 reg; ++ ++ fqid_max = 0; ++ init_ccsrmempeek(); ++ if (qman_ccsr_start) { ++ if (!qman_ccsrmempeek(®, QM_FQD_AR)) { ++ /* extract the size of the FQD window */ ++ reg = reg & 0x3f; ++ /* calculate valid frame queue descriptor range */ ++ fqid_max = (1 << (reg + 1)) / QM_FQD_BLOCK_SIZE; ++ } ++ } ++ dfs_root = debugfs_create_dir("qman", NULL); ++ fqd_root = debugfs_create_dir("fqd", dfs_root); ++ if (dfs_root == NULL || fqd_root == NULL) { ++ ret = -ENOMEM; ++ pr_err("Cannot create qman/fqd debugfs dir\n"); ++ goto _return; ++ } ++ if (fqid_max) { ++ QMAN_DBGFS_ENTRY_ROOT("ccsrmempeek", S_IRUGO | S_IWUGO, ++ NULL, &qman_ccsrmempeek_fops); ++ } ++ QMAN_DBGFS_ENTRY_ROOT("query_fq_np_fields", S_IRUGO | S_IWUGO, ++ &query_fq_np_fields_data, &query_fq_np_fields_fops); ++ ++ QMAN_DBGFS_ENTRY_ROOT("query_fq_fields", S_IRUGO | S_IWUGO, ++ &query_fq_fields_data, &query_fq_fields_fops); ++ ++ QMAN_DBGFS_ENTRY_ROOT("query_wq_lengths", S_IRUGO | S_IWUGO, ++ &query_wq_lengths_data, &query_wq_lengths_fops); ++ ++ QMAN_DBGFS_ENTRY_ROOT("query_cgr", S_IRUGO | S_IWUGO, ++ &query_cgr_data, &query_cgr_fops); ++ ++ QMAN_DBGFS_ENTRY_ROOT("query_congestion", S_IRUGO, ++ NULL, &query_congestion_fops); ++ ++ QMAN_DBGFS_ENTRY_ROOT("testwrite_cgr", S_IRUGO, ++ NULL, &testwrite_cgr_fops); ++ ++ QMAN_DBGFS_ENTRY_ROOT("testwrite_cgr_cgrid", S_IRUGO | S_IWUGO, ++ NULL, &teswrite_cgr_cgrid_fops); ++ ++ QMAN_DBGFS_ENTRY_ROOT("testwrite_cgr_ibcnt", S_IRUGO | S_IWUGO, ++ NULL, &teswrite_cgr_ibcnt_fops); ++ ++ QMAN_DBGFS_ENTRY_ROOT("query_ceetm_ccgr", S_IRUGO | S_IWUGO, ++ &query_ccgr_data, &query_ccgr_fops); ++ /* Create files with fqd_root as parent */ ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("stateoos", S_IRUGO, ++ (void *)&fqd_states[QM_MCR_NP_STATE_OOS], &qman_fqd_state_fops); ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("state_retired", S_IRUGO, ++ (void *)&fqd_states[QM_MCR_NP_STATE_RETIRED], ++ &qman_fqd_state_fops); ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("state_tentatively_sched", S_IRUGO, ++ (void *)&fqd_states[QM_MCR_NP_STATE_TEN_SCHED], ++ &qman_fqd_state_fops); ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("state_truly_sched", S_IRUGO, ++ (void *)&fqd_states[QM_MCR_NP_STATE_TRU_SCHED], ++ &qman_fqd_state_fops); ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("state_parked", S_IRUGO, ++ (void *)&fqd_states[QM_MCR_NP_STATE_PARKED], ++ &qman_fqd_state_fops); ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("state_active", S_IRUGO, ++ (void *)&fqd_states[QM_MCR_NP_STATE_ACTIVE], ++ &qman_fqd_state_fops); ++ QMAN_DBGFS_ENTRY_ROOT("query_cq_fields", S_IRUGO | S_IWUGO, ++ &query_cq_fields_data, &query_cq_fields_fops); ++ QMAN_DBGFS_ENTRY_ROOT("query_ceetm_xsfdr_in_use", S_IRUGO | S_IWUGO, ++ &query_ceetm_xsfdr_data, &query_ceetm_xsfdr_fops); ++ ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("cge_enable", 17); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("cge_disable", 16); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("tde_enable", 15); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("tde_disable", 14); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("orp_enable", 13); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("orp_disable", 12); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("ctx_a_stashing_enable", 11); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("ctx_a_stashing_disable", 10); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("cpc_enable", 9); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("cpc_disable", 8); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("sfdr_enable", 7); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("sfdr_disable", 6); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("avoid_blocking_enable", 5); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("avoid_blocking_disable", 4); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("hold_active_enable", 3); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("hold_active_disable", 2); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("prefer_in_cache_enable", 1); ++ ++ QMAN_DBGFS_ENTRY_FQDSTATE("prefer_in_cache_disable", 0); ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("summary", S_IRUGO, ++ NULL, &qman_fqd_summary_fops); ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("wq", S_IRUGO | S_IWUGO, ++ NULL, &qman_fqd_dest_wq_fops); ++ ++ QMAN_DBGFS_ENTRY_FQDROOT("cred", S_IRUGO, ++ NULL, &qman_fqd_cred_fops); ++ ++ return 0; ++ ++_return: ++ debugfs_remove_recursive(dfs_root); ++ return ret; ++} ++ ++static void __exit qman_debugfs_module_exit(void) ++{ ++ debugfs_remove_recursive(dfs_root); ++} ++ ++module_init(qman_debugfs_module_init); ++module_exit(qman_debugfs_module_exit); ++MODULE_LICENSE("Dual BSD/GPL"); +diff --git a/drivers/staging/fsl_qbman/qman_driver.c b/drivers/staging/fsl_qbman/qman_driver.c +new file mode 100644 +index 0000000..c3e5718 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_driver.c +@@ -0,0 +1,963 @@ ++/* Copyright 2008-2012 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 "qman_private.h" ++ ++#include /* hard_smp_processor_id() if !CONFIG_SMP */ ++#ifdef CONFIG_HOTPLUG_CPU ++#include ++#endif ++ ++/* Global variable containing revision id (even on non-control plane systems ++ * where CCSR isn't available) */ ++u16 qman_ip_rev; ++EXPORT_SYMBOL(qman_ip_rev); ++u8 qman_ip_cfg; ++EXPORT_SYMBOL(qman_ip_cfg); ++u16 qm_channel_pool1 = QMAN_CHANNEL_POOL1; ++EXPORT_SYMBOL(qm_channel_pool1); ++u16 qm_channel_caam = QMAN_CHANNEL_CAAM; ++EXPORT_SYMBOL(qm_channel_caam); ++u16 qm_channel_pme = QMAN_CHANNEL_PME; ++EXPORT_SYMBOL(qm_channel_pme); ++u16 qm_channel_dce = QMAN_CHANNEL_DCE; ++EXPORT_SYMBOL(qm_channel_dce); ++u16 qman_portal_max; ++EXPORT_SYMBOL(qman_portal_max); ++ ++u32 qman_clk; ++struct qm_ceetm qman_ceetms[QMAN_CEETM_MAX]; ++/* the qman ceetm instances on the given SoC */ ++u8 num_ceetms; ++ ++/* size of the fqd region in bytes */ ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++static u32 fqd_size = (PAGE_SIZE << CONFIG_FSL_QMAN_FQD_SZ); ++#endif ++ ++/* For these variables, and the portal-initialisation logic, the ++ * comments in bman_driver.c apply here so won't be repeated. */ ++static struct qman_portal *shared_portals[NR_CPUS]; ++static int num_shared_portals; ++static int shared_portals_idx; ++static LIST_HEAD(unused_pcfgs); ++static DEFINE_SPINLOCK(unused_pcfgs_lock); ++ ++/* A SDQCR mask comprising all the available/visible pool channels */ ++static u32 pools_sdqcr; ++ ++#define STR_ERR_NOPROP "No '%s' property in node %s\n" ++#define STR_ERR_CELL "'%s' is not a %d-cell range in node %s\n" ++#define STR_FQID_RANGE "fsl,fqid-range" ++#define STR_POOL_CHAN_RANGE "fsl,pool-channel-range" ++#define STR_CGRID_RANGE "fsl,cgrid-range" ++ ++/* A "fsl,fqid-range" node; release the given range to the allocator */ ++static __init int fsl_fqid_range_init(struct device_node *node) ++{ ++ int ret; ++ const u32 *range = of_get_property(node, STR_FQID_RANGE, &ret); ++ if (!range) { ++ pr_err(STR_ERR_NOPROP, STR_FQID_RANGE, node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err(STR_ERR_CELL, STR_FQID_RANGE, 2, node->full_name); ++ return -EINVAL; ++ } ++ qman_seed_fqid_range(range[0], range[1]); ++ pr_info("Qman: FQID allocator includes range %d:%d\n", ++ range[0], range[1]); ++ return 0; ++} ++ ++/* A "fsl,pool-channel-range" node; add to the SDQCR mask only */ ++static __init int fsl_pool_channel_range_sdqcr(struct device_node *node) ++{ ++ int ret; ++ const u32 *chanid = of_get_property(node, STR_POOL_CHAN_RANGE, &ret); ++ if (!chanid) { ++ pr_err(STR_ERR_NOPROP, STR_POOL_CHAN_RANGE, node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err(STR_ERR_CELL, STR_POOL_CHAN_RANGE, 1, node->full_name); ++ return -EINVAL; ++ } ++ for (ret = 0; ret < chanid[1]; ret++) ++ pools_sdqcr |= QM_SDQCR_CHANNELS_POOL_CONV(chanid[0] + ret); ++ return 0; ++} ++ ++/* A "fsl,pool-channel-range" node; release the given range to the allocator */ ++static __init int fsl_pool_channel_range_init(struct device_node *node) ++{ ++ int ret; ++ const u32 *chanid = of_get_property(node, STR_POOL_CHAN_RANGE, &ret); ++ if (!chanid) { ++ pr_err(STR_ERR_NOPROP, STR_POOL_CHAN_RANGE, node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err(STR_ERR_CELL, STR_POOL_CHAN_RANGE, 1, node->full_name); ++ return -EINVAL; ++ } ++ qman_seed_pool_range(chanid[0], chanid[1]); ++ pr_info("Qman: pool channel allocator includes range %d:%d\n", ++ chanid[0], chanid[1]); ++ return 0; ++} ++ ++/* A "fsl,cgrid-range" node; release the given range to the allocator */ ++static __init int fsl_cgrid_range_init(struct device_node *node) ++{ ++ struct qman_cgr cgr; ++ int ret, errors = 0; ++ const u32 *range = of_get_property(node, STR_CGRID_RANGE, &ret); ++ if (!range) { ++ pr_err(STR_ERR_NOPROP, STR_CGRID_RANGE, node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err(STR_ERR_CELL, STR_CGRID_RANGE, 2, node->full_name); ++ return -EINVAL; ++ } ++ qman_seed_cgrid_range(range[0], range[1]); ++ pr_info("Qman: CGRID allocator includes range %d:%d\n", ++ range[0], range[1]); ++ for (cgr.cgrid = 0; cgr.cgrid < __CGR_NUM; cgr.cgrid++) { ++ ret = qman_modify_cgr(&cgr, QMAN_CGR_FLAG_USE_INIT, NULL); ++ if (ret) ++ errors++; ++ } ++ if (errors) ++ pr_err("Warning: %d error%s while initialising CGRs %d:%d\n", ++ errors, (errors > 1) ? "s" : "", range[0], range[1]); ++ return 0; ++} ++ ++static __init int fsl_ceetm_init(struct device_node *node) ++{ ++ enum qm_dc_portal dcp_portal; ++ struct qm_ceetm_sp *sp; ++ struct qm_ceetm_lni *lni; ++ int ret, i; ++ const u32 *range; ++ ++ /* Find LFQID range */ ++ range = of_get_property(node, "fsl,ceetm-lfqid-range", &ret); ++ if (!range) { ++ pr_err("No fsl,ceetm-lfqid-range in node %s\n", ++ node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err("fsl,ceetm-lfqid-range is not a 2-cell range in node" ++ " %s\n", node->full_name); ++ return -EINVAL; ++ } ++ ++ dcp_portal = (range[0] & 0x0F0000) >> 16; ++ if (dcp_portal > qm_dc_portal_fman1) { ++ pr_err("The DCP portal %d doesn't support CEETM\n", dcp_portal); ++ return -EINVAL; ++ } ++ ++ if (dcp_portal == qm_dc_portal_fman0) ++ qman_seed_ceetm0_lfqid_range(range[0], range[1]); ++ if (dcp_portal == qm_dc_portal_fman1) ++ qman_seed_ceetm1_lfqid_range(range[0], range[1]); ++ pr_debug("Qman: The lfqid allocator of CEETM %d includes range" ++ " 0x%x:0x%x\n", dcp_portal, range[0], range[1]); ++ ++ qman_ceetms[dcp_portal].idx = dcp_portal; ++ INIT_LIST_HEAD(&qman_ceetms[dcp_portal].sub_portals); ++ INIT_LIST_HEAD(&qman_ceetms[dcp_portal].lnis); ++ ++ /* Find Sub-portal range */ ++ range = of_get_property(node, "fsl,ceetm-sp-range", &ret); ++ if (!range) { ++ pr_err("No fsl,ceetm-sp-range in node %s\n", node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err("fsl,ceetm-sp-range is not a 2-cell range in node %s\n", ++ node->full_name); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < range[1]; i++) { ++ sp = kzalloc(sizeof(*sp), GFP_KERNEL); ++ if (!sp) { ++ pr_err("Can't alloc memory for sub-portal %d\n", ++ range[0] + i); ++ return -ENOMEM; ++ } ++ sp->idx = range[0] + i; ++ sp->dcp_idx = dcp_portal; ++ sp->is_claimed = 0; ++ list_add_tail(&sp->node, &qman_ceetms[dcp_portal].sub_portals); ++ sp++; ++ } ++ pr_debug("Qman: Reserve sub-portal %d:%d for CEETM %d\n", ++ range[0], range[1], dcp_portal); ++ qman_ceetms[dcp_portal].sp_range[0] = range[0]; ++ qman_ceetms[dcp_portal].sp_range[1] = range[1]; ++ ++ /* Find LNI range */ ++ range = of_get_property(node, "fsl,ceetm-lni-range", &ret); ++ if (!range) { ++ pr_err("No fsl,ceetm-lni-range in node %s\n", node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err("fsl,ceetm-lni-range is not a 2-cell range in node %s\n", ++ node->full_name); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < range[1]; i++) { ++ lni = kzalloc(sizeof(*lni), GFP_KERNEL); ++ if (!lni) { ++ pr_err("Can't alloc memory for LNI %d\n", ++ range[0] + i); ++ return -ENOMEM; ++ } ++ lni->idx = range[0] + i; ++ lni->dcp_idx = dcp_portal; ++ lni->is_claimed = 0; ++ INIT_LIST_HEAD(&lni->channels); ++ list_add_tail(&lni->node, &qman_ceetms[dcp_portal].lnis); ++ lni++; ++ } ++ pr_debug("Qman: Reserve LNI %d:%d for CEETM %d\n", ++ range[0], range[1], dcp_portal); ++ qman_ceetms[dcp_portal].lni_range[0] = range[0]; ++ qman_ceetms[dcp_portal].lni_range[1] = range[1]; ++ ++ /* Find CEETM channel range */ ++ range = of_get_property(node, "fsl,ceetm-channel-range", &ret); ++ if (!range) { ++ pr_err("No fsl,ceetm-channel-range in node %s\n", ++ node->full_name); ++ return -EINVAL; ++ } ++ if (ret != 8) { ++ pr_err("fsl,ceetm-channel-range is not a 2-cell range in node" ++ "%s\n", node->full_name); ++ return -EINVAL; ++ } ++ ++ if (dcp_portal == qm_dc_portal_fman0) ++ qman_seed_ceetm0_channel_range(range[0], range[1]); ++ if (dcp_portal == qm_dc_portal_fman1) ++ qman_seed_ceetm1_channel_range(range[0], range[1]); ++ pr_debug("Qman: The channel allocator of CEETM %d includes" ++ " range %d:%d\n", dcp_portal, range[0], range[1]); ++ ++ /* Set CEETM PRES register */ ++ ret = qman_ceetm_set_prescaler(dcp_portal); ++ if (ret) ++ return ret; ++ return 0; ++} ++ ++static void qman_get_ip_revision(struct device_node *dn) ++{ ++ u16 ip_rev = 0; ++ u8 ip_cfg = QMAN_REV_CFG_0; ++ for_each_compatible_node(dn, NULL, "fsl,qman-portal") { ++ if (!of_device_is_available(dn)) ++ continue; ++ if (of_device_is_compatible(dn, "fsl,qman-portal-1.0") || ++ of_device_is_compatible(dn, "fsl,qman-portal-1.0.0")) { ++ pr_err("QMAN rev1.0 on P4080 rev1 is not supported!\n"); ++ BUG_ON(1); ++ } else if (of_device_is_compatible(dn, "fsl,qman-portal-1.1") || ++ of_device_is_compatible(dn, "fsl,qman-portal-1.1.0")) { ++ ip_rev = QMAN_REV11; ++ qman_portal_max = 10; ++ } else if (of_device_is_compatible(dn, "fsl,qman-portal-1.2") || ++ of_device_is_compatible(dn, "fsl,qman-portal-1.2.0")) { ++ ip_rev = QMAN_REV12; ++ qman_portal_max = 10; ++ } else if (of_device_is_compatible(dn, "fsl,qman-portal-2.0") || ++ of_device_is_compatible(dn, "fsl,qman-portal-2.0.0")) { ++ ip_rev = QMAN_REV20; ++ qman_portal_max = 3; ++ } else if (of_device_is_compatible(dn, ++ "fsl,qman-portal-3.0.0")) { ++ ip_rev = QMAN_REV30; ++ qman_portal_max = 50; ++ } else if (of_device_is_compatible(dn, ++ "fsl,qman-portal-3.0.1")) { ++ ip_rev = QMAN_REV30; ++ qman_portal_max = 25; ++ ip_cfg = QMAN_REV_CFG_1; ++ } else if (of_device_is_compatible(dn, ++ "fsl,qman-portal-3.1.0")) { ++ ip_rev = QMAN_REV31; ++ qman_portal_max = 50; ++ } else if (of_device_is_compatible(dn, ++ "fsl,qman-portal-3.1.1")) { ++ ip_rev = QMAN_REV31; ++ qman_portal_max = 25; ++ ip_cfg = QMAN_REV_CFG_1; ++ } else if (of_device_is_compatible(dn, ++ "fsl,qman-portal-3.1.2")) { ++ ip_rev = QMAN_REV31; ++ qman_portal_max = 18; ++ ip_cfg = QMAN_REV_CFG_2; ++ } else if (of_device_is_compatible(dn, ++ "fsl,qman-portal-3.1.3")) { ++ ip_rev = QMAN_REV31; ++ qman_portal_max = 10; ++ ip_cfg = QMAN_REV_CFG_3; ++ } else { ++ pr_warn("unknown QMan version in portal node," ++ "default to rev1.1\n"); ++ ip_rev = QMAN_REV11; ++ qman_portal_max = 10; ++ } ++ ++ if (!qman_ip_rev) { ++ if (ip_rev) { ++ qman_ip_rev = ip_rev; ++ qman_ip_cfg = ip_cfg; ++ } else { ++ pr_warn("unknown Qman version," ++ " default to rev1.1\n"); ++ qman_ip_rev = QMAN_REV11; ++ qman_ip_cfg = QMAN_REV_CFG_0; ++ } ++ } else if (ip_rev && (qman_ip_rev != ip_rev)) ++ pr_warn("Revision=0x%04x, but portal '%s' has" ++ " 0x%04x\n", ++ qman_ip_rev, dn->full_name, ip_rev); ++ if (qman_ip_rev == ip_rev) ++ break; ++ } ++} ++ ++/* Parse a portal node, perform generic mapping duties and return the config. It ++ * is not known at this stage for what purpose (or even if) the portal will be ++ * used. */ ++static struct qm_portal_config * __init parse_pcfg(struct device_node *node) ++{ ++ struct qm_portal_config *pcfg; ++ const u32 *index, *channel; ++ int irq, ret; ++ resource_size_t len; ++ ++ pcfg = kmalloc(sizeof(*pcfg), GFP_KERNEL); ++ if (!pcfg) { ++ pr_err("can't allocate portal config"); ++ return NULL; ++ } ++ ++ /* ++ * This is a *horrible hack*, but the IOMMU/PAMU driver needs a ++ * 'struct device' in order to get the PAMU stashing setup and the QMan ++ * portal [driver] won't function at all without ring stashing ++ * ++ * Making the QMan portal driver nice and proper is part of the ++ * upstreaming effort ++ */ ++ pcfg->dev.bus = &platform_bus_type; ++ pcfg->dev.of_node = node; ++#ifdef CONFIG_IOMMU_API ++ pcfg->dev.archdata.iommu_domain = NULL; ++#endif ++ ++ ret = of_address_to_resource(node, DPA_PORTAL_CE, ++ &pcfg->addr_phys[DPA_PORTAL_CE]); ++ if (ret) { ++ pr_err("Can't get %s property '%s'\n", node->full_name, ++ "reg::CE"); ++ goto err; ++ } ++ ret = of_address_to_resource(node, DPA_PORTAL_CI, ++ &pcfg->addr_phys[DPA_PORTAL_CI]); ++ if (ret) { ++ pr_err("Can't get %s property '%s'\n", node->full_name, ++ "reg::CI"); ++ goto err; ++ } ++ index = of_get_property(node, "cell-index", &ret); ++ if (!index || (ret != 4)) { ++ pr_err("Can't get %s property '%s'\n", node->full_name, ++ "cell-index"); ++ goto err; ++ } ++ if (*index >= qman_portal_max) ++ goto err; ++ ++ channel = of_get_property(node, "fsl,qman-channel-id", &ret); ++ if (!channel || (ret != 4)) { ++ pr_err("Can't get %s property '%s'\n", node->full_name, ++ "fsl,qman-channel-id"); ++ goto err; ++ } ++ if (*channel != (*index + QM_CHANNEL_SWPORTAL0)) ++ pr_err("Warning: node %s has mismatched %s and %s\n", ++ node->full_name, "cell-index", "fsl,qman-channel-id"); ++ pcfg->public_cfg.channel = *channel; ++ pcfg->public_cfg.cpu = -1; ++ irq = irq_of_parse_and_map(node, 0); ++ if (irq == NO_IRQ) { ++ pr_err("Can't get %s property '%s'\n", node->full_name, ++ "interrupts"); ++ goto err; ++ } ++ pcfg->public_cfg.irq = irq; ++ pcfg->public_cfg.index = *index; ++#ifdef CONFIG_FSL_QMAN_CONFIG ++ /* We need the same LIODN offset for all portals */ ++ qman_liodn_fixup(pcfg->public_cfg.channel); ++#endif ++ ++ len = resource_size(&pcfg->addr_phys[DPA_PORTAL_CE]); ++ if (len != (unsigned long)len) ++ goto err; ++ pcfg->addr_virt[DPA_PORTAL_CE] = ioremap_prot( ++ pcfg->addr_phys[DPA_PORTAL_CE].start, ++ (unsigned long)len, ++ 0); ++ pcfg->addr_virt[DPA_PORTAL_CI] = ioremap_prot( ++ pcfg->addr_phys[DPA_PORTAL_CI].start, ++ resource_size(&pcfg->addr_phys[DPA_PORTAL_CI]), ++ _PAGE_GUARDED | _PAGE_NO_CACHE); ++ ++ return pcfg; ++err: ++ kfree(pcfg); ++ return NULL; ++} ++ ++static struct qm_portal_config *get_pcfg(struct list_head *list) ++{ ++ struct qm_portal_config *pcfg; ++ if (list_empty(list)) ++ return NULL; ++ pcfg = list_entry(list->prev, struct qm_portal_config, list); ++ list_del(&pcfg->list); ++ return pcfg; ++} ++ ++static struct qm_portal_config *get_pcfg_idx(struct list_head *list, u32 idx) ++{ ++ struct qm_portal_config *pcfg; ++ if (list_empty(list)) ++ return NULL; ++ list_for_each_entry(pcfg, list, list) { ++ if (pcfg->public_cfg.index == idx) { ++ list_del(&pcfg->list); ++ return pcfg; ++ } ++ } ++ return NULL; ++} ++ ++static void portal_set_cpu(struct qm_portal_config *pcfg, int cpu) ++{ ++#ifdef CONFIG_FSL_PAMU ++ int ret; ++ int window_count = 1; ++ struct iommu_domain_geometry geom_attr; ++ struct pamu_stash_attribute stash_attr; ++ ++ pcfg->iommu_domain = iommu_domain_alloc(&platform_bus_type); ++ if (!pcfg->iommu_domain) { ++ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_alloc() failed", ++ __func__); ++ goto _no_iommu; ++ } ++ geom_attr.aperture_start = 0; ++ geom_attr.aperture_end = ++ ((dma_addr_t)1 << min(8 * sizeof(dma_addr_t), (size_t)36)) - 1; ++ geom_attr.force_aperture = true; ++ ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_GEOMETRY, ++ &geom_attr); ++ if (ret < 0) { ++ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d", ++ __func__, ret); ++ goto _iommu_domain_free; ++ } ++ ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_WINDOWS, ++ &window_count); ++ if (ret < 0) { ++ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d", ++ __func__, ret); ++ goto _iommu_domain_free; ++ } ++ stash_attr.cpu = cpu; ++ stash_attr.cache = PAMU_ATTR_CACHE_L1; ++ /* set stash information for the window */ ++ stash_attr.window = 0; ++ ret = iommu_domain_set_attr(pcfg->iommu_domain, ++ DOMAIN_ATTR_FSL_PAMU_STASH, ++ &stash_attr); ++ if (ret < 0) { ++ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d", ++ __func__, ret); ++ goto _iommu_domain_free; ++ } ++ ret = iommu_domain_window_enable(pcfg->iommu_domain, 0, 0, 1ULL << 36, ++ IOMMU_READ | IOMMU_WRITE); ++ if (ret < 0) { ++ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_window_enable() = %d", ++ __func__, ret); ++ goto _iommu_domain_free; ++ } ++ ret = iommu_attach_device(pcfg->iommu_domain, &pcfg->dev); ++ if (ret < 0) { ++ pr_err(KBUILD_MODNAME ":%s(): iommu_device_attach() = %d", ++ __func__, ret); ++ goto _iommu_domain_free; ++ } ++ ret = iommu_domain_set_attr(pcfg->iommu_domain, ++ DOMAIN_ATTR_FSL_PAMU_ENABLE, ++ &window_count); ++ if (ret < 0) { ++ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d", ++ __func__, ret); ++ goto _iommu_detach_device; ++ } ++ ++_no_iommu: ++#endif ++#ifdef CONFIG_FSL_QMAN_CONFIG ++ if (qman_set_sdest(pcfg->public_cfg.channel, cpu)) ++#endif ++ pr_warn("Failed to set QMan portal's stash request queue\n"); ++ ++ return; ++ ++#ifdef CONFIG_FSL_PAMU ++_iommu_detach_device: ++ iommu_detach_device(pcfg->iommu_domain, NULL); ++_iommu_domain_free: ++ iommu_domain_free(pcfg->iommu_domain); ++#endif ++} ++ ++struct qm_portal_config *qm_get_unused_portal_idx(u32 idx) ++{ ++ struct qm_portal_config *ret; ++ spin_lock(&unused_pcfgs_lock); ++ if (idx == QBMAN_ANY_PORTAL_IDX) ++ ret = get_pcfg(&unused_pcfgs); ++ else ++ ret = get_pcfg_idx(&unused_pcfgs, idx); ++ spin_unlock(&unused_pcfgs_lock); ++ /* Bind stashing LIODNs to the CPU we are currently executing on, and ++ * set the portal to use the stashing request queue corresonding to the ++ * cpu as well. The user-space driver assumption is that the pthread has ++ * to already be affine to one cpu only before opening a portal. If that ++ * check is circumvented, the only risk is a performance degradation - ++ * stashing will go to whatever cpu they happened to be running on when ++ * opening the device file, and if that isn't the cpu they subsequently ++ * bind to and do their polling on, tough. */ ++ if (ret) ++ portal_set_cpu(ret, hard_smp_processor_id()); ++ return ret; ++} ++ ++struct qm_portal_config *qm_get_unused_portal(void) ++{ ++ return qm_get_unused_portal_idx(QBMAN_ANY_PORTAL_IDX); ++} ++ ++void qm_put_unused_portal(struct qm_portal_config *pcfg) ++{ ++ spin_lock(&unused_pcfgs_lock); ++ list_add(&pcfg->list, &unused_pcfgs); ++ spin_unlock(&unused_pcfgs_lock); ++} ++ ++static struct qman_portal *init_pcfg(struct qm_portal_config *pcfg) ++{ ++ struct qman_portal *p; ++ ++ pcfg->iommu_domain = NULL; ++ portal_set_cpu(pcfg, pcfg->public_cfg.cpu); ++ p = qman_create_affine_portal(pcfg, NULL); ++ if (p) { ++ u32 irq_sources = 0; ++ /* Determine what should be interrupt-vs-poll driven */ ++#ifdef CONFIG_FSL_DPA_PIRQ_SLOW ++ irq_sources |= QM_PIRQ_EQCI | QM_PIRQ_EQRI | QM_PIRQ_MRI | ++ QM_PIRQ_CSCI | QM_PIRQ_CCSCI; ++#endif ++#ifdef CONFIG_FSL_DPA_PIRQ_FAST ++ irq_sources |= QM_PIRQ_DQRI; ++#endif ++ qman_p_irqsource_add(p, irq_sources); ++ pr_info("Qman portal %sinitialised, cpu %d\n", ++ pcfg->public_cfg.is_shared ? "(shared) " : "", ++ pcfg->public_cfg.cpu); ++ } else ++ pr_crit("Qman portal failure on cpu %d\n", ++ pcfg->public_cfg.cpu); ++ return p; ++} ++ ++static void init_slave(int cpu) ++{ ++ struct qman_portal *p; ++ struct cpumask oldmask = *tsk_cpus_allowed(current); ++ set_cpus_allowed_ptr(current, get_cpu_mask(cpu)); ++ p = qman_create_affine_slave(shared_portals[shared_portals_idx++], cpu); ++ if (!p) ++ pr_err("Qman slave portal failure on cpu %d\n", cpu); ++ else ++ pr_info("Qman portal %sinitialised, cpu %d\n", "(slave) ", cpu); ++ set_cpus_allowed_ptr(current, &oldmask); ++ if (shared_portals_idx >= num_shared_portals) ++ shared_portals_idx = 0; ++} ++ ++static struct cpumask want_unshared __initdata; ++static struct cpumask want_shared __initdata; ++ ++static int __init parse_qportals(char *str) ++{ ++ return parse_portals_bootarg(str, &want_shared, &want_unshared, ++ "qportals"); ++} ++__setup("qportals=", parse_qportals); ++ ++static void qman_portal_update_sdest(const struct qm_portal_config *pcfg, ++ unsigned int cpu) ++{ ++#ifdef CONFIG_FSL_PAMU ++ struct pamu_stash_attribute stash_attr; ++ int ret; ++ ++ if (pcfg->iommu_domain) { ++ stash_attr.cpu = cpu; ++ stash_attr.cache = PAMU_ATTR_CACHE_L1; ++ /* set stash information for the window */ ++ stash_attr.window = 0; ++ ret = iommu_domain_set_attr(pcfg->iommu_domain, ++ DOMAIN_ATTR_FSL_PAMU_STASH, &stash_attr); ++ if (ret < 0) { ++ pr_err("Failed to update pamu stash setting\n"); ++ return; ++ } ++ } ++#ifdef CONFIG_FSL_QMAN_CONFIG ++ if (qman_set_sdest(pcfg->public_cfg.channel, cpu)) ++#endif ++ pr_warn("Failed to update portal's stash request queue\n"); ++#endif ++} ++ ++static void qman_offline_cpu(unsigned int cpu) ++{ ++ struct qman_portal *p; ++ const struct qm_portal_config *pcfg; ++ p = (struct qman_portal *)affine_portals[cpu]; ++ if (p) { ++ pcfg = qman_get_qm_portal_config(p); ++ if (pcfg) { ++ irq_set_affinity(pcfg->public_cfg.irq, cpumask_of(0)); ++ qman_portal_update_sdest(pcfg, 0); ++ } ++ } ++} ++ ++#ifdef CONFIG_HOTPLUG_CPU ++static void qman_online_cpu(unsigned int cpu) ++{ ++ struct qman_portal *p; ++ const struct qm_portal_config *pcfg; ++ p = (struct qman_portal *)affine_portals[cpu]; ++ if (p) { ++ pcfg = qman_get_qm_portal_config(p); ++ if (pcfg) { ++ irq_set_affinity(pcfg->public_cfg.irq, cpumask_of(cpu)); ++ qman_portal_update_sdest(pcfg, cpu); ++ } ++ } ++} ++ ++static int __cpuinit qman_hotplug_cpu_callback(struct notifier_block *nfb, ++ unsigned long action, void *hcpu) ++{ ++ unsigned int cpu = (unsigned long)hcpu; ++ ++ switch (action) { ++ case CPU_ONLINE: ++ case CPU_ONLINE_FROZEN: ++ qman_online_cpu(cpu); ++ break; ++ case CPU_DOWN_PREPARE: ++ case CPU_DOWN_PREPARE_FROZEN: ++ qman_offline_cpu(cpu); ++ default: ++ break; ++ } ++ return NOTIFY_OK; ++} ++ ++static struct notifier_block qman_hotplug_cpu_notifier = { ++ .notifier_call = qman_hotplug_cpu_callback, ++}; ++#endif /* CONFIG_HOTPLUG_CPU */ ++ ++__init int qman_init(void) ++{ ++ struct cpumask slave_cpus; ++ struct cpumask unshared_cpus = *cpu_none_mask; ++ struct cpumask shared_cpus = *cpu_none_mask; ++ LIST_HEAD(unshared_pcfgs); ++ LIST_HEAD(shared_pcfgs); ++ struct device_node *dn; ++ struct qm_portal_config *pcfg; ++ struct qman_portal *p; ++ int cpu, ret; ++ const u32 *clk; ++ struct cpumask offline_cpus; ++ ++ /* Initialise the Qman (CCSR) device */ ++ for_each_compatible_node(dn, NULL, "fsl,qman") { ++ if (!qman_init_ccsr(dn)) ++ pr_info("Qman err interrupt handler present\n"); ++ else ++ pr_err("Qman CCSR setup failed\n"); ++ ++ clk = of_get_property(dn, "clock-frequency", NULL); ++ if (!clk) ++ pr_warn("Can't find Qman clock frequency\n"); ++ else ++ qman_clk = *clk; ++ } ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ /* Setup lookup table for FQ demux */ ++ ret = qman_setup_fq_lookup_table(fqd_size/64); ++ if (ret) ++ return ret; ++#endif ++ ++ /* Get qman ip revision */ ++ qman_get_ip_revision(dn); ++ if ((qman_ip_rev & 0xff00) >= QMAN_REV30) { ++ qm_channel_pool1 = QMAN_CHANNEL_POOL1_REV3; ++ qm_channel_caam = QMAN_CHANNEL_CAAM_REV3; ++ qm_channel_pme = QMAN_CHANNEL_PME_REV3; ++ } ++ if ((qman_ip_rev == QMAN_REV31) && (qman_ip_cfg == QMAN_REV_CFG_2)) ++ qm_channel_dce = QMAN_CHANNEL_DCE_QMANREV312; ++ ++ /* ++ * Parse the ceetm node to get how many ceetm instances are supported ++ * on the current silicon. num_ceetms must be confirmed before portals ++ * are intiailized. ++ */ ++ num_ceetms = 0; ++ for_each_compatible_node(dn, NULL, "fsl,qman-ceetm") ++ num_ceetms++; ++ ++ /* Parse pool channels into the SDQCR mask. (Must happen before portals ++ * are initialised.) */ ++ for_each_compatible_node(dn, NULL, "fsl,pool-channel-range") { ++ ret = fsl_pool_channel_range_sdqcr(dn); ++ if (ret) ++ return ret; ++ } ++ ++ memset(affine_portals, 0, sizeof(void *) * num_possible_cpus()); ++ /* Initialise portals. See bman_driver.c for comments */ ++ for_each_compatible_node(dn, NULL, "fsl,qman-portal") { ++ if (!of_device_is_available(dn)) ++ continue; ++ pcfg = parse_pcfg(dn); ++ if (pcfg) { ++ pcfg->public_cfg.pools = pools_sdqcr; ++ list_add_tail(&pcfg->list, &unused_pcfgs); ++ } ++ } ++ for_each_possible_cpu(cpu) { ++ if (cpumask_test_cpu(cpu, &want_shared)) { ++ pcfg = get_pcfg(&unused_pcfgs); ++ if (!pcfg) ++ break; ++ pcfg->public_cfg.cpu = cpu; ++ list_add_tail(&pcfg->list, &shared_pcfgs); ++ cpumask_set_cpu(cpu, &shared_cpus); ++ } ++ if (cpumask_test_cpu(cpu, &want_unshared)) { ++ if (cpumask_test_cpu(cpu, &shared_cpus)) ++ continue; ++ pcfg = get_pcfg(&unused_pcfgs); ++ if (!pcfg) ++ break; ++ pcfg->public_cfg.cpu = cpu; ++ list_add_tail(&pcfg->list, &unshared_pcfgs); ++ cpumask_set_cpu(cpu, &unshared_cpus); ++ } ++ } ++ if (list_empty(&shared_pcfgs) && list_empty(&unshared_pcfgs)) { ++ for_each_possible_cpu(cpu) { ++ pcfg = get_pcfg(&unused_pcfgs); ++ if (!pcfg) ++ break; ++ pcfg->public_cfg.cpu = cpu; ++ list_add_tail(&pcfg->list, &unshared_pcfgs); ++ cpumask_set_cpu(cpu, &unshared_cpus); ++ } ++ } ++ cpumask_andnot(&slave_cpus, cpu_possible_mask, &shared_cpus); ++ cpumask_andnot(&slave_cpus, &slave_cpus, &unshared_cpus); ++ if (cpumask_empty(&slave_cpus)) { ++ if (!list_empty(&shared_pcfgs)) { ++ cpumask_or(&unshared_cpus, &unshared_cpus, ++ &shared_cpus); ++ cpumask_clear(&shared_cpus); ++ list_splice_tail(&shared_pcfgs, &unshared_pcfgs); ++ INIT_LIST_HEAD(&shared_pcfgs); ++ } ++ } else { ++ if (list_empty(&shared_pcfgs)) { ++ pcfg = get_pcfg(&unshared_pcfgs); ++ if (!pcfg) { ++ pr_crit("No QMan portals available!\n"); ++ return 0; ++ } ++ cpumask_clear_cpu(pcfg->public_cfg.cpu, &unshared_cpus); ++ cpumask_set_cpu(pcfg->public_cfg.cpu, &shared_cpus); ++ list_add_tail(&pcfg->list, &shared_pcfgs); ++ } ++ } ++ list_for_each_entry(pcfg, &unshared_pcfgs, list) { ++ pcfg->public_cfg.is_shared = 0; ++ p = init_pcfg(pcfg); ++ if (!p) { ++ pr_crit("Unable to configure portals\n"); ++ return 0; ++ } ++ } ++ list_for_each_entry(pcfg, &shared_pcfgs, list) { ++ pcfg->public_cfg.is_shared = 1; ++ p = init_pcfg(pcfg); ++ if (p) ++ shared_portals[num_shared_portals++] = p; ++ } ++ if (!cpumask_empty(&slave_cpus)) ++ for_each_cpu(cpu, &slave_cpus) ++ init_slave(cpu); ++ pr_info("Qman portals initialised\n"); ++ cpumask_andnot(&offline_cpus, cpu_possible_mask, cpu_online_mask); ++ for_each_cpu(cpu, &offline_cpus) ++ qman_offline_cpu(cpu); ++#ifdef CONFIG_HOTPLUG_CPU ++ register_hotcpu_notifier(&qman_hotplug_cpu_notifier); ++#endif ++ return 0; ++} ++ ++__init int qman_resource_init(void) ++{ ++ struct device_node *dn; ++ int ret; ++ ++ /* Initialise FQID allocation ranges */ ++ for_each_compatible_node(dn, NULL, "fsl,fqid-range") { ++ ret = fsl_fqid_range_init(dn); ++ if (ret) ++ return ret; ++ } ++ /* Initialise CGRID allocation ranges */ ++ for_each_compatible_node(dn, NULL, "fsl,cgrid-range") { ++ ret = fsl_cgrid_range_init(dn); ++ if (ret) ++ return ret; ++ } ++ /* Parse pool channels into the allocator. (Must happen after portals ++ * are initialised.) */ ++ for_each_compatible_node(dn, NULL, "fsl,pool-channel-range") { ++ ret = fsl_pool_channel_range_init(dn); ++ if (ret) ++ return ret; ++ } ++ ++ /* Parse CEETM */ ++ for_each_compatible_node(dn, NULL, "fsl,qman-ceetm") { ++ ret = fsl_ceetm_init(dn); ++ if (ret) ++ return ret; ++ } ++ return 0; ++} ++ ++#ifdef CONFIG_SUSPEND ++void suspend_unused_qportal(void) ++{ ++ struct qm_portal_config *pcfg; ++ ++ if (list_empty(&unused_pcfgs)) ++ return; ++ ++ list_for_each_entry(pcfg, &unused_pcfgs, list) { ++#ifdef CONFIG_PM_DEBUG ++ pr_info("Need to save qportal %d\n", pcfg->public_cfg.index); ++#endif ++ /* save isdr, disable all via isdr, clear isr */ ++ pcfg->saved_isdr = ++ __raw_readl(pcfg->addr_virt[DPA_PORTAL_CI] + 0xe08); ++ __raw_writel(0xffffffff, pcfg->addr_virt[DPA_PORTAL_CI] + ++ 0xe08); ++ __raw_writel(0xffffffff, pcfg->addr_virt[DPA_PORTAL_CI] + ++ 0xe00); ++ } ++ return; ++} ++ ++void resume_unused_qportal(void) ++{ ++ struct qm_portal_config *pcfg; ++ ++ if (list_empty(&unused_pcfgs)) ++ return; ++ ++ list_for_each_entry(pcfg, &unused_pcfgs, list) { ++#ifdef CONFIG_PM_DEBUG ++ pr_info("Need to resume qportal %d\n", pcfg->public_cfg.index); ++#endif ++ /* restore isdr */ ++ __raw_writel(pcfg->saved_isdr, ++ pcfg->addr_virt[DPA_PORTAL_CI] + 0xe08); ++ } ++ return; ++} ++#endif ++ +diff --git a/drivers/staging/fsl_qbman/qman_high.c b/drivers/staging/fsl_qbman/qman_high.c +new file mode 100644 +index 0000000..c50828b +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_high.c +@@ -0,0 +1,5245 @@ ++/* Copyright 2008-2012 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 "qman_low.h" ++ ++/* Compilation constants */ ++#define DQRR_MAXFILL 15 ++#define EQCR_ITHRESH 4 /* if EQCR congests, interrupt threshold */ ++#define IRQNAME "QMan portal %d" ++#define MAX_IRQNAME 16 /* big enough for "QMan portal %d" */ ++ ++/* Divide 'n' by 'd', rounding down if 'r' is negative, rounding up if it's ++ * positive, and rounding to the closest value if it's zero. NB, this macro ++ * implicitly upgrades parameters to unsigned 64-bit, so feed it with types ++ * that are compatible with this. NB, these arguments should not be expressions ++ * unless it is safe for them to be evaluated multiple times. Eg. do not pass ++ * in "some_value++" as a parameter to the macro! */ ++#define ROUNDING(n, d, r) \ ++ (((r) < 0) ? div64_u64((n), (d)) : \ ++ (((r) > 0) ? div64_u64(((n) + (d) - 1), (d)) : \ ++ div64_u64(((n) + ((d) / 2)), (d)))) ++ ++/* Lock/unlock frame queues, subject to the "LOCKED" flag. This is about ++ * inter-processor locking only. Note, FQLOCK() is always called either under a ++ * local_irq_save() or from interrupt context - hence there's no need for irq ++ * protection (and indeed, attempting to nest irq-protection doesn't work, as ++ * the "irq en/disable" machinery isn't recursive...). */ ++#define FQLOCK(fq) \ ++ do { \ ++ struct qman_fq *__fq478 = (fq); \ ++ if (fq_isset(__fq478, QMAN_FQ_FLAG_LOCKED)) \ ++ spin_lock(&__fq478->fqlock); \ ++ } while (0) ++#define FQUNLOCK(fq) \ ++ do { \ ++ struct qman_fq *__fq478 = (fq); \ ++ if (fq_isset(__fq478, QMAN_FQ_FLAG_LOCKED)) \ ++ spin_unlock(&__fq478->fqlock); \ ++ } while (0) ++ ++static inline void fq_set(struct qman_fq *fq, u32 mask) ++{ ++ set_bits(mask, &fq->flags); ++} ++static inline void fq_clear(struct qman_fq *fq, u32 mask) ++{ ++ clear_bits(mask, &fq->flags); ++} ++static inline int fq_isset(struct qman_fq *fq, u32 mask) ++{ ++ return fq->flags & mask; ++} ++static inline int fq_isclear(struct qman_fq *fq, u32 mask) ++{ ++ return !(fq->flags & mask); ++} ++ ++struct qman_portal { ++ struct qm_portal p; ++ unsigned long bits; /* PORTAL_BITS_*** - dynamic, strictly internal */ ++ unsigned long irq_sources; ++ u32 use_eqcr_ci_stashing; ++ u32 slowpoll; /* only used when interrupts are off */ ++ struct qman_fq *vdqcr_owned; /* only 1 volatile dequeue at a time */ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ struct qman_fq *eqci_owned; /* only 1 enqueue WAIT_SYNC at a time */ ++#endif ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ raw_spinlock_t sharing_lock; /* only used if is_shared */ ++ int is_shared; ++ struct qman_portal *sharing_redirect; ++#endif ++ u32 sdqcr; ++ int dqrr_disable_ref; ++ /* A portal-specific handler for DCP ERNs. If this is NULL, the global ++ * handler is called instead. */ ++ qman_cb_dc_ern cb_dc_ern; ++ /* When the cpu-affine portal is activated, this is non-NULL */ ++ const struct qm_portal_config *config; ++ /* This is needed for providing a non-NULL device to dma_map_***() */ ++ struct platform_device *pdev; ++ struct dpa_rbtree retire_table; ++ char irqname[MAX_IRQNAME]; ++ /* 2-element array. cgrs[0] is mask, cgrs[1] is snapshot. */ ++ struct qman_cgrs *cgrs; ++ /* linked-list of CSCN handlers. */ ++ struct list_head cgr_cbs; ++ /* list lock */ ++ spinlock_t cgr_lock; ++ /* 2-element array. ccgrs[0] is mask, ccgrs[1] is snapshot. */ ++ struct qman_ccgrs *ccgrs[QMAN_CEETM_MAX]; ++ /* 256-element array, each is a linked-list of CCSCN handlers. */ ++ struct list_head ccgr_cbs[QMAN_CEETM_MAX]; ++ /* list lock */ ++ spinlock_t ccgr_lock; ++ /* track if memory was allocated by the driver */ ++ u8 alloced; ++ /* power management data */ ++ u32 save_isdr; ++}; ++ ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++#define PORTAL_IRQ_LOCK(p, irqflags) \ ++ do { \ ++ if ((p)->is_shared) \ ++ raw_spin_lock_irqsave(&(p)->sharing_lock, irqflags); \ ++ else \ ++ local_irq_save(irqflags); \ ++ } while (0) ++#define PORTAL_IRQ_UNLOCK(p, irqflags) \ ++ do { \ ++ if ((p)->is_shared) \ ++ raw_spin_unlock_irqrestore(&(p)->sharing_lock, \ ++ irqflags); \ ++ else \ ++ local_irq_restore(irqflags); \ ++ } while (0) ++#else ++#define PORTAL_IRQ_LOCK(p, irqflags) local_irq_save(irqflags) ++#define PORTAL_IRQ_UNLOCK(p, irqflags) local_irq_restore(irqflags) ++#endif ++ ++/* Global handler for DCP ERNs. Used when the portal receiving the message does ++ * not have a portal-specific handler. */ ++static qman_cb_dc_ern cb_dc_ern; ++ ++static cpumask_t affine_mask; ++static DEFINE_SPINLOCK(affine_mask_lock); ++static u16 affine_channels[NR_CPUS]; ++static DEFINE_PER_CPU(struct qman_portal, qman_affine_portal); ++void *affine_portals[NR_CPUS]; ++ ++/* "raw" gets the cpu-local struct whether it's a redirect or not. */ ++static inline struct qman_portal *get_raw_affine_portal(void) ++{ ++ return &get_cpu_var(qman_affine_portal); ++} ++/* For ops that can redirect, this obtains the portal to use */ ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++static inline struct qman_portal *get_affine_portal(void) ++{ ++ struct qman_portal *p = get_raw_affine_portal(); ++ if (p->sharing_redirect) ++ return p->sharing_redirect; ++ return p; ++} ++#else ++#define get_affine_portal() get_raw_affine_portal() ++#endif ++/* For every "get", there must be a "put" */ ++static inline void put_affine_portal(void) ++{ ++ put_cpu_var(qman_affine_portal); ++} ++/* Exception: poll functions assume the caller is cpu-affine and in no risk of ++ * re-entrance, which are the two reasons we usually use the get/put_cpu_var() ++ * semantic - ie. to disable pre-emption. Some use-cases expect the execution ++ * context to remain as non-atomic during poll-triggered callbacks as it was ++ * when the poll API was first called (eg. NAPI), so we go out of our way in ++ * this case to not disable pre-emption. */ ++static inline struct qman_portal *get_poll_portal(void) ++{ ++ return &get_cpu_var(qman_affine_portal); ++} ++#define put_poll_portal() ++ ++/* This gives a FQID->FQ lookup to cover the fact that we can't directly demux ++ * retirement notifications (the fact they are sometimes h/w-consumed means that ++ * contextB isn't always a s/w demux - and as we can't know which case it is ++ * when looking at the notification, we have to use the slow lookup for all of ++ * them). NB, it's possible to have multiple FQ objects refer to the same FQID ++ * (though at most one of them should be the consumer), so this table isn't for ++ * all FQs - FQs are added when retirement commands are issued, and removed when ++ * they complete, which also massively reduces the size of this table. */ ++IMPLEMENT_DPA_RBTREE(fqtree, struct qman_fq, node, fqid); ++ ++/* This is what everything can wait on, even if it migrates to a different cpu ++ * to the one whose affine portal it is waiting on. */ ++static DECLARE_WAIT_QUEUE_HEAD(affine_queue); ++ ++static inline int table_push_fq(struct qman_portal *p, struct qman_fq *fq) ++{ ++ int ret = fqtree_push(&p->retire_table, fq); ++ if (ret) ++ pr_err("ERROR: double FQ-retirement %d\n", fq->fqid); ++ return ret; ++} ++ ++static inline void table_del_fq(struct qman_portal *p, struct qman_fq *fq) ++{ ++ fqtree_del(&p->retire_table, fq); ++} ++ ++static inline struct qman_fq *table_find_fq(struct qman_portal *p, u32 fqid) ++{ ++ return fqtree_find(&p->retire_table, fqid); ++} ++ ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++static void **qman_fq_lookup_table; ++static size_t qman_fq_lookup_table_size; ++ ++int qman_setup_fq_lookup_table(size_t num_entries) ++{ ++ num_entries++; ++ /* Allocate 1 more entry since the first entry is not used */ ++ qman_fq_lookup_table = vzalloc((num_entries * sizeof(void *))); ++ if (!qman_fq_lookup_table) { ++ pr_err("QMan: Could not allocate fq lookup table\n"); ++ return -ENOMEM; ++ } ++ qman_fq_lookup_table_size = num_entries; ++ pr_info("QMan: Allocated lookup table at %p, entry count %lu\n", ++ qman_fq_lookup_table, ++ (unsigned long)qman_fq_lookup_table_size); ++ return 0; ++} ++ ++/* global structure that maintains fq object mapping */ ++static DEFINE_SPINLOCK(fq_hash_table_lock); ++ ++static int find_empty_fq_table_entry(u32 *entry, struct qman_fq *fq) ++{ ++ u32 i; ++ ++ spin_lock(&fq_hash_table_lock); ++ /* Can't use index zero because this has special meaning ++ * in context_b field. */ ++ for (i = 1; i < qman_fq_lookup_table_size; i++) { ++ if (qman_fq_lookup_table[i] == NULL) { ++ *entry = i; ++ qman_fq_lookup_table[i] = fq; ++ spin_unlock(&fq_hash_table_lock); ++ return 0; ++ } ++ } ++ spin_unlock(&fq_hash_table_lock); ++ return -ENOMEM; ++} ++ ++static void clear_fq_table_entry(u32 entry) ++{ ++ spin_lock(&fq_hash_table_lock); ++ BUG_ON(entry >= qman_fq_lookup_table_size); ++ qman_fq_lookup_table[entry] = NULL; ++ spin_unlock(&fq_hash_table_lock); ++} ++ ++static inline struct qman_fq *get_fq_table_entry(u32 entry) ++{ ++ BUG_ON(entry >= qman_fq_lookup_table_size); ++ return qman_fq_lookup_table[entry]; ++} ++#endif ++ ++/* In the case that slow- and fast-path handling are both done by qman_poll() ++ * (ie. because there is no interrupt handling), we ought to balance how often ++ * we do the fast-path poll versus the slow-path poll. We'll use two decrementer ++ * sources, so we call the fast poll 'n' times before calling the slow poll ++ * once. The idle decrementer constant is used when the last slow-poll detected ++ * no work to do, and the busy decrementer constant when the last slow-poll had ++ * work to do. */ ++#define SLOW_POLL_IDLE 1000 ++#define SLOW_POLL_BUSY 10 ++static u32 __poll_portal_slow(struct qman_portal *p, u32 is); ++static inline unsigned int __poll_portal_fast(struct qman_portal *p, ++ unsigned int poll_limit); ++ ++/* Portal interrupt handler */ ++static irqreturn_t portal_isr(__always_unused int irq, void *ptr) ++{ ++ struct qman_portal *p = ptr; ++ /* ++ * The CSCI/CCSCI source is cleared inside __poll_portal_slow(), because ++ * it could race against a Query Congestion State command also given ++ * as part of the handling of this interrupt source. We mustn't ++ * clear it a second time in this top-level function. ++ */ ++ u32 clear = QM_DQAVAIL_MASK | (p->irq_sources & ++ ~(QM_PIRQ_CSCI | QM_PIRQ_CCSCI)); ++ u32 is = qm_isr_status_read(&p->p) & p->irq_sources; ++ /* DQRR-handling if it's interrupt-driven */ ++ if (is & QM_PIRQ_DQRI) ++ __poll_portal_fast(p, CONFIG_FSL_QMAN_POLL_LIMIT); ++ /* Handling of anything else that's interrupt-driven */ ++ clear |= __poll_portal_slow(p, is); ++ qm_isr_status_clear(&p->p, clear); ++ return IRQ_HANDLED; ++} ++ ++/* This inner version is used privately by qman_create_affine_portal(), as well ++ * as by the exported qman_stop_dequeues(). */ ++static inline void qman_stop_dequeues_ex(struct qman_portal *p) ++{ ++ unsigned long irqflags __maybe_unused; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ if (!(p->dqrr_disable_ref++)) ++ qm_dqrr_set_maxfill(&p->p, 0); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++} ++ ++static int drain_mr(struct qm_portal *p) ++{ ++ const struct qm_mr_entry *msg; ++loop: ++ msg = qm_mr_current(p); ++ if (!msg) { ++ /* if MR was full and h/w had other FQRNI entries to produce, we ++ * need to allow it time to produce those entries once the ++ * existing entries are consumed. A worst-case situation ++ * (fully-loaded system) means h/w sequencers may have to do 3-4 ++ * other things before servicing the portal's MR pump, each of ++ * which (if slow) may take ~50 qman cycles (which is ~200 ++ * processor cycles). So rounding up and then multiplying this ++ * worst-case estimate by a factor of 10, just to be ++ * ultra-paranoid, goes as high as 10,000 cycles. NB, we consume ++ * one entry at a time, so h/w has an opportunity to produce new ++ * entries well before the ring has been fully consumed, so ++ * we're being *really* paranoid here. */ ++ u64 now, then = mfatb(); ++ do { ++ now = mfatb(); ++ } while ((then + 10000) > now); ++ msg = qm_mr_current(p); ++ if (!msg) ++ return 0; ++ } ++ qm_mr_next(p); ++ qm_mr_cci_consume(p, 1); ++ goto loop; ++} ++ ++#ifdef CONFIG_SUSPEND ++static int _qman_portal_suspend_noirq(struct device *dev) ++{ ++ struct qman_portal *p = (struct qman_portal *)dev->platform_data; ++#ifdef CONFIG_PM_DEBUG ++ struct platform_device *pdev = to_platform_device(dev); ++#endif ++ ++ p->save_isdr = qm_isr_disable_read(&p->p); ++ qm_isr_disable_write(&p->p, 0xffffffff); ++ qm_isr_status_clear(&p->p, 0xffffffff); ++#ifdef CONFIG_PM_DEBUG ++ pr_info("Suspend for %s\n", pdev->name); ++#endif ++ return 0; ++} ++ ++static int _qman_portal_resume_noirq(struct device *dev) ++{ ++ struct qman_portal *p = (struct qman_portal *)dev->platform_data; ++ ++ /* restore isdr */ ++ qm_isr_disable_write(&p->p, p->save_isdr); ++ return 0; ++} ++#else ++#define _qman_portal_suspend_noirq NULL ++#define _qman_portal_resume_noirq NULL ++#endif ++ ++struct dev_pm_domain qman_portal_device_pm_domain = { ++ .ops = { ++ USE_PLATFORM_PM_SLEEP_OPS ++ .suspend_noirq = _qman_portal_suspend_noirq, ++ .resume_noirq = _qman_portal_resume_noirq, ++ } ++}; ++ ++struct qman_portal *qman_create_portal( ++ struct qman_portal *portal, ++ const struct qm_portal_config *config, ++ const struct qman_cgrs *cgrs) ++{ ++ struct qm_portal *__p; ++ char buf[16]; ++ int ret; ++ u32 isdr; ++ ++ if (!portal) { ++ portal = kmalloc(sizeof(*portal), GFP_KERNEL); ++ if (!portal) ++ return portal; ++ portal->alloced = 1; ++ } else ++ portal->alloced = 0; ++ ++ __p = &portal->p; ++ ++ portal->use_eqcr_ci_stashing = ((qman_ip_rev >= QMAN_REV30) ? ++ 1 : 0); ++ ++ /* prep the low-level portal struct with the mapped addresses from the ++ * config, everything that follows depends on it and "config" is more ++ * for (de)reference... */ ++ __p->addr.addr_ce = config->addr_virt[DPA_PORTAL_CE]; ++ __p->addr.addr_ci = config->addr_virt[DPA_PORTAL_CI]; ++ /* ++ * If CI-stashing is used, the current defaults use a threshold of 3, ++ * and stash with high-than-DQRR priority. ++ */ ++ if (qm_eqcr_init(__p, qm_eqcr_pvb, ++ portal->use_eqcr_ci_stashing ? 3 : 0, 1)) { ++ pr_err("Qman EQCR initialisation failed\n"); ++ goto fail_eqcr; ++ } ++ if (qm_dqrr_init(__p, config, qm_dqrr_dpush, qm_dqrr_pvb, ++ qm_dqrr_cdc, DQRR_MAXFILL)) { ++ pr_err("Qman DQRR initialisation failed\n"); ++ goto fail_dqrr; ++ } ++ if (qm_mr_init(__p, qm_mr_pvb, qm_mr_cci)) { ++ pr_err("Qman MR initialisation failed\n"); ++ goto fail_mr; ++ } ++ if (qm_mc_init(__p)) { ++ pr_err("Qman MC initialisation failed\n"); ++ goto fail_mc; ++ } ++ if (qm_isr_init(__p)) { ++ pr_err("Qman ISR initialisation failed\n"); ++ goto fail_isr; ++ } ++ /* static interrupt-gating controls */ ++ qm_dqrr_set_ithresh(__p, CONFIG_FSL_QMAN_PIRQ_DQRR_ITHRESH); ++ qm_mr_set_ithresh(__p, CONFIG_FSL_QMAN_PIRQ_MR_ITHRESH); ++ qm_isr_set_iperiod(__p, CONFIG_FSL_QMAN_PIRQ_IPERIOD); ++ portal->cgrs = kmalloc(2 * sizeof(*cgrs), GFP_KERNEL); ++ if (!portal->cgrs) ++ goto fail_cgrs; ++ /* initial snapshot is no-depletion */ ++ qman_cgrs_init(&portal->cgrs[1]); ++ if (cgrs) ++ portal->cgrs[0] = *cgrs; ++ else ++ /* if the given mask is NULL, assume all CGRs can be seen */ ++ qman_cgrs_fill(&portal->cgrs[0]); ++ INIT_LIST_HEAD(&portal->cgr_cbs); ++ spin_lock_init(&portal->cgr_lock); ++ if (num_ceetms) { ++ for (ret = 0; ret < num_ceetms; ret++) { ++ portal->ccgrs[ret] = kmalloc(2 * ++ sizeof(struct qman_ccgrs), GFP_KERNEL); ++ if (!portal->ccgrs[ret]) ++ goto fail_ccgrs; ++ qman_ccgrs_init(&portal->ccgrs[ret][1]); ++ qman_ccgrs_fill(&portal->ccgrs[ret][0]); ++ INIT_LIST_HEAD(&portal->ccgr_cbs[ret]); ++ } ++ } ++ spin_lock_init(&portal->ccgr_lock); ++ portal->bits = 0; ++ portal->slowpoll = 0; ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ portal->eqci_owned = NULL; ++#endif ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ raw_spin_lock_init(&portal->sharing_lock); ++ portal->is_shared = config->public_cfg.is_shared; ++ portal->sharing_redirect = NULL; ++#endif ++ portal->sdqcr = QM_SDQCR_SOURCE_CHANNELS | QM_SDQCR_COUNT_UPTO3 | ++ QM_SDQCR_DEDICATED_PRECEDENCE | QM_SDQCR_TYPE_PRIO_QOS | ++ QM_SDQCR_TOKEN_SET(0xab) | QM_SDQCR_CHANNELS_DEDICATED; ++ portal->dqrr_disable_ref = 0; ++ portal->cb_dc_ern = NULL; ++ sprintf(buf, "qportal-%d", config->public_cfg.channel); ++ portal->pdev = platform_device_alloc(buf, -1); ++ if (!portal->pdev) ++ goto fail_devalloc; ++ if (dma_set_mask(&portal->pdev->dev, DMA_BIT_MASK(40))) ++ goto fail_devadd; ++ portal->pdev->dev.pm_domain = &qman_portal_device_pm_domain; ++ portal->pdev->dev.platform_data = portal; ++ ret = platform_device_add(portal->pdev); ++ if (ret) ++ goto fail_devadd; ++ dpa_rbtree_init(&portal->retire_table); ++ isdr = 0xffffffff; ++ qm_isr_disable_write(__p, isdr); ++ portal->irq_sources = 0; ++ qm_isr_enable_write(__p, portal->irq_sources); ++ qm_isr_status_clear(__p, 0xffffffff); ++ snprintf(portal->irqname, MAX_IRQNAME, IRQNAME, config->public_cfg.cpu); ++ if (request_irq(config->public_cfg.irq, portal_isr, 0, portal->irqname, ++ portal)) { ++ pr_err("request_irq() failed\n"); ++ goto fail_irq; ++ } ++ if ((config->public_cfg.cpu != -1) && ++ irq_can_set_affinity(config->public_cfg.irq) && ++ irq_set_affinity(config->public_cfg.irq, ++ cpumask_of(config->public_cfg.cpu))) { ++ pr_err("irq_set_affinity() failed\n"); ++ goto fail_affinity; ++ } ++ ++ /* Need EQCR to be empty before continuing */ ++ isdr ^= QM_PIRQ_EQCI; ++ qm_isr_disable_write(__p, isdr); ++ ret = qm_eqcr_get_fill(__p); ++ if (ret) { ++ pr_err("Qman EQCR unclean\n"); ++ goto fail_eqcr_empty; ++ } ++ isdr ^= (QM_PIRQ_DQRI | QM_PIRQ_MRI); ++ qm_isr_disable_write(__p, isdr); ++ while (qm_dqrr_current(__p) != NULL) ++ qm_dqrr_cdc_consume_n(__p, 0xffff); ++ drain_mr(__p); ++ /* Success */ ++ portal->config = config; ++ qm_isr_disable_write(__p, 0); ++ qm_isr_uninhibit(__p); ++ /* Write a sane SDQCR */ ++ qm_dqrr_sdqcr_set(__p, portal->sdqcr); ++ return portal; ++fail_eqcr_empty: ++fail_affinity: ++ free_irq(config->public_cfg.irq, portal); ++fail_irq: ++ platform_device_del(portal->pdev); ++fail_devadd: ++ platform_device_put(portal->pdev); ++fail_devalloc: ++ if (num_ceetms) ++ for (ret = 0; ret < num_ceetms; ret++) ++ kfree(portal->ccgrs[ret]); ++fail_ccgrs: ++ kfree(portal->cgrs); ++fail_cgrs: ++ qm_isr_finish(__p); ++fail_isr: ++ qm_mc_finish(__p); ++fail_mc: ++ qm_mr_finish(__p); ++fail_mr: ++ qm_dqrr_finish(__p); ++fail_dqrr: ++ qm_eqcr_finish(__p); ++fail_eqcr: ++ if (portal->alloced) ++ kfree(portal); ++ return NULL; ++} ++ ++struct qman_portal *qman_create_affine_portal( ++ const struct qm_portal_config *config, ++ const struct qman_cgrs *cgrs) ++{ ++ struct qman_portal *res; ++ struct qman_portal *portal; ++ ++ portal = &per_cpu(qman_affine_portal, config->public_cfg.cpu); ++ res = qman_create_portal(portal, config, cgrs); ++ if (res) { ++ spin_lock(&affine_mask_lock); ++ cpumask_set_cpu(config->public_cfg.cpu, &affine_mask); ++ affine_channels[config->public_cfg.cpu] = ++ config->public_cfg.channel; ++ affine_portals[config->public_cfg.cpu] = portal; ++ spin_unlock(&affine_mask_lock); ++ } ++ return res; ++} ++ ++/* These checks are BUG_ON()s because the driver is already supposed to avoid ++ * these cases. */ ++struct qman_portal *qman_create_affine_slave(struct qman_portal *redirect, ++ int cpu) ++{ ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ struct qman_portal *p; ++ p = &per_cpu(qman_affine_portal, cpu); ++ /* Check that we don't already have our own portal */ ++ BUG_ON(p->config); ++ /* Check that we aren't already slaving to another portal */ ++ BUG_ON(p->is_shared); ++ /* Check that 'redirect' is prepared to have us */ ++ BUG_ON(!redirect->config->public_cfg.is_shared); ++ /* These are the only elements to initialise when redirecting */ ++ p->irq_sources = 0; ++ p->sharing_redirect = redirect; ++ affine_portals[cpu] = p; ++ return p; ++#else ++ BUG(); ++ return NULL; ++#endif ++} ++ ++void qman_destroy_portal(struct qman_portal *qm) ++{ ++ const struct qm_portal_config *pcfg; ++ int i; ++ ++ /* Stop dequeues on the portal */ ++ qm_dqrr_sdqcr_set(&qm->p, 0); ++ ++ /* NB we do this to "quiesce" EQCR. If we add enqueue-completions or ++ * something related to QM_PIRQ_EQCI, this may need fixing. ++ * Also, due to the prefetching model used for CI updates in the enqueue ++ * path, this update will only invalidate the CI cacheline *after* ++ * working on it, so we need to call this twice to ensure a full update ++ * irrespective of where the enqueue processing was at when the teardown ++ * began. */ ++ qm_eqcr_cce_update(&qm->p); ++ qm_eqcr_cce_update(&qm->p); ++ pcfg = qm->config; ++ ++ free_irq(pcfg->public_cfg.irq, qm); ++ ++ kfree(qm->cgrs); ++ if (num_ceetms) ++ for (i = 0; i < num_ceetms; i++) ++ kfree(qm->ccgrs[i]); ++ qm_isr_finish(&qm->p); ++ qm_mc_finish(&qm->p); ++ qm_mr_finish(&qm->p); ++ qm_dqrr_finish(&qm->p); ++ qm_eqcr_finish(&qm->p); ++ ++ platform_device_del(qm->pdev); ++ platform_device_put(qm->pdev); ++ ++ qm->config = NULL; ++ if (qm->alloced) ++ kfree(qm); ++} ++ ++const struct qm_portal_config *qman_destroy_affine_portal(void) ++{ ++ /* We don't want to redirect if we're a slave, use "raw" */ ++ struct qman_portal *qm = get_raw_affine_portal(); ++ const struct qm_portal_config *pcfg; ++ int cpu; ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (qm->sharing_redirect) { ++ qm->sharing_redirect = NULL; ++ put_affine_portal(); ++ return NULL; ++ } ++ qm->is_shared = 0; ++#endif ++ pcfg = qm->config; ++ cpu = pcfg->public_cfg.cpu; ++ ++ qman_destroy_portal(qm); ++ ++ spin_lock(&affine_mask_lock); ++ cpumask_clear_cpu(cpu, &affine_mask); ++ spin_unlock(&affine_mask_lock); ++ put_affine_portal(); ++ return pcfg; ++} ++ ++const struct qman_portal_config *qman_p_get_portal_config(struct qman_portal *p) ++{ ++ return &p->config->public_cfg; ++} ++EXPORT_SYMBOL(qman_p_get_portal_config); ++ ++const struct qman_portal_config *qman_get_portal_config(void) ++{ ++ struct qman_portal *p = get_affine_portal(); ++ const struct qman_portal_config *ret = qman_p_get_portal_config(p); ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_get_portal_config); ++ ++/* Inline helper to reduce nesting in __poll_portal_slow() */ ++static inline void fq_state_change(struct qman_portal *p, struct qman_fq *fq, ++ const struct qm_mr_entry *msg, u8 verb) ++{ ++ FQLOCK(fq); ++ switch (verb) { ++ case QM_MR_VERB_FQRL: ++ DPA_ASSERT(fq_isset(fq, QMAN_FQ_STATE_ORL)); ++ fq_clear(fq, QMAN_FQ_STATE_ORL); ++ table_del_fq(p, fq); ++ break; ++ case QM_MR_VERB_FQRN: ++ DPA_ASSERT((fq->state == qman_fq_state_parked) || ++ (fq->state == qman_fq_state_sched)); ++ DPA_ASSERT(fq_isset(fq, QMAN_FQ_STATE_CHANGING)); ++ fq_clear(fq, QMAN_FQ_STATE_CHANGING); ++ if (msg->fq.fqs & QM_MR_FQS_NOTEMPTY) ++ fq_set(fq, QMAN_FQ_STATE_NE); ++ if (msg->fq.fqs & QM_MR_FQS_ORLPRESENT) ++ fq_set(fq, QMAN_FQ_STATE_ORL); ++ else ++ table_del_fq(p, fq); ++ fq->state = qman_fq_state_retired; ++ break; ++ case QM_MR_VERB_FQPN: ++ DPA_ASSERT(fq->state == qman_fq_state_sched); ++ DPA_ASSERT(fq_isclear(fq, QMAN_FQ_STATE_CHANGING)); ++ fq->state = qman_fq_state_parked; ++ } ++ FQUNLOCK(fq); ++} ++ ++static u32 __poll_portal_slow(struct qman_portal *p, u32 is) ++{ ++ const struct qm_mr_entry *msg; ++ ++ if (is & QM_PIRQ_CSCI) { ++ struct qman_cgrs rr, c; ++ struct qm_mc_result *mcr; ++ struct qman_cgr *cgr; ++ unsigned long irqflags __maybe_unused; ++ ++ spin_lock_irqsave(&p->cgr_lock, irqflags); ++ /* ++ * The CSCI bit must be cleared _before_ issuing the ++ * Query Congestion State command, to ensure that a long ++ * CGR State Change callback cannot miss an intervening ++ * state change. ++ */ ++ qm_isr_status_clear(&p->p, QM_PIRQ_CSCI); ++ qm_mc_start(&p->p); ++ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYCONGESTION); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ /* mask out the ones I'm not interested in */ ++ qman_cgrs_and(&rr, (const struct qman_cgrs *) ++ &mcr->querycongestion.state, &p->cgrs[0]); ++ /* check previous snapshot for delta, enter/exit congestion */ ++ qman_cgrs_xor(&c, &rr, &p->cgrs[1]); ++ /* update snapshot */ ++ qman_cgrs_cp(&p->cgrs[1], &rr); ++ /* Invoke callback */ ++ list_for_each_entry(cgr, &p->cgr_cbs, node) ++ if (cgr->cb && qman_cgrs_get(&c, cgr->cgrid)) ++ cgr->cb(p, cgr, qman_cgrs_get(&rr, cgr->cgrid)); ++ spin_unlock_irqrestore(&p->cgr_lock, irqflags); ++ } ++ if (is & QM_PIRQ_CCSCI) { ++ struct qman_ccgrs rr, c, congestion_result; ++ struct qm_mc_result *mcr; ++ struct qm_mc_command *mcc; ++ struct qm_ceetm_ccg *ccg; ++ unsigned long irqflags __maybe_unused; ++ int i, j; ++ ++ spin_lock_irqsave(&p->ccgr_lock, irqflags); ++ /* ++ * The CCSCI bit must be cleared _before_ issuing the ++ * Query Congestion State command, to ensure that a long ++ * CCGR State Change callback cannot miss an intervening ++ * state change. ++ */ ++ qm_isr_status_clear(&p->p, QM_PIRQ_CCSCI); ++ ++ for (i = 0; i < num_ceetms; i++) { ++ for (j = 0; j < 2; j++) { ++ mcc = qm_mc_start(&p->p); ++ mcc->ccgr_query.ccgrid = ++ CEETM_QUERY_CONGESTION_STATE | j; ++ mcc->ccgr_query.dcpid = i; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CCGR_QUERY); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ congestion_result.q[j] = ++ mcr->ccgr_query.congestion_state.state; ++ } ++ /* mask out the ones I'm not interested in */ ++ qman_ccgrs_and(&rr, &congestion_result, ++ &p->ccgrs[i][0]); ++ /* ++ * check previous snapshot for delta, enter/exit ++ * congestion. ++ */ ++ qman_ccgrs_xor(&c, &rr, &p->ccgrs[i][1]); ++ /* update snapshot */ ++ qman_ccgrs_cp(&p->ccgrs[i][1], &rr); ++ /* Invoke callback */ ++ list_for_each_entry(ccg, &p->ccgr_cbs[i], cb_node) ++ if (ccg->cb && qman_ccgrs_get(&c, ++ (ccg->parent->idx << 4) | ccg->idx)) ++ ccg->cb(ccg, ccg->cb_ctx, ++ qman_ccgrs_get(&rr, ++ (ccg->parent->idx << 4) ++ | ccg->idx)); ++ } ++ spin_unlock_irqrestore(&p->ccgr_lock, irqflags); ++ } ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (is & QM_PIRQ_EQCI) { ++ unsigned long irqflags; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ p->eqci_owned = NULL; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ wake_up(&affine_queue); ++ } ++#endif ++ ++ if (is & QM_PIRQ_EQRI) { ++ unsigned long irqflags __maybe_unused; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ qm_eqcr_cce_update(&p->p); ++ qm_eqcr_set_ithresh(&p->p, 0); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ wake_up(&affine_queue); ++ } ++ ++ if (is & QM_PIRQ_MRI) { ++ struct qman_fq *fq; ++ u8 verb, num = 0; ++mr_loop: ++ qm_mr_pvb_update(&p->p); ++ msg = qm_mr_current(&p->p); ++ if (!msg) ++ goto mr_done; ++ verb = msg->verb & QM_MR_VERB_TYPE_MASK; ++ /* The message is a software ERN iff the 0x20 bit is set */ ++ if (verb & 0x20) { ++ switch (verb) { ++ case QM_MR_VERB_FQRNI: ++ /* nada, we drop FQRNIs on the floor */ ++ break; ++ case QM_MR_VERB_FQRN: ++ case QM_MR_VERB_FQRL: ++ /* Lookup in the retirement table */ ++ fq = table_find_fq(p, msg->fq.fqid); ++ BUG_ON(!fq); ++ fq_state_change(p, fq, msg, verb); ++ if (fq->cb.fqs) ++ fq->cb.fqs(p, fq, msg); ++ break; ++ case QM_MR_VERB_FQPN: ++ /* Parked */ ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ fq = get_fq_table_entry(msg->fq.contextB); ++#else ++ fq = (void *)(uintptr_t)msg->fq.contextB; ++#endif ++ fq_state_change(p, fq, msg, verb); ++ if (fq->cb.fqs) ++ fq->cb.fqs(p, fq, msg); ++ break; ++ case QM_MR_VERB_DC_ERN: ++ /* DCP ERN */ ++ if (p->cb_dc_ern) ++ p->cb_dc_ern(p, msg); ++ else if (cb_dc_ern) ++ cb_dc_ern(p, msg); ++ else { ++ static int warn_once; ++ if (!warn_once) { ++ pr_crit("Leaking DCP ERNs!\n"); ++ warn_once = 1; ++ } ++ } ++ break; ++ default: ++ pr_crit("Invalid MR verb 0x%02x\n", verb); ++ } ++ } else { ++ /* Its a software ERN */ ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ fq = get_fq_table_entry(msg->ern.tag); ++#else ++ fq = (void *)(uintptr_t)msg->ern.tag; ++#endif ++ fq->cb.ern(p, fq, msg); ++ } ++ num++; ++ qm_mr_next(&p->p); ++ goto mr_loop; ++mr_done: ++ qm_mr_cci_consume(&p->p, num); ++ } ++ /* ++ * QM_PIRQ_CSCI/CCSCI has already been cleared, as part of its specific ++ * processing. If that interrupt source has meanwhile been re-asserted, ++ * we mustn't clear it here (or in the top-level interrupt handler). ++ */ ++ return is & (QM_PIRQ_EQCI | QM_PIRQ_EQRI | QM_PIRQ_MRI); ++} ++ ++/* remove some slowish-path stuff from the "fast path" and make sure it isn't ++ * inlined. */ ++static noinline void clear_vdqcr(struct qman_portal *p, struct qman_fq *fq) ++{ ++ p->vdqcr_owned = NULL; ++ FQLOCK(fq); ++ fq_clear(fq, QMAN_FQ_STATE_VDQCR); ++ FQUNLOCK(fq); ++ wake_up(&affine_queue); ++} ++ ++/* Look: no locks, no irq_save()s, no preempt_disable()s! :-) The only states ++ * that would conflict with other things if they ran at the same time on the ++ * same cpu are; ++ * ++ * (i) setting/clearing vdqcr_owned, and ++ * (ii) clearing the NE (Not Empty) flag. ++ * ++ * Both are safe. Because; ++ * ++ * (i) this clearing can only occur after qman_volatile_dequeue() has set the ++ * vdqcr_owned field (which it does before setting VDQCR), and ++ * qman_volatile_dequeue() blocks interrupts and preemption while this is ++ * done so that we can't interfere. ++ * (ii) the NE flag is only cleared after qman_retire_fq() has set it, and as ++ * with (i) that API prevents us from interfering until it's safe. ++ * ++ * The good thing is that qman_volatile_dequeue() and qman_retire_fq() run far ++ * less frequently (ie. per-FQ) than __poll_portal_fast() does, so the nett ++ * advantage comes from this function not having to "lock" anything at all. ++ * ++ * Note also that the callbacks are invoked at points which are safe against the ++ * above potential conflicts, but that this function itself is not re-entrant ++ * (this is because the function tracks one end of each FIFO in the portal and ++ * we do *not* want to lock that). So the consequence is that it is safe for ++ * user callbacks to call into any Qman API *except* qman_poll() (as that's the ++ * sole API that could be invoking the callback through this function). ++ */ ++static inline unsigned int __poll_portal_fast(struct qman_portal *p, ++ unsigned int poll_limit) ++{ ++ const struct qm_dqrr_entry *dq; ++ struct qman_fq *fq; ++ enum qman_cb_dqrr_result res; ++ unsigned int limit = 0; ++ ++loop: ++ qm_dqrr_pvb_update(&p->p); ++ dq = qm_dqrr_current(&p->p); ++ if (!dq) ++ goto done; ++ if (dq->stat & QM_DQRR_STAT_UNSCHEDULED) { ++ /* VDQCR: don't trust contextB as the FQ may have been ++ * configured for h/w consumption and we're draining it ++ * post-retirement. */ ++ fq = p->vdqcr_owned; ++ /* We only set QMAN_FQ_STATE_NE when retiring, so we only need ++ * to check for clearing it when doing volatile dequeues. It's ++ * one less thing to check in the critical path (SDQCR). */ ++ if (dq->stat & QM_DQRR_STAT_FQ_EMPTY) ++ fq_clear(fq, QMAN_FQ_STATE_NE); ++ /* this is duplicated from the SDQCR code, but we have stuff to ++ * do before *and* after this callback, and we don't want ++ * multiple if()s in the critical path (SDQCR). */ ++ res = fq->cb.dqrr(p, fq, dq); ++ if (res == qman_cb_dqrr_stop) ++ goto done; ++ /* Check for VDQCR completion */ ++ if (dq->stat & QM_DQRR_STAT_DQCR_EXPIRED) ++ clear_vdqcr(p, fq); ++ } else { ++ /* SDQCR: contextB points to the FQ */ ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ fq = get_fq_table_entry(dq->contextB); ++#else ++ fq = (void *)(uintptr_t)dq->contextB; ++#endif ++ /* Now let the callback do its stuff */ ++ res = fq->cb.dqrr(p, fq, dq); ++ /* The callback can request that we exit without consuming this ++ * entry nor advancing; */ ++ if (res == qman_cb_dqrr_stop) ++ goto done; ++ } ++ /* Interpret 'dq' from a driver perspective. */ ++ /* Parking isn't possible unless HELDACTIVE was set. NB, ++ * FORCEELIGIBLE implies HELDACTIVE, so we only need to ++ * check for HELDACTIVE to cover both. */ ++ DPA_ASSERT((dq->stat & QM_DQRR_STAT_FQ_HELDACTIVE) || ++ (res != qman_cb_dqrr_park)); ++ /* Defer just means "skip it, I'll consume it myself later on" */ ++ if (res != qman_cb_dqrr_defer) ++ qm_dqrr_cdc_consume_1ptr(&p->p, dq, (res == qman_cb_dqrr_park)); ++ /* Move forward */ ++ qm_dqrr_next(&p->p); ++ /* Entry processed and consumed, increment our counter. The callback can ++ * request that we exit after consuming the entry, and we also exit if ++ * we reach our processing limit, so loop back only if neither of these ++ * conditions is met. */ ++ if ((++limit < poll_limit) && (res != qman_cb_dqrr_consume_stop)) ++ goto loop; ++done: ++ return limit; ++} ++ ++u32 qman_irqsource_get(void) ++{ ++ /* "irqsource" and "poll" APIs mustn't redirect when sharing, they ++ * should shut the user out if they are not the primary CPU hosting the ++ * portal. That's why we use the "raw" interface. */ ++ struct qman_portal *p = get_raw_affine_portal(); ++ u32 ret = p->irq_sources & QM_PIRQ_VISIBLE; ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_irqsource_get); ++ ++int qman_p_irqsource_add(struct qman_portal *p, u32 bits __maybe_unused) ++{ ++ __maybe_unused unsigned long irqflags; ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (p->sharing_redirect) ++ return -EINVAL; ++ else ++#endif ++ { ++ PORTAL_IRQ_LOCK(p, irqflags); ++ set_bits(bits & QM_PIRQ_VISIBLE, &p->irq_sources); ++ qm_isr_enable_write(&p->p, p->irq_sources); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ } ++ return 0; ++} ++EXPORT_SYMBOL(qman_p_irqsource_add); ++ ++int qman_irqsource_add(u32 bits __maybe_unused) ++{ ++ struct qman_portal *p = get_raw_affine_portal(); ++ int ret; ++ ret = qman_p_irqsource_add(p, bits); ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_irqsource_add); ++ ++int qman_p_irqsource_remove(struct qman_portal *p, u32 bits) ++{ ++ __maybe_unused unsigned long irqflags; ++ u32 ier; ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (p->sharing_redirect) { ++ put_affine_portal(); ++ return -EINVAL; ++ } ++#endif ++ /* Our interrupt handler only processes+clears status register bits that ++ * are in p->irq_sources. As we're trimming that mask, if one of them ++ * were to assert in the status register just before we remove it from ++ * the enable register, there would be an interrupt-storm when we ++ * release the IRQ lock. So we wait for the enable register update to ++ * take effect in h/w (by reading it back) and then clear all other bits ++ * in the status register. Ie. we clear them from ISR once it's certain ++ * IER won't allow them to reassert. */ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ bits &= QM_PIRQ_VISIBLE; ++ clear_bits(bits, &p->irq_sources); ++ qm_isr_enable_write(&p->p, p->irq_sources); ++ ier = qm_isr_enable_read(&p->p); ++ /* Using "~ier" (rather than "bits" or "~p->irq_sources") creates a ++ * data-dependency, ie. to protect against re-ordering. */ ++ qm_isr_status_clear(&p->p, ~ier); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ return 0; ++} ++EXPORT_SYMBOL(qman_p_irqsource_remove); ++ ++int qman_irqsource_remove(u32 bits) ++{ ++ struct qman_portal *p = get_raw_affine_portal(); ++ int ret; ++ ret = qman_p_irqsource_remove(p, bits); ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_irqsource_remove); ++ ++const cpumask_t *qman_affine_cpus(void) ++{ ++ return &affine_mask; ++} ++EXPORT_SYMBOL(qman_affine_cpus); ++ ++u16 qman_affine_channel(int cpu) ++{ ++ if (cpu < 0) { ++ struct qman_portal *portal = get_raw_affine_portal(); ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ BUG_ON(portal->sharing_redirect); ++#endif ++ cpu = portal->config->public_cfg.cpu; ++ put_affine_portal(); ++ } ++ BUG_ON(!cpumask_test_cpu(cpu, &affine_mask)); ++ return affine_channels[cpu]; ++} ++EXPORT_SYMBOL(qman_affine_channel); ++ ++void *qman_get_affine_portal(int cpu) ++{ ++ return affine_portals[cpu]; ++} ++EXPORT_SYMBOL(qman_get_affine_portal); ++ ++int qman_p_poll_dqrr(struct qman_portal *p, unsigned int limit) ++{ ++ int ret; ++ ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (unlikely(p->sharing_redirect)) ++ ret = -EINVAL; ++ else ++#endif ++ { ++ BUG_ON(p->irq_sources & QM_PIRQ_DQRI); ++ ret = __poll_portal_fast(p, limit); ++ } ++ return ret; ++} ++EXPORT_SYMBOL(qman_p_poll_dqrr); ++ ++int qman_poll_dqrr(unsigned int limit) ++{ ++ struct qman_portal *p = get_poll_portal(); ++ int ret; ++ ret = qman_p_poll_dqrr(p, limit); ++ put_poll_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_poll_dqrr); ++ ++u32 qman_p_poll_slow(struct qman_portal *p) ++{ ++ u32 ret; ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (unlikely(p->sharing_redirect)) ++ ret = (u32)-1; ++ else ++#endif ++ { ++ u32 is = qm_isr_status_read(&p->p) & ~p->irq_sources; ++ ret = __poll_portal_slow(p, is); ++ qm_isr_status_clear(&p->p, ret); ++ } ++ return ret; ++} ++EXPORT_SYMBOL(qman_p_poll_slow); ++ ++u32 qman_poll_slow(void) ++{ ++ struct qman_portal *p = get_poll_portal(); ++ u32 ret; ++ ret = qman_p_poll_slow(p); ++ put_poll_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_poll_slow); ++ ++/* Legacy wrapper */ ++void qman_p_poll(struct qman_portal *p) ++{ ++#ifdef CONFIG_FSL_DPA_PORTAL_SHARE ++ if (unlikely(p->sharing_redirect)) ++ return; ++#endif ++ if ((~p->irq_sources) & QM_PIRQ_SLOW) { ++ if (!(p->slowpoll--)) { ++ u32 is = qm_isr_status_read(&p->p) & ~p->irq_sources; ++ u32 active = __poll_portal_slow(p, is); ++ if (active) { ++ qm_isr_status_clear(&p->p, active); ++ p->slowpoll = SLOW_POLL_BUSY; ++ } else ++ p->slowpoll = SLOW_POLL_IDLE; ++ } ++ } ++ if ((~p->irq_sources) & QM_PIRQ_DQRI) ++ __poll_portal_fast(p, CONFIG_FSL_QMAN_POLL_LIMIT); ++} ++EXPORT_SYMBOL(qman_p_poll); ++ ++void qman_poll(void) ++{ ++ struct qman_portal *p = get_poll_portal(); ++ qman_p_poll(p); ++ put_poll_portal(); ++} ++EXPORT_SYMBOL(qman_poll); ++ ++void qman_p_stop_dequeues(struct qman_portal *p) ++{ ++ qman_stop_dequeues_ex(p); ++} ++EXPORT_SYMBOL(qman_p_stop_dequeues); ++ ++void qman_stop_dequeues(void) ++{ ++ struct qman_portal *p = get_affine_portal(); ++ qman_p_stop_dequeues(p); ++ put_affine_portal(); ++} ++EXPORT_SYMBOL(qman_stop_dequeues); ++ ++void qman_p_start_dequeues(struct qman_portal *p) ++{ ++ unsigned long irqflags __maybe_unused; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ DPA_ASSERT(p->dqrr_disable_ref > 0); ++ if (!(--p->dqrr_disable_ref)) ++ qm_dqrr_set_maxfill(&p->p, DQRR_MAXFILL); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++} ++EXPORT_SYMBOL(qman_p_start_dequeues); ++ ++void qman_start_dequeues(void) ++{ ++ struct qman_portal *p = get_affine_portal(); ++ qman_p_start_dequeues(p); ++ put_affine_portal(); ++} ++EXPORT_SYMBOL(qman_start_dequeues); ++ ++void qman_p_static_dequeue_add(struct qman_portal *p, u32 pools) ++{ ++ unsigned long irqflags __maybe_unused; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ pools &= p->config->public_cfg.pools; ++ p->sdqcr |= pools; ++ qm_dqrr_sdqcr_set(&p->p, p->sdqcr); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++} ++EXPORT_SYMBOL(qman_p_static_dequeue_add); ++ ++void qman_static_dequeue_add(u32 pools) ++{ ++ struct qman_portal *p = get_affine_portal(); ++ qman_p_static_dequeue_add(p, pools); ++ put_affine_portal(); ++} ++EXPORT_SYMBOL(qman_static_dequeue_add); ++ ++void qman_p_static_dequeue_del(struct qman_portal *p, u32 pools) ++{ ++ unsigned long irqflags __maybe_unused; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ pools &= p->config->public_cfg.pools; ++ p->sdqcr &= ~pools; ++ qm_dqrr_sdqcr_set(&p->p, p->sdqcr); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++} ++EXPORT_SYMBOL(qman_p_static_dequeue_del); ++ ++void qman_static_dequeue_del(u32 pools) ++{ ++ struct qman_portal *p = get_affine_portal(); ++ qman_p_static_dequeue_del(p, pools); ++ put_affine_portal(); ++} ++EXPORT_SYMBOL(qman_static_dequeue_del); ++ ++u32 qman_p_static_dequeue_get(struct qman_portal *p) ++{ ++ return p->sdqcr; ++} ++EXPORT_SYMBOL(qman_p_static_dequeue_get); ++ ++u32 qman_static_dequeue_get(void) ++{ ++ struct qman_portal *p = get_affine_portal(); ++ u32 ret = qman_p_static_dequeue_get(p); ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_static_dequeue_get); ++ ++void qman_p_dca(struct qman_portal *p, struct qm_dqrr_entry *dq, ++ int park_request) ++{ ++ qm_dqrr_cdc_consume_1ptr(&p->p, dq, park_request); ++} ++EXPORT_SYMBOL(qman_p_dca); ++ ++void qman_dca(struct qm_dqrr_entry *dq, int park_request) ++{ ++ struct qman_portal *p = get_affine_portal(); ++ qman_p_dca(p, dq, park_request); ++ put_affine_portal(); ++} ++EXPORT_SYMBOL(qman_dca); ++ ++/*******************/ ++/* Frame queue API */ ++/*******************/ ++ ++static const char *mcr_result_str(u8 result) ++{ ++ switch (result) { ++ case QM_MCR_RESULT_NULL: ++ return "QM_MCR_RESULT_NULL"; ++ case QM_MCR_RESULT_OK: ++ return "QM_MCR_RESULT_OK"; ++ case QM_MCR_RESULT_ERR_FQID: ++ return "QM_MCR_RESULT_ERR_FQID"; ++ case QM_MCR_RESULT_ERR_FQSTATE: ++ return "QM_MCR_RESULT_ERR_FQSTATE"; ++ case QM_MCR_RESULT_ERR_NOTEMPTY: ++ return "QM_MCR_RESULT_ERR_NOTEMPTY"; ++ case QM_MCR_RESULT_PENDING: ++ return "QM_MCR_RESULT_PENDING"; ++ case QM_MCR_RESULT_ERR_BADCOMMAND: ++ return "QM_MCR_RESULT_ERR_BADCOMMAND"; ++ } ++ return ""; ++} ++ ++int qman_create_fq(u32 fqid, u32 flags, struct qman_fq *fq) ++{ ++ struct qm_fqd fqd; ++ struct qm_mcr_queryfq_np np; ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ ++ if (flags & QMAN_FQ_FLAG_DYNAMIC_FQID) { ++ int ret = qman_alloc_fqid(&fqid); ++ if (ret) ++ return ret; ++ } ++ spin_lock_init(&fq->fqlock); ++ fq->fqid = fqid; ++ fq->flags = flags; ++ fq->state = qman_fq_state_oos; ++ fq->cgr_groupid = 0; ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ if (unlikely(find_empty_fq_table_entry(&fq->key, fq))) ++ return -ENOMEM; ++#endif ++ if (!(flags & QMAN_FQ_FLAG_AS_IS) || (flags & QMAN_FQ_FLAG_NO_MODIFY)) ++ return 0; ++ /* Everything else is AS_IS support */ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ mcc = qm_mc_start(&p->p); ++ mcc->queryfq.fqid = fqid; ++ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYFQ); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYFQ); ++ if (mcr->result != QM_MCR_RESULT_OK) { ++ pr_err("QUERYFQ failed: %s\n", mcr_result_str(mcr->result)); ++ goto err; ++ } ++ fqd = mcr->queryfq.fqd; ++ mcc = qm_mc_start(&p->p); ++ mcc->queryfq_np.fqid = fqid; ++ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYFQ_NP); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYFQ_NP); ++ if (mcr->result != QM_MCR_RESULT_OK) { ++ pr_err("QUERYFQ_NP failed: %s\n", mcr_result_str(mcr->result)); ++ goto err; ++ } ++ np = mcr->queryfq_np; ++ /* Phew, have queryfq and queryfq_np results, stitch together ++ * the FQ object from those. */ ++ fq->cgr_groupid = fqd.cgid; ++ switch (np.state & QM_MCR_NP_STATE_MASK) { ++ case QM_MCR_NP_STATE_OOS: ++ break; ++ case QM_MCR_NP_STATE_RETIRED: ++ fq->state = qman_fq_state_retired; ++ if (np.frm_cnt) ++ fq_set(fq, QMAN_FQ_STATE_NE); ++ break; ++ case QM_MCR_NP_STATE_TEN_SCHED: ++ case QM_MCR_NP_STATE_TRU_SCHED: ++ case QM_MCR_NP_STATE_ACTIVE: ++ fq->state = qman_fq_state_sched; ++ if (np.state & QM_MCR_NP_STATE_R) ++ fq_set(fq, QMAN_FQ_STATE_CHANGING); ++ break; ++ case QM_MCR_NP_STATE_PARKED: ++ fq->state = qman_fq_state_parked; ++ break; ++ default: ++ DPA_ASSERT(NULL == "invalid FQ state"); ++ } ++ if (fqd.fq_ctrl & QM_FQCTRL_CGE) ++ fq->state |= QMAN_FQ_STATE_CGR_EN; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return 0; ++err: ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (flags & QMAN_FQ_FLAG_DYNAMIC_FQID) ++ qman_release_fqid(fqid); ++ return -EIO; ++} ++EXPORT_SYMBOL(qman_create_fq); ++ ++void qman_destroy_fq(struct qman_fq *fq, u32 flags __maybe_unused) ++{ ++ ++ /* We don't need to lock the FQ as it is a pre-condition that the FQ be ++ * quiesced. Instead, run some checks. */ ++ switch (fq->state) { ++ case qman_fq_state_parked: ++ DPA_ASSERT(flags & QMAN_FQ_DESTROY_PARKED); ++ case qman_fq_state_oos: ++ if (fq_isset(fq, QMAN_FQ_FLAG_DYNAMIC_FQID)) ++ qman_release_fqid(fq->fqid); ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ clear_fq_table_entry(fq->key); ++#endif ++ return; ++ default: ++ break; ++ } ++ DPA_ASSERT(NULL == "qman_free_fq() on unquiesced FQ!"); ++} ++EXPORT_SYMBOL(qman_destroy_fq); ++ ++u32 qman_fq_fqid(struct qman_fq *fq) ++{ ++ return fq->fqid; ++} ++EXPORT_SYMBOL(qman_fq_fqid); ++ ++void qman_fq_state(struct qman_fq *fq, enum qman_fq_state *state, u32 *flags) ++{ ++ if (state) ++ *state = fq->state; ++ if (flags) ++ *flags = fq->flags; ++} ++EXPORT_SYMBOL(qman_fq_state); ++ ++int qman_init_fq(struct qman_fq *fq, u32 flags, struct qm_mcc_initfq *opts) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res, myverb = (flags & QMAN_INITFQ_FLAG_SCHED) ? ++ QM_MCC_VERB_INITFQ_SCHED : QM_MCC_VERB_INITFQ_PARKED; ++ ++ if ((fq->state != qman_fq_state_oos) && ++ (fq->state != qman_fq_state_parked)) ++ return -EINVAL; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (unlikely(fq_isset(fq, QMAN_FQ_FLAG_NO_MODIFY))) ++ return -EINVAL; ++#endif ++ if (opts && (opts->we_mask & QM_INITFQ_WE_OAC)) { ++ /* And can't be set at the same time as TDTHRESH */ ++ if (opts->we_mask & QM_INITFQ_WE_TDTHRESH) ++ return -EINVAL; ++ } ++ /* Issue an INITFQ_[PARKED|SCHED] management command */ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ FQLOCK(fq); ++ if (unlikely((fq_isset(fq, QMAN_FQ_STATE_CHANGING)) || ++ ((fq->state != qman_fq_state_oos) && ++ (fq->state != qman_fq_state_parked)))) { ++ FQUNLOCK(fq); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return -EBUSY; ++ } ++ mcc = qm_mc_start(&p->p); ++ if (opts) ++ mcc->initfq = *opts; ++ mcc->initfq.fqid = fq->fqid; ++ mcc->initfq.count = 0; ++ /* If the FQ does *not* have the TO_DCPORTAL flag, contextB is set as a ++ * demux pointer. Otherwise, the caller-provided value is allowed to ++ * stand, don't overwrite it. */ ++ if (fq_isclear(fq, QMAN_FQ_FLAG_TO_DCPORTAL)) { ++ dma_addr_t phys_fq; ++ mcc->initfq.we_mask |= QM_INITFQ_WE_CONTEXTB; ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ mcc->initfq.fqd.context_b = fq->key; ++#else ++ mcc->initfq.fqd.context_b = (u32)(uintptr_t)fq; ++#endif ++ /* and the physical address - NB, if the user wasn't trying to ++ * set CONTEXTA, clear the stashing settings. */ ++ if (!(mcc->initfq.we_mask & QM_INITFQ_WE_CONTEXTA)) { ++ mcc->initfq.we_mask |= QM_INITFQ_WE_CONTEXTA; ++ memset(&mcc->initfq.fqd.context_a, 0, ++ sizeof(mcc->initfq.fqd.context_a)); ++ } else { ++ phys_fq = dma_map_single(&p->pdev->dev, fq, sizeof(*fq), ++ DMA_TO_DEVICE); ++ qm_fqd_stashing_set64(&mcc->initfq.fqd, phys_fq); ++ } ++ } ++ if (flags & QMAN_INITFQ_FLAG_LOCAL) { ++ mcc->initfq.fqd.dest.channel = p->config->public_cfg.channel; ++ if (!(mcc->initfq.we_mask & QM_INITFQ_WE_DESTWQ)) { ++ mcc->initfq.we_mask |= QM_INITFQ_WE_DESTWQ; ++ mcc->initfq.fqd.dest.wq = 4; ++ } ++ } ++ qm_mc_commit(&p->p, myverb); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == myverb); ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ FQUNLOCK(fq); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return -EIO; ++ } ++ if (opts) { ++ if (opts->we_mask & QM_INITFQ_WE_FQCTRL) { ++ if (opts->fqd.fq_ctrl & QM_FQCTRL_CGE) ++ fq_set(fq, QMAN_FQ_STATE_CGR_EN); ++ else ++ fq_clear(fq, QMAN_FQ_STATE_CGR_EN); ++ } ++ if (opts->we_mask & QM_INITFQ_WE_CGID) ++ fq->cgr_groupid = opts->fqd.cgid; ++ } ++ fq->state = (flags & QMAN_INITFQ_FLAG_SCHED) ? ++ qman_fq_state_sched : qman_fq_state_parked; ++ FQUNLOCK(fq); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return 0; ++} ++EXPORT_SYMBOL(qman_init_fq); ++ ++int qman_schedule_fq(struct qman_fq *fq) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ int ret = 0; ++ u8 res; ++ ++ if (fq->state != qman_fq_state_parked) ++ return -EINVAL; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (unlikely(fq_isset(fq, QMAN_FQ_FLAG_NO_MODIFY))) ++ return -EINVAL; ++#endif ++ /* Issue a ALTERFQ_SCHED management command */ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ FQLOCK(fq); ++ if (unlikely((fq_isset(fq, QMAN_FQ_STATE_CHANGING)) || ++ (fq->state != qman_fq_state_parked))) { ++ ret = -EBUSY; ++ goto out; ++ } ++ mcc = qm_mc_start(&p->p); ++ mcc->alterfq.fqid = fq->fqid; ++ qm_mc_commit(&p->p, QM_MCC_VERB_ALTER_SCHED); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_SCHED); ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ ret = -EIO; ++ goto out; ++ } ++ fq->state = qman_fq_state_sched; ++out: ++ FQUNLOCK(fq); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_schedule_fq); ++ ++int qman_retire_fq(struct qman_fq *fq, u32 *flags) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ int rval; ++ u8 res; ++ ++ if ((fq->state != qman_fq_state_parked) && ++ (fq->state != qman_fq_state_sched)) ++ return -EINVAL; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (unlikely(fq_isset(fq, QMAN_FQ_FLAG_NO_MODIFY))) ++ return -EINVAL; ++#endif ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ FQLOCK(fq); ++ if (unlikely((fq_isset(fq, QMAN_FQ_STATE_CHANGING)) || ++ (fq->state == qman_fq_state_retired) || ++ (fq->state == qman_fq_state_oos))) { ++ rval = -EBUSY; ++ goto out; ++ } ++ rval = table_push_fq(p, fq); ++ if (rval) ++ goto out; ++ mcc = qm_mc_start(&p->p); ++ mcc->alterfq.fqid = fq->fqid; ++ qm_mc_commit(&p->p, QM_MCC_VERB_ALTER_RETIRE); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_RETIRE); ++ res = mcr->result; ++ /* "Elegant" would be to treat OK/PENDING the same way; set CHANGING, ++ * and defer the flags until FQRNI or FQRN (respectively) show up. But ++ * "Friendly" is to process OK immediately, and not set CHANGING. We do ++ * friendly, otherwise the caller doesn't necessarily have a fully ++ * "retired" FQ on return even if the retirement was immediate. However ++ * this does mean some code duplication between here and ++ * fq_state_change(). */ ++ if (likely(res == QM_MCR_RESULT_OK)) { ++ rval = 0; ++ /* Process 'fq' right away, we'll ignore FQRNI */ ++ if (mcr->alterfq.fqs & QM_MCR_FQS_NOTEMPTY) ++ fq_set(fq, QMAN_FQ_STATE_NE); ++ if (mcr->alterfq.fqs & QM_MCR_FQS_ORLPRESENT) ++ fq_set(fq, QMAN_FQ_STATE_ORL); ++ else ++ table_del_fq(p, fq); ++ if (flags) ++ *flags = fq->flags; ++ fq->state = qman_fq_state_retired; ++ if (fq->cb.fqs) { ++ /* Another issue with supporting "immediate" retirement ++ * is that we're forced to drop FQRNIs, because by the ++ * time they're seen it may already be "too late" (the ++ * fq may have been OOS'd and free()'d already). But if ++ * the upper layer wants a callback whether it's ++ * immediate or not, we have to fake a "MR" entry to ++ * look like an FQRNI... */ ++ struct qm_mr_entry msg; ++ msg.verb = QM_MR_VERB_FQRNI; ++ msg.fq.fqs = mcr->alterfq.fqs; ++ msg.fq.fqid = fq->fqid; ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ msg.fq.contextB = fq->key; ++#else ++ msg.fq.contextB = (u32)(uintptr_t)fq; ++#endif ++ fq->cb.fqs(p, fq, &msg); ++ } ++ } else if (res == QM_MCR_RESULT_PENDING) { ++ rval = 1; ++ fq_set(fq, QMAN_FQ_STATE_CHANGING); ++ } else { ++ rval = -EIO; ++ table_del_fq(p, fq); ++ } ++out: ++ FQUNLOCK(fq); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return rval; ++} ++EXPORT_SYMBOL(qman_retire_fq); ++ ++int qman_oos_fq(struct qman_fq *fq) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ int ret = 0; ++ u8 res; ++ ++ if (fq->state != qman_fq_state_retired) ++ return -EINVAL; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (unlikely(fq_isset(fq, QMAN_FQ_FLAG_NO_MODIFY))) ++ return -EINVAL; ++#endif ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ FQLOCK(fq); ++ if (unlikely((fq_isset(fq, QMAN_FQ_STATE_BLOCKOOS)) || ++ (fq->state != qman_fq_state_retired))) { ++ ret = -EBUSY; ++ goto out; ++ } ++ mcc = qm_mc_start(&p->p); ++ mcc->alterfq.fqid = fq->fqid; ++ qm_mc_commit(&p->p, QM_MCC_VERB_ALTER_OOS); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_OOS); ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ ret = -EIO; ++ goto out; ++ } ++ fq->state = qman_fq_state_oos; ++out: ++ FQUNLOCK(fq); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_oos_fq); ++ ++int qman_fq_flow_control(struct qman_fq *fq, int xon) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ int ret = 0; ++ u8 res; ++ u8 myverb; ++ ++ if ((fq->state == qman_fq_state_oos) || ++ (fq->state == qman_fq_state_retired) || ++ (fq->state == qman_fq_state_parked)) ++ return -EINVAL; ++ ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (unlikely(fq_isset(fq, QMAN_FQ_FLAG_NO_MODIFY))) ++ return -EINVAL; ++#endif ++ /* Issue a ALTER_FQXON or ALTER_FQXOFF management command */ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ FQLOCK(fq); ++ if (unlikely((fq_isset(fq, QMAN_FQ_STATE_CHANGING)) || ++ (fq->state == qman_fq_state_parked) || ++ (fq->state == qman_fq_state_oos) || ++ (fq->state == qman_fq_state_retired))) { ++ ret = -EBUSY; ++ goto out; ++ } ++ mcc = qm_mc_start(&p->p); ++ mcc->alterfq.fqid = fq->fqid; ++ mcc->alterfq.count = 0; ++ myverb = xon ? QM_MCC_VERB_ALTER_FQXON : QM_MCC_VERB_ALTER_FQXOFF; ++ ++ qm_mc_commit(&p->p, myverb); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == myverb); ++ ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ ret = -EIO; ++ goto out; ++ } ++out: ++ FQUNLOCK(fq); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_fq_flow_control); ++ ++int qman_query_fq(struct qman_fq *fq, struct qm_fqd *fqd) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ mcc = qm_mc_start(&p->p); ++ mcc->queryfq.fqid = fq->fqid; ++ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYFQ); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ); ++ res = mcr->result; ++ if (res == QM_MCR_RESULT_OK) ++ *fqd = mcr->queryfq.fqd; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (res != QM_MCR_RESULT_OK) ++ return -EIO; ++ return 0; ++} ++EXPORT_SYMBOL(qman_query_fq); ++ ++int qman_query_fq_np(struct qman_fq *fq, struct qm_mcr_queryfq_np *np) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ mcc = qm_mc_start(&p->p); ++ mcc->queryfq.fqid = fq->fqid; ++ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYFQ_NP); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ_NP); ++ res = mcr->result; ++ if (res == QM_MCR_RESULT_OK) ++ *np = mcr->queryfq_np; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (res == QM_MCR_RESULT_ERR_FQID) ++ return -ERANGE; ++ else if (res != QM_MCR_RESULT_OK) ++ return -EIO; ++ return 0; ++} ++EXPORT_SYMBOL(qman_query_fq_np); ++ ++int qman_query_wq(u8 query_dedicated, struct qm_mcr_querywq *wq) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ u8 res, myverb; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ myverb = (query_dedicated) ? QM_MCR_VERB_QUERYWQ_DEDICATED : ++ QM_MCR_VERB_QUERYWQ; ++ mcc = qm_mc_start(&p->p); ++ mcc->querywq.channel.id = wq->channel.id; ++ qm_mc_commit(&p->p, myverb); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == myverb); ++ res = mcr->result; ++ if (res == QM_MCR_RESULT_OK) ++ *wq = mcr->querywq; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("QUERYWQ failed: %s\n", mcr_result_str(res)); ++ return -EIO; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(qman_query_wq); ++ ++int qman_testwrite_cgr(struct qman_cgr *cgr, u64 i_bcnt, ++ struct qm_mcr_cgrtestwrite *result) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ mcc = qm_mc_start(&p->p); ++ mcc->cgrtestwrite.cgid = cgr->cgrid; ++ mcc->cgrtestwrite.i_bcnt_hi = (u8)(i_bcnt >> 32); ++ mcc->cgrtestwrite.i_bcnt_lo = (u32)i_bcnt; ++ qm_mc_commit(&p->p, QM_MCC_VERB_CGRTESTWRITE); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_CGRTESTWRITE); ++ res = mcr->result; ++ if (res == QM_MCR_RESULT_OK) ++ *result = mcr->cgrtestwrite; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CGR TEST WRITE failed: %s\n", mcr_result_str(res)); ++ return -EIO; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(qman_testwrite_cgr); ++ ++int qman_query_cgr(struct qman_cgr *cgr, struct qm_mcr_querycgr *cgrd) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ mcc = qm_mc_start(&p->p); ++ mcc->querycgr.cgid = cgr->cgrid; ++ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYCGR); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYCGR); ++ res = mcr->result; ++ if (res == QM_MCR_RESULT_OK) ++ *cgrd = mcr->querycgr; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("QUERY_CGR failed: %s\n", mcr_result_str(res)); ++ return -EIO; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(qman_query_cgr); ++ ++int qman_query_congestion(struct qm_mcr_querycongestion *congestion) ++{ ++ struct qm_mc_result *mcr; ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ qm_mc_start(&p->p); ++ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYCONGESTION); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_MCC_VERB_QUERYCONGESTION); ++ res = mcr->result; ++ if (res == QM_MCR_RESULT_OK) ++ *congestion = mcr->querycongestion; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("QUERY_CONGESTION failed: %s\n", mcr_result_str(res)); ++ return -EIO; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(qman_query_congestion); ++ ++/* internal function used as a wait_event() expression */ ++static int set_p_vdqcr(struct qman_portal *p, struct qman_fq *fq, u32 vdqcr) ++{ ++ unsigned long irqflags __maybe_unused; ++ int ret = -EBUSY; ++ PORTAL_IRQ_LOCK(p, irqflags); ++ if (!p->vdqcr_owned) { ++ FQLOCK(fq); ++ if (fq_isset(fq, QMAN_FQ_STATE_VDQCR)) ++ goto escape; ++ fq_set(fq, QMAN_FQ_STATE_VDQCR); ++ FQUNLOCK(fq); ++ p->vdqcr_owned = fq; ++ ret = 0; ++ } ++escape: ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ if (!ret) ++ qm_dqrr_vdqcr_set(&p->p, vdqcr); ++ return ret; ++} ++ ++static int set_vdqcr(struct qman_portal **p, struct qman_fq *fq, u32 vdqcr) ++{ ++ int ret; ++ *p = get_affine_portal(); ++ ret = set_p_vdqcr(*p, fq, vdqcr); ++ put_affine_portal(); ++ return ret; ++} ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++static int wait_p_vdqcr_start(struct qman_portal *p, struct qman_fq *fq, ++ u32 vdqcr, u32 flags) ++{ ++ int ret = 0; ++ if (flags & QMAN_VOLATILE_FLAG_WAIT_INT) ++ ret = wait_event_interruptible(affine_queue, ++ !(ret = set_p_vdqcr(p, fq, vdqcr))); ++ else ++ wait_event(affine_queue, !(ret = set_p_vdqcr(p, fq, vdqcr))); ++ return ret; ++} ++ ++static int wait_vdqcr_start(struct qman_portal **p, struct qman_fq *fq, ++ u32 vdqcr, u32 flags) ++{ ++ int ret = 0; ++ if (flags & QMAN_VOLATILE_FLAG_WAIT_INT) ++ ret = wait_event_interruptible(affine_queue, ++ !(ret = set_vdqcr(p, fq, vdqcr))); ++ else ++ wait_event(affine_queue, !(ret = set_vdqcr(p, fq, vdqcr))); ++ return ret; ++} ++#endif ++ ++int qman_p_volatile_dequeue(struct qman_portal *p, struct qman_fq *fq, ++ u32 flags __maybe_unused, u32 vdqcr) ++{ ++ int ret; ++ ++ if ((fq->state != qman_fq_state_parked) && ++ (fq->state != qman_fq_state_retired)) ++ return -EINVAL; ++ if (vdqcr & QM_VDQCR_FQID_MASK) ++ return -EINVAL; ++ if (fq_isset(fq, QMAN_FQ_STATE_VDQCR)) ++ return -EBUSY; ++ vdqcr = (vdqcr & ~QM_VDQCR_FQID_MASK) | fq->fqid; ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & QMAN_VOLATILE_FLAG_WAIT) ++ ret = wait_p_vdqcr_start(p, fq, vdqcr, flags); ++ else ++#endif ++ ret = set_p_vdqcr(p, fq, vdqcr); ++ if (ret) ++ return ret; ++ /* VDQCR is set */ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & QMAN_VOLATILE_FLAG_FINISH) { ++ if (flags & QMAN_VOLATILE_FLAG_WAIT_INT) ++ /* NB: don't propagate any error - the caller wouldn't ++ * know whether the VDQCR was issued or not. A signal ++ * could arrive after returning anyway, so the caller ++ * can check signal_pending() if that's an issue. */ ++ wait_event_interruptible(affine_queue, ++ !fq_isset(fq, QMAN_FQ_STATE_VDQCR)); ++ else ++ wait_event(affine_queue, ++ !fq_isset(fq, QMAN_FQ_STATE_VDQCR)); ++ } ++#endif ++ return 0; ++} ++EXPORT_SYMBOL(qman_p_volatile_dequeue); ++ ++int qman_volatile_dequeue(struct qman_fq *fq, u32 flags __maybe_unused, ++ u32 vdqcr) ++{ ++ struct qman_portal *p; ++ int ret; ++ ++ if ((fq->state != qman_fq_state_parked) && ++ (fq->state != qman_fq_state_retired)) ++ return -EINVAL; ++ if (vdqcr & QM_VDQCR_FQID_MASK) ++ return -EINVAL; ++ if (fq_isset(fq, QMAN_FQ_STATE_VDQCR)) ++ return -EBUSY; ++ vdqcr = (vdqcr & ~QM_VDQCR_FQID_MASK) | fq->fqid; ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & QMAN_VOLATILE_FLAG_WAIT) ++ ret = wait_vdqcr_start(&p, fq, vdqcr, flags); ++ else ++#endif ++ ret = set_vdqcr(&p, fq, vdqcr); ++ if (ret) ++ return ret; ++ /* VDQCR is set */ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & QMAN_VOLATILE_FLAG_FINISH) { ++ if (flags & QMAN_VOLATILE_FLAG_WAIT_INT) ++ /* NB: don't propagate any error - the caller wouldn't ++ * know whether the VDQCR was issued or not. A signal ++ * could arrive after returning anyway, so the caller ++ * can check signal_pending() if that's an issue. */ ++ wait_event_interruptible(affine_queue, ++ !fq_isset(fq, QMAN_FQ_STATE_VDQCR)); ++ else ++ wait_event(affine_queue, ++ !fq_isset(fq, QMAN_FQ_STATE_VDQCR)); ++ } ++#endif ++ return 0; ++} ++EXPORT_SYMBOL(qman_volatile_dequeue); ++ ++static noinline void update_eqcr_ci(struct qman_portal *p, u8 avail) ++{ ++ if (avail) ++ qm_eqcr_cce_prefetch(&p->p); ++ else ++ qm_eqcr_cce_update(&p->p); ++} ++ ++int qman_eqcr_is_empty(void) ++{ ++ unsigned long irqflags __maybe_unused; ++ struct qman_portal *p = get_affine_portal(); ++ u8 avail; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ update_eqcr_ci(p, 0); ++ avail = qm_eqcr_get_fill(&p->p); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return avail == 0; ++} ++EXPORT_SYMBOL(qman_eqcr_is_empty); ++ ++void qman_set_dc_ern(qman_cb_dc_ern handler, int affine) ++{ ++ if (affine) { ++ unsigned long irqflags __maybe_unused; ++ struct qman_portal *p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ p->cb_dc_ern = handler; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ } else ++ cb_dc_ern = handler; ++} ++EXPORT_SYMBOL(qman_set_dc_ern); ++ ++static inline struct qm_eqcr_entry *try_p_eq_start(struct qman_portal *p, ++ unsigned long *irqflags __maybe_unused, ++ struct qman_fq *fq, ++ const struct qm_fd *fd, ++ u32 flags) ++{ ++ struct qm_eqcr_entry *eq; ++ u8 avail; ++ PORTAL_IRQ_LOCK(p, (*irqflags)); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) && ++ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) { ++ if (p->eqci_owned) { ++ PORTAL_IRQ_UNLOCK(p, (*irqflags)); ++ return NULL; ++ } ++ p->eqci_owned = fq; ++ } ++#endif ++ if (p->use_eqcr_ci_stashing) { ++ /* ++ * The stashing case is easy, only update if we need to in ++ * order to try and liberate ring entries. ++ */ ++ eq = qm_eqcr_start_stash(&p->p); ++ } else { ++ /* ++ * The non-stashing case is harder, need to prefetch ahead of ++ * time. ++ */ ++ avail = qm_eqcr_get_avail(&p->p); ++ if (avail < 2) ++ update_eqcr_ci(p, avail); ++ eq = qm_eqcr_start_no_stash(&p->p); ++ } ++ ++ if (unlikely(!eq)) { ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) && ++ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) ++ p->eqci_owned = NULL; ++#endif ++ PORTAL_IRQ_UNLOCK(p, (*irqflags)); ++ return NULL; ++ } ++ if (flags & QMAN_ENQUEUE_FLAG_DCA) ++ eq->dca = QM_EQCR_DCA_ENABLE | ++ ((flags & QMAN_ENQUEUE_FLAG_DCA_PARK) ? ++ QM_EQCR_DCA_PARK : 0) | ++ ((flags >> 8) & QM_EQCR_DCA_IDXMASK); ++ eq->fqid = fq->fqid; ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ eq->tag = fq->key; ++#else ++ eq->tag = (u32)(uintptr_t)fq; ++#endif ++ eq->fd = *fd; ++ return eq; ++} ++ ++static inline struct qm_eqcr_entry *try_eq_start(struct qman_portal **p, ++ unsigned long *irqflags __maybe_unused, ++ struct qman_fq *fq, ++ const struct qm_fd *fd, ++ u32 flags) ++{ ++ struct qm_eqcr_entry *eq; ++ *p = get_affine_portal(); ++ eq = try_p_eq_start(*p, irqflags, fq, fd, flags); ++ if (!eq) ++ put_affine_portal(); ++ return eq; ++} ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++static noinline struct qm_eqcr_entry *__wait_eq_start(struct qman_portal **p, ++ unsigned long *irqflags __maybe_unused, ++ struct qman_fq *fq, ++ const struct qm_fd *fd, ++ u32 flags) ++{ ++ struct qm_eqcr_entry *eq = try_eq_start(p, irqflags, fq, fd, flags); ++ if (!eq) ++ qm_eqcr_set_ithresh(&(*p)->p, EQCR_ITHRESH); ++ return eq; ++} ++static noinline struct qm_eqcr_entry *wait_eq_start(struct qman_portal **p, ++ unsigned long *irqflags __maybe_unused, ++ struct qman_fq *fq, ++ const struct qm_fd *fd, ++ u32 flags) ++{ ++ struct qm_eqcr_entry *eq; ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT) ++ /* NB: return NULL if signal occurs before completion. Signal ++ * can occur during return. Caller must check for signal */ ++ wait_event_interruptible(affine_queue, ++ (eq = __wait_eq_start(p, irqflags, fq, fd, flags))); ++ else ++ wait_event(affine_queue, ++ (eq = __wait_eq_start(p, irqflags, fq, fd, flags))); ++ return eq; ++} ++static noinline struct qm_eqcr_entry *__wait_p_eq_start(struct qman_portal *p, ++ unsigned long *irqflags __maybe_unused, ++ struct qman_fq *fq, ++ const struct qm_fd *fd, ++ u32 flags) ++{ ++ struct qm_eqcr_entry *eq = try_p_eq_start(p, irqflags, fq, fd, flags); ++ if (!eq) ++ qm_eqcr_set_ithresh(&p->p, EQCR_ITHRESH); ++ return eq; ++} ++static noinline struct qm_eqcr_entry *wait_p_eq_start(struct qman_portal *p, ++ unsigned long *irqflags __maybe_unused, ++ struct qman_fq *fq, ++ const struct qm_fd *fd, ++ u32 flags) ++{ ++ struct qm_eqcr_entry *eq; ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT) ++ /* NB: return NULL if signal occurs before completion. Signal ++ * can occur during return. Caller must check for signal */ ++ wait_event_interruptible(affine_queue, ++ (eq = __wait_p_eq_start(p, irqflags, fq, fd, flags))); ++ else ++ wait_event(affine_queue, ++ (eq = __wait_p_eq_start(p, irqflags, fq, fd, flags))); ++ return eq; ++} ++#endif ++ ++int qman_p_enqueue(struct qman_portal *p, struct qman_fq *fq, ++ const struct qm_fd *fd, u32 flags) ++{ ++ struct qm_eqcr_entry *eq; ++ unsigned long irqflags __maybe_unused; ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT) ++ eq = wait_p_eq_start(p, &irqflags, fq, fd, flags); ++ else ++#endif ++ eq = try_p_eq_start(p, &irqflags, fq, fd, flags); ++ if (!eq) ++ return -EBUSY; ++ /* Note: QM_EQCR_VERB_INTERRUPT == QMAN_ENQUEUE_FLAG_WAIT_SYNC */ ++ qm_eqcr_pvb_commit(&p->p, QM_EQCR_VERB_CMD_ENQUEUE | ++ (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT))); ++ /* Factor the below out, it's used from qman_enqueue_orp() too */ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) && ++ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) { ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT) ++ /* NB: return success even if signal occurs before ++ * condition is true. pvb_commit guarantees success */ ++ wait_event_interruptible(affine_queue, ++ (p->eqci_owned != fq)); ++ else ++ wait_event(affine_queue, (p->eqci_owned != fq)); ++ } ++#endif ++ return 0; ++} ++EXPORT_SYMBOL(qman_p_enqueue); ++ ++int qman_enqueue(struct qman_fq *fq, const struct qm_fd *fd, u32 flags) ++{ ++ struct qman_portal *p; ++ struct qm_eqcr_entry *eq; ++ unsigned long irqflags __maybe_unused; ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT) ++ eq = wait_eq_start(&p, &irqflags, fq, fd, flags); ++ else ++#endif ++ eq = try_eq_start(&p, &irqflags, fq, fd, flags); ++ if (!eq) ++ return -EBUSY; ++ /* Note: QM_EQCR_VERB_INTERRUPT == QMAN_ENQUEUE_FLAG_WAIT_SYNC */ ++ qm_eqcr_pvb_commit(&p->p, QM_EQCR_VERB_CMD_ENQUEUE | ++ (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT))); ++ /* Factor the below out, it's used from qman_enqueue_orp() too */ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) && ++ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) { ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT) ++ /* NB: return success even if signal occurs before ++ * condition is true. pvb_commit guarantees success */ ++ wait_event_interruptible(affine_queue, ++ (p->eqci_owned != fq)); ++ else ++ wait_event(affine_queue, (p->eqci_owned != fq)); ++ } ++#endif ++ return 0; ++} ++EXPORT_SYMBOL(qman_enqueue); ++ ++int qman_p_enqueue_orp(struct qman_portal *p, struct qman_fq *fq, ++ const struct qm_fd *fd, u32 flags, ++ struct qman_fq *orp, u16 orp_seqnum) ++{ ++ struct qm_eqcr_entry *eq; ++ unsigned long irqflags __maybe_unused; ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT) ++ eq = wait_p_eq_start(p, &irqflags, fq, fd, flags); ++ else ++#endif ++ eq = try_p_eq_start(p, &irqflags, fq, fd, flags); ++ if (!eq) ++ return -EBUSY; ++ /* Process ORP-specifics here */ ++ if (flags & QMAN_ENQUEUE_FLAG_NLIS) ++ orp_seqnum |= QM_EQCR_SEQNUM_NLIS; ++ else { ++ orp_seqnum &= ~QM_EQCR_SEQNUM_NLIS; ++ if (flags & QMAN_ENQUEUE_FLAG_NESN) ++ orp_seqnum |= QM_EQCR_SEQNUM_NESN; ++ else ++ /* No need to check 4 QMAN_ENQUEUE_FLAG_HOLE */ ++ orp_seqnum &= ~QM_EQCR_SEQNUM_NESN; ++ } ++ eq->seqnum = orp_seqnum; ++ eq->orp = orp->fqid; ++ /* Note: QM_EQCR_VERB_INTERRUPT == QMAN_ENQUEUE_FLAG_WAIT_SYNC */ ++ qm_eqcr_pvb_commit(&p->p, QM_EQCR_VERB_ORP | ++ ((flags & (QMAN_ENQUEUE_FLAG_HOLE | QMAN_ENQUEUE_FLAG_NESN)) ? ++ 0 : QM_EQCR_VERB_CMD_ENQUEUE) | ++ (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT))); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) && ++ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) { ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT) ++ /* NB: return success even if signal occurs before ++ * condition is true. pvb_commit guarantees success */ ++ wait_event_interruptible(affine_queue, ++ (p->eqci_owned != fq)); ++ else ++ wait_event(affine_queue, (p->eqci_owned != fq)); ++ } ++#endif ++ return 0; ++} ++EXPORT_SYMBOL(qman_p_enqueue_orp); ++ ++int qman_enqueue_orp(struct qman_fq *fq, const struct qm_fd *fd, u32 flags, ++ struct qman_fq *orp, u16 orp_seqnum) ++{ ++ struct qman_portal *p; ++ struct qm_eqcr_entry *eq; ++ unsigned long irqflags __maybe_unused; ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT) ++ eq = wait_eq_start(&p, &irqflags, fq, fd, flags); ++ else ++#endif ++ eq = try_eq_start(&p, &irqflags, fq, fd, flags); ++ if (!eq) ++ return -EBUSY; ++ /* Process ORP-specifics here */ ++ if (flags & QMAN_ENQUEUE_FLAG_NLIS) ++ orp_seqnum |= QM_EQCR_SEQNUM_NLIS; ++ else { ++ orp_seqnum &= ~QM_EQCR_SEQNUM_NLIS; ++ if (flags & QMAN_ENQUEUE_FLAG_NESN) ++ orp_seqnum |= QM_EQCR_SEQNUM_NESN; ++ else ++ /* No need to check 4 QMAN_ENQUEUE_FLAG_HOLE */ ++ orp_seqnum &= ~QM_EQCR_SEQNUM_NESN; ++ } ++ eq->seqnum = orp_seqnum; ++ eq->orp = orp->fqid; ++ /* Note: QM_EQCR_VERB_INTERRUPT == QMAN_ENQUEUE_FLAG_WAIT_SYNC */ ++ qm_eqcr_pvb_commit(&p->p, QM_EQCR_VERB_ORP | ++ ((flags & (QMAN_ENQUEUE_FLAG_HOLE | QMAN_ENQUEUE_FLAG_NESN)) ? ++ 0 : QM_EQCR_VERB_CMD_ENQUEUE) | ++ (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT))); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) && ++ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) { ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT) ++ /* NB: return success even if signal occurs before ++ * condition is true. pvb_commit guarantees success */ ++ wait_event_interruptible(affine_queue, ++ (p->eqci_owned != fq)); ++ else ++ wait_event(affine_queue, (p->eqci_owned != fq)); ++ } ++#endif ++ return 0; ++} ++EXPORT_SYMBOL(qman_enqueue_orp); ++ ++int qman_p_enqueue_precommit(struct qman_portal *p, struct qman_fq *fq, ++ const struct qm_fd *fd, u32 flags, ++ qman_cb_precommit cb, void *cb_arg) ++{ ++ struct qm_eqcr_entry *eq; ++ unsigned long irqflags __maybe_unused; ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT) ++ eq = wait_p_eq_start(p, &irqflags, fq, fd, flags); ++ else ++#endif ++ eq = try_p_eq_start(p, &irqflags, fq, fd, flags); ++ if (!eq) ++ return -EBUSY; ++ /* invoke user supplied callback function before writing commit verb */ ++ if (cb(cb_arg)) { ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ return -EINVAL; ++ } ++ /* Note: QM_EQCR_VERB_INTERRUPT == QMAN_ENQUEUE_FLAG_WAIT_SYNC */ ++ qm_eqcr_pvb_commit(&p->p, QM_EQCR_VERB_CMD_ENQUEUE | ++ (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT))); ++ /* Factor the below out, it's used from qman_enqueue_orp() too */ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) && ++ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) { ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT) ++ /* NB: return success even if signal occurs before ++ * condition is true. pvb_commit guarantees success */ ++ wait_event_interruptible(affine_queue, ++ (p->eqci_owned != fq)); ++ else ++ wait_event(affine_queue, (p->eqci_owned != fq)); ++ } ++#endif ++ return 0; ++} ++EXPORT_SYMBOL(qman_p_enqueue_precommit); ++ ++int qman_enqueue_precommit(struct qman_fq *fq, const struct qm_fd *fd, ++ u32 flags, qman_cb_precommit cb, void *cb_arg) ++{ ++ struct qman_portal *p; ++ struct qm_eqcr_entry *eq; ++ unsigned long irqflags __maybe_unused; ++ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT) ++ eq = wait_eq_start(&p, &irqflags, fq, fd, flags); ++ else ++#endif ++ eq = try_eq_start(&p, &irqflags, fq, fd, flags); ++ if (!eq) ++ return -EBUSY; ++ /* invoke user supplied callback function before writing commit verb */ ++ if (cb(cb_arg)) { ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return -EINVAL; ++ } ++ /* Note: QM_EQCR_VERB_INTERRUPT == QMAN_ENQUEUE_FLAG_WAIT_SYNC */ ++ qm_eqcr_pvb_commit(&p->p, QM_EQCR_VERB_CMD_ENQUEUE | ++ (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT))); ++ /* Factor the below out, it's used from qman_enqueue_orp() too */ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) && ++ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) { ++ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT) ++ /* NB: return success even if signal occurs before ++ * condition is true. pvb_commit guarantees success */ ++ wait_event_interruptible(affine_queue, ++ (p->eqci_owned != fq)); ++ else ++ wait_event(affine_queue, (p->eqci_owned != fq)); ++ } ++#endif ++ return 0; ++} ++EXPORT_SYMBOL(qman_enqueue_precommit); ++ ++int qman_modify_cgr(struct qman_cgr *cgr, u32 flags, ++ struct qm_mcc_initcgr *opts) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ u8 verb = QM_MCC_VERB_MODIFYCGR; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ mcc = qm_mc_start(&p->p); ++ if (opts) ++ mcc->initcgr = *opts; ++ mcc->initcgr.cgid = cgr->cgrid; ++ if (flags & QMAN_CGR_FLAG_USE_INIT) ++ verb = QM_MCC_VERB_INITCGR; ++ qm_mc_commit(&p->p, verb); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == verb); ++ res = mcr->result; ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return (res == QM_MCR_RESULT_OK) ? 0 : -EIO; ++} ++EXPORT_SYMBOL(qman_modify_cgr); ++ ++#define TARG_MASK(n) (0x80000000 >> (n->config->public_cfg.channel - \ ++ QM_CHANNEL_SWPORTAL0)) ++#define TARG_DCP_MASK(n) (0x80000000 >> (10 + n)) ++#define PORTAL_IDX(n) (n->config->public_cfg.channel - QM_CHANNEL_SWPORTAL0) ++ ++static u8 qman_cgr_cpus[__CGR_NUM]; ++ ++int qman_create_cgr(struct qman_cgr *cgr, u32 flags, ++ struct qm_mcc_initcgr *opts) ++{ ++ unsigned long irqflags __maybe_unused; ++ struct qm_mcr_querycgr cgr_state; ++ struct qm_mcc_initcgr local_opts; ++ int ret; ++ struct qman_portal *p; ++ ++ /* We have to check that the provided CGRID is within the limits of the ++ * data-structures, for obvious reasons. However we'll let h/w take ++ * care of determining whether it's within the limits of what exists on ++ * the SoC. */ ++ if (cgr->cgrid >= __CGR_NUM) ++ return -EINVAL; ++ ++ preempt_disable(); ++ p = get_affine_portal(); ++ qman_cgr_cpus[cgr->cgrid] = smp_processor_id(); ++ preempt_enable(); ++ ++ memset(&local_opts, 0, sizeof(struct qm_mcc_initcgr)); ++ cgr->chan = p->config->public_cfg.channel; ++ spin_lock_irqsave(&p->cgr_lock, irqflags); ++ ++ /* if no opts specified, just add it to the list */ ++ if (!opts) ++ goto add_list; ++ ++ ret = qman_query_cgr(cgr, &cgr_state); ++ if (ret) ++ goto release_lock; ++ if (opts) ++ local_opts = *opts; ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) ++ local_opts.cgr.cscn_targ_upd_ctrl = ++ QM_CGR_TARG_UDP_CTRL_WRITE_BIT | PORTAL_IDX(p); ++ else ++ /* Overwrite TARG */ ++ local_opts.cgr.cscn_targ = cgr_state.cgr.cscn_targ | ++ TARG_MASK(p); ++ local_opts.we_mask |= QM_CGR_WE_CSCN_TARG; ++ ++ /* send init if flags indicate so */ ++ if (opts && (flags & QMAN_CGR_FLAG_USE_INIT)) ++ ret = qman_modify_cgr(cgr, QMAN_CGR_FLAG_USE_INIT, &local_opts); ++ else ++ ret = qman_modify_cgr(cgr, 0, &local_opts); ++ if (ret) ++ goto release_lock; ++add_list: ++ list_add(&cgr->node, &p->cgr_cbs); ++ ++ /* Determine if newly added object requires its callback to be called */ ++ ret = qman_query_cgr(cgr, &cgr_state); ++ if (ret) { ++ /* we can't go back, so proceed and return success, but screen ++ * and wail to the log file */ ++ pr_crit("CGR HW state partially modified\n"); ++ ret = 0; ++ goto release_lock; ++ } ++ if (cgr->cb && cgr_state.cgr.cscn_en && qman_cgrs_get(&p->cgrs[1], ++ cgr->cgrid)) ++ cgr->cb(p, cgr, 1); ++release_lock: ++ spin_unlock_irqrestore(&p->cgr_lock, irqflags); ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_create_cgr); ++ ++int qman_create_cgr_to_dcp(struct qman_cgr *cgr, u32 flags, u16 dcp_portal, ++ struct qm_mcc_initcgr *opts) ++{ ++ unsigned long irqflags __maybe_unused; ++ struct qm_mcc_initcgr local_opts; ++ struct qm_mcr_querycgr cgr_state; ++ int ret; ++ ++ /* We have to check that the provided CGRID is within the limits of the ++ * data-structures, for obvious reasons. However we'll let h/w take ++ * care of determining whether it's within the limits of what exists on ++ * the SoC. ++ */ ++ if (cgr->cgrid >= __CGR_NUM) ++ return -EINVAL; ++ ++ ret = qman_query_cgr(cgr, &cgr_state); ++ if (ret) ++ return ret; ++ ++ memset(&local_opts, 0, sizeof(struct qm_mcc_initcgr)); ++ if (opts) ++ local_opts = *opts; ++ ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) ++ local_opts.cgr.cscn_targ_upd_ctrl = ++ QM_CGR_TARG_UDP_CTRL_WRITE_BIT | ++ QM_CGR_TARG_UDP_CTRL_DCP | dcp_portal; ++ else ++ local_opts.cgr.cscn_targ = cgr_state.cgr.cscn_targ | ++ TARG_DCP_MASK(dcp_portal); ++ local_opts.we_mask |= QM_CGR_WE_CSCN_TARG; ++ ++ /* send init if flags indicate so */ ++ if (opts && (flags & QMAN_CGR_FLAG_USE_INIT)) ++ ret = qman_modify_cgr(cgr, QMAN_CGR_FLAG_USE_INIT, ++ &local_opts); ++ else ++ ret = qman_modify_cgr(cgr, 0, &local_opts); ++ ++ return ret; ++} ++EXPORT_SYMBOL(qman_create_cgr_to_dcp); ++ ++int qman_delete_cgr(struct qman_cgr *cgr) ++{ ++ unsigned long irqflags __maybe_unused; ++ struct qm_mcr_querycgr cgr_state; ++ struct qm_mcc_initcgr local_opts; ++ int ret = 0; ++ struct qman_cgr *i; ++ struct qman_portal *p = get_affine_portal(); ++ ++ if (cgr->chan != p->config->public_cfg.channel) { ++ pr_crit("Attempting to delete cgr from different portal " ++ "than it was create: create 0x%x, delete 0x%x\n", ++ cgr->chan, p->config->public_cfg.channel); ++ ret = -EINVAL; ++ goto put_portal; ++ } ++ memset(&local_opts, 0, sizeof(struct qm_mcc_initcgr)); ++ spin_lock_irqsave(&p->cgr_lock, irqflags); ++ list_del(&cgr->node); ++ /* ++ * If there are no other CGR objects for this CGRID in the list, update ++ * CSCN_TARG accordingly ++ */ ++ list_for_each_entry(i, &p->cgr_cbs, node) ++ if ((i->cgrid == cgr->cgrid) && i->cb) ++ goto release_lock; ++ ret = qman_query_cgr(cgr, &cgr_state); ++ if (ret) { ++ /* add back to the list */ ++ list_add(&cgr->node, &p->cgr_cbs); ++ goto release_lock; ++ } ++ /* Overwrite TARG */ ++ local_opts.we_mask = QM_CGR_WE_CSCN_TARG; ++ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) ++ local_opts.cgr.cscn_targ_upd_ctrl = PORTAL_IDX(p); ++ else ++ local_opts.cgr.cscn_targ = cgr_state.cgr.cscn_targ & ++ ~(TARG_MASK(p)); ++ ret = qman_modify_cgr(cgr, 0, &local_opts); ++ if (ret) ++ /* add back to the list */ ++ list_add(&cgr->node, &p->cgr_cbs); ++release_lock: ++ spin_unlock_irqrestore(&p->cgr_lock, irqflags); ++put_portal: ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_delete_cgr); ++ ++struct cgr_comp { ++ struct qman_cgr *cgr; ++ struct completion completion; ++}; ++ ++static int qman_delete_cgr_thread(void *p) ++{ ++ struct cgr_comp *cgr_comp = (struct cgr_comp *)p; ++ int res; ++ ++ res = qman_delete_cgr((struct qman_cgr *)cgr_comp->cgr); ++ complete(&cgr_comp->completion); ++ ++ return res; ++} ++ ++void qman_delete_cgr_safe(struct qman_cgr *cgr) ++{ ++ struct task_struct *thread; ++ struct cgr_comp cgr_comp; ++ ++ preempt_disable(); ++ if (qman_cgr_cpus[cgr->cgrid] != smp_processor_id()) { ++ init_completion(&cgr_comp.completion); ++ cgr_comp.cgr = cgr; ++ thread = kthread_create(qman_delete_cgr_thread, &cgr_comp, ++ "cgr_del"); ++ ++ if (likely(!IS_ERR(thread))) { ++ kthread_bind(thread, qman_cgr_cpus[cgr->cgrid]); ++ wake_up_process(thread); ++ wait_for_completion(&cgr_comp.completion); ++ preempt_enable(); ++ return; ++ } ++ } ++ qman_delete_cgr(cgr); ++ preempt_enable(); ++} ++EXPORT_SYMBOL(qman_delete_cgr_safe); ++ ++int qm_get_clock(u64 *clock_hz) ++{ ++ if (!qman_clk) { ++ pr_warn("Qman clock speed is unknown\n"); ++ return -EINVAL; ++ } ++ *clock_hz = (u64)qman_clk; ++ return 0; ++} ++EXPORT_SYMBOL(qm_get_clock); ++ ++int qm_set_clock(u64 clock_hz) ++{ ++ if (qman_clk) ++ return -1; ++ qman_clk = (u32)clock_hz; ++ return 0; ++} ++EXPORT_SYMBOL(qm_set_clock); ++ ++/* CEETM management command */ ++static int qman_ceetm_configure_lfqmt(struct qm_mcc_ceetm_lfqmt_config *opts) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->lfqmt_config = *opts; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_LFQMT_CONFIG); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_LFQMT_CONFIG); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: CONFIGURE LFQMT failed\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++static int qman_ceetm_query_lfqmt(int lfqid, ++ struct qm_mcr_ceetm_lfqmt_query *lfqmt_query) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->lfqmt_query.lfqid = lfqid; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_LFQMT_QUERY); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_LFQMT_QUERY); ++ res = mcr->result; ++ if (res == QM_MCR_RESULT_OK) ++ *lfqmt_query = mcr->lfqmt_query; ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: QUERY LFQMT failed\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++static int qman_ceetm_configure_cq(struct qm_mcc_ceetm_cq_config *opts) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->cq_config = *opts; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CQ_CONFIG); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ res = mcr->result; ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_CQ_CONFIG); ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: CONFIGURE CQ failed\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++int qman_ceetm_query_cq(unsigned int cqid, unsigned int dcpid, ++ struct qm_mcr_ceetm_cq_query *cq_query) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->cq_query.cqid = cqid; ++ mcc->cq_query.dcpid = dcpid; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CQ_QUERY); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ res = mcr->result; ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_CQ_QUERY); ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: QUERY CQ failed\n"); ++ return -EIO; ++ } ++ ++ *cq_query = mcr->cq_query; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_query_cq); ++ ++static int qman_ceetm_configure_dct(struct qm_mcc_ceetm_dct_config *opts) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->dct_config = *opts; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_DCT_CONFIG); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_DCT_CONFIG); ++ res = mcr->result; ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: CONFIGURE DCT failed\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++static int qman_ceetm_query_dct(struct qm_mcc_ceetm_dct_query *opts, ++ struct qm_mcr_ceetm_dct_query *dct_query) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p = get_affine_portal(); ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->dct_query = *opts; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_DCT_QUERY); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_DCT_QUERY); ++ res = mcr->result; ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: QUERY DCT failed\n"); ++ return -EIO; ++ } ++ ++ *dct_query = mcr->dct_query; ++ return 0; ++} ++ ++static int qman_ceetm_configure_class_scheduler( ++ struct qm_mcc_ceetm_class_scheduler_config *opts) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->csch_config = *opts; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CLASS_SCHEDULER_CONFIG); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_CLASS_SCHEDULER_CONFIG); ++ res = mcr->result; ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: CONFIGURE CLASS SCHEDULER failed\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++static int qman_ceetm_query_class_scheduler(struct qm_ceetm_channel *channel, ++ struct qm_mcr_ceetm_class_scheduler_query *query) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->csch_query.cqcid = channel->idx; ++ mcc->csch_query.dcpid = channel->dcp_idx; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CLASS_SCHEDULER_QUERY); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_CLASS_SCHEDULER_QUERY); ++ res = mcr->result; ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: QUERY CLASS SCHEDULER failed\n"); ++ return -EIO; ++ } ++ *query = mcr->csch_query; ++ return 0; ++} ++ ++static int qman_ceetm_configure_mapping_shaper_tcfc( ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config *opts) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->mst_config = *opts; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_MAPPING_SHAPER_TCFC_CONFIG); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_MAPPING_SHAPER_TCFC_CONFIG); ++ res = mcr->result; ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: CONFIGURE CHANNEL MAPPING failed\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++static int qman_ceetm_query_mapping_shaper_tcfc( ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query *opts, ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query *response) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->mst_query = *opts; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_MAPPING_SHAPER_TCFC_QUERY); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_MAPPING_SHAPER_TCFC_QUERY); ++ res = mcr->result; ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: QUERY CHANNEL MAPPING failed\n"); ++ return -EIO; ++ } ++ ++ *response = mcr->mst_query; ++ return 0; ++} ++ ++static int qman_ceetm_configure_ccgr(struct qm_mcc_ceetm_ccgr_config *opts) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->ccgr_config = *opts; ++ ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CCGR_CONFIG); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_CCGR_CONFIG); ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: CONFIGURE CCGR failed\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++int qman_ceetm_query_ccgr(struct qm_mcc_ceetm_ccgr_query *ccgr_query, ++ struct qm_mcr_ceetm_ccgr_query *response) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->ccgr_query = *ccgr_query; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CCGR_QUERY); ++ ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_CCGR_QUERY); ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: QUERY CCGR failed\n"); ++ return -EIO; ++ } ++ *response = mcr->ccgr_query; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_query_ccgr); ++ ++static int qman_ceetm_cq_peek_pop_xsfdrread(struct qm_ceetm_cq *cq, ++ u8 command_type, u16 xsfdr, ++ struct qm_mcr_ceetm_cq_peek_pop_xsfdrread *cq_ppxr) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ switch (command_type) { ++ case 0: ++ case 1: ++ mcc->cq_ppxr.cqid = (cq->parent->idx << 4) | cq->idx; ++ break; ++ case 2: ++ mcc->cq_ppxr.xsfdr = xsfdr; ++ break; ++ default: ++ break; ++ } ++ mcc->cq_ppxr.ct = command_type; ++ mcc->cq_ppxr.dcpid = cq->parent->dcp_idx; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CQ_PEEK_POP_XFDRREAD); ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_CQ_PEEK_POP_XFDRREAD); ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: CQ PEEK/POP/XSFDR READ failed\n"); ++ return -EIO; ++ } ++ *cq_ppxr = mcr->cq_ppxr; ++ return 0; ++} ++ ++static int qman_ceetm_query_statistics(u16 cid, ++ enum qm_dc_portal dcp_idx, ++ u16 command_type, ++ struct qm_mcr_ceetm_statistics_query *query_result) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->stats_query_write.cid = cid; ++ mcc->stats_query_write.dcpid = dcp_idx; ++ mcc->stats_query_write.ct = command_type; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_STATISTICS_QUERY_WRITE); ++ ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_STATISTICS_QUERY_WRITE); ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: STATISTICS QUERY failed\n"); ++ return -EIO; ++ } ++ *query_result = mcr->stats_query; ++ return 0; ++} ++ ++static int qman_ceetm_write_statistics(u16 cid, enum qm_dc_portal dcp_idx, ++ u16 command_type, u64 frame_count, u64 byte_count) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ mcc->stats_query_write.cid = cid; ++ mcc->stats_query_write.dcpid = dcp_idx; ++ mcc->stats_query_write.ct = command_type; ++ mcc->stats_query_write.frm_cnt = frame_count; ++ mcc->stats_query_write.byte_cnt = byte_count; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_STATISTICS_QUERY_WRITE); ++ ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_STATISTICS_QUERY_WRITE); ++ ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ ++ res = mcr->result; ++ if (res != QM_MCR_RESULT_OK) { ++ pr_err("CEETM: STATISTICS WRITE failed\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++int qman_ceetm_bps2tokenrate(u64 bps, struct qm_ceetm_rate *token_rate, ++ int rounding) ++{ ++ u16 pres; ++ u64 temp; ++ u64 qman_freq; ++ int ret; ++ ++ /* Read PRES from CEET_CFG_PRES register */ ++ ret = qman_ceetm_get_prescaler(&pres); ++ if (ret) ++ return -EINVAL; ++ ++ ret = qm_get_clock(&qman_freq); ++ if (ret) ++ return -EINVAL; ++ ++ /* token-rate = bytes-per-second * update-reference-period ++ * ++ * Where token-rate is N/8192 for a integer N, and ++ * update-reference-period is (2^22)/(PRES*QHz), where PRES ++ * is the prescalar value and QHz is the QMan clock frequency. ++ * So: ++ * ++ * token-rate = (byte-per-second*2^22)/PRES*QHZ) ++ * ++ * Converting to bits-per-second gives; ++ * ++ * token-rate = (bps*2^19) / (PRES*QHZ) ++ * N = (bps*2^32) / (PRES*QHz) ++ * ++ * And to avoid 64-bit overflow if 'bps' is larger than 4Gbps ++ * (yet minimise rounding error if 'bps' is small), we reorganise ++ * the formula to use two 16-bit shifts rather than 1 32-bit shift. ++ * N = (((bps*2^16)/PRES)*2^16)/QHz ++ */ ++ temp = ROUNDING((bps << 16), pres, rounding); ++ temp = ROUNDING((temp << 16), qman_freq, rounding); ++ token_rate->whole = temp >> 13; ++ token_rate->fraction = temp & (((u64)1 << 13) - 1); ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_bps2tokenrate); ++ ++int qman_ceetm_tokenrate2bps(const struct qm_ceetm_rate *token_rate, u64 *bps, ++ int rounding) ++{ ++ u16 pres; ++ u64 temp; ++ u64 qman_freq; ++ int ret; ++ ++ /* Read PRES from CEET_CFG_PRES register */ ++ ret = qman_ceetm_get_prescaler(&pres); ++ if (ret) ++ return -EINVAL; ++ ++ ret = qm_get_clock(&qman_freq); ++ if (ret) ++ return -EINVAL; ++ ++ /* bytes-per-second = token-rate / update-reference-period ++ * ++ * where "token-rate" is N/8192 for an integer N, and ++ * "update-reference-period" is (2^22)/(PRES*QHz), where PRES is ++ * the prescalar value and QHz is the QMan clock frequency. So; ++ * ++ * bytes-per-second = (N/8192) / (4194304/PRES*QHz) ++ * = N*PRES*QHz / (4194304*8192) ++ * = N*PRES*QHz / (2^35) ++ * ++ * Converting to bits-per-second gives; ++ * ++ * bps = N*PRES*QHZ / (2^32) ++ * ++ * Note, the numerator has a maximum width of 72 bits! So to ++ * avoid 64-bit overflow errors, we calculate PRES*QHZ (maximum ++ * width 48 bits) divided by 2^9 (reducing to maximum 39 bits), before ++ * multiplying by N (goes to maximum of 63 bits). ++ * ++ * temp = PRES*QHZ / (2^16) ++ * kbps = temp*N / (2^16) ++ */ ++ temp = ROUNDING(qman_freq * pres, (u64)1 << 16 , rounding); ++ temp *= ((token_rate->whole << 13) + token_rate->fraction); ++ *bps = ROUNDING(temp, (u64)(1) << 16, rounding); ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_tokenrate2bps); ++ ++int qman_ceetm_sp_claim(struct qm_ceetm_sp **sp, enum qm_dc_portal dcp_idx, ++ unsigned int sp_idx) ++{ ++ struct qm_ceetm_sp *p; ++ ++ DPA_ASSERT((dcp_idx == qm_dc_portal_fman0) || ++ (dcp_idx == qm_dc_portal_fman1)); ++ ++ if ((sp_idx < qman_ceetms[dcp_idx].sp_range[0]) || ++ (sp_idx > (qman_ceetms[dcp_idx].sp_range[0] + ++ qman_ceetms[dcp_idx].sp_range[1]))) { ++ pr_err("Sub-portal index doesn't exist\n"); ++ return -EINVAL; ++ } ++ ++ list_for_each_entry(p, &qman_ceetms[dcp_idx].sub_portals, node) { ++ if ((p->idx == sp_idx) && (p->is_claimed == 0)) { ++ p->is_claimed = 1; ++ *sp = p; ++ return 0; ++ } ++ } ++ pr_err("The sub-portal#%d is not available!\n", sp_idx); ++ return -ENODEV; ++} ++EXPORT_SYMBOL(qman_ceetm_sp_claim); ++ ++int qman_ceetm_sp_release(struct qm_ceetm_sp *sp) ++{ ++ struct qm_ceetm_sp *p; ++ ++ if (sp->lni && sp->lni->is_claimed == 1) { ++ pr_err("The dependency of sub-portal has not been released!\n"); ++ return -EBUSY; ++ } ++ ++ list_for_each_entry(p, &qman_ceetms[sp->dcp_idx].sub_portals, node) { ++ if (p->idx == sp->idx) { ++ p->is_claimed = 0; ++ p->lni = NULL; ++ } ++ } ++ /* Disable CEETM mode of this sub-portal */ ++ qman_sp_disable_ceetm_mode(sp->dcp_idx, sp->idx); ++ ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_sp_release); ++ ++int qman_ceetm_lni_claim(struct qm_ceetm_lni **lni, enum qm_dc_portal dcp_idx, ++ unsigned int lni_idx) ++{ ++ struct qm_ceetm_lni *p; ++ ++ if ((lni_idx < qman_ceetms[dcp_idx].lni_range[0]) || ++ (lni_idx > (qman_ceetms[dcp_idx].lni_range[0] + ++ qman_ceetms[dcp_idx].lni_range[1]))) { ++ pr_err("The lni index is out of range\n"); ++ return -EINVAL; ++ } ++ ++ list_for_each_entry(p, &qman_ceetms[dcp_idx].lnis, node) { ++ if ((p->idx == lni_idx) && (p->is_claimed == 0)) { ++ *lni = p; ++ p->is_claimed = 1; ++ return 0; ++ } ++ } ++ ++ pr_err("The LNI#%d is not available!\n", lni_idx); ++ return -EINVAL; ++} ++EXPORT_SYMBOL(qman_ceetm_lni_claim); ++ ++int qman_ceetm_lni_release(struct qm_ceetm_lni *lni) ++{ ++ struct qm_ceetm_lni *p; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ ++ if (!list_empty(&lni->channels)) { ++ pr_err("The LNI dependencies are not released!\n"); ++ return -EBUSY; ++ } ++ ++ list_for_each_entry(p, &qman_ceetms[lni->dcp_idx].lnis, node) { ++ if (p->idx == lni->idx) { ++ p->shaper_enable = 0; ++ p->shaper_couple = 0; ++ p->cr_token_rate.whole = 0; ++ p->cr_token_rate.fraction = 0; ++ p->er_token_rate.whole = 0; ++ p->er_token_rate.fraction = 0; ++ p->cr_token_bucket_limit = 0; ++ p->er_token_bucket_limit = 0; ++ p->is_claimed = 0; ++ } ++ } ++ config_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ config_opts.dcpid = lni->dcp_idx; ++ memset(&config_opts.shaper_config, 0, ++ sizeof(config_opts.shaper_config)); ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_lni_release); ++ ++int qman_ceetm_sp_set_lni(struct qm_ceetm_sp *sp, struct qm_ceetm_lni *lni) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ ++ config_opts.cid = CEETM_COMMAND_SP_MAPPING | sp->idx; ++ config_opts.dcpid = sp->dcp_idx; ++ config_opts.sp_mapping.map_lni_id = lni->idx; ++ sp->lni = lni; ++ ++ if (qman_ceetm_configure_mapping_shaper_tcfc(&config_opts)) ++ return -EINVAL; ++ ++ /* Enable CEETM mode for this sub-portal */ ++ return qman_sp_enable_ceetm_mode(sp->dcp_idx, sp->idx); ++} ++EXPORT_SYMBOL(qman_ceetm_sp_set_lni); ++ ++int qman_ceetm_sp_get_lni(struct qm_ceetm_sp *sp, unsigned int *lni_idx) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ ++ query_opts.cid = CEETM_COMMAND_SP_MAPPING | sp->idx; ++ query_opts.dcpid = sp->dcp_idx; ++ if (qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result)) { ++ pr_err("Can't get SP <-> LNI mapping\n"); ++ return -EINVAL; ++ } ++ *lni_idx = query_result.sp_mapping_query.map_lni_id; ++ sp->lni->idx = query_result.sp_mapping_query.map_lni_id; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_sp_get_lni); ++ ++int qman_ceetm_lni_enable_shaper(struct qm_ceetm_lni *lni, int coupled, ++ int oal) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ ++ lni->shaper_enable = 1; ++ lni->shaper_couple = coupled; ++ lni->oal = oal; ++ ++ config_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ config_opts.dcpid = lni->dcp_idx; ++ config_opts.shaper_config.cpl = (coupled << 7) | lni->oal; ++ config_opts.shaper_config.crtcr = (lni->cr_token_rate.whole << 13) | ++ lni->cr_token_rate.fraction; ++ config_opts.shaper_config.ertcr = (lni->er_token_rate.whole << 13) | ++ lni->er_token_rate.fraction; ++ config_opts.shaper_config.crtbl = lni->cr_token_bucket_limit; ++ config_opts.shaper_config.ertbl = lni->er_token_bucket_limit; ++ config_opts.shaper_config.mps = 60; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_lni_enable_shaper); ++ ++int qman_ceetm_lni_disable_shaper(struct qm_ceetm_lni *lni) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ ++ if (!lni->shaper_enable) { ++ pr_err("The shaper has been disabled\n"); ++ return -EINVAL; ++ } ++ ++ config_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ config_opts.dcpid = lni->dcp_idx; ++ config_opts.shaper_config.cpl = (lni->shaper_couple << 7) | lni->oal; ++ config_opts.shaper_config.crtbl = lni->cr_token_bucket_limit; ++ config_opts.shaper_config.ertbl = lni->er_token_bucket_limit; ++ /* Set CR/ER rate with all 1's to configure an infinite rate, thus ++ * disable the shaping. ++ */ ++ config_opts.shaper_config.crtcr = 0xFFFFFF; ++ config_opts.shaper_config.ertcr = 0xFFFFFF; ++ config_opts.shaper_config.mps = 60; ++ lni->shaper_enable = 0; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_lni_disable_shaper); ++ ++int qman_ceetm_lni_is_shaper_enabled(struct qm_ceetm_lni *lni) ++{ ++ return lni->shaper_enable; ++} ++EXPORT_SYMBOL(qman_ceetm_lni_is_shaper_enabled); ++ ++int qman_ceetm_lni_set_commit_rate(struct qm_ceetm_lni *lni, ++ const struct qm_ceetm_rate *token_rate, ++ u16 token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ lni->cr_token_rate.whole = token_rate->whole; ++ lni->cr_token_rate.fraction = token_rate->fraction; ++ lni->cr_token_bucket_limit = token_limit; ++ if (lni->shaper_enable) { ++ query_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ query_opts.dcpid = lni->dcp_idx; ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, ++ &query_result); ++ if (ret) { ++ pr_err("Fail to get current LNI shaper setting\n"); ++ return -EINVAL; ++ } ++ ++ config_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ config_opts.dcpid = lni->dcp_idx; ++ config_opts.shaper_config.crtcr = (token_rate->whole << 13) | ++ (token_rate->fraction); ++ config_opts.shaper_config.crtbl = token_limit; ++ config_opts.shaper_config.cpl = query_result.shaper_query.cpl; ++ config_opts.shaper_config.ertcr = ++ query_result.shaper_query.ertcr; ++ config_opts.shaper_config.ertbl = ++ query_result.shaper_query.ertbl; ++ config_opts.shaper_config.mps = query_result.shaper_query.mps; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++ } else { ++ return 0; ++ } ++} ++EXPORT_SYMBOL(qman_ceetm_lni_set_commit_rate); ++ ++int qman_ceetm_lni_set_commit_rate_bps(struct qm_ceetm_lni *lni, ++ u64 bps, ++ u16 token_limit) ++{ ++ struct qm_ceetm_rate token_rate; ++ int ret; ++ ++ ret = qman_ceetm_bps2tokenrate(bps, &token_rate, 0); ++ if (ret) { ++ pr_err("Can not convert bps to token rate\n"); ++ return -EINVAL; ++ } ++ ++ return qman_ceetm_lni_set_commit_rate(lni, &token_rate, token_limit); ++} ++EXPORT_SYMBOL(qman_ceetm_lni_set_commit_rate_bps); ++ ++int qman_ceetm_lni_get_commit_rate(struct qm_ceetm_lni *lni, ++ struct qm_ceetm_rate *token_rate, ++ u16 *token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ query_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ query_opts.dcpid = lni->dcp_idx; ++ ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret) { ++ pr_err("The LNI CR rate or limit is not set\n"); ++ return -EINVAL; ++ } ++ token_rate->whole = query_result.shaper_query.crtcr >> 13; ++ token_rate->fraction = query_result.shaper_query.crtcr & 0x1FFF; ++ *token_limit = query_result.shaper_query.crtbl; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_lni_get_commit_rate); ++ ++int qman_ceetm_lni_get_commit_rate_bps(struct qm_ceetm_lni *lni, ++ u64 *bps, u16 *token_limit) ++{ ++ struct qm_ceetm_rate token_rate; ++ int ret; ++ ++ ret = qman_ceetm_lni_get_commit_rate(lni, &token_rate, token_limit); ++ if (ret) { ++ pr_err("The LNI CR rate or limit is not available\n"); ++ return -EINVAL; ++ } ++ ++ return qman_ceetm_tokenrate2bps(&token_rate, bps, 0); ++} ++EXPORT_SYMBOL(qman_ceetm_lni_get_commit_rate_bps); ++ ++int qman_ceetm_lni_set_excess_rate(struct qm_ceetm_lni *lni, ++ const struct qm_ceetm_rate *token_rate, ++ u16 token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ lni->er_token_rate.whole = token_rate->whole; ++ lni->er_token_rate.fraction = token_rate->fraction; ++ lni->er_token_bucket_limit = token_limit; ++ if (lni->shaper_enable) { ++ query_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ query_opts.dcpid = lni->dcp_idx; ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, ++ &query_result); ++ if (ret) { ++ pr_err("Fail to get current LNI shaper setting\n"); ++ return -EINVAL; ++ } ++ ++ config_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ config_opts.dcpid = lni->dcp_idx; ++ config_opts.shaper_config.ertcr = ++ (token_rate->whole << 13) | (token_rate->fraction); ++ config_opts.shaper_config.ertbl = token_limit; ++ config_opts.shaper_config.cpl = query_result.shaper_query.cpl; ++ config_opts.shaper_config.crtcr = ++ query_result.shaper_query.crtcr; ++ config_opts.shaper_config.crtbl = ++ query_result.shaper_query.crtbl; ++ config_opts.shaper_config.mps = query_result.shaper_query.mps; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++ } else { ++ return 0; ++ } ++} ++EXPORT_SYMBOL(qman_ceetm_lni_set_excess_rate); ++ ++int qman_ceetm_lni_set_excess_rate_bps(struct qm_ceetm_lni *lni, ++ u64 bps, ++ u16 token_limit) ++{ ++ struct qm_ceetm_rate token_rate; ++ int ret; ++ ++ ret = qman_ceetm_bps2tokenrate(bps, &token_rate, 0); ++ if (ret) { ++ pr_err("Can not convert bps to token rate\n"); ++ return -EINVAL; ++ } ++ ++ return qman_ceetm_lni_set_excess_rate(lni, &token_rate, token_limit); ++} ++EXPORT_SYMBOL(qman_ceetm_lni_set_excess_rate_bps); ++ ++int qman_ceetm_lni_get_excess_rate(struct qm_ceetm_lni *lni, ++ struct qm_ceetm_rate *token_rate, ++ u16 *token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ query_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx; ++ query_opts.dcpid = lni->dcp_idx; ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret) { ++ pr_err("The LNI ER rate or limit is not set\n"); ++ return -EINVAL; ++ } ++ token_rate->whole = query_result.shaper_query.ertcr >> 13; ++ token_rate->fraction = query_result.shaper_query.ertcr & 0x1FFF; ++ *token_limit = query_result.shaper_query.ertbl; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_lni_get_excess_rate); ++ ++int qman_ceetm_lni_get_excess_rate_bps(struct qm_ceetm_lni *lni, ++ u64 *bps, u16 *token_limit) ++{ ++ struct qm_ceetm_rate token_rate; ++ int ret; ++ ++ ret = qman_ceetm_lni_get_excess_rate(lni, &token_rate, token_limit); ++ if (ret) { ++ pr_err("The LNI ER rate or limit is not available\n"); ++ return -EINVAL; ++ } ++ ++ return qman_ceetm_tokenrate2bps(&token_rate, bps, 0); ++} ++EXPORT_SYMBOL(qman_ceetm_lni_get_excess_rate_bps); ++ ++#define QMAN_CEETM_LNITCFCC_CQ_LEVEL_SHIFT(n) ((15 - n) * 4) ++#define QMAN_CEETM_LNITCFCC_ENABLE 0x8 ++int qman_ceetm_lni_set_tcfcc(struct qm_ceetm_lni *lni, ++ unsigned int cq_level, ++ int traffic_class) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ u64 lnitcfcc; ++ ++ if ((cq_level > 15) | (traffic_class > 7)) { ++ pr_err("The CQ or traffic class id is out of range\n"); ++ return -EINVAL; ++ } ++ ++ query_opts.cid = CEETM_COMMAND_TCFC | lni->idx; ++ query_opts.dcpid = lni->dcp_idx; ++ if (qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result)) { ++ pr_err("Fail to query tcfcc\n"); ++ return -EINVAL; ++ } ++ ++ lnitcfcc = query_result.tcfc_query.lnitcfcc; ++ if (traffic_class == -1) { ++ /* disable tcfc for this CQ */ ++ lnitcfcc &= ~((u64)QMAN_CEETM_LNITCFCC_ENABLE << ++ QMAN_CEETM_LNITCFCC_CQ_LEVEL_SHIFT(cq_level)); ++ } else { ++ lnitcfcc &= ~((u64)0xF << ++ QMAN_CEETM_LNITCFCC_CQ_LEVEL_SHIFT(cq_level)); ++ lnitcfcc |= ((u64)(QMAN_CEETM_LNITCFCC_ENABLE | ++ traffic_class)) << ++ QMAN_CEETM_LNITCFCC_CQ_LEVEL_SHIFT(cq_level); ++ } ++ config_opts.tcfc_config.lnitcfcc = lnitcfcc; ++ config_opts.cid = CEETM_COMMAND_TCFC | lni->idx; ++ config_opts.dcpid = lni->dcp_idx; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_lni_set_tcfcc); ++ ++#define QMAN_CEETM_LNITCFCC_TC_MASK 0x7 ++int qman_ceetm_lni_get_tcfcc(struct qm_ceetm_lni *lni, unsigned int cq_level, ++ int *traffic_class) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ u8 lnitcfcc; ++ ++ if (cq_level > 15) { ++ pr_err("the CQ level is out of range\n"); ++ return -EINVAL; ++ } ++ ++ query_opts.cid = CEETM_COMMAND_TCFC | lni->idx; ++ query_opts.dcpid = lni->dcp_idx; ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret) ++ return ret; ++ lnitcfcc = (u8)(query_result.tcfc_query.lnitcfcc >> ++ QMAN_CEETM_LNITCFCC_CQ_LEVEL_SHIFT(cq_level)); ++ if (lnitcfcc & QMAN_CEETM_LNITCFCC_ENABLE) ++ *traffic_class = lnitcfcc & QMAN_CEETM_LNITCFCC_TC_MASK; ++ else ++ *traffic_class = -1; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_lni_get_tcfcc); ++ ++#define QMAN_CEETM_ENABLE_CHANNEL_SHAPER 0x80 ++int qman_ceetm_channel_claim(struct qm_ceetm_channel **channel, ++ struct qm_ceetm_lni *lni) ++{ ++ struct qm_ceetm_channel *p; ++ u32 channel_idx; ++ int ret = 0; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ static u8 map; ++ ++ if (lni->dcp_idx == qm_dc_portal_fman0) { ++ ret = qman_alloc_ceetm0_channel(&channel_idx); ++ } else if (lni->dcp_idx == qm_dc_portal_fman1) { ++ ret = qman_alloc_ceetm1_channel(&channel_idx); ++ } else { ++ pr_err("dcp_idx %u does not correspond to a known fman in this driver\n", ++ lni->dcp_idx); ++ return -EINVAL; ++ } ++ ++ if (ret) { ++ pr_err("The is no channel available for LNI#%d\n", lni->idx); ++ return -ENODEV; ++ } ++ ++ p = kzalloc(sizeof(*p), GFP_KERNEL); ++ if (!p) ++ return -ENOMEM; ++ p->idx = channel_idx; ++ p->dcp_idx = lni->dcp_idx; ++ list_add_tail(&p->node, &lni->channels); ++ INIT_LIST_HEAD(&p->class_queues); ++ INIT_LIST_HEAD(&p->ccgs); ++ config_opts.cid = CEETM_COMMAND_CHANNEL_MAPPING | channel_idx; ++ config_opts.dcpid = lni->dcp_idx; ++ map = (u8)~QMAN_CEETM_ENABLE_CHANNEL_SHAPER; ++ map &= lni->idx; ++ config_opts.channel_mapping.map = map; ++ if (qman_ceetm_configure_mapping_shaper_tcfc(&config_opts)) { ++ pr_err("Can't map channel#%d for LNI#%d\n", ++ channel_idx, lni->idx); ++ return -EINVAL; ++ } ++ *channel = p; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_claim); ++ ++int qman_ceetm_channel_release(struct qm_ceetm_channel *channel) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ if (!list_empty(&channel->class_queues)) { ++ pr_err("CEETM channel#%d has class queue unreleased!\n", ++ channel->idx); ++ return -EBUSY; ++ } ++ if (!list_empty(&channel->ccgs)) { ++ pr_err("CEETM channel#%d has ccg unreleased!\n", ++ channel->idx); ++ return -EBUSY; ++ } ++ ++ /* channel->dcp_idx corresponds to known fman validation */ ++ if ((channel->dcp_idx != qm_dc_portal_fman0) && ++ (channel->dcp_idx != qm_dc_portal_fman1)) { ++ pr_err("dcp_idx %u does not correspond to a known fman in this driver\n", ++ channel->dcp_idx); ++ return -EINVAL; ++ } ++ ++ config_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ config_opts.dcpid = channel->dcp_idx; ++ memset(&config_opts.shaper_config, 0, ++ sizeof(config_opts.shaper_config)); ++ if (qman_ceetm_configure_mapping_shaper_tcfc(&config_opts)) { ++ pr_err("Can't reset channel shapping parameters\n"); ++ return -EINVAL; ++ } ++ ++ if (channel->dcp_idx == qm_dc_portal_fman0) { ++ qman_release_ceetm0_channelid(channel->idx); ++ } else if (channel->dcp_idx == qm_dc_portal_fman1) { ++ qman_release_ceetm1_channelid(channel->idx); ++ } else { ++ pr_err("dcp_idx %u does not correspond to a known fman in this driver\n", ++ channel->dcp_idx); ++ return -EINVAL; ++ } ++ list_del(&channel->node); ++ kfree(channel); ++ ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_release); ++ ++int qman_ceetm_channel_enable_shaper(struct qm_ceetm_channel *channel, ++ int coupled) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ u8 map; ++ ++ if (channel->shaper_enable == 1) { ++ pr_err("This channel shaper has been enabled!\n"); ++ return -EINVAL; ++ } ++ ++ channel->shaper_enable = 1; ++ channel->shaper_couple = coupled; ++ ++ query_opts.cid = (u16)(CEETM_COMMAND_CHANNEL_MAPPING | channel->idx); ++ query_opts.dcpid = (u8)channel->dcp_idx; ++ ++ if (qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result)) { ++ pr_err("Can't query channel mapping\n"); ++ return -EINVAL; ++ } ++ ++ map = query_result.channel_mapping_query.map; ++ map |= QMAN_CEETM_ENABLE_CHANNEL_SHAPER; ++ ++ config_opts.cid = CEETM_COMMAND_CHANNEL_MAPPING | channel->idx; ++ config_opts.dcpid = channel->dcp_idx; ++ config_opts.channel_mapping.map = map; ++ if (qman_ceetm_configure_mapping_shaper_tcfc(&config_opts)) { ++ pr_err("Can't enable shaper for channel #%d\n", ++ channel->idx); ++ return -EINVAL; ++ } ++ ++ config_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ config_opts.shaper_config.cpl = coupled << 7; ++ config_opts.shaper_config.crtcr = (channel->cr_token_rate.whole << 13) | ++ channel->cr_token_rate.fraction; ++ config_opts.shaper_config.ertcr = (channel->er_token_rate.whole << 13) | ++ channel->er_token_rate.fraction; ++ config_opts.shaper_config.crtbl = channel->cr_token_bucket_limit; ++ config_opts.shaper_config.ertbl = channel->er_token_bucket_limit; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_channel_enable_shaper); ++ ++int qman_ceetm_channel_disable_shaper(struct qm_ceetm_channel *channel) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ u8 map; ++ ++ query_opts.cid = CEETM_COMMAND_CHANNEL_MAPPING | channel->idx; ++ query_opts.dcpid = channel->dcp_idx; ++ ++ if (qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result)) { ++ pr_err("Can't query channel mapping\n"); ++ return -EINVAL; ++ } ++ ++ map = query_result.channel_mapping_query.map; ++ map &= ~QMAN_CEETM_ENABLE_CHANNEL_SHAPER; ++ ++ config_opts.cid = CEETM_COMMAND_CHANNEL_MAPPING | channel->idx; ++ config_opts.dcpid = channel->dcp_idx; ++ config_opts.channel_mapping.map = map; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_channel_disable_shaper); ++ ++int qman_ceetm_channel_is_shaper_enabled(struct qm_ceetm_channel *channel) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ u8 map; ++ ++ query_opts.cid = CEETM_COMMAND_CHANNEL_MAPPING | channel->idx; ++ query_opts.dcpid = channel->dcp_idx; ++ ++ if (qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result)) { ++ pr_err("Can't query channel mapping\n"); ++ return -EINVAL; ++ } ++ ++ map = query_result.channel_mapping_query.map; ++ return (map & QMAN_CEETM_ENABLE_CHANNEL_SHAPER) ? 1 : 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_is_shaper_enabled); ++ ++int qman_ceetm_channel_set_commit_rate(struct qm_ceetm_channel *channel, ++ const struct qm_ceetm_rate *token_rate, ++ u16 token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ query_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ query_opts.dcpid = channel->dcp_idx; ++ ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret) { ++ pr_err("Fail to get the current channel shaper setting\n"); ++ return -EINVAL; ++ } ++ ++ channel->cr_token_rate.whole = token_rate->whole; ++ channel->cr_token_rate.fraction = token_rate->fraction; ++ channel->cr_token_bucket_limit = token_limit; ++ config_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ config_opts.dcpid = channel->dcp_idx; ++ config_opts.shaper_config.crtcr = (token_rate->whole << 13) | ++ (token_rate->fraction); ++ config_opts.shaper_config.crtbl = token_limit; ++ config_opts.shaper_config.cpl = query_result.shaper_query.cpl; ++ config_opts.shaper_config.ertcr = query_result.shaper_query.ertcr; ++ config_opts.shaper_config.ertbl = query_result.shaper_query.ertbl; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_channel_set_commit_rate); ++ ++int qman_ceetm_channel_set_commit_rate_bps(struct qm_ceetm_channel *channel, ++ u64 bps, u16 token_limit) ++{ ++ struct qm_ceetm_rate token_rate; ++ int ret; ++ ++ ret = qman_ceetm_bps2tokenrate(bps, &token_rate, 0); ++ if (ret) { ++ pr_err("Can not convert bps to token rate\n"); ++ return -EINVAL; ++ } ++ return qman_ceetm_channel_set_commit_rate(channel, &token_rate, ++ token_limit); ++} ++EXPORT_SYMBOL(qman_ceetm_channel_set_commit_rate_bps); ++ ++int qman_ceetm_channel_get_commit_rate(struct qm_ceetm_channel *channel, ++ struct qm_ceetm_rate *token_rate, ++ u16 *token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ query_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ query_opts.dcpid = channel->dcp_idx; ++ ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret | !query_result.shaper_query.crtcr | ++ !query_result.shaper_query.crtbl) { ++ pr_err("The channel commit rate or limit is not set\n"); ++ return -EINVAL; ++ } ++ token_rate->whole = query_result.shaper_query.crtcr >> 13; ++ token_rate->fraction = query_result.shaper_query.crtcr & 0x1FFF; ++ *token_limit = query_result.shaper_query.crtbl; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_get_commit_rate); ++ ++int qman_ceetm_channel_get_commit_rate_bps(struct qm_ceetm_channel *channel, ++ u64 *bps, u16 *token_limit) ++{ ++ struct qm_ceetm_rate token_rate; ++ int ret; ++ ++ ret = qman_ceetm_channel_get_commit_rate(channel, &token_rate, ++ token_limit); ++ if (ret) { ++ pr_err("The channel CR rate or limit is not available\n"); ++ return -EINVAL; ++ } ++ ++ return qman_ceetm_tokenrate2bps(&token_rate, bps, 0); ++} ++EXPORT_SYMBOL(qman_ceetm_channel_get_commit_rate_bps); ++ ++int qman_ceetm_channel_set_excess_rate(struct qm_ceetm_channel *channel, ++ const struct qm_ceetm_rate *token_rate, ++ u16 token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ query_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ query_opts.dcpid = channel->dcp_idx; ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret) { ++ pr_err("Fail to get the current channel shaper setting\n"); ++ return -EINVAL; ++ } ++ ++ channel->er_token_rate.whole = token_rate->whole; ++ channel->er_token_rate.fraction = token_rate->fraction; ++ channel->er_token_bucket_limit = token_limit; ++ config_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ config_opts.dcpid = channel->dcp_idx; ++ config_opts.shaper_config.ertcr = ++ (token_rate->whole << 13) | (token_rate->fraction); ++ config_opts.shaper_config.ertbl = token_limit; ++ config_opts.shaper_config.cpl = query_result.shaper_query.cpl; ++ config_opts.shaper_config.crtcr = query_result.shaper_query.crtcr; ++ config_opts.shaper_config.crtbl = query_result.shaper_query.crtbl; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_channel_set_excess_rate); ++ ++int qman_ceetm_channel_set_excess_rate_bps(struct qm_ceetm_channel *channel, ++ u64 bps, u16 token_limit) ++{ ++ struct qm_ceetm_rate token_rate; ++ int ret; ++ ++ ret = qman_ceetm_bps2tokenrate(bps, &token_rate, 0); ++ if (ret) { ++ pr_err("Can not convert bps to token rate\n"); ++ return -EINVAL; ++ } ++ return qman_ceetm_channel_set_excess_rate(channel, &token_rate, ++ token_limit); ++} ++EXPORT_SYMBOL(qman_ceetm_channel_set_excess_rate_bps); ++ ++int qman_ceetm_channel_get_excess_rate(struct qm_ceetm_channel *channel, ++ struct qm_ceetm_rate *token_rate, ++ u16 *token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ query_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ query_opts.dcpid = channel->dcp_idx; ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret | !query_result.shaper_query.ertcr | ++ !query_result.shaper_query.ertbl) { ++ pr_err("The channel excess rate or limit is not set\n"); ++ return -EINVAL; ++ } ++ token_rate->whole = query_result.shaper_query.ertcr >> 13; ++ token_rate->fraction = query_result.shaper_query.ertcr & 0x1FFF; ++ *token_limit = query_result.shaper_query.ertbl; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_get_excess_rate); ++ ++int qman_ceetm_channel_get_excess_rate_bps(struct qm_ceetm_channel *channel, ++ u64 *bps, u16 *token_limit) ++{ ++ struct qm_ceetm_rate token_rate; ++ int ret; ++ ++ ret = qman_ceetm_channel_get_excess_rate(channel, &token_rate, ++ token_limit); ++ if (ret) { ++ pr_err("The channel ER rate or limit is not available\n"); ++ return -EINVAL; ++ } ++ ++ return qman_ceetm_tokenrate2bps(&token_rate, bps, 0); ++} ++EXPORT_SYMBOL(qman_ceetm_channel_get_excess_rate_bps); ++ ++int qman_ceetm_channel_set_weight(struct qm_ceetm_channel *channel, ++ u16 token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts; ++ ++ if (channel->shaper_enable) { ++ pr_err("This channel is a shaped one\n"); ++ return -EINVAL; ++ } ++ ++ channel->cr_token_bucket_limit = token_limit; ++ config_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ config_opts.dcpid = channel->dcp_idx; ++ config_opts.shaper_config.crtbl = token_limit; ++ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_channel_set_weight); ++ ++int qman_ceetm_channel_get_weight(struct qm_ceetm_channel *channel, ++ u16 *token_limit) ++{ ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result; ++ int ret; ++ ++ query_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx; ++ query_opts.dcpid = channel->dcp_idx; ++ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result); ++ if (ret | !query_result.shaper_query.crtbl) { ++ pr_err("This unshaped channel's uFQ wight is unavailable\n"); ++ return -EINVAL; ++ } ++ *token_limit = query_result.shaper_query.crtbl; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_get_weight); ++ ++int qman_ceetm_channel_set_group(struct qm_ceetm_channel *channel, int group_b, ++ unsigned int prio_a, unsigned int prio_b) ++{ ++ struct qm_mcc_ceetm_class_scheduler_config config_opts; ++ struct qm_mcr_ceetm_class_scheduler_query query_result; ++ int i; ++ ++ if (!prio_a || (prio_a > 7)) { ++ pr_err("The priority of group A is out of range\n"); ++ return -EINVAL; ++ } ++ if ((group_b && !prio_b) || (prio_b > 7)) { ++ pr_err("The priority of group B is out of range\n"); ++ return -EINVAL; ++ } ++ ++ if (qman_ceetm_query_class_scheduler(channel, &query_result)) { ++ pr_err("Can't query channel#%d's scheduler!\n", channel->idx); ++ return -EINVAL; ++ } ++ ++ config_opts.cqcid = channel->idx; ++ config_opts.dcpid = channel->dcp_idx; ++ if (!group_b) ++ config_opts.gpc = (u8)((1 << 6) | prio_a); ++ else ++ config_opts.gpc = (u8)((prio_b << 3) | prio_a); ++ ++ for (i = 0; i < 8; i++) ++ config_opts.w[i] = query_result.w[i]; ++ config_opts.crem = query_result.crem; ++ config_opts.erem = query_result.erem; ++ ++ return qman_ceetm_configure_class_scheduler(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_channel_set_group); ++ ++int qman_ceetm_channel_get_group(struct qm_ceetm_channel *channel, int *group_b, ++ unsigned int *prio_a, unsigned int *prio_b) ++{ ++ struct qm_mcr_ceetm_class_scheduler_query query_result; ++ ++ if (qman_ceetm_query_class_scheduler(channel, &query_result)) { ++ pr_err("Can't query channel#%d's scheduler!\n", channel->idx); ++ return -EINVAL; ++ } ++ *group_b = (query_result.gpc >> 6) & 0x1; ++ *prio_a = query_result.gpc & 0x7; ++ *prio_b = (query_result.gpc >> 3) & 0x7; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_get_group); ++ ++#define GROUP_A_ELIGIBILITY_SET (1 << 8) ++#define GROUP_B_ELIGIBILITY_SET (1 << 9) ++#define CQ_ELIGIBILITY_SET(n) (1 << (7 - n)) ++int qman_ceetm_channel_set_group_cr_eligibility(struct qm_ceetm_channel ++ *channel, int group_b, int cre) ++{ ++ struct qm_mcc_ceetm_class_scheduler_config csch_config; ++ struct qm_mcr_ceetm_class_scheduler_query csch_query; ++ int i; ++ ++ if (qman_ceetm_query_class_scheduler(channel, &csch_query)) { ++ pr_err("Cannot get the channel %d scheduler setting.\n", ++ channel->idx); ++ return -EINVAL; ++ } ++ csch_config.cqcid = channel->idx; ++ csch_config.dcpid = channel->dcp_idx; ++ csch_config.gpc = csch_query.gpc; ++ for (i = 0; i < 8; i++) ++ csch_config.w[i] = csch_query.w[i]; ++ csch_config.erem = csch_query.erem; ++ if (group_b) ++ csch_config.crem = (csch_query.crem & ~GROUP_B_ELIGIBILITY_SET) ++ | (cre ? GROUP_B_ELIGIBILITY_SET : 0); ++ else ++ csch_config.crem = (csch_query.crem & ~GROUP_A_ELIGIBILITY_SET) ++ | (cre ? GROUP_A_ELIGIBILITY_SET : 0); ++ ++ if (qman_ceetm_configure_class_scheduler(&csch_config)) { ++ pr_err("Cannot config channel %d's scheduler with " ++ "group_%c's cr eligibility\n", channel->idx, ++ group_b ? 'b' : 'a'); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_set_group_cr_eligibility); ++ ++int qman_ceetm_channel_set_group_er_eligibility(struct qm_ceetm_channel ++ *channel, int group_b, int ere) ++{ ++ struct qm_mcc_ceetm_class_scheduler_config csch_config; ++ struct qm_mcr_ceetm_class_scheduler_query csch_query; ++ int i; ++ ++ if (qman_ceetm_query_class_scheduler(channel, &csch_query)) { ++ pr_err("Cannot get the channel %d scheduler setting.\n", ++ channel->idx); ++ return -EINVAL; ++ } ++ csch_config.cqcid = channel->idx; ++ csch_config.dcpid = channel->dcp_idx; ++ csch_config.gpc = csch_query.gpc; ++ for (i = 0; i < 8; i++) ++ csch_config.w[i] = csch_query.w[i]; ++ csch_config.crem = csch_query.crem; ++ if (group_b) ++ csch_config.erem = (csch_query.erem & ~GROUP_B_ELIGIBILITY_SET) ++ | (ere ? GROUP_B_ELIGIBILITY_SET : 0); ++ else ++ csch_config.erem = (csch_query.erem & ~GROUP_A_ELIGIBILITY_SET) ++ | (ere ? GROUP_A_ELIGIBILITY_SET : 0); ++ ++ if (qman_ceetm_configure_class_scheduler(&csch_config)) { ++ pr_err("Cannot config channel %d's scheduler with " ++ "group_%c's er eligibility\n", channel->idx, ++ group_b ? 'b' : 'a'); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_set_group_er_eligibility); ++ ++int qman_ceetm_channel_set_cq_cr_eligibility(struct qm_ceetm_channel *channel, ++ unsigned int idx, int cre) ++{ ++ struct qm_mcc_ceetm_class_scheduler_config csch_config; ++ struct qm_mcr_ceetm_class_scheduler_query csch_query; ++ int i; ++ ++ if (idx > 7) { ++ pr_err("CQ index is out of range\n"); ++ return -EINVAL; ++ } ++ if (qman_ceetm_query_class_scheduler(channel, &csch_query)) { ++ pr_err("Cannot get the channel %d scheduler setting.\n", ++ channel->idx); ++ return -EINVAL; ++ } ++ csch_config.cqcid = channel->idx; ++ csch_config.dcpid = channel->dcp_idx; ++ csch_config.gpc = csch_query.gpc; ++ for (i = 0; i < 8; i++) ++ csch_config.w[i] = csch_query.w[i]; ++ csch_config.erem = csch_query.erem; ++ csch_config.crem = (csch_query.crem & ~CQ_ELIGIBILITY_SET(idx)) | ++ (cre ? CQ_ELIGIBILITY_SET(idx) : 0); ++ if (qman_ceetm_configure_class_scheduler(&csch_config)) { ++ pr_err("Cannot config channel scheduler to set " ++ "cr eligibility mask for CQ#%d\n", idx); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_set_cq_cr_eligibility); ++ ++int qman_ceetm_channel_set_cq_er_eligibility(struct qm_ceetm_channel *channel, ++ unsigned int idx, int ere) ++{ ++ struct qm_mcc_ceetm_class_scheduler_config csch_config; ++ struct qm_mcr_ceetm_class_scheduler_query csch_query; ++ int i; ++ ++ if (idx > 7) { ++ pr_err("CQ index is out of range\n"); ++ return -EINVAL; ++ } ++ if (qman_ceetm_query_class_scheduler(channel, &csch_query)) { ++ pr_err("Cannot get the channel %d scheduler setting.\n", ++ channel->idx); ++ return -EINVAL; ++ } ++ csch_config.cqcid = channel->idx; ++ csch_config.dcpid = channel->dcp_idx; ++ csch_config.gpc = csch_query.gpc; ++ for (i = 0; i < 8; i++) ++ csch_config.w[i] = csch_query.w[i]; ++ csch_config.crem = csch_query.crem; ++ csch_config.erem = (csch_query.erem & ~CQ_ELIGIBILITY_SET(idx)) | ++ (ere ? CQ_ELIGIBILITY_SET(idx) : 0); ++ if (qman_ceetm_configure_class_scheduler(&csch_config)) { ++ pr_err("Cannot config channel scheduler to set " ++ "er eligibility mask for CQ#%d\n", idx); ++ return -EINVAL; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_channel_set_cq_er_eligibility); ++ ++int qman_ceetm_cq_claim(struct qm_ceetm_cq **cq, ++ struct qm_ceetm_channel *channel, unsigned int idx, ++ struct qm_ceetm_ccg *ccg) ++{ ++ struct qm_ceetm_cq *p; ++ struct qm_mcc_ceetm_cq_config cq_config; ++ ++ if (idx > 7) { ++ pr_err("The independent class queue id is out of range\n"); ++ return -EINVAL; ++ } ++ ++ list_for_each_entry(p, &channel->class_queues, node) { ++ if (p->idx == idx) { ++ pr_err("The CQ#%d has been claimed!\n", idx); ++ return -EINVAL; ++ } ++ } ++ ++ p = kmalloc(sizeof(*p), GFP_KERNEL); ++ if (!p) { ++ pr_err("Can't allocate memory for CQ#%d!\n", idx); ++ return -ENOMEM; ++ } ++ ++ list_add_tail(&p->node, &channel->class_queues); ++ p->idx = idx; ++ p->is_claimed = 1; ++ p->parent = channel; ++ INIT_LIST_HEAD(&p->bound_lfqids); ++ ++ if (ccg) { ++ cq_config.cqid = (channel->idx << 4) | idx; ++ cq_config.dcpid = channel->dcp_idx; ++ cq_config.ccgid = ccg->idx; ++ if (qman_ceetm_configure_cq(&cq_config)) { ++ pr_err("Can't configure the CQ#%d with CCGRID#%d\n", ++ idx, ccg->idx); ++ list_del(&p->node); ++ kfree(p); ++ return -EINVAL; ++ } ++ } ++ ++ *cq = p; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cq_claim); ++ ++int qman_ceetm_cq_claim_A(struct qm_ceetm_cq **cq, ++ struct qm_ceetm_channel *channel, unsigned int idx, ++ struct qm_ceetm_ccg *ccg) ++{ ++ struct qm_ceetm_cq *p; ++ struct qm_mcc_ceetm_cq_config cq_config; ++ ++ if ((idx < 7) || (idx > 15)) { ++ pr_err("This grouped class queue id is out of range\n"); ++ return -EINVAL; ++ } ++ ++ list_for_each_entry(p, &channel->class_queues, node) { ++ if (p->idx == idx) { ++ pr_err("The CQ#%d has been claimed!\n", idx); ++ return -EINVAL; ++ } ++ } ++ ++ p = kmalloc(sizeof(*p), GFP_KERNEL); ++ if (!p) { ++ pr_err("Can't allocate memory for CQ#%d!\n", idx); ++ return -ENOMEM; ++ } ++ ++ list_add_tail(&p->node, &channel->class_queues); ++ p->idx = idx; ++ p->is_claimed = 1; ++ p->parent = channel; ++ INIT_LIST_HEAD(&p->bound_lfqids); ++ ++ if (ccg) { ++ cq_config.cqid = (channel->idx << 4) | idx; ++ cq_config.dcpid = channel->dcp_idx; ++ cq_config.ccgid = ccg->idx; ++ if (qman_ceetm_configure_cq(&cq_config)) { ++ pr_err("Can't configure the CQ#%d with CCGRID#%d\n", ++ idx, ccg->idx); ++ list_del(&p->node); ++ kfree(p); ++ return -EINVAL; ++ } ++ } ++ *cq = p; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cq_claim_A); ++ ++int qman_ceetm_cq_claim_B(struct qm_ceetm_cq **cq, ++ struct qm_ceetm_channel *channel, unsigned int idx, ++ struct qm_ceetm_ccg *ccg) ++{ ++ struct qm_ceetm_cq *p; ++ struct qm_mcc_ceetm_cq_config cq_config; ++ ++ if ((idx < 11) || (idx > 15)) { ++ pr_err("This grouped class queue id is out of range\n"); ++ return -EINVAL; ++ } ++ ++ list_for_each_entry(p, &channel->class_queues, node) { ++ if (p->idx == idx) { ++ pr_err("The CQ#%d has been claimed!\n", idx); ++ return -EINVAL; ++ } ++ } ++ ++ p = kmalloc(sizeof(*p), GFP_KERNEL); ++ if (!p) { ++ pr_err("Can't allocate memory for CQ#%d!\n", idx); ++ return -ENOMEM; ++ } ++ ++ list_add_tail(&p->node, &channel->class_queues); ++ p->idx = idx; ++ p->is_claimed = 1; ++ p->parent = channel; ++ INIT_LIST_HEAD(&p->bound_lfqids); ++ ++ if (ccg) { ++ cq_config.cqid = (channel->idx << 4) | idx; ++ cq_config.dcpid = channel->dcp_idx; ++ cq_config.ccgid = ccg->idx; ++ if (qman_ceetm_configure_cq(&cq_config)) { ++ pr_err("Can't configure the CQ#%d with CCGRID#%d\n", ++ idx, ccg->idx); ++ list_del(&p->node); ++ kfree(p); ++ return -EINVAL; ++ } ++ } ++ *cq = p; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cq_claim_B); ++ ++int qman_ceetm_cq_release(struct qm_ceetm_cq *cq) ++{ ++ if (!list_empty(&cq->bound_lfqids)) { ++ pr_err("The CQ#%d has unreleased LFQID\n", cq->idx); ++ return -EBUSY; ++ } ++ list_del(&cq->node); ++ qman_ceetm_drain_cq(cq); ++ kfree(cq); ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cq_release); ++ ++int qman_ceetm_set_queue_weight(struct qm_ceetm_cq *cq, ++ struct qm_ceetm_weight_code *weight_code) ++{ ++ struct qm_mcc_ceetm_class_scheduler_config config_opts; ++ struct qm_mcr_ceetm_class_scheduler_query query_result; ++ int i; ++ ++ if (cq->idx < 8) { ++ pr_err("Can not set weight for ungrouped class queue\n"); ++ return -EINVAL; ++ } ++ ++ if (qman_ceetm_query_class_scheduler(cq->parent, &query_result)) { ++ pr_err("Can't query channel#%d's scheduler!\n", ++ cq->parent->idx); ++ return -EINVAL; ++ } ++ ++ config_opts.cqcid = cq->parent->idx; ++ config_opts.dcpid = cq->parent->dcp_idx; ++ config_opts.crem = query_result.crem; ++ config_opts.erem = query_result.erem; ++ config_opts.gpc = query_result.gpc; ++ for (i = 0; i < 8; i++) ++ config_opts.w[i] = query_result.w[i]; ++ config_opts.w[cq->idx - 8] = ((weight_code->y << 3) | ++ (weight_code->x & 0x7)); ++ return qman_ceetm_configure_class_scheduler(&config_opts); ++} ++EXPORT_SYMBOL(qman_ceetm_set_queue_weight); ++ ++int qman_ceetm_get_queue_weight(struct qm_ceetm_cq *cq, ++ struct qm_ceetm_weight_code *weight_code) ++{ ++ struct qm_mcr_ceetm_class_scheduler_query query_result; ++ ++ if (cq->idx < 8) { ++ pr_err("Can not get weight for ungrouped class queue\n"); ++ return -EINVAL; ++ } ++ ++ if (qman_ceetm_query_class_scheduler(cq->parent, ++ &query_result)) { ++ pr_err("Can't get the weight code for CQ#%d!\n", cq->idx); ++ return -EINVAL; ++ } ++ weight_code->y = query_result.w[cq->idx - 8] >> 3; ++ weight_code->x = query_result.w[cq->idx - 8] & 0x7; ++ ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_get_queue_weight); ++ ++/* The WBFS code is represent as {x,y}, the effect wieght can be calculated as: ++ * effective weight = 2^x / (1 - (y/64)) ++ * = 2^(x+6) / (64 - y) ++ */ ++static void reduce_fraction(u32 *n, u32 *d) ++{ ++ u32 factor = 2; ++ u32 lesser = (*n < *d) ? *n : *d; ++ /* If factor exceeds the square-root of the lesser of *n and *d, ++ * then there's no point continuing. Proof: if there was a factor ++ * bigger than the square root, that would imply there exists ++ * another factor smaller than the square-root with which it ++ * multiplies to give 'lesser' - but that's a contradiction ++ * because the other factor would have already been found and ++ * divided out. ++ */ ++ while ((factor * factor) <= lesser) { ++ /* If 'factor' is a factor of *n and *d, divide them both ++ * by 'factor' as many times as possible. ++ */ ++ while (!(*n % factor) && !(*d % factor)) { ++ *n /= factor; ++ *d /= factor; ++ lesser /= factor; ++ } ++ if (factor == 2) ++ factor = 3; ++ else ++ factor += 2; ++ } ++} ++ ++int qman_ceetm_wbfs2ratio(struct qm_ceetm_weight_code *weight_code, ++ u32 *numerator, ++ u32 *denominator) ++{ ++ *numerator = (u32) 1 << (weight_code->x + 6); ++ *denominator = 64 - weight_code->y; ++ reduce_fraction(numerator, denominator); ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_wbfs2ratio); ++ ++/* For a given x, the weight is between 2^x (inclusive) and 2^(x+1) (exclusive). ++ * So find 'x' by range, and then estimate 'y' using: ++ * 64 - y = 2^(x + 6) / weight ++ * = 2^(x + 6) / (n/d) ++ * = d * 2^(x+6) / n ++ * y = 64 - (d * 2^(x+6) / n) ++ */ ++int qman_ceetm_ratio2wbfs(u32 numerator, ++ u32 denominator, ++ struct qm_ceetm_weight_code *weight_code, ++ int rounding) ++{ ++ unsigned int y, x = 0; ++ /* search incrementing 'x' until: ++ * weight < 2^(x+1) ++ * n/d < 2^(x+1) ++ * n < d * 2^(x+1) ++ */ ++ while ((x < 8) && (numerator >= (denominator << (x + 1)))) ++ x++; ++ if (x >= 8) ++ return -ERANGE; ++ /* because of the subtraction, use '-rounding' */ ++ y = 64 - ROUNDING(denominator << (x + 6), numerator, -rounding); ++ if (y >= 32) ++ return -ERANGE; ++ weight_code->x = x; ++ weight_code->y = y; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_ratio2wbfs); ++ ++int qman_ceetm_set_queue_weight_in_ratio(struct qm_ceetm_cq *cq, u32 ratio) ++{ ++ struct qm_ceetm_weight_code weight_code; ++ ++ if (qman_ceetm_ratio2wbfs(ratio, 100, &weight_code, 0)) { ++ pr_err("Cannot get wbfs code for cq %x\n", cq->idx); ++ return -EINVAL; ++ } ++ return qman_ceetm_set_queue_weight(cq, &weight_code); ++} ++EXPORT_SYMBOL(qman_ceetm_set_queue_weight_in_ratio); ++ ++int qman_ceetm_get_queue_weight_in_ratio(struct qm_ceetm_cq *cq, u32 *ratio) ++{ ++ struct qm_ceetm_weight_code weight_code; ++ u32 n, d; ++ ++ if (qman_ceetm_get_queue_weight(cq, &weight_code)) { ++ pr_err("Cannot query the weight code for cq%x\n", cq->idx); ++ return -EINVAL; ++ } ++ ++ if (qman_ceetm_wbfs2ratio(&weight_code, &n, &d)) { ++ pr_err("Cannot get the ratio with wbfs code\n"); ++ return -EINVAL; ++ } ++ ++ *ratio = (n * (u32)100) / d; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_get_queue_weight_in_ratio); ++ ++int qman_ceetm_cq_get_dequeue_statistics(struct qm_ceetm_cq *cq, u32 flags, ++ u64 *frame_count, u64 *byte_count) ++{ ++ struct qm_mcr_ceetm_statistics_query result; ++ u16 cid, command_type; ++ enum qm_dc_portal dcp_idx; ++ int ret; ++ ++ cid = (cq->parent->idx << 4) | cq->idx; ++ dcp_idx = cq->parent->dcp_idx; ++ if (flags == QMAN_CEETM_FLAG_CLEAR_STATISTICS_COUNTER) ++ command_type = CEETM_QUERY_DEQUEUE_CLEAR_STATISTICS; ++ else ++ command_type = CEETM_QUERY_DEQUEUE_STATISTICS; ++ ++ ret = qman_ceetm_query_statistics(cid, dcp_idx, command_type, &result); ++ if (ret) { ++ pr_err("Can't query the statistics of CQ#%d!\n", cq->idx); ++ return -EINVAL; ++ } ++ ++ *frame_count = result.frm_cnt; ++ *byte_count = result.byte_cnt; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cq_get_dequeue_statistics); ++ ++int qman_ceetm_drain_cq(struct qm_ceetm_cq *cq) ++{ ++ struct qm_mcr_ceetm_cq_peek_pop_xsfdrread ppxr; ++ int ret; ++ ++ do { ++ ret = qman_ceetm_cq_peek_pop_xsfdrread(cq, 1, 0, &ppxr); ++ if (ret) { ++ pr_err("Failed to pop frame from CQ\n"); ++ return -EINVAL; ++ } ++ } while (!(ppxr.stat & 0x2)); ++ ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_drain_cq); ++ ++#define CEETM_LFQMT_LFQID_MSB 0xF00000 ++#define CEETM_LFQMT_LFQID_LSB 0x000FFF ++int qman_ceetm_lfq_claim(struct qm_ceetm_lfq **lfq, ++ struct qm_ceetm_cq *cq) ++{ ++ struct qm_ceetm_lfq *p; ++ u32 lfqid; ++ int ret = 0; ++ struct qm_mcc_ceetm_lfqmt_config lfqmt_config; ++ ++ if (cq->parent->dcp_idx == qm_dc_portal_fman0) { ++ ret = qman_alloc_ceetm0_lfqid(&lfqid); ++ } else if (cq->parent->dcp_idx == qm_dc_portal_fman1) { ++ ret = qman_alloc_ceetm1_lfqid(&lfqid); ++ } else { ++ pr_err("dcp_idx %u does not correspond to a known fman in this driver\n", ++ cq->parent->dcp_idx); ++ return -EINVAL; ++ } ++ ++ if (ret) { ++ pr_err("There is no lfqid avalaible for CQ#%d!\n", cq->idx); ++ return -ENODEV; ++ } ++ p = kmalloc(sizeof(*p), GFP_KERNEL); ++ if (!p) ++ return -ENOMEM; ++ p->idx = lfqid; ++ p->dctidx = (u16)(lfqid & CEETM_LFQMT_LFQID_LSB); ++ p->parent = cq->parent; ++ list_add_tail(&p->node, &cq->bound_lfqids); ++ ++ lfqmt_config.lfqid = CEETM_LFQMT_LFQID_MSB | ++ (cq->parent->dcp_idx << 16) | ++ (lfqid & CEETM_LFQMT_LFQID_LSB); ++ lfqmt_config.cqid = (cq->parent->idx << 4) | (cq->idx); ++ lfqmt_config.dctidx = p->dctidx; ++ if (qman_ceetm_configure_lfqmt(&lfqmt_config)) { ++ pr_err("Can't configure LFQMT for LFQID#%d @ CQ#%d\n", ++ lfqid, cq->idx); ++ list_del(&p->node); ++ kfree(p); ++ return -EINVAL; ++ } ++ *lfq = p; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_lfq_claim); ++ ++int qman_ceetm_lfq_release(struct qm_ceetm_lfq *lfq) ++{ ++ if (lfq->parent->dcp_idx == qm_dc_portal_fman0) { ++ qman_release_ceetm0_lfqid(lfq->idx); ++ } else if (lfq->parent->dcp_idx == qm_dc_portal_fman1) { ++ qman_release_ceetm1_lfqid(lfq->idx); ++ } else { ++ pr_err("dcp_idx %u does not correspond to a known fman in this driver\n", ++ lfq->parent->dcp_idx); ++ return -EINVAL; ++ } ++ list_del(&lfq->node); ++ kfree(lfq); ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_lfq_release); ++ ++int qman_ceetm_lfq_set_context(struct qm_ceetm_lfq *lfq, u64 context_a, ++ u32 context_b) ++{ ++ struct qm_mcc_ceetm_dct_config dct_config; ++ lfq->context_a = context_a; ++ lfq->context_b = context_b; ++ dct_config.dctidx = (u16)lfq->dctidx; ++ dct_config.dcpid = lfq->parent->dcp_idx; ++ dct_config.context_b = context_b; ++ dct_config.context_a = context_a; ++ return qman_ceetm_configure_dct(&dct_config); ++} ++EXPORT_SYMBOL(qman_ceetm_lfq_set_context); ++ ++int qman_ceetm_lfq_get_context(struct qm_ceetm_lfq *lfq, u64 *context_a, ++ u32 *context_b) ++{ ++ struct qm_mcc_ceetm_dct_query dct_query; ++ struct qm_mcr_ceetm_dct_query query_result; ++ ++ dct_query.dctidx = (u16)lfq->dctidx; ++ dct_query.dcpid = lfq->parent->dcp_idx; ++ if (qman_ceetm_query_dct(&dct_query, &query_result)) { ++ pr_err("Can't query LFQID#%d's context!\n", lfq->idx); ++ return -EINVAL; ++ } ++ *context_a = query_result.context_a; ++ *context_b = query_result.context_b; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_lfq_get_context); ++ ++int qman_ceetm_create_fq(struct qm_ceetm_lfq *lfq, struct qman_fq *fq) ++{ ++ spin_lock_init(&fq->fqlock); ++ fq->fqid = lfq->idx; ++ fq->flags = QMAN_FQ_FLAG_NO_MODIFY; ++ if (lfq->ern) ++ fq->cb.ern = lfq->ern; ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ if (unlikely(find_empty_fq_table_entry(&fq->key, fq))) ++ return -ENOMEM; ++#endif ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_create_fq); ++ ++int qman_ceetm_ccg_claim(struct qm_ceetm_ccg **ccg, ++ struct qm_ceetm_channel *channel, ++ unsigned int idx, ++ void (*cscn)(struct qm_ceetm_ccg *, ++ void *cb_ctx, ++ int congested), ++ void *cb_ctx) ++{ ++ struct qm_ceetm_ccg *p; ++ ++ if (idx > 15) { ++ pr_err("The given ccg index is out of range\n"); ++ return -EINVAL; ++ } ++ ++ list_for_each_entry(p, &channel->ccgs, node) { ++ if (p->idx == idx) { ++ pr_err("The CCG#%d has been claimed\n", idx); ++ return -EINVAL; ++ } ++ } ++ ++ p = kmalloc(sizeof(*p), GFP_KERNEL); ++ if (!p) { ++ pr_err("Can't allocate memory for CCG#%d!\n", idx); ++ return -ENOMEM; ++ } ++ ++ list_add_tail(&p->node, &channel->ccgs); ++ ++ p->idx = idx; ++ p->parent = channel; ++ p->cb = cscn; ++ p->cb_ctx = cb_ctx; ++ INIT_LIST_HEAD(&p->cb_node); ++ ++ *ccg = p; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_ccg_claim); ++ ++int qman_ceetm_ccg_release(struct qm_ceetm_ccg *ccg) ++{ ++ unsigned long irqflags __maybe_unused; ++ struct qm_mcc_ceetm_ccgr_config config_opts; ++ int ret = 0; ++ struct qman_portal *p = get_affine_portal(); ++ ++ memset(&config_opts, 0, sizeof(struct qm_mcc_ceetm_ccgr_config)); ++ spin_lock_irqsave(&p->ccgr_lock, irqflags); ++ if (!list_empty(&ccg->cb_node)) ++ list_del(&ccg->cb_node); ++ config_opts.ccgrid = CEETM_CCGR_CM_CONFIGURE | ++ (ccg->parent->idx << 4) | ccg->idx; ++ config_opts.dcpid = ccg->parent->dcp_idx; ++ config_opts.we_mask = QM_CCGR_WE_CSCN_TUPD; ++ config_opts.cm_config.cscn_tupd = PORTAL_IDX(p); ++ ret = qman_ceetm_configure_ccgr(&config_opts); ++ spin_unlock_irqrestore(&p->ccgr_lock, irqflags); ++ ++ list_del(&ccg->node); ++ kfree(ccg); ++ return ret; ++} ++EXPORT_SYMBOL(qman_ceetm_ccg_release); ++ ++int qman_ceetm_ccg_set(struct qm_ceetm_ccg *ccg, u16 we_mask, ++ const struct qm_ceetm_ccg_params *params) ++{ ++ struct qm_mcc_ceetm_ccgr_config config_opts; ++ unsigned long irqflags __maybe_unused; ++ int ret; ++ struct qman_portal *p; ++ ++ if (((ccg->parent->idx << 4) | ccg->idx) >= (2 * __CGR_NUM)) ++ return -EINVAL; ++ ++ p = get_affine_portal(); ++ ++ memset(&config_opts, 0, sizeof(struct qm_mcc_ceetm_ccgr_config)); ++ spin_lock_irqsave(&p->ccgr_lock, irqflags); ++ ++ config_opts.ccgrid = CEETM_CCGR_CM_CONFIGURE | ++ (ccg->parent->idx << 4) | ccg->idx; ++ config_opts.dcpid = ccg->parent->dcp_idx; ++ config_opts.we_mask = we_mask; ++ if (we_mask & QM_CCGR_WE_CSCN_EN) { ++ config_opts.we_mask |= QM_CCGR_WE_CSCN_TUPD; ++ config_opts.cm_config.cscn_tupd = ++ QM_CGR_TARG_UDP_CTRL_WRITE_BIT | PORTAL_IDX(p); ++ } ++ config_opts.cm_config.ctl = (params->wr_en_g << 6) | ++ (params->wr_en_y << 5) | ++ (params->wr_en_r << 4) | ++ (params->td_en << 3) | ++ (params->td_mode << 2) | ++ (params->cscn_en << 1) | ++ (params->mode); ++ config_opts.cm_config.oal = params->oal; ++ config_opts.cm_config.cs_thres = params->cs_thres_in; ++ config_opts.cm_config.cs_thres_x = params->cs_thres_out; ++ config_opts.cm_config.td_thres = params->td_thres; ++ config_opts.cm_config.wr_parm_g = params->wr_parm_g; ++ config_opts.cm_config.wr_parm_y = params->wr_parm_y; ++ config_opts.cm_config.wr_parm_r = params->wr_parm_r; ++ ret = qman_ceetm_configure_ccgr(&config_opts); ++ if (ret) { ++ pr_err("Configure CCGR CM failed!\n"); ++ goto release_lock; ++ } ++ ++ if (we_mask & QM_CCGR_WE_CSCN_EN) ++ if (list_empty(&ccg->cb_node)) ++ list_add(&ccg->cb_node, ++ &p->ccgr_cbs[ccg->parent->dcp_idx]); ++release_lock: ++ spin_unlock_irqrestore(&p->ccgr_lock, irqflags); ++ put_affine_portal(); ++ return ret; ++} ++EXPORT_SYMBOL(qman_ceetm_ccg_set); ++ ++#define CEETM_CCGR_CTL_MASK 0x01 ++int qman_ceetm_ccg_get(struct qm_ceetm_ccg *ccg, ++ struct qm_ceetm_ccg_params *params) ++{ ++ struct qm_mcc_ceetm_ccgr_query query_opts; ++ struct qm_mcr_ceetm_ccgr_query query_result; ++ ++ query_opts.ccgrid = CEETM_CCGR_CM_QUERY | ++ (ccg->parent->idx << 4) | ccg->idx; ++ query_opts.dcpid = ccg->parent->dcp_idx; ++ ++ if (qman_ceetm_query_ccgr(&query_opts, &query_result)) { ++ pr_err("Can't query CCGR#%d\n", ccg->idx); ++ return -EINVAL; ++ } ++ ++ params->wr_parm_r = query_result.cm_query.wr_parm_r; ++ params->wr_parm_y = query_result.cm_query.wr_parm_y; ++ params->wr_parm_g = query_result.cm_query.wr_parm_g; ++ params->td_thres = query_result.cm_query.td_thres; ++ params->cs_thres_out = query_result.cm_query.cs_thres_x; ++ params->cs_thres_in = query_result.cm_query.cs_thres; ++ params->oal = query_result.cm_query.oal; ++ params->wr_en_g = (query_result.cm_query.ctl >> 6) & ++ CEETM_CCGR_CTL_MASK; ++ params->wr_en_y = (query_result.cm_query.ctl >> 5) & ++ CEETM_CCGR_CTL_MASK; ++ params->wr_en_r = (query_result.cm_query.ctl >> 4) & ++ CEETM_CCGR_CTL_MASK; ++ params->td_en = (query_result.cm_query.ctl >> 3) & ++ CEETM_CCGR_CTL_MASK; ++ params->td_mode = (query_result.cm_query.ctl >> 2) & ++ CEETM_CCGR_CTL_MASK; ++ params->cscn_en = (query_result.cm_query.ctl >> 1) & ++ CEETM_CCGR_CTL_MASK; ++ params->mode = (query_result.cm_query.ctl & CEETM_CCGR_CTL_MASK); ++ ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_ccg_get); ++ ++int qman_ceetm_ccg_get_reject_statistics(struct qm_ceetm_ccg *ccg, u32 flags, ++ u64 *frame_count, u64 *byte_count) ++{ ++ struct qm_mcr_ceetm_statistics_query result; ++ u16 cid, command_type; ++ enum qm_dc_portal dcp_idx; ++ int ret; ++ ++ cid = (ccg->parent->idx << 4) | ccg->idx; ++ dcp_idx = ccg->parent->dcp_idx; ++ if (flags == QMAN_CEETM_FLAG_CLEAR_STATISTICS_COUNTER) ++ command_type = CEETM_QUERY_REJECT_CLEAR_STATISTICS; ++ else ++ command_type = CEETM_QUERY_REJECT_STATISTICS; ++ ++ ret = qman_ceetm_query_statistics(cid, dcp_idx, command_type, &result); ++ if (ret) { ++ pr_err("Can't query the statistics of CCG#%d!\n", ccg->idx); ++ return -EINVAL; ++ } ++ ++ *frame_count = result.frm_cnt; ++ *byte_count = result.byte_cnt; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_ccg_get_reject_statistics); ++ ++int qman_ceetm_cscn_swp_get(struct qm_ceetm_ccg *ccg, ++ u16 swp_idx, ++ unsigned int *cscn_enabled) ++{ ++ struct qm_mcc_ceetm_ccgr_query query_opts; ++ struct qm_mcr_ceetm_ccgr_query query_result; ++ int i; ++ ++ DPA_ASSERT(swp_idx < 127); ++ query_opts.ccgrid = CEETM_CCGR_CM_QUERY | ++ (ccg->parent->idx << 4) | ccg->idx; ++ query_opts.dcpid = ccg->parent->dcp_idx; ++ ++ if (qman_ceetm_query_ccgr(&query_opts, &query_result)) { ++ pr_err("Can't query CCGR#%d\n", ccg->idx); ++ return -EINVAL; ++ } ++ ++ i = swp_idx / 32; ++ i = 3 - i; ++ *cscn_enabled = (query_result.cm_query.cscn_targ_swp[i] >> ++ (31 - swp_idx % 32)); ++ ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cscn_swp_get); ++ ++int qman_ceetm_cscn_dcp_set(struct qm_ceetm_ccg *ccg, ++ u16 dcp_idx, ++ u8 vcgid, ++ unsigned int cscn_enabled, ++ u16 we_mask, ++ const struct qm_ceetm_ccg_params *params) ++{ ++ struct qm_mcc_ceetm_ccgr_config config_opts; ++ int ret; ++ ++ config_opts.ccgrid = CEETM_CCGR_CM_CONFIGURE | ++ (ccg->parent->idx << 4) | ccg->idx; ++ config_opts.dcpid = ccg->parent->dcp_idx; ++ config_opts.we_mask = we_mask | QM_CCGR_WE_CSCN_TUPD | QM_CCGR_WE_CDV; ++ config_opts.cm_config.cdv = vcgid; ++ config_opts.cm_config.cscn_tupd = (cscn_enabled << 15) | ++ QM_CGR_TARG_UDP_CTRL_DCP | dcp_idx; ++ config_opts.cm_config.ctl = (params->wr_en_g << 6) | ++ (params->wr_en_y << 5) | ++ (params->wr_en_r << 4) | ++ (params->td_en << 3) | ++ (params->td_mode << 2) | ++ (params->cscn_en << 1) | ++ (params->mode); ++ config_opts.cm_config.cs_thres = params->cs_thres_in; ++ config_opts.cm_config.cs_thres_x = params->cs_thres_out; ++ config_opts.cm_config.td_thres = params->td_thres; ++ config_opts.cm_config.wr_parm_g = params->wr_parm_g; ++ config_opts.cm_config.wr_parm_y = params->wr_parm_y; ++ config_opts.cm_config.wr_parm_r = params->wr_parm_r; ++ ++ ret = qman_ceetm_configure_ccgr(&config_opts); ++ if (ret) { ++ pr_err("Configure CSCN_TARG_DCP failed!\n"); ++ return -EINVAL; ++ } ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cscn_dcp_set); ++ ++int qman_ceetm_cscn_dcp_get(struct qm_ceetm_ccg *ccg, ++ u16 dcp_idx, ++ u8 *vcgid, ++ unsigned int *cscn_enabled) ++{ ++ struct qm_mcc_ceetm_ccgr_query query_opts; ++ struct qm_mcr_ceetm_ccgr_query query_result; ++ ++ query_opts.ccgrid = CEETM_CCGR_CM_QUERY | ++ (ccg->parent->idx << 4) | ccg->idx; ++ query_opts.dcpid = ccg->parent->dcp_idx; ++ ++ if (qman_ceetm_query_ccgr(&query_opts, &query_result)) { ++ pr_err("Can't query CCGR#%d\n", ccg->idx); ++ return -EINVAL; ++ } ++ ++ *vcgid = query_result.cm_query.cdv; ++ *cscn_enabled = (query_result.cm_query.cscn_targ_dcp >> ++ dcp_idx) & 0x1; ++ return 0; ++} ++EXPORT_SYMBOL(qman_ceetm_cscn_dcp_get); ++ ++int qman_ceetm_querycongestion(struct __qm_mcr_querycongestion *ccg_state, ++ unsigned int dcp_idx) ++{ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ u8 res; ++ int i; ++ ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ ++ mcc = qm_mc_start(&p->p); ++ for (i = 0; i < 2; i++) { ++ mcc->ccgr_query.ccgrid = CEETM_QUERY_CONGESTION_STATE | i; ++ mcc->ccgr_query.dcpid = dcp_idx; ++ qm_mc_commit(&p->p, QM_CEETM_VERB_CCGR_QUERY); ++ ++ while (!(mcr = qm_mc_result(&p->p))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_CEETM_VERB_CCGR_QUERY); ++ res = mcr->result; ++ if (res == QM_MCR_RESULT_OK) { ++ *(ccg_state + i) = ++ mcr->ccgr_query.congestion_state.state; ++ } else { ++ pr_err("QUERY CEETM CONGESTION STATE failed\n"); ++ return -EIO; ++ } ++ } ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return 0; ++} ++ ++int qman_set_wpm(int wpm_enable) ++{ ++ return qm_set_wpm(wpm_enable); ++} ++EXPORT_SYMBOL(qman_set_wpm); ++ ++int qman_get_wpm(int *wpm_enable) ++{ ++ return qm_get_wpm(wpm_enable); ++} ++EXPORT_SYMBOL(qman_get_wpm); ++ ++int qman_shutdown_fq(u32 fqid) ++{ ++ struct qman_portal *p; ++ unsigned long irqflags __maybe_unused; ++ int ret; ++ struct qm_portal *low_p; ++ p = get_affine_portal(); ++ PORTAL_IRQ_LOCK(p, irqflags); ++ low_p = &p->p; ++ ret = qm_shutdown_fq(&low_p, 1, fqid); ++ PORTAL_IRQ_UNLOCK(p, irqflags); ++ put_affine_portal(); ++ return ret; ++} ++ ++const struct qm_portal_config *qman_get_qm_portal_config( ++ struct qman_portal *portal) ++{ ++ return portal->sharing_redirect ? NULL : portal->config; ++} +diff --git a/drivers/staging/fsl_qbman/qman_low.h b/drivers/staging/fsl_qbman/qman_low.h +new file mode 100644 +index 0000000..407a82c +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_low.h +@@ -0,0 +1,1346 @@ ++/* Copyright 2008-2011 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 "qman_private.h" ++ ++/***************************/ ++/* Portal register assists */ ++/***************************/ ++ ++/* Cache-inhibited register offsets */ ++#define QM_REG_EQCR_PI_CINH 0x0000 ++#define QM_REG_EQCR_CI_CINH 0x0004 ++#define QM_REG_EQCR_ITR 0x0008 ++#define QM_REG_DQRR_PI_CINH 0x0040 ++#define QM_REG_DQRR_CI_CINH 0x0044 ++#define QM_REG_DQRR_ITR 0x0048 ++#define QM_REG_DQRR_DCAP 0x0050 ++#define QM_REG_DQRR_SDQCR 0x0054 ++#define QM_REG_DQRR_VDQCR 0x0058 ++#define QM_REG_DQRR_PDQCR 0x005c ++#define QM_REG_MR_PI_CINH 0x0080 ++#define QM_REG_MR_CI_CINH 0x0084 ++#define QM_REG_MR_ITR 0x0088 ++#define QM_REG_CFG 0x0100 ++#define QM_REG_ISR 0x0e00 ++#define QM_REG_IIR 0x0e0c ++#define QM_REG_ITPR 0x0e14 ++ ++/* Cache-enabled register offsets */ ++#define QM_CL_EQCR 0x0000 ++#define QM_CL_DQRR 0x1000 ++#define QM_CL_MR 0x2000 ++#define QM_CL_EQCR_PI_CENA 0x3000 ++#define QM_CL_EQCR_CI_CENA 0x3100 ++#define QM_CL_DQRR_PI_CENA 0x3200 ++#define QM_CL_DQRR_CI_CENA 0x3300 ++#define QM_CL_MR_PI_CENA 0x3400 ++#define QM_CL_MR_CI_CENA 0x3500 ++#define QM_CL_CR 0x3800 ++#define QM_CL_RR0 0x3900 ++#define QM_CL_RR1 0x3940 ++ ++/* BTW, the drivers (and h/w programming model) already obtain the required ++ * synchronisation for portal accesses via lwsync(), hwsync(), and ++ * data-dependencies. Use of barrier()s or other order-preserving primitives ++ * simply degrade performance. Hence the use of the __raw_*() interfaces, which ++ * simply ensure that the compiler treats the portal registers as volatile (ie. ++ * non-coherent). */ ++ ++/* Cache-inhibited register access. */ ++#define __qm_in(qm, o) __raw_readl((qm)->addr_ci + (o)) ++#define __qm_out(qm, o, val) __raw_writel((val), (qm)->addr_ci + (o)) ++#define qm_in(reg) __qm_in(&portal->addr, QM_REG_##reg) ++#define qm_out(reg, val) __qm_out(&portal->addr, QM_REG_##reg, val) ++ ++/* Cache-enabled (index) register access */ ++#define __qm_cl_touch_ro(qm, o) dcbt_ro((qm)->addr_ce + (o)) ++#define __qm_cl_touch_rw(qm, o) dcbt_rw((qm)->addr_ce + (o)) ++#define __qm_cl_in(qm, o) __raw_readl((qm)->addr_ce + (o)) ++#define __qm_cl_out(qm, o, val) \ ++ do { \ ++ u32 *__tmpclout = (qm)->addr_ce + (o); \ ++ __raw_writel((val), __tmpclout); \ ++ dcbf(__tmpclout); \ ++ } while (0) ++#define __qm_cl_invalidate(qm, o) dcbi((qm)->addr_ce + (o)) ++#define qm_cl_touch_ro(reg) __qm_cl_touch_ro(&portal->addr, QM_CL_##reg##_CENA) ++#define qm_cl_touch_rw(reg) __qm_cl_touch_rw(&portal->addr, QM_CL_##reg##_CENA) ++#define qm_cl_in(reg) __qm_cl_in(&portal->addr, QM_CL_##reg##_CENA) ++#define qm_cl_out(reg, val) __qm_cl_out(&portal->addr, QM_CL_##reg##_CENA, val) ++#define qm_cl_invalidate(reg)\ ++ __qm_cl_invalidate(&portal->addr, QM_CL_##reg##_CENA) ++ ++/* Cache-enabled ring access */ ++#define qm_cl(base, idx) ((void *)base + ((idx) << 6)) ++ ++/* Cyclic helper for rings. FIXME: once we are able to do fine-grain perf ++ * analysis, look at using the "extra" bit in the ring index registers to avoid ++ * cyclic issues. */ ++static inline u8 qm_cyc_diff(u8 ringsize, u8 first, u8 last) ++{ ++ /* 'first' is included, 'last' is excluded */ ++ if (first <= last) ++ return last - first; ++ return ringsize + last - first; ++} ++ ++/* Portal modes. ++ * Enum types; ++ * pmode == production mode ++ * cmode == consumption mode, ++ * dmode == h/w dequeue mode. ++ * Enum values use 3 letter codes. First letter matches the portal mode, ++ * remaining two letters indicate; ++ * ci == cache-inhibited portal register ++ * ce == cache-enabled portal register ++ * vb == in-band valid-bit (cache-enabled) ++ * dc == DCA (Discrete Consumption Acknowledgement), DQRR-only ++ * As for "enum qm_dqrr_dmode", it should be self-explanatory. ++ */ ++enum qm_eqcr_pmode { /* matches QCSP_CFG::EPM */ ++ qm_eqcr_pci = 0, /* PI index, cache-inhibited */ ++ qm_eqcr_pce = 1, /* PI index, cache-enabled */ ++ qm_eqcr_pvb = 2 /* valid-bit */ ++}; ++enum qm_dqrr_dmode { /* matches QCSP_CFG::DP */ ++ qm_dqrr_dpush = 0, /* SDQCR + VDQCR */ ++ qm_dqrr_dpull = 1 /* PDQCR */ ++}; ++enum qm_dqrr_pmode { /* s/w-only */ ++ qm_dqrr_pci, /* reads DQRR_PI_CINH */ ++ qm_dqrr_pce, /* reads DQRR_PI_CENA */ ++ qm_dqrr_pvb /* reads valid-bit */ ++}; ++enum qm_dqrr_cmode { /* matches QCSP_CFG::DCM */ ++ qm_dqrr_cci = 0, /* CI index, cache-inhibited */ ++ qm_dqrr_cce = 1, /* CI index, cache-enabled */ ++ qm_dqrr_cdc = 2 /* Discrete Consumption Acknowledgement */ ++}; ++enum qm_mr_pmode { /* s/w-only */ ++ qm_mr_pci, /* reads MR_PI_CINH */ ++ qm_mr_pce, /* reads MR_PI_CENA */ ++ qm_mr_pvb /* reads valid-bit */ ++}; ++enum qm_mr_cmode { /* matches QCSP_CFG::MM */ ++ qm_mr_cci = 0, /* CI index, cache-inhibited */ ++ qm_mr_cce = 1 /* CI index, cache-enabled */ ++}; ++ ++ ++/* ------------------------- */ ++/* --- Portal structures --- */ ++ ++#define QM_EQCR_SIZE 8 ++#define QM_DQRR_SIZE 16 ++#define QM_MR_SIZE 8 ++ ++struct qm_eqcr { ++ struct qm_eqcr_entry *ring, *cursor; ++ u8 ci, available, ithresh, vbit; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ u32 busy; ++ enum qm_eqcr_pmode pmode; ++#endif ++}; ++ ++struct qm_dqrr { ++ const struct qm_dqrr_entry *ring, *cursor; ++ u8 pi, ci, fill, ithresh, vbit; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ enum qm_dqrr_dmode dmode; ++ enum qm_dqrr_pmode pmode; ++ enum qm_dqrr_cmode cmode; ++#endif ++}; ++ ++struct qm_mr { ++ const struct qm_mr_entry *ring, *cursor; ++ u8 pi, ci, fill, ithresh, vbit; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ enum qm_mr_pmode pmode; ++ enum qm_mr_cmode cmode; ++#endif ++}; ++ ++struct qm_mc { ++ struct qm_mc_command *cr; ++ struct qm_mc_result *rr; ++ u8 rridx, vbit; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ enum { ++ /* Can be _mc_start()ed */ ++ qman_mc_idle, ++ /* Can be _mc_commit()ed or _mc_abort()ed */ ++ qman_mc_user, ++ /* Can only be _mc_retry()ed */ ++ qman_mc_hw ++ } state; ++#endif ++}; ++ ++#define QM_PORTAL_ALIGNMENT ____cacheline_aligned ++ ++struct qm_addr { ++ void __iomem *addr_ce; /* cache-enabled */ ++ void __iomem *addr_ci; /* cache-inhibited */ ++}; ++ ++struct qm_portal { ++ /* In the non-CONFIG_FSL_DPA_CHECKING case, the following stuff up to ++ * and including 'mc' fits within a cacheline (yay!). The 'config' part ++ * is setup-only, so isn't a cause for a concern. In other words, don't ++ * rearrange this structure on a whim, there be dragons ... */ ++ struct qm_addr addr; ++ struct qm_eqcr eqcr; ++ struct qm_dqrr dqrr; ++ struct qm_mr mr; ++ struct qm_mc mc; ++} QM_PORTAL_ALIGNMENT; ++ ++ ++/* ---------------- */ ++/* --- EQCR API --- */ ++ ++/* Bit-wise logic to wrap a ring pointer by clearing the "carry bit" */ ++#define EQCR_CARRYCLEAR(p) \ ++ (void *)((unsigned long)(p) & (~(unsigned long)(QM_EQCR_SIZE << 6))) ++ ++/* Bit-wise logic to convert a ring pointer to a ring index */ ++static inline u8 EQCR_PTR2IDX(struct qm_eqcr_entry *e) ++{ ++ return ((uintptr_t)e >> 6) & (QM_EQCR_SIZE - 1); ++} ++ ++/* Increment the 'cursor' ring pointer, taking 'vbit' into account */ ++static inline void EQCR_INC(struct qm_eqcr *eqcr) ++{ ++ /* NB: this is odd-looking, but experiments show that it generates fast ++ * code with essentially no branching overheads. We increment to the ++ * next EQCR pointer and handle overflow and 'vbit'. */ ++ struct qm_eqcr_entry *partial = eqcr->cursor + 1; ++ eqcr->cursor = EQCR_CARRYCLEAR(partial); ++ if (partial != eqcr->cursor) ++ eqcr->vbit ^= QM_EQCR_VERB_VBIT; ++} ++ ++static inline int qm_eqcr_init(struct qm_portal *portal, ++ enum qm_eqcr_pmode pmode, ++ unsigned int eq_stash_thresh, ++ int eq_stash_prio) ++{ ++ /* This use of 'register', as well as all other occurrences, is because ++ * it has been observed to generate much faster code with gcc than is ++ * otherwise the case. */ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ u32 cfg; ++ u8 pi; ++ ++ eqcr->ring = portal->addr.addr_ce + QM_CL_EQCR; ++ eqcr->ci = qm_in(EQCR_CI_CINH) & (QM_EQCR_SIZE - 1); ++ qm_cl_invalidate(EQCR_CI); ++ pi = qm_in(EQCR_PI_CINH) & (QM_EQCR_SIZE - 1); ++ eqcr->cursor = eqcr->ring + pi; ++ eqcr->vbit = (qm_in(EQCR_PI_CINH) & QM_EQCR_SIZE) ? ++ QM_EQCR_VERB_VBIT : 0; ++ eqcr->available = QM_EQCR_SIZE - 1 - ++ qm_cyc_diff(QM_EQCR_SIZE, eqcr->ci, pi); ++ eqcr->ithresh = qm_in(EQCR_ITR); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ eqcr->busy = 0; ++ eqcr->pmode = pmode; ++#endif ++ cfg = (qm_in(CFG) & 0x00ffffff) | ++ (eq_stash_thresh << 28) | /* QCSP_CFG: EST */ ++ (eq_stash_prio << 26) | /* QCSP_CFG: EP */ ++ ((pmode & 0x3) << 24); /* QCSP_CFG::EPM */ ++ qm_out(CFG, cfg); ++ return 0; ++} ++ ++static inline unsigned int qm_eqcr_get_ci_stashing(struct qm_portal *portal) ++{ ++ return (qm_in(CFG) >> 28) & 0x7; ++} ++ ++static inline void qm_eqcr_finish(struct qm_portal *portal) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ u8 pi, ci; ++ u32 cfg; ++ ++ /* ++ * Disable EQCI stashing because the QMan only ++ * presents the value it previously stashed to ++ * maintain coherency. Setting the stash threshold ++ * to 1 then 0 ensures that QMan has resyncronized ++ * its internal copy so that the portal is clean ++ * when it is reinitialized in the future ++ */ ++ cfg = (qm_in(CFG) & 0x0fffffff) | ++ (1 << 28); /* QCSP_CFG: EST */ ++ qm_out(CFG, cfg); ++ cfg &= 0x0fffffff; /* stash threshold = 0 */ ++ qm_out(CFG, cfg); ++ ++ pi = qm_in(EQCR_PI_CINH) & (QM_EQCR_SIZE - 1); ++ ci = qm_in(EQCR_CI_CINH) & (QM_EQCR_SIZE - 1); ++ ++ /* Refresh EQCR CI cache value */ ++ qm_cl_invalidate(EQCR_CI); ++ eqcr->ci = qm_cl_in(EQCR_CI) & (QM_EQCR_SIZE - 1); ++ ++ DPA_ASSERT(!eqcr->busy); ++ if (pi != EQCR_PTR2IDX(eqcr->cursor)) ++ pr_crit("losing uncommited EQCR entries\n"); ++ if (ci != eqcr->ci) ++ pr_crit("missing existing EQCR completions\n"); ++ if (eqcr->ci != EQCR_PTR2IDX(eqcr->cursor)) ++ pr_crit("EQCR destroyed unquiesced\n"); ++} ++ ++static inline struct qm_eqcr_entry *qm_eqcr_start_no_stash(struct qm_portal ++ *portal) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ DPA_ASSERT(!eqcr->busy); ++ if (!eqcr->available) ++ return NULL; ++ ++ ++#ifdef CONFIG_FSL_DPA_CHECKING ++ eqcr->busy = 1; ++#endif ++ dcbz_64(eqcr->cursor); ++ return eqcr->cursor; ++} ++ ++static inline struct qm_eqcr_entry *qm_eqcr_start_stash(struct qm_portal ++ *portal) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ u8 diff, old_ci; ++ ++ DPA_ASSERT(!eqcr->busy); ++ if (!eqcr->available) { ++ old_ci = eqcr->ci; ++ eqcr->ci = qm_cl_in(EQCR_CI) & (QM_EQCR_SIZE - 1); ++ diff = qm_cyc_diff(QM_EQCR_SIZE, old_ci, eqcr->ci); ++ eqcr->available += diff; ++ if (!diff) ++ return NULL; ++ } ++#ifdef CONFIG_FSL_DPA_CHECKING ++ eqcr->busy = 1; ++#endif ++ dcbz_64(eqcr->cursor); ++ return eqcr->cursor; ++} ++ ++static inline void qm_eqcr_abort(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_eqcr *eqcr = &portal->eqcr; ++ DPA_ASSERT(eqcr->busy); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ eqcr->busy = 0; ++#endif ++} ++ ++static inline struct qm_eqcr_entry *qm_eqcr_pend_and_next( ++ struct qm_portal *portal, u8 myverb) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ DPA_ASSERT(eqcr->busy); ++ DPA_ASSERT(eqcr->pmode != qm_eqcr_pvb); ++ if (eqcr->available == 1) ++ return NULL; ++ eqcr->cursor->__dont_write_directly__verb = myverb | eqcr->vbit; ++ dcbf(eqcr->cursor); ++ EQCR_INC(eqcr); ++ eqcr->available--; ++ dcbz_64(eqcr->cursor); ++ return eqcr->cursor; ++} ++ ++#define EQCR_COMMIT_CHECKS(eqcr) \ ++do { \ ++ DPA_ASSERT(eqcr->busy); \ ++ DPA_ASSERT(eqcr->cursor->orp == (eqcr->cursor->orp & 0x00ffffff)); \ ++ DPA_ASSERT(eqcr->cursor->fqid == (eqcr->cursor->fqid & 0x00ffffff)); \ ++} while (0) ++ ++static inline void qm_eqcr_pci_commit(struct qm_portal *portal, u8 myverb) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ EQCR_COMMIT_CHECKS(eqcr); ++ DPA_ASSERT(eqcr->pmode == qm_eqcr_pci); ++ eqcr->cursor->__dont_write_directly__verb = myverb | eqcr->vbit; ++ EQCR_INC(eqcr); ++ eqcr->available--; ++ dcbf(eqcr->cursor); ++ hwsync(); ++ qm_out(EQCR_PI_CINH, EQCR_PTR2IDX(eqcr->cursor)); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ eqcr->busy = 0; ++#endif ++} ++ ++static inline void qm_eqcr_pce_prefetch(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_eqcr *eqcr = &portal->eqcr; ++ DPA_ASSERT(eqcr->pmode == qm_eqcr_pce); ++ qm_cl_invalidate(EQCR_PI); ++ qm_cl_touch_rw(EQCR_PI); ++} ++ ++static inline void qm_eqcr_pce_commit(struct qm_portal *portal, u8 myverb) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ EQCR_COMMIT_CHECKS(eqcr); ++ DPA_ASSERT(eqcr->pmode == qm_eqcr_pce); ++ eqcr->cursor->__dont_write_directly__verb = myverb | eqcr->vbit; ++ EQCR_INC(eqcr); ++ eqcr->available--; ++ dcbf(eqcr->cursor); ++ lwsync(); ++ qm_cl_out(EQCR_PI, EQCR_PTR2IDX(eqcr->cursor)); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ eqcr->busy = 0; ++#endif ++} ++ ++static inline void qm_eqcr_pvb_commit(struct qm_portal *portal, u8 myverb) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ struct qm_eqcr_entry *eqcursor; ++ EQCR_COMMIT_CHECKS(eqcr); ++ DPA_ASSERT(eqcr->pmode == qm_eqcr_pvb); ++ lwsync(); ++ eqcursor = eqcr->cursor; ++ eqcursor->__dont_write_directly__verb = myverb | eqcr->vbit; ++ dcbf(eqcursor); ++ EQCR_INC(eqcr); ++ eqcr->available--; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ eqcr->busy = 0; ++#endif ++} ++ ++static inline u8 qm_eqcr_cci_update(struct qm_portal *portal) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ u8 diff, old_ci = eqcr->ci; ++ eqcr->ci = qm_in(EQCR_CI_CINH) & (QM_EQCR_SIZE - 1); ++ diff = qm_cyc_diff(QM_EQCR_SIZE, old_ci, eqcr->ci); ++ eqcr->available += diff; ++ return diff; ++} ++ ++static inline void qm_eqcr_cce_prefetch(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_eqcr *eqcr = &portal->eqcr; ++ qm_cl_touch_ro(EQCR_CI); ++} ++ ++static inline u8 qm_eqcr_cce_update(struct qm_portal *portal) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ u8 diff, old_ci = eqcr->ci; ++ eqcr->ci = qm_cl_in(EQCR_CI) & (QM_EQCR_SIZE - 1); ++ qm_cl_invalidate(EQCR_CI); ++ diff = qm_cyc_diff(QM_EQCR_SIZE, old_ci, eqcr->ci); ++ eqcr->available += diff; ++ return diff; ++} ++ ++static inline u8 qm_eqcr_get_ithresh(struct qm_portal *portal) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ return eqcr->ithresh; ++} ++ ++static inline void qm_eqcr_set_ithresh(struct qm_portal *portal, u8 ithresh) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ eqcr->ithresh = ithresh; ++ qm_out(EQCR_ITR, ithresh); ++} ++ ++static inline u8 qm_eqcr_get_avail(struct qm_portal *portal) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ return eqcr->available; ++} ++ ++static inline u8 qm_eqcr_get_fill(struct qm_portal *portal) ++{ ++ register struct qm_eqcr *eqcr = &portal->eqcr; ++ return QM_EQCR_SIZE - 1 - eqcr->available; ++} ++ ++ ++/* ---------------- */ ++/* --- DQRR API --- */ ++ ++/* FIXME: many possible improvements; ++ * - look at changing the API to use pointer rather than index parameters now ++ * that 'cursor' is a pointer, ++ * - consider moving other parameters to pointer if it could help (ci) ++ */ ++ ++#define DQRR_CARRYCLEAR(p) \ ++ (void *)((unsigned long)(p) & (~(unsigned long)(QM_DQRR_SIZE << 6))) ++ ++static inline u8 DQRR_PTR2IDX(const struct qm_dqrr_entry *e) ++{ ++ return ((uintptr_t)e >> 6) & (QM_DQRR_SIZE - 1); ++} ++ ++static inline const struct qm_dqrr_entry *DQRR_INC( ++ const struct qm_dqrr_entry *e) ++{ ++ return DQRR_CARRYCLEAR(e + 1); ++} ++ ++static inline void qm_dqrr_set_maxfill(struct qm_portal *portal, u8 mf) ++{ ++ qm_out(CFG, (qm_in(CFG) & 0xff0fffff) | ++ ((mf & (QM_DQRR_SIZE - 1)) << 20)); ++} ++ ++static inline void qm_dqrr_cci_consume(struct qm_portal *portal, u8 num) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cci); ++ dqrr->ci = (dqrr->ci + num) & (QM_DQRR_SIZE - 1); ++ qm_out(DQRR_CI_CINH, dqrr->ci); ++} ++ ++static inline void qm_dqrr_cce_consume(struct qm_portal *portal, u8 num) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cce); ++ dqrr->ci = (dqrr->ci + num) & (QM_DQRR_SIZE - 1); ++ qm_cl_out(DQRR_CI, dqrr->ci); ++} ++ ++static inline void qm_dqrr_cdc_consume_n(struct qm_portal *portal, u16 bitmask) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc); ++ qm_out(DQRR_DCAP, (1 << 8) | /* DQRR_DCAP::S */ ++ ((u32)bitmask << 16)); /* DQRR_DCAP::DCAP_CI */ ++ dqrr->ci = qm_in(DQRR_CI_CINH) & (QM_DQRR_SIZE - 1); ++ dqrr->fill = qm_cyc_diff(QM_DQRR_SIZE, dqrr->ci, dqrr->pi); ++} ++ ++static inline int qm_dqrr_init(struct qm_portal *portal, ++ const struct qm_portal_config *config, ++ enum qm_dqrr_dmode dmode, ++ __maybe_unused enum qm_dqrr_pmode pmode, ++ enum qm_dqrr_cmode cmode, u8 max_fill) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ u32 cfg; ++ ++ /* Make sure the DQRR will be idle when we enable */ ++ qm_out(DQRR_SDQCR, 0); ++ qm_out(DQRR_VDQCR, 0); ++ qm_out(DQRR_PDQCR, 0); ++ dqrr->ring = portal->addr.addr_ce + QM_CL_DQRR; ++ dqrr->pi = qm_in(DQRR_PI_CINH) & (QM_DQRR_SIZE - 1); ++ dqrr->ci = qm_in(DQRR_CI_CINH) & (QM_DQRR_SIZE - 1); ++ dqrr->cursor = dqrr->ring + dqrr->ci; ++ dqrr->fill = qm_cyc_diff(QM_DQRR_SIZE, dqrr->ci, dqrr->pi); ++ dqrr->vbit = (qm_in(DQRR_PI_CINH) & QM_DQRR_SIZE) ? ++ QM_DQRR_VERB_VBIT : 0; ++ dqrr->ithresh = qm_in(DQRR_ITR); ++ ++ /* Free up pending DQRR entries if any as per current DCM */ ++ if (dqrr->fill) { ++ enum qm_dqrr_cmode dcm = (qm_in(CFG) >> 16) & 3; ++ ++#ifdef CONFIG_FSL_DPA_CHECKING ++ dqrr->cmode = dcm; ++#endif ++ switch (dcm) { ++ case qm_dqrr_cci: ++ qm_dqrr_cci_consume(portal, dqrr->fill); ++ break; ++ case qm_dqrr_cce: ++ qm_dqrr_cce_consume(portal, dqrr->fill); ++ break; ++ case qm_dqrr_cdc: ++ qm_dqrr_cdc_consume_n(portal, (QM_DQRR_SIZE - 1)); ++ break; ++ default: ++ DPA_ASSERT(0); ++ } ++ } ++ ++#ifdef CONFIG_FSL_DPA_CHECKING ++ dqrr->dmode = dmode; ++ dqrr->pmode = pmode; ++ dqrr->cmode = cmode; ++#endif ++ /* Invalidate every ring entry before beginning */ ++ for (cfg = 0; cfg < QM_DQRR_SIZE; cfg++) ++ dcbi(qm_cl(dqrr->ring, cfg)); ++ cfg = (qm_in(CFG) & 0xff000f00) | ++ ((max_fill & (QM_DQRR_SIZE - 1)) << 20) | /* DQRR_MF */ ++ ((dmode & 1) << 18) | /* DP */ ++ ((cmode & 3) << 16) | /* DCM */ ++ 0xa0 | /* RE+SE */ ++ (0 ? 0x40 : 0) | /* Ignore RP */ ++ (0 ? 0x10 : 0); /* Ignore SP */ ++ qm_out(CFG, cfg); ++ qm_dqrr_set_maxfill(portal, max_fill); ++ return 0; ++} ++ ++static inline void qm_dqrr_finish(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if ((dqrr->cmode != qm_dqrr_cdc) && ++ (dqrr->ci != DQRR_PTR2IDX(dqrr->cursor))) ++ pr_crit("Ignoring completed DQRR entries\n"); ++#endif ++} ++ ++static inline const struct qm_dqrr_entry *qm_dqrr_current( ++ struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ if (!dqrr->fill) ++ return NULL; ++ return dqrr->cursor; ++} ++ ++static inline u8 qm_dqrr_cursor(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ return DQRR_PTR2IDX(dqrr->cursor); ++} ++ ++static inline u8 qm_dqrr_next(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->fill); ++ dqrr->cursor = DQRR_INC(dqrr->cursor); ++ return --dqrr->fill; ++} ++ ++static inline u8 qm_dqrr_pci_update(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ u8 diff, old_pi = dqrr->pi; ++ DPA_ASSERT(dqrr->pmode == qm_dqrr_pci); ++ dqrr->pi = qm_in(DQRR_PI_CINH) & (QM_DQRR_SIZE - 1); ++ diff = qm_cyc_diff(QM_DQRR_SIZE, old_pi, dqrr->pi); ++ dqrr->fill += diff; ++ return diff; ++} ++ ++static inline void qm_dqrr_pce_prefetch(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->pmode == qm_dqrr_pce); ++ qm_cl_invalidate(DQRR_PI); ++ qm_cl_touch_ro(DQRR_PI); ++} ++ ++static inline u8 qm_dqrr_pce_update(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ u8 diff, old_pi = dqrr->pi; ++ DPA_ASSERT(dqrr->pmode == qm_dqrr_pce); ++ dqrr->pi = qm_cl_in(DQRR_PI) & (QM_DQRR_SIZE - 1); ++ diff = qm_cyc_diff(QM_DQRR_SIZE, old_pi, dqrr->pi); ++ dqrr->fill += diff; ++ return diff; ++} ++ ++static inline void qm_dqrr_pvb_update(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ const struct qm_dqrr_entry *res = qm_cl(dqrr->ring, dqrr->pi); ++ DPA_ASSERT(dqrr->pmode == qm_dqrr_pvb); ++ /* when accessing 'verb', use __raw_readb() to ensure that compiler ++ * inlining doesn't try to optimise out "excess reads". */ ++ if ((__raw_readb(&res->verb) & QM_DQRR_VERB_VBIT) == dqrr->vbit) { ++ dqrr->pi = (dqrr->pi + 1) & (QM_DQRR_SIZE - 1); ++ if (!dqrr->pi) ++ dqrr->vbit ^= QM_DQRR_VERB_VBIT; ++ dqrr->fill++; ++ } ++} ++ ++ ++static inline void qm_dqrr_cci_consume_to_current(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cci); ++ dqrr->ci = DQRR_PTR2IDX(dqrr->cursor); ++ qm_out(DQRR_CI_CINH, dqrr->ci); ++} ++ ++static inline void qm_dqrr_cce_prefetch(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cce); ++ qm_cl_invalidate(DQRR_CI); ++ qm_cl_touch_rw(DQRR_CI); ++} ++ ++static inline void qm_dqrr_cce_consume_to_current(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cce); ++ dqrr->ci = DQRR_PTR2IDX(dqrr->cursor); ++ qm_cl_out(DQRR_CI, dqrr->ci); ++} ++ ++static inline void qm_dqrr_cdc_consume_1(struct qm_portal *portal, u8 idx, ++ int park) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc); ++ DPA_ASSERT(idx < QM_DQRR_SIZE); ++ qm_out(DQRR_DCAP, (0 << 8) | /* S */ ++ ((park ? 1 : 0) << 6) | /* PK */ ++ idx); /* DCAP_CI */ ++} ++ ++static inline void qm_dqrr_cdc_consume_1ptr(struct qm_portal *portal, ++ const struct qm_dqrr_entry *dq, ++ int park) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ u8 idx = DQRR_PTR2IDX(dq); ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc); ++ DPA_ASSERT((dqrr->ring + idx) == dq); ++ DPA_ASSERT(idx < QM_DQRR_SIZE); ++ qm_out(DQRR_DCAP, (0 << 8) | /* DQRR_DCAP::S */ ++ ((park ? 1 : 0) << 6) | /* DQRR_DCAP::PK */ ++ idx); /* DQRR_DCAP::DCAP_CI */ ++} ++ ++static inline u8 qm_dqrr_cdc_cci(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc); ++ return qm_in(DQRR_CI_CINH) & (QM_DQRR_SIZE - 1); ++} ++ ++static inline void qm_dqrr_cdc_cce_prefetch(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc); ++ qm_cl_invalidate(DQRR_CI); ++ qm_cl_touch_ro(DQRR_CI); ++} ++ ++static inline u8 qm_dqrr_cdc_cce(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc); ++ return qm_cl_in(DQRR_CI) & (QM_DQRR_SIZE - 1); ++} ++ ++static inline u8 qm_dqrr_get_ci(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode != qm_dqrr_cdc); ++ return dqrr->ci; ++} ++ ++static inline void qm_dqrr_park(struct qm_portal *portal, u8 idx) ++{ ++ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode != qm_dqrr_cdc); ++ qm_out(DQRR_DCAP, (0 << 8) | /* S */ ++ (1 << 6) | /* PK */ ++ (idx & (QM_DQRR_SIZE - 1))); /* DCAP_CI */ ++} ++ ++static inline void qm_dqrr_park_current(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ DPA_ASSERT(dqrr->cmode != qm_dqrr_cdc); ++ qm_out(DQRR_DCAP, (0 << 8) | /* S */ ++ (1 << 6) | /* PK */ ++ DQRR_PTR2IDX(dqrr->cursor)); /* DCAP_CI */ ++} ++ ++static inline void qm_dqrr_sdqcr_set(struct qm_portal *portal, u32 sdqcr) ++{ ++ qm_out(DQRR_SDQCR, sdqcr); ++} ++ ++static inline u32 qm_dqrr_sdqcr_get(struct qm_portal *portal) ++{ ++ return qm_in(DQRR_SDQCR); ++} ++ ++static inline void qm_dqrr_vdqcr_set(struct qm_portal *portal, u32 vdqcr) ++{ ++ qm_out(DQRR_VDQCR, vdqcr); ++} ++ ++static inline u32 qm_dqrr_vdqcr_get(struct qm_portal *portal) ++{ ++ return qm_in(DQRR_VDQCR); ++} ++ ++static inline void qm_dqrr_pdqcr_set(struct qm_portal *portal, u32 pdqcr) ++{ ++ qm_out(DQRR_PDQCR, pdqcr); ++} ++ ++static inline u32 qm_dqrr_pdqcr_get(struct qm_portal *portal) ++{ ++ return qm_in(DQRR_PDQCR); ++} ++ ++static inline u8 qm_dqrr_get_ithresh(struct qm_portal *portal) ++{ ++ register struct qm_dqrr *dqrr = &portal->dqrr; ++ return dqrr->ithresh; ++} ++ ++static inline void qm_dqrr_set_ithresh(struct qm_portal *portal, u8 ithresh) ++{ ++ qm_out(DQRR_ITR, ithresh); ++} ++ ++static inline u8 qm_dqrr_get_maxfill(struct qm_portal *portal) ++{ ++ return (qm_in(CFG) & 0x00f00000) >> 20; ++} ++ ++ ++/* -------------- */ ++/* --- MR API --- */ ++ ++#define MR_CARRYCLEAR(p) \ ++ (void *)((unsigned long)(p) & (~(unsigned long)(QM_MR_SIZE << 6))) ++ ++static inline u8 MR_PTR2IDX(const struct qm_mr_entry *e) ++{ ++ return ((uintptr_t)e >> 6) & (QM_MR_SIZE - 1); ++} ++ ++static inline const struct qm_mr_entry *MR_INC(const struct qm_mr_entry *e) ++{ ++ return MR_CARRYCLEAR(e + 1); ++} ++ ++static inline int qm_mr_init(struct qm_portal *portal, enum qm_mr_pmode pmode, ++ enum qm_mr_cmode cmode) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ u32 cfg; ++ ++ mr->ring = portal->addr.addr_ce + QM_CL_MR; ++ mr->pi = qm_in(MR_PI_CINH) & (QM_MR_SIZE - 1); ++ mr->ci = qm_in(MR_CI_CINH) & (QM_MR_SIZE - 1); ++ mr->cursor = mr->ring + mr->ci; ++ mr->fill = qm_cyc_diff(QM_MR_SIZE, mr->ci, mr->pi); ++ mr->vbit = (qm_in(MR_PI_CINH) & QM_MR_SIZE) ? QM_MR_VERB_VBIT : 0; ++ mr->ithresh = qm_in(MR_ITR); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mr->pmode = pmode; ++ mr->cmode = cmode; ++#endif ++ cfg = (qm_in(CFG) & 0xfffff0ff) | ++ ((cmode & 1) << 8); /* QCSP_CFG:MM */ ++ qm_out(CFG, cfg); ++ return 0; ++} ++ ++static inline void qm_mr_finish(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ if (mr->ci != MR_PTR2IDX(mr->cursor)) ++ pr_crit("Ignoring completed MR entries\n"); ++} ++ ++static inline const struct qm_mr_entry *qm_mr_current(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ if (!mr->fill) ++ return NULL; ++ return mr->cursor; ++} ++ ++static inline u8 qm_mr_cursor(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ return MR_PTR2IDX(mr->cursor); ++} ++ ++static inline u8 qm_mr_next(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ DPA_ASSERT(mr->fill); ++ mr->cursor = MR_INC(mr->cursor); ++ return --mr->fill; ++} ++ ++static inline u8 qm_mr_pci_update(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ u8 diff, old_pi = mr->pi; ++ DPA_ASSERT(mr->pmode == qm_mr_pci); ++ mr->pi = qm_in(MR_PI_CINH); ++ diff = qm_cyc_diff(QM_MR_SIZE, old_pi, mr->pi); ++ mr->fill += diff; ++ return diff; ++} ++ ++static inline void qm_mr_pce_prefetch(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_mr *mr = &portal->mr; ++ DPA_ASSERT(mr->pmode == qm_mr_pce); ++ qm_cl_invalidate(MR_PI); ++ qm_cl_touch_ro(MR_PI); ++} ++ ++static inline u8 qm_mr_pce_update(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ u8 diff, old_pi = mr->pi; ++ DPA_ASSERT(mr->pmode == qm_mr_pce); ++ mr->pi = qm_cl_in(MR_PI) & (QM_MR_SIZE - 1); ++ diff = qm_cyc_diff(QM_MR_SIZE, old_pi, mr->pi); ++ mr->fill += diff; ++ return diff; ++} ++ ++static inline void qm_mr_pvb_update(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ const struct qm_mr_entry *res = qm_cl(mr->ring, mr->pi); ++ DPA_ASSERT(mr->pmode == qm_mr_pvb); ++ /* when accessing 'verb', use __raw_readb() to ensure that compiler ++ * inlining doesn't try to optimise out "excess reads". */ ++ if ((__raw_readb(&res->verb) & QM_MR_VERB_VBIT) == mr->vbit) { ++ mr->pi = (mr->pi + 1) & (QM_MR_SIZE - 1); ++ if (!mr->pi) ++ mr->vbit ^= QM_MR_VERB_VBIT; ++ mr->fill++; ++ res = MR_INC(res); ++ } ++ dcbit_ro(res); ++} ++ ++static inline void qm_mr_cci_consume(struct qm_portal *portal, u8 num) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ DPA_ASSERT(mr->cmode == qm_mr_cci); ++ mr->ci = (mr->ci + num) & (QM_MR_SIZE - 1); ++ qm_out(MR_CI_CINH, mr->ci); ++} ++ ++static inline void qm_mr_cci_consume_to_current(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ DPA_ASSERT(mr->cmode == qm_mr_cci); ++ mr->ci = MR_PTR2IDX(mr->cursor); ++ qm_out(MR_CI_CINH, mr->ci); ++} ++ ++static inline void qm_mr_cce_prefetch(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_mr *mr = &portal->mr; ++ DPA_ASSERT(mr->cmode == qm_mr_cce); ++ qm_cl_invalidate(MR_CI); ++ qm_cl_touch_rw(MR_CI); ++} ++ ++static inline void qm_mr_cce_consume(struct qm_portal *portal, u8 num) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ DPA_ASSERT(mr->cmode == qm_mr_cce); ++ mr->ci = (mr->ci + num) & (QM_MR_SIZE - 1); ++ qm_cl_out(MR_CI, mr->ci); ++} ++ ++static inline void qm_mr_cce_consume_to_current(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ DPA_ASSERT(mr->cmode == qm_mr_cce); ++ mr->ci = MR_PTR2IDX(mr->cursor); ++ qm_cl_out(MR_CI, mr->ci); ++} ++ ++static inline u8 qm_mr_get_ci(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ return mr->ci; ++} ++ ++static inline u8 qm_mr_get_ithresh(struct qm_portal *portal) ++{ ++ register struct qm_mr *mr = &portal->mr; ++ return mr->ithresh; ++} ++ ++static inline void qm_mr_set_ithresh(struct qm_portal *portal, u8 ithresh) ++{ ++ qm_out(MR_ITR, ithresh); ++} ++ ++ ++/* ------------------------------ */ ++/* --- Management command API --- */ ++ ++static inline int qm_mc_init(struct qm_portal *portal) ++{ ++ register struct qm_mc *mc = &portal->mc; ++ mc->cr = portal->addr.addr_ce + QM_CL_CR; ++ mc->rr = portal->addr.addr_ce + QM_CL_RR0; ++ mc->rridx = (__raw_readb(&mc->cr->__dont_write_directly__verb) & ++ QM_MCC_VERB_VBIT) ? 0 : 1; ++ mc->vbit = mc->rridx ? QM_MCC_VERB_VBIT : 0; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = qman_mc_idle; ++#endif ++ return 0; ++} ++ ++static inline void qm_mc_finish(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_mc *mc = &portal->mc; ++ DPA_ASSERT(mc->state == qman_mc_idle); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ if (mc->state != qman_mc_idle) ++ pr_crit("Losing incomplete MC command\n"); ++#endif ++} ++ ++static inline struct qm_mc_command *qm_mc_start(struct qm_portal *portal) ++{ ++ register struct qm_mc *mc = &portal->mc; ++ DPA_ASSERT(mc->state == qman_mc_idle); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = qman_mc_user; ++#endif ++ dcbz_64(mc->cr); ++ return mc->cr; ++} ++ ++static inline void qm_mc_abort(struct qm_portal *portal) ++{ ++ __maybe_unused register struct qm_mc *mc = &portal->mc; ++ DPA_ASSERT(mc->state == qman_mc_user); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = qman_mc_idle; ++#endif ++} ++ ++static inline void qm_mc_commit(struct qm_portal *portal, u8 myverb) ++{ ++ register struct qm_mc *mc = &portal->mc; ++ struct qm_mc_result *rr = mc->rr + mc->rridx; ++ DPA_ASSERT(mc->state == qman_mc_user); ++ lwsync(); ++ mc->cr->__dont_write_directly__verb = myverb | mc->vbit; ++ dcbf(mc->cr); ++ dcbit_ro(rr); ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = qman_mc_hw; ++#endif ++} ++ ++static inline struct qm_mc_result *qm_mc_result(struct qm_portal *portal) ++{ ++ register struct qm_mc *mc = &portal->mc; ++ struct qm_mc_result *rr = mc->rr + mc->rridx; ++ DPA_ASSERT(mc->state == qman_mc_hw); ++ /* The inactive response register's verb byte always returns zero until ++ * its command is submitted and completed. This includes the valid-bit, ++ * in case you were wondering... */ ++ if (!__raw_readb(&rr->verb)) { ++ dcbit_ro(rr); ++ return NULL; ++ } ++ mc->rridx ^= 1; ++ mc->vbit ^= QM_MCC_VERB_VBIT; ++#ifdef CONFIG_FSL_DPA_CHECKING ++ mc->state = qman_mc_idle; ++#endif ++ return rr; ++} ++ ++ ++/* ------------------------------------- */ ++/* --- Portal interrupt register API --- */ ++ ++static inline int qm_isr_init(__always_unused struct qm_portal *portal) ++{ ++ return 0; ++} ++ ++static inline void qm_isr_finish(__always_unused struct qm_portal *portal) ++{ ++} ++ ++static inline void qm_isr_set_iperiod(struct qm_portal *portal, u16 iperiod) ++{ ++ qm_out(ITPR, iperiod); ++} ++ ++static inline u32 __qm_isr_read(struct qm_portal *portal, enum qm_isr_reg n) ++{ ++ return __qm_in(&portal->addr, QM_REG_ISR + (n << 2)); ++} ++ ++static inline void __qm_isr_write(struct qm_portal *portal, enum qm_isr_reg n, ++ u32 val) ++{ ++ __qm_out(&portal->addr, QM_REG_ISR + (n << 2), val); ++} ++ ++/* Cleanup FQs */ ++static inline int qm_shutdown_fq(struct qm_portal **portal, int portal_count, ++ u32 fqid) ++{ ++ ++ struct qm_mc_command *mcc; ++ struct qm_mc_result *mcr; ++ u8 state; ++ int orl_empty, fq_empty, i, drain = 0; ++ u32 result; ++ u32 channel, wq; ++ ++ /* Determine the state of the FQID */ ++ mcc = qm_mc_start(portal[0]); ++ mcc->queryfq_np.fqid = fqid; ++ qm_mc_commit(portal[0], QM_MCC_VERB_QUERYFQ_NP); ++ while (!(mcr = qm_mc_result(portal[0]))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ_NP); ++ state = mcr->queryfq_np.state & QM_MCR_NP_STATE_MASK; ++ if (state == QM_MCR_NP_STATE_OOS) ++ return 0; /* Already OOS, no need to do anymore checks */ ++ ++ /* Query which channel the FQ is using */ ++ mcc = qm_mc_start(portal[0]); ++ mcc->queryfq.fqid = fqid; ++ qm_mc_commit(portal[0], QM_MCC_VERB_QUERYFQ); ++ while (!(mcr = qm_mc_result(portal[0]))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ); ++ ++ /* Need to store these since the MCR gets reused */ ++ channel = mcr->queryfq.fqd.dest.channel; ++ wq = mcr->queryfq.fqd.dest.wq; ++ ++ switch (state) { ++ case QM_MCR_NP_STATE_TEN_SCHED: ++ case QM_MCR_NP_STATE_TRU_SCHED: ++ case QM_MCR_NP_STATE_ACTIVE: ++ case QM_MCR_NP_STATE_PARKED: ++ orl_empty = 0; ++ mcc = qm_mc_start(portal[0]); ++ mcc->alterfq.fqid = fqid; ++ qm_mc_commit(portal[0], QM_MCC_VERB_ALTER_RETIRE); ++ while (!(mcr = qm_mc_result(portal[0]))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_MCR_VERB_ALTER_RETIRE); ++ result = mcr->result; /* Make a copy as we reuse MCR below */ ++ ++ if (result == QM_MCR_RESULT_PENDING) { ++ /* Need to wait for the FQRN in the message ring, which ++ will only occur once the FQ has been drained. In ++ order for the FQ to drain the portal needs to be set ++ to dequeue from the channel the FQ is scheduled on */ ++ const struct qm_mr_entry *msg; ++ const struct qm_dqrr_entry *dqrr = NULL; ++ int found_fqrn = 0; ++ u16 dequeue_wq = 0; ++ ++ /* Flag that we need to drain FQ */ ++ drain = 1; ++ ++ if (channel >= qm_channel_pool1 && ++ channel < (qm_channel_pool1 + 15)) { ++ /* Pool channel, enable the bit in the portal */ ++ dequeue_wq = (channel - ++ qm_channel_pool1 + 1)<<4 | wq; ++ } else if (channel < qm_channel_pool1) { ++ /* Dedicated channel */ ++ dequeue_wq = wq; ++ } else { ++ pr_info("Cannot recover FQ 0x%x, it is " ++ "scheduled on channel 0x%x", ++ fqid, channel); ++ return -EBUSY; ++ } ++ /* Set the sdqcr to drain this channel */ ++ if (channel < qm_channel_pool1) ++ for (i = 0; i < portal_count; i++) ++ qm_dqrr_sdqcr_set(portal[i], ++ QM_SDQCR_TYPE_ACTIVE | ++ QM_SDQCR_CHANNELS_DEDICATED); ++ else ++ for (i = 0; i < portal_count; i++) ++ qm_dqrr_sdqcr_set( ++ portal[i], ++ QM_SDQCR_TYPE_ACTIVE | ++ QM_SDQCR_CHANNELS_POOL_CONV ++ (channel)); ++ while (!found_fqrn) { ++ /* Keep draining DQRR while checking the MR*/ ++ for (i = 0; i < portal_count; i++) { ++ qm_dqrr_pvb_update(portal[i]); ++ dqrr = qm_dqrr_current(portal[i]); ++ while (dqrr) { ++ qm_dqrr_cdc_consume_1ptr( ++ portal[i], dqrr, 0); ++ qm_dqrr_pvb_update(portal[i]); ++ qm_dqrr_next(portal[i]); ++ dqrr = qm_dqrr_current( ++ portal[i]); ++ } ++ /* Process message ring too */ ++ qm_mr_pvb_update(portal[i]); ++ msg = qm_mr_current(portal[i]); ++ while (msg) { ++ if ((msg->verb & ++ QM_MR_VERB_TYPE_MASK) ++ == QM_MR_VERB_FQRN) ++ found_fqrn = 1; ++ qm_mr_next(portal[i]); ++ qm_mr_cci_consume_to_current( ++ portal[i]); ++ qm_mr_pvb_update(portal[i]); ++ msg = qm_mr_current(portal[i]); ++ } ++ cpu_relax(); ++ } ++ } ++ } ++ if (result != QM_MCR_RESULT_OK && ++ result != QM_MCR_RESULT_PENDING) { ++ /* error */ ++ pr_err("qman_retire_fq failed on FQ 0x%x, result=0x%x\n", ++ fqid, result); ++ return -1; ++ } ++ if (!(mcr->alterfq.fqs & QM_MCR_FQS_ORLPRESENT)) { ++ /* ORL had no entries, no need to wait until the ++ ERNs come in */ ++ orl_empty = 1; ++ } ++ /* Retirement succeeded, check to see if FQ needs ++ to be drained */ ++ if (drain || mcr->alterfq.fqs & QM_MCR_FQS_NOTEMPTY) { ++ /* FQ is Not Empty, drain using volatile DQ commands */ ++ fq_empty = 0; ++ do { ++ const struct qm_dqrr_entry *dqrr = NULL; ++ u32 vdqcr = fqid | QM_VDQCR_NUMFRAMES_SET(3); ++ qm_dqrr_vdqcr_set(portal[0], vdqcr); ++ ++ /* Wait for a dequeue to occur */ ++ while (dqrr == NULL) { ++ qm_dqrr_pvb_update(portal[0]); ++ dqrr = qm_dqrr_current(portal[0]); ++ if (!dqrr) ++ cpu_relax(); ++ } ++ /* Process the dequeues, making sure to ++ empty the ring completely */ ++ while (dqrr) { ++ if (dqrr->fqid == fqid && ++ dqrr->stat & QM_DQRR_STAT_FQ_EMPTY) ++ fq_empty = 1; ++ qm_dqrr_cdc_consume_1ptr(portal[0], ++ dqrr, 0); ++ qm_dqrr_pvb_update(portal[0]); ++ qm_dqrr_next(portal[0]); ++ dqrr = qm_dqrr_current(portal[0]); ++ } ++ } while (fq_empty == 0); ++ } ++ for (i = 0; i < portal_count; i++) ++ qm_dqrr_sdqcr_set(portal[i], 0); ++ ++ /* Wait for the ORL to have been completely drained */ ++ while (orl_empty == 0) { ++ const struct qm_mr_entry *msg; ++ qm_mr_pvb_update(portal[0]); ++ msg = qm_mr_current(portal[0]); ++ while (msg) { ++ if ((msg->verb & QM_MR_VERB_TYPE_MASK) == ++ QM_MR_VERB_FQRL) ++ orl_empty = 1; ++ qm_mr_next(portal[0]); ++ qm_mr_cci_consume_to_current(portal[0]); ++ qm_mr_pvb_update(portal[0]); ++ msg = qm_mr_current(portal[0]); ++ } ++ cpu_relax(); ++ } ++ mcc = qm_mc_start(portal[0]); ++ mcc->alterfq.fqid = fqid; ++ qm_mc_commit(portal[0], QM_MCC_VERB_ALTER_OOS); ++ while (!(mcr = qm_mc_result(portal[0]))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_MCR_VERB_ALTER_OOS); ++ if (mcr->result != QM_MCR_RESULT_OK) { ++ pr_err("OOS after drain Failed on FQID 0x%x, result 0x%x\n", ++ fqid, mcr->result); ++ return -1; ++ } ++ return 0; ++ case QM_MCR_NP_STATE_RETIRED: ++ /* Send OOS Command */ ++ mcc = qm_mc_start(portal[0]); ++ mcc->alterfq.fqid = fqid; ++ qm_mc_commit(portal[0], QM_MCC_VERB_ALTER_OOS); ++ while (!(mcr = qm_mc_result(portal[0]))) ++ cpu_relax(); ++ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == ++ QM_MCR_VERB_ALTER_OOS); ++ if (mcr->result) { ++ pr_err("OOS Failed on FQID 0x%x\n", fqid); ++ return -1; ++ } ++ return 0; ++ } ++ return -1; ++} +diff --git a/drivers/staging/fsl_qbman/qman_private.h b/drivers/staging/fsl_qbman/qman_private.h +new file mode 100644 +index 0000000..e9f60d5 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_private.h +@@ -0,0 +1,386 @@ ++/* Copyright 2008-2012 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 "dpa_sys.h" ++#include ++#include ++#include ++ ++#if !defined(CONFIG_FSL_QMAN_FQ_LOOKUP) && defined(CONFIG_PPC64) ++#error "_PPC64 requires _FSL_QMAN_FQ_LOOKUP" ++#endif ++ ++ /* ----------------- */ ++ /* Congestion Groups */ ++ /* ----------------- */ ++/* This wrapper represents a bit-array for the state of the 256 Qman congestion ++ * groups. Is also used as a *mask* for congestion groups, eg. so we ignore ++ * those that don't concern us. We harness the structure and accessor details ++ * already used in the management command to query congestion groups. */ ++struct qman_cgrs { ++ struct __qm_mcr_querycongestion q; ++}; ++static inline void qman_cgrs_init(struct qman_cgrs *c) ++{ ++ memset(c, 0, sizeof(*c)); ++} ++static inline void qman_cgrs_fill(struct qman_cgrs *c) ++{ ++ memset(c, 0xff, sizeof(*c)); ++} ++static inline int qman_cgrs_get(struct qman_cgrs *c, int num) ++{ ++ return QM_MCR_QUERYCONGESTION(&c->q, num); ++} ++static inline void qman_cgrs_set(struct qman_cgrs *c, int num) ++{ ++ c->q.__state[__CGR_WORD(num)] |= (0x80000000 >> __CGR_SHIFT(num)); ++} ++static inline void qman_cgrs_unset(struct qman_cgrs *c, int num) ++{ ++ c->q.__state[__CGR_WORD(num)] &= ~(0x80000000 >> __CGR_SHIFT(num)); ++} ++static inline int qman_cgrs_next(struct qman_cgrs *c, int num) ++{ ++ while ((++num < __CGR_NUM) && !qman_cgrs_get(c, num)) ++ ; ++ return num; ++} ++static inline void qman_cgrs_cp(struct qman_cgrs *dest, ++ const struct qman_cgrs *src) ++{ ++ *dest = *src; ++} ++static inline void qman_cgrs_and(struct qman_cgrs *dest, ++ const struct qman_cgrs *a, const struct qman_cgrs *b) ++{ ++ int ret; ++ u32 *_d = dest->q.__state; ++ const u32 *_a = a->q.__state; ++ const u32 *_b = b->q.__state; ++ for (ret = 0; ret < 8; ret++) ++ *(_d++) = *(_a++) & *(_b++); ++} ++static inline void qman_cgrs_xor(struct qman_cgrs *dest, ++ const struct qman_cgrs *a, const struct qman_cgrs *b) ++{ ++ int ret; ++ u32 *_d = dest->q.__state; ++ const u32 *_a = a->q.__state; ++ const u32 *_b = b->q.__state; ++ for (ret = 0; ret < 8; ret++) ++ *(_d++) = *(_a++) ^ *(_b++); ++} ++ ++ /* ----------------------- */ ++ /* CEETM Congestion Groups */ ++ /* ----------------------- */ ++/* This wrapper represents a bit-array for the state of the 512 Qman CEETM ++ * congestion groups. ++ */ ++struct qman_ccgrs { ++ struct __qm_mcr_querycongestion q[2]; ++}; ++static inline void qman_ccgrs_init(struct qman_ccgrs *c) ++{ ++ memset(c, 0, sizeof(*c)); ++} ++static inline void qman_ccgrs_fill(struct qman_ccgrs *c) ++{ ++ memset(c, 0xff, sizeof(*c)); ++} ++static inline int qman_ccgrs_get(struct qman_ccgrs *c, int num) ++{ ++ if (num < __CGR_NUM) ++ return QM_MCR_QUERYCONGESTION(&c->q[0], num); ++ else ++ return QM_MCR_QUERYCONGESTION(&c->q[1], (num - __CGR_NUM)); ++} ++static inline int qman_ccgrs_next(struct qman_ccgrs *c, int num) ++{ ++ while ((++num < __CGR_NUM) && !qman_ccgrs_get(c, num)) ++ ; ++ return num; ++} ++static inline void qman_ccgrs_cp(struct qman_ccgrs *dest, ++ const struct qman_ccgrs *src) ++{ ++ *dest = *src; ++} ++static inline void qman_ccgrs_and(struct qman_ccgrs *dest, ++ const struct qman_ccgrs *a, const struct qman_ccgrs *b) ++{ ++ int ret, i; ++ u32 *_d; ++ const u32 *_a, *_b; ++ for (i = 0; i < 2; i++) { ++ _d = dest->q[i].__state; ++ _a = a->q[i].__state; ++ _b = b->q[i].__state; ++ for (ret = 0; ret < 8; ret++) ++ *(_d++) = *(_a++) & *(_b++); ++ } ++} ++static inline void qman_ccgrs_xor(struct qman_ccgrs *dest, ++ const struct qman_ccgrs *a, const struct qman_ccgrs *b) ++{ ++ int ret, i; ++ u32 *_d; ++ const u32 *_a, *_b; ++ for (i = 0; i < 2; i++) { ++ _d = dest->q[i].__state; ++ _a = a->q[i].__state; ++ _b = b->q[i].__state; ++ for (ret = 0; ret < 8; ret++) ++ *(_d++) = *(_a++) ^ *(_b++); ++ } ++} ++ ++/* used by CCSR and portal interrupt code */ ++enum qm_isr_reg { ++ qm_isr_status = 0, ++ qm_isr_enable = 1, ++ qm_isr_disable = 2, ++ qm_isr_inhibit = 3 ++}; ++ ++struct qm_portal_config { ++ /* Corenet portal addresses; ++ * [0]==cache-enabled, [1]==cache-inhibited. */ ++ __iomem void *addr_virt[2]; ++ struct resource addr_phys[2]; ++ struct device dev; ++ struct iommu_domain *iommu_domain; ++ /* Allow these to be joined in lists */ ++ struct list_head list; ++ /* User-visible portal configuration settings */ ++ struct qman_portal_config public_cfg; ++ /* power management saved data */ ++ u32 saved_isdr; ++}; ++ ++/* Revision info (for errata and feature handling) */ ++#define QMAN_REV11 0x0101 ++#define QMAN_REV12 0x0102 ++#define QMAN_REV20 0x0200 ++#define QMAN_REV30 0x0300 ++#define QMAN_REV31 0x0301 ++/* QMan REV_2 register contains the Cfg option */ ++#define QMAN_REV_CFG_0 0x0 ++#define QMAN_REV_CFG_1 0x1 ++#define QMAN_REV_CFG_2 0x2 ++#define QMAN_REV_CFG_3 0x3 ++ ++extern u16 qman_ip_rev; /* 0 if uninitialised, otherwise QMAN_REVx */ ++extern u8 qman_ip_cfg; ++extern u32 qman_clk; ++extern u16 qman_portal_max; ++ ++#ifdef CONFIG_FSL_QMAN_CONFIG ++/* Hooks from qman_driver.c to qman_config.c */ ++int qman_init_ccsr(struct device_node *node); ++void qman_liodn_fixup(u16 channel); ++int qman_set_sdest(u16 channel, unsigned int cpu_idx); ++#endif ++ ++int qm_set_wpm(int wpm); ++int qm_get_wpm(int *wpm); ++ ++/* Hooks from qman_driver.c in to qman_high.c */ ++struct qman_portal *qman_create_portal( ++ struct qman_portal *portal, ++ const struct qm_portal_config *config, ++ const struct qman_cgrs *cgrs); ++ ++struct qman_portal *qman_create_affine_portal( ++ const struct qm_portal_config *config, ++ const struct qman_cgrs *cgrs); ++struct qman_portal *qman_create_affine_slave(struct qman_portal *redirect, ++ int cpu); ++const struct qm_portal_config *qman_destroy_affine_portal(void); ++void qman_destroy_portal(struct qman_portal *qm); ++ ++/* Hooks from fsl_usdpaa.c to qman_driver.c */ ++struct qm_portal_config *qm_get_unused_portal(void); ++struct qm_portal_config *qm_get_unused_portal_idx(uint32_t idx); ++ ++void qm_put_unused_portal(struct qm_portal_config *pcfg); ++void qm_set_liodns(struct qm_portal_config *pcfg); ++ ++/* This CGR feature is supported by h/w and required by unit-tests and the ++ * debugfs hooks, so is implemented in the driver. However it allows an explicit ++ * corruption of h/w fields by s/w that are usually incorruptible (because the ++ * counters are usually maintained entirely within h/w). As such, we declare ++ * this API internally. */ ++int qman_testwrite_cgr(struct qman_cgr *cgr, u64 i_bcnt, ++ struct qm_mcr_cgrtestwrite *result); ++ ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++/* If the fq object pointer is greater than the size of context_b field, ++ * than a lookup table is required. */ ++int qman_setup_fq_lookup_table(size_t num_entries); ++#endif ++ ++ ++/*************************************************/ ++/* QMan s/w corenet portal, low-level i/face */ ++/*************************************************/ ++ ++/* Note: most functions are only used by the high-level interface, so are ++ * inlined from qman_low.h. The stuff below is for use by other parts of the ++ * driver. */ ++ ++/* For qm_dqrr_sdqcr_set(); Choose one SOURCE. Choose one COUNT. Choose one ++ * dequeue TYPE. Choose TOKEN (8-bit). ++ * If SOURCE == CHANNELS, ++ * Choose CHANNELS_DEDICATED and/or CHANNELS_POOL(n). ++ * You can choose DEDICATED_PRECEDENCE if the portal channel should have ++ * priority. ++ * If SOURCE == SPECIFICWQ, ++ * Either select the work-queue ID with SPECIFICWQ_WQ(), or select the ++ * channel (SPECIFICWQ_DEDICATED or SPECIFICWQ_POOL()) and specify the ++ * work-queue priority (0-7) with SPECIFICWQ_WQ() - either way, you get the ++ * same value. ++ */ ++#define QM_SDQCR_SOURCE_CHANNELS 0x0 ++#define QM_SDQCR_SOURCE_SPECIFICWQ 0x40000000 ++#define QM_SDQCR_COUNT_EXACT1 0x0 ++#define QM_SDQCR_COUNT_UPTO3 0x20000000 ++#define QM_SDQCR_DEDICATED_PRECEDENCE 0x10000000 ++#define QM_SDQCR_TYPE_MASK 0x03000000 ++#define QM_SDQCR_TYPE_NULL 0x0 ++#define QM_SDQCR_TYPE_PRIO_QOS 0x01000000 ++#define QM_SDQCR_TYPE_ACTIVE_QOS 0x02000000 ++#define QM_SDQCR_TYPE_ACTIVE 0x03000000 ++#define QM_SDQCR_TOKEN_MASK 0x00ff0000 ++#define QM_SDQCR_TOKEN_SET(v) (((v) & 0xff) << 16) ++#define QM_SDQCR_TOKEN_GET(v) (((v) >> 16) & 0xff) ++#define QM_SDQCR_CHANNELS_DEDICATED 0x00008000 ++#define QM_SDQCR_SPECIFICWQ_MASK 0x000000f7 ++#define QM_SDQCR_SPECIFICWQ_DEDICATED 0x00000000 ++#define QM_SDQCR_SPECIFICWQ_POOL(n) ((n) << 4) ++#define QM_SDQCR_SPECIFICWQ_WQ(n) (n) ++ ++/* For qm_dqrr_vdqcr_set(): use FQID(n) to fill in the frame queue ID */ ++#define QM_VDQCR_FQID_MASK 0x00ffffff ++#define QM_VDQCR_FQID(n) ((n) & QM_VDQCR_FQID_MASK) ++ ++/* For qm_dqrr_pdqcr_set(); Choose one MODE. Choose one COUNT. ++ * If MODE==SCHEDULED ++ * Choose SCHEDULED_CHANNELS or SCHEDULED_SPECIFICWQ. Choose one dequeue TYPE. ++ * If CHANNELS, ++ * Choose CHANNELS_DEDICATED and/or CHANNELS_POOL() channels. ++ * You can choose DEDICATED_PRECEDENCE if the portal channel should have ++ * priority. ++ * If SPECIFICWQ, ++ * Either select the work-queue ID with SPECIFICWQ_WQ(), or select the ++ * channel (SPECIFICWQ_DEDICATED or SPECIFICWQ_POOL()) and specify the ++ * work-queue priority (0-7) with SPECIFICWQ_WQ() - either way, you get the ++ * same value. ++ * If MODE==UNSCHEDULED ++ * Choose FQID(). ++ */ ++#define QM_PDQCR_MODE_SCHEDULED 0x0 ++#define QM_PDQCR_MODE_UNSCHEDULED 0x80000000 ++#define QM_PDQCR_SCHEDULED_CHANNELS 0x0 ++#define QM_PDQCR_SCHEDULED_SPECIFICWQ 0x40000000 ++#define QM_PDQCR_COUNT_EXACT1 0x0 ++#define QM_PDQCR_COUNT_UPTO3 0x20000000 ++#define QM_PDQCR_DEDICATED_PRECEDENCE 0x10000000 ++#define QM_PDQCR_TYPE_MASK 0x03000000 ++#define QM_PDQCR_TYPE_NULL 0x0 ++#define QM_PDQCR_TYPE_PRIO_QOS 0x01000000 ++#define QM_PDQCR_TYPE_ACTIVE_QOS 0x02000000 ++#define QM_PDQCR_TYPE_ACTIVE 0x03000000 ++#define QM_PDQCR_CHANNELS_DEDICATED 0x00008000 ++#define QM_PDQCR_CHANNELS_POOL(n) (0x00008000 >> (n)) ++#define QM_PDQCR_SPECIFICWQ_MASK 0x000000f7 ++#define QM_PDQCR_SPECIFICWQ_DEDICATED 0x00000000 ++#define QM_PDQCR_SPECIFICWQ_POOL(n) ((n) << 4) ++#define QM_PDQCR_SPECIFICWQ_WQ(n) (n) ++#define QM_PDQCR_FQID(n) ((n) & 0xffffff) ++ ++/* Used by all portal interrupt registers except 'inhibit' ++ * Channels with frame availability ++ */ ++#define QM_PIRQ_DQAVAIL 0x0000ffff ++ ++/* The DQAVAIL interrupt fields break down into these bits; */ ++#define QM_DQAVAIL_PORTAL 0x8000 /* Portal channel */ ++#define QM_DQAVAIL_POOL(n) (0x8000 >> (n)) /* Pool channel, n==[1..15] */ ++#define QM_DQAVAIL_MASK 0xffff ++/* This mask contains all the "irqsource" bits visible to API users */ ++#define QM_PIRQ_VISIBLE (QM_PIRQ_SLOW | QM_PIRQ_DQRI) ++ ++/* These are qm__(). So for example, qm_disable_write() means "write ++ * the disable register" rather than "disable the ability to write". */ ++#define qm_isr_status_read(qm) __qm_isr_read(qm, qm_isr_status) ++#define qm_isr_status_clear(qm, m) __qm_isr_write(qm, qm_isr_status, m) ++#define qm_isr_enable_read(qm) __qm_isr_read(qm, qm_isr_enable) ++#define qm_isr_enable_write(qm, v) __qm_isr_write(qm, qm_isr_enable, v) ++#define qm_isr_disable_read(qm) __qm_isr_read(qm, qm_isr_disable) ++#define qm_isr_disable_write(qm, v) __qm_isr_write(qm, qm_isr_disable, v) ++/* TODO: unfortunate name-clash here, reword? */ ++#define qm_isr_inhibit(qm) __qm_isr_write(qm, qm_isr_inhibit, 1) ++#define qm_isr_uninhibit(qm) __qm_isr_write(qm, qm_isr_inhibit, 0) ++ ++#ifdef CONFIG_FSL_QMAN_CONFIG ++int qman_have_ccsr(void); ++#else ++#define qman_have_ccsr 0 ++#endif ++ ++__init int qman_init(void); ++__init int qman_resource_init(void); ++ ++/* CEETM related */ ++#define QMAN_CEETM_MAX 2 ++extern u8 num_ceetms; ++extern struct qm_ceetm qman_ceetms[QMAN_CEETM_MAX]; ++int qman_sp_enable_ceetm_mode(enum qm_dc_portal portal, u16 sub_portal); ++int qman_sp_disable_ceetm_mode(enum qm_dc_portal portal, u16 sub_portal); ++int qman_ceetm_set_prescaler(enum qm_dc_portal portal); ++int qman_ceetm_get_prescaler(u16 *pres); ++int qman_ceetm_query_cq(unsigned int cqid, unsigned int dcpid, ++ struct qm_mcr_ceetm_cq_query *cq_query); ++int qman_ceetm_query_ccgr(struct qm_mcc_ceetm_ccgr_query *ccgr_query, ++ struct qm_mcr_ceetm_ccgr_query *response); ++int qman_ceetm_get_xsfdr(enum qm_dc_portal portal, unsigned int *num); ++ ++extern void *affine_portals[NR_CPUS]; ++const struct qm_portal_config *qman_get_qm_portal_config( ++ struct qman_portal *portal); ++ ++/* power management */ ++#ifdef CONFIG_SUSPEND ++void suspend_unused_qportal(void); ++void resume_unused_qportal(void); ++#endif +diff --git a/drivers/staging/fsl_qbman/qman_test.c b/drivers/staging/fsl_qbman/qman_test.c +new file mode 100644 +index 0000000..7995dd8 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_test.c +@@ -0,0 +1,57 @@ ++/* Copyright 2008-2011 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 "qman_test.h" ++ ++MODULE_AUTHOR("Geoff Thorpe"); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("Qman testing"); ++ ++static int test_init(void) ++{ ++ int loop = 1; ++ while (loop--) { ++#ifdef CONFIG_FSL_QMAN_TEST_STASH_POTATO ++ qman_test_hotpotato(); ++#endif ++#ifdef CONFIG_FSL_QMAN_TEST_HIGH ++ qman_test_high(); ++#endif ++ } ++ return 0; ++} ++ ++static void test_exit(void) ++{ ++} ++ ++module_init(test_init); ++module_exit(test_exit); +diff --git a/drivers/staging/fsl_qbman/qman_test.h b/drivers/staging/fsl_qbman/qman_test.h +new file mode 100644 +index 0000000..49c5679 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_test.h +@@ -0,0 +1,44 @@ ++/* Copyright 2008-2011 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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++void qman_test_hotpotato(void); ++void qman_test_high(void); ++ +diff --git a/drivers/staging/fsl_qbman/qman_test_high.c b/drivers/staging/fsl_qbman/qman_test_high.c +new file mode 100644 +index 0000000..45a459b +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_test_high.c +@@ -0,0 +1,213 @@ ++/* Copyright 2008-2011 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 "qman_test.h" ++ ++/*************/ ++/* constants */ ++/*************/ ++ ++#define CGR_ID 27 ++#define POOL_ID 2 ++#define FQ_FLAGS QMAN_FQ_FLAG_DYNAMIC_FQID ++#define NUM_ENQUEUES 10 ++#define NUM_PARTIAL 4 ++#define PORTAL_SDQCR (QM_SDQCR_SOURCE_CHANNELS | \ ++ QM_SDQCR_TYPE_PRIO_QOS | \ ++ QM_SDQCR_TOKEN_SET(0x98) | \ ++ QM_SDQCR_CHANNELS_DEDICATED | \ ++ QM_SDQCR_CHANNELS_POOL(POOL_ID)) ++#define PORTAL_OPAQUE ((void *)0xf00dbeef) ++#define VDQCR_FLAGS (QMAN_VOLATILE_FLAG_WAIT | QMAN_VOLATILE_FLAG_FINISH) ++ ++/*************************************/ ++/* Predeclarations (eg. for fq_base) */ ++/*************************************/ ++ ++static enum qman_cb_dqrr_result cb_dqrr(struct qman_portal *, ++ struct qman_fq *, ++ const struct qm_dqrr_entry *); ++static void cb_ern(struct qman_portal *, struct qman_fq *, ++ const struct qm_mr_entry *); ++static void cb_fqs(struct qman_portal *, struct qman_fq *, ++ const struct qm_mr_entry *); ++ ++/***************/ ++/* global vars */ ++/***************/ ++ ++static struct qm_fd fd, fd_dq; ++static struct qman_fq fq_base = { ++ .cb.dqrr = cb_dqrr, ++ .cb.ern = cb_ern, ++ .cb.fqs = cb_fqs ++}; ++static DECLARE_WAIT_QUEUE_HEAD(waitqueue); ++static int retire_complete, sdqcr_complete; ++ ++/**********************/ ++/* internal functions */ ++/**********************/ ++ ++/* Helpers for initialising and "incrementing" a frame descriptor */ ++static void fd_init(struct qm_fd *__fd) ++{ ++ qm_fd_addr_set64(__fd, 0xabdeadbeefLLU); ++ __fd->format = qm_fd_contig_big; ++ __fd->length29 = 0x0000ffff; ++ __fd->cmd = 0xfeedf00d; ++} ++ ++static void fd_inc(struct qm_fd *__fd) ++{ ++ u64 t = qm_fd_addr_get64(__fd); ++ int z = t >> 40; ++ t <<= 1; ++ if (z) ++ t |= 1; ++ qm_fd_addr_set64(__fd, t); ++ __fd->length29--; ++ __fd->cmd++; ++} ++ ++/* The only part of the 'fd' we can't memcmp() is the ppid */ ++static int fd_cmp(const struct qm_fd *a, const struct qm_fd *b) ++{ ++ int r = (qm_fd_addr_get64(a) == qm_fd_addr_get64(b)) ? 0 : -1; ++ if (!r) ++ r = a->format - b->format; ++ if (!r) ++ r = a->opaque - b->opaque; ++ if (!r) ++ r = a->cmd - b->cmd; ++ return r; ++} ++ ++/********/ ++/* test */ ++/********/ ++ ++static void do_enqueues(struct qman_fq *fq) ++{ ++ unsigned int loop; ++ for (loop = 0; loop < NUM_ENQUEUES; loop++) { ++ if (qman_enqueue(fq, &fd, QMAN_ENQUEUE_FLAG_WAIT | ++ (((loop + 1) == NUM_ENQUEUES) ? ++ QMAN_ENQUEUE_FLAG_WAIT_SYNC : 0))) ++ panic("qman_enqueue() failed\n"); ++ fd_inc(&fd); ++ } ++} ++ ++void qman_test_high(void) ++{ ++ unsigned int flags; ++ int res; ++ struct qman_fq *fq = &fq_base; ++ ++ pr_info("qman_test_high starting\n"); ++ fd_init(&fd); ++ fd_init(&fd_dq); ++ ++ /* Initialise (parked) FQ */ ++ if (qman_create_fq(0, FQ_FLAGS, fq)) ++ panic("qman_create_fq() failed\n"); ++ if (qman_init_fq(fq, QMAN_INITFQ_FLAG_LOCAL, NULL)) ++ panic("qman_init_fq() failed\n"); ++ ++ /* Do enqueues + VDQCR, twice. (Parked FQ) */ ++ do_enqueues(fq); ++ pr_info("VDQCR (till-empty);\n"); ++ if (qman_volatile_dequeue(fq, VDQCR_FLAGS, ++ QM_VDQCR_NUMFRAMES_TILLEMPTY)) ++ panic("qman_volatile_dequeue() failed\n"); ++ do_enqueues(fq); ++ pr_info("VDQCR (%d of %d);\n", NUM_PARTIAL, NUM_ENQUEUES); ++ if (qman_volatile_dequeue(fq, VDQCR_FLAGS, ++ QM_VDQCR_NUMFRAMES_SET(NUM_PARTIAL))) ++ panic("qman_volatile_dequeue() failed\n"); ++ pr_info("VDQCR (%d of %d);\n", NUM_ENQUEUES - NUM_PARTIAL, ++ NUM_ENQUEUES); ++ if (qman_volatile_dequeue(fq, VDQCR_FLAGS, ++ QM_VDQCR_NUMFRAMES_SET(NUM_ENQUEUES - NUM_PARTIAL))) ++ panic("qman_volatile_dequeue() failed\n"); ++ ++ do_enqueues(fq); ++ pr_info("scheduled dequeue (till-empty)\n"); ++ if (qman_schedule_fq(fq)) ++ panic("qman_schedule_fq() failed\n"); ++ wait_event(waitqueue, sdqcr_complete); ++ ++ /* Retire and OOS the FQ */ ++ res = qman_retire_fq(fq, &flags); ++ if (res < 0) ++ panic("qman_retire_fq() failed\n"); ++ wait_event(waitqueue, retire_complete); ++ if (flags & QMAN_FQ_STATE_BLOCKOOS) ++ panic("leaking frames\n"); ++ if (qman_oos_fq(fq)) ++ panic("qman_oos_fq() failed\n"); ++ qman_destroy_fq(fq, 0); ++ pr_info("qman_test_high finished\n"); ++} ++ ++static enum qman_cb_dqrr_result cb_dqrr(struct qman_portal *p, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dq) ++{ ++ if (fd_cmp(&fd_dq, &dq->fd)) { ++ pr_err("BADNESS: dequeued frame doesn't match;\n"); ++ BUG(); ++ } ++ fd_inc(&fd_dq); ++ if (!(dq->stat & QM_DQRR_STAT_UNSCHEDULED) && !fd_cmp(&fd_dq, &fd)) { ++ sdqcr_complete = 1; ++ wake_up(&waitqueue); ++ } ++ return qman_cb_dqrr_consume; ++} ++ ++static void cb_ern(struct qman_portal *p, struct qman_fq *fq, ++ const struct qm_mr_entry *msg) ++{ ++ panic("cb_ern() unimplemented"); ++} ++ ++static void cb_fqs(struct qman_portal *p, struct qman_fq *fq, ++ const struct qm_mr_entry *msg) ++{ ++ u8 verb = (msg->verb & QM_MR_VERB_TYPE_MASK); ++ if ((verb != QM_MR_VERB_FQRN) && (verb != QM_MR_VERB_FQRNI)) ++ panic("unexpected FQS message"); ++ pr_info("Retirement message received\n"); ++ retire_complete = 1; ++ wake_up(&waitqueue); ++} +diff --git a/drivers/staging/fsl_qbman/qman_test_hotpotato.c b/drivers/staging/fsl_qbman/qman_test_hotpotato.c +new file mode 100644 +index 0000000..05b744d +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_test_hotpotato.c +@@ -0,0 +1,497 @@ ++/* Copyright 2009-2012 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 ++#include ++#include ++#include "qman_test.h" ++ ++/* Algorithm: ++ * ++ * Each cpu will have HP_PER_CPU "handlers" set up, each of which incorporates ++ * an rx/tx pair of FQ objects (both of which are stashed on dequeue). The ++ * organisation of FQIDs is such that the HP_PER_CPU*NUM_CPUS handlers will ++ * shuttle a "hot potato" frame around them such that every forwarding action ++ * moves it from one cpu to another. (The use of more than one handler per cpu ++ * is to allow enough handlers/FQs to truly test the significance of caching - ++ * ie. when cache-expiries are occurring.) ++ * ++ * The "hot potato" frame content will be HP_NUM_WORDS*4 bytes in size, and the ++ * first and last words of the frame data will undergo a transformation step on ++ * each forwarding action. To achieve this, each handler will be assigned a ++ * 32-bit "mixer", that is produced using a 32-bit LFSR. When a frame is ++ * received by a handler, the mixer of the expected sender is XOR'd into all ++ * words of the entire frame, which is then validated against the original ++ * values. Then, before forwarding, the entire frame is XOR'd with the mixer of ++ * the current handler. Apart from validating that the frame is taking the ++ * expected path, this also provides some quasi-realistic overheads to each ++ * forwarding action - dereferencing *all* the frame data, computation, and ++ * conditional branching. There is a "special" handler designated to act as the ++ * instigator of the test by creating an enqueuing the "hot potato" frame, and ++ * to determine when the test has completed by counting HP_LOOPS iterations. ++ * ++ * Init phases: ++ * ++ * 1. prepare each cpu's 'hp_cpu' struct using on_each_cpu(,,1) and link them ++ * into 'hp_cpu_list'. Specifically, set processor_id, allocate HP_PER_CPU ++ * handlers and link-list them (but do no other handler setup). ++ * ++ * 2. scan over 'hp_cpu_list' HP_PER_CPU times, the first time sets each ++ * hp_cpu's 'iterator' to point to its first handler. With each loop, ++ * allocate rx/tx FQIDs and mixer values to the hp_cpu's iterator handler ++ * and advance the iterator for the next loop. This includes a final fixup, ++ * which connects the last handler to the first (and which is why phase 2 ++ * and 3 are separate). ++ * ++ * 3. scan over 'hp_cpu_list' HP_PER_CPU times, the first time sets each ++ * hp_cpu's 'iterator' to point to its first handler. With each loop, ++ * initialise FQ objects and advance the iterator for the next loop. ++ * Moreover, do this initialisation on the cpu it applies to so that Rx FQ ++ * initialisation targets the correct cpu. ++ */ ++ ++/* helper to run something on all cpus (can't use on_each_cpu(), as that invokes ++ * the fn from irq context, which is too restrictive). */ ++struct bstrap { ++ void (*fn)(void); ++ atomic_t started; ++}; ++static int bstrap_fn(void *__bstrap) ++{ ++ struct bstrap *bstrap = __bstrap; ++ atomic_inc(&bstrap->started); ++ bstrap->fn(); ++ while (!kthread_should_stop()) ++ msleep(1); ++ return 0; ++} ++static int on_all_cpus(void (*fn)(void)) ++{ ++ int cpu; ++ for_each_cpu(cpu, cpu_online_mask) { ++ struct bstrap bstrap = { ++ .fn = fn, ++ .started = ATOMIC_INIT(0) ++ }; ++ struct task_struct *k = kthread_create(bstrap_fn, &bstrap, ++ "hotpotato%d", cpu); ++ int ret; ++ if (IS_ERR(k)) ++ return -ENOMEM; ++ kthread_bind(k, cpu); ++ wake_up_process(k); ++ /* If we call kthread_stop() before the "wake up" has had an ++ * effect, then the thread may exit with -EINTR without ever ++ * running the function. So poll until it's started before ++ * requesting it to stop. */ ++ while (!atomic_read(&bstrap.started)) ++ msleep(10); ++ ret = kthread_stop(k); ++ if (ret) ++ return ret; ++ } ++ return 0; ++} ++ ++struct hp_handler { ++ ++ /* The following data is stashed when 'rx' is dequeued; */ ++ /* -------------- */ ++ /* The Rx FQ, dequeues of which will stash the entire hp_handler */ ++ struct qman_fq rx; ++ /* The Tx FQ we should forward to */ ++ struct qman_fq tx; ++ /* The value we XOR post-dequeue, prior to validating */ ++ u32 rx_mixer; ++ /* The value we XOR pre-enqueue, after validating */ ++ u32 tx_mixer; ++ /* what the hotpotato address should be on dequeue */ ++ dma_addr_t addr; ++ u32 *frame_ptr; ++ ++ /* The following data isn't (necessarily) stashed on dequeue; */ ++ /* -------------- */ ++ u32 fqid_rx, fqid_tx; ++ /* list node for linking us into 'hp_cpu' */ ++ struct list_head node; ++ /* Just to check ... */ ++ unsigned int processor_id; ++} ____cacheline_aligned; ++ ++struct hp_cpu { ++ /* identify the cpu we run on; */ ++ unsigned int processor_id; ++ /* root node for the per-cpu list of handlers */ ++ struct list_head handlers; ++ /* list node for linking us into 'hp_cpu_list' */ ++ struct list_head node; ++ /* when repeatedly scanning 'hp_list', each time linking the n'th ++ * handlers together, this is used as per-cpu iterator state */ ++ struct hp_handler *iterator; ++}; ++ ++/* Each cpu has one of these */ ++static DEFINE_PER_CPU(struct hp_cpu, hp_cpus); ++ ++/* links together the hp_cpu structs, in first-come first-serve order. */ ++static LIST_HEAD(hp_cpu_list); ++static spinlock_t hp_lock = __SPIN_LOCK_UNLOCKED(hp_lock); ++ ++static unsigned int hp_cpu_list_length; ++ ++/* the "special" handler, that starts and terminates the test. */ ++static struct hp_handler *special_handler; ++static int loop_counter; ++ ++/* handlers are allocated out of this, so they're properly aligned. */ ++static struct kmem_cache *hp_handler_slab; ++ ++/* this is the frame data */ ++static void *__frame_ptr; ++static u32 *frame_ptr; ++static dma_addr_t frame_dma; ++ ++/* the main function waits on this */ ++static DECLARE_WAIT_QUEUE_HEAD(queue); ++ ++#define HP_PER_CPU 2 ++#define HP_LOOPS 8 ++/* 80 bytes, like a small ethernet frame, and bleeds into a second cacheline */ ++#define HP_NUM_WORDS 80 ++/* First word of the LFSR-based frame data */ ++#define HP_FIRST_WORD 0xabbaf00d ++ ++static inline u32 do_lfsr(u32 prev) ++{ ++ return (prev >> 1) ^ (-(prev & 1u) & 0xd0000001u); ++} ++ ++static void allocate_frame_data(void) ++{ ++ u32 lfsr = HP_FIRST_WORD; ++ int loop; ++ struct platform_device *pdev = platform_device_alloc("foobar", -1); ++ if (!pdev) ++ panic("platform_device_alloc() failed"); ++ if (platform_device_add(pdev)) ++ panic("platform_device_add() failed"); ++ __frame_ptr = kmalloc(4 * HP_NUM_WORDS, GFP_KERNEL); ++ if (!__frame_ptr) ++ panic("kmalloc() failed"); ++ frame_ptr = (void *)(((unsigned long)__frame_ptr + 63) & ++ ~(unsigned long)63); ++ for (loop = 0; loop < HP_NUM_WORDS; loop++) { ++ frame_ptr[loop] = lfsr; ++ lfsr = do_lfsr(lfsr); ++ } ++ frame_dma = dma_map_single(&pdev->dev, frame_ptr, 4 * HP_NUM_WORDS, ++ DMA_BIDIRECTIONAL); ++ platform_device_del(pdev); ++ platform_device_put(pdev); ++} ++ ++static void deallocate_frame_data(void) ++{ ++ kfree(__frame_ptr); ++} ++ ++static inline void process_frame_data(struct hp_handler *handler, ++ const struct qm_fd *fd) ++{ ++ u32 *p = handler->frame_ptr; ++ u32 lfsr = HP_FIRST_WORD; ++ int loop; ++ if (qm_fd_addr_get64(fd) != handler->addr) ++ panic("bad frame address"); ++ for (loop = 0; loop < HP_NUM_WORDS; loop++, p++) { ++ *p ^= handler->rx_mixer; ++ if (*p != lfsr) ++ panic("corrupt frame data"); ++ *p ^= handler->tx_mixer; ++ lfsr = do_lfsr(lfsr); ++ } ++} ++ ++static enum qman_cb_dqrr_result normal_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dqrr) ++{ ++ struct hp_handler *handler = (struct hp_handler *)fq; ++ ++ process_frame_data(handler, &dqrr->fd); ++ if (qman_enqueue(&handler->tx, &dqrr->fd, 0)) ++ panic("qman_enqueue() failed"); ++ return qman_cb_dqrr_consume; ++} ++ ++static enum qman_cb_dqrr_result special_dqrr(struct qman_portal *portal, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dqrr) ++{ ++ struct hp_handler *handler = (struct hp_handler *)fq; ++ ++ process_frame_data(handler, &dqrr->fd); ++ if (++loop_counter < HP_LOOPS) { ++ if (qman_enqueue(&handler->tx, &dqrr->fd, 0)) ++ panic("qman_enqueue() failed"); ++ } else { ++ pr_info("Received final (%dth) frame\n", loop_counter); ++ wake_up(&queue); ++ } ++ return qman_cb_dqrr_consume; ++} ++ ++static void create_per_cpu_handlers(void) ++{ ++ struct hp_handler *handler; ++ int loop; ++ struct hp_cpu *hp_cpu = &get_cpu_var(hp_cpus); ++ ++ hp_cpu->processor_id = smp_processor_id(); ++ spin_lock(&hp_lock); ++ list_add_tail(&hp_cpu->node, &hp_cpu_list); ++ hp_cpu_list_length++; ++ spin_unlock(&hp_lock); ++ INIT_LIST_HEAD(&hp_cpu->handlers); ++ for (loop = 0; loop < HP_PER_CPU; loop++) { ++ handler = kmem_cache_alloc(hp_handler_slab, GFP_KERNEL); ++ if (!handler) ++ panic("kmem_cache_alloc() failed"); ++ handler->processor_id = hp_cpu->processor_id; ++ handler->addr = frame_dma; ++ handler->frame_ptr = frame_ptr; ++ list_add_tail(&handler->node, &hp_cpu->handlers); ++ } ++} ++ ++static void destroy_per_cpu_handlers(void) ++{ ++ struct list_head *loop, *tmp; ++ struct hp_cpu *hp_cpu = &get_cpu_var(hp_cpus); ++ ++ spin_lock(&hp_lock); ++ list_del(&hp_cpu->node); ++ spin_unlock(&hp_lock); ++ list_for_each_safe(loop, tmp, &hp_cpu->handlers) { ++ u32 flags; ++ struct hp_handler *handler = list_entry(loop, struct hp_handler, ++ node); ++ if (qman_retire_fq(&handler->rx, &flags)) ++ panic("qman_retire_fq(rx) failed"); ++ BUG_ON(flags & QMAN_FQ_STATE_BLOCKOOS); ++ if (qman_oos_fq(&handler->rx)) ++ panic("qman_oos_fq(rx) failed"); ++ qman_destroy_fq(&handler->rx, 0); ++ qman_destroy_fq(&handler->tx, 0); ++ qman_release_fqid(handler->fqid_rx); ++ list_del(&handler->node); ++ kmem_cache_free(hp_handler_slab, handler); ++ } ++} ++ ++static inline u8 num_cachelines(u32 offset) ++{ ++ u8 res = (offset + (L1_CACHE_BYTES - 1)) ++ / (L1_CACHE_BYTES); ++ if (res > 3) ++ return 3; ++ return res; ++} ++#define STASH_DATA_CL \ ++ num_cachelines(HP_NUM_WORDS * 4) ++#define STASH_CTX_CL \ ++ num_cachelines(offsetof(struct hp_handler, fqid_rx)) ++ ++static void init_handler(void *__handler) ++{ ++ struct qm_mcc_initfq opts; ++ struct hp_handler *handler = __handler; ++ BUG_ON(handler->processor_id != smp_processor_id()); ++ /* Set up rx */ ++ memset(&handler->rx, 0, sizeof(handler->rx)); ++ if (handler == special_handler) ++ handler->rx.cb.dqrr = special_dqrr; ++ else ++ handler->rx.cb.dqrr = normal_dqrr; ++ if (qman_create_fq(handler->fqid_rx, 0, &handler->rx)) ++ panic("qman_create_fq(rx) failed"); ++ memset(&opts, 0, sizeof(opts)); ++ opts.we_mask = QM_INITFQ_WE_FQCTRL | QM_INITFQ_WE_CONTEXTA; ++ opts.fqd.fq_ctrl = QM_FQCTRL_CTXASTASHING; ++ opts.fqd.context_a.stashing.data_cl = STASH_DATA_CL; ++ opts.fqd.context_a.stashing.context_cl = STASH_CTX_CL; ++ if (qman_init_fq(&handler->rx, QMAN_INITFQ_FLAG_SCHED | ++ QMAN_INITFQ_FLAG_LOCAL, &opts)) ++ panic("qman_init_fq(rx) failed"); ++ /* Set up tx */ ++ memset(&handler->tx, 0, sizeof(handler->tx)); ++ if (qman_create_fq(handler->fqid_tx, QMAN_FQ_FLAG_NO_MODIFY, ++ &handler->tx)) ++ panic("qman_create_fq(tx) failed"); ++} ++ ++static void init_phase2(void) ++{ ++ int loop; ++ u32 fqid = 0; ++ u32 lfsr = 0xdeadbeef; ++ struct hp_cpu *hp_cpu; ++ struct hp_handler *handler; ++ ++ for (loop = 0; loop < HP_PER_CPU; loop++) { ++ list_for_each_entry(hp_cpu, &hp_cpu_list, node) { ++ int ret; ++ if (!loop) ++ hp_cpu->iterator = list_first_entry( ++ &hp_cpu->handlers, ++ struct hp_handler, node); ++ else ++ hp_cpu->iterator = list_entry( ++ hp_cpu->iterator->node.next, ++ struct hp_handler, node); ++ /* Rx FQID is the previous handler's Tx FQID */ ++ hp_cpu->iterator->fqid_rx = fqid; ++ /* Allocate new FQID for Tx */ ++ ret = qman_alloc_fqid(&fqid); ++ if (ret) ++ panic("qman_alloc_fqid() failed"); ++ hp_cpu->iterator->fqid_tx = fqid; ++ /* Rx mixer is the previous handler's Tx mixer */ ++ hp_cpu->iterator->rx_mixer = lfsr; ++ /* Get new mixer for Tx */ ++ lfsr = do_lfsr(lfsr); ++ hp_cpu->iterator->tx_mixer = lfsr; ++ } ++ } ++ /* Fix up the first handler (fqid_rx==0, rx_mixer=0xdeadbeef) */ ++ hp_cpu = list_first_entry(&hp_cpu_list, struct hp_cpu, node); ++ handler = list_first_entry(&hp_cpu->handlers, struct hp_handler, node); ++ BUG_ON((handler->fqid_rx != 0) || (handler->rx_mixer != 0xdeadbeef)); ++ handler->fqid_rx = fqid; ++ handler->rx_mixer = lfsr; ++ /* and tag it as our "special" handler */ ++ special_handler = handler; ++} ++ ++static void init_phase3(void) ++{ ++ int loop; ++ struct hp_cpu *hp_cpu; ++ ++ for (loop = 0; loop < HP_PER_CPU; loop++) { ++ list_for_each_entry(hp_cpu, &hp_cpu_list, node) { ++ if (!loop) ++ hp_cpu->iterator = list_first_entry( ++ &hp_cpu->handlers, ++ struct hp_handler, node); ++ else ++ hp_cpu->iterator = list_entry( ++ hp_cpu->iterator->node.next, ++ struct hp_handler, node); ++ preempt_disable(); ++ if (hp_cpu->processor_id == smp_processor_id()) ++ init_handler(hp_cpu->iterator); ++ else ++ smp_call_function_single(hp_cpu->processor_id, ++ init_handler, hp_cpu->iterator, 1); ++ preempt_enable(); ++ } ++ } ++} ++ ++static void send_first_frame(void *ignore) ++{ ++ u32 *p = special_handler->frame_ptr; ++ u32 lfsr = HP_FIRST_WORD; ++ int loop; ++ struct qm_fd fd; ++ ++ BUG_ON(special_handler->processor_id != smp_processor_id()); ++ memset(&fd, 0, sizeof(fd)); ++ qm_fd_addr_set64(&fd, special_handler->addr); ++ fd.format = qm_fd_contig_big; ++ fd.length29 = HP_NUM_WORDS * 4; ++ for (loop = 0; loop < HP_NUM_WORDS; loop++, p++) { ++ if (*p != lfsr) ++ panic("corrupt frame data"); ++ *p ^= special_handler->tx_mixer; ++ lfsr = do_lfsr(lfsr); ++ } ++ pr_info("Sending first frame\n"); ++ if (qman_enqueue(&special_handler->tx, &fd, 0)) ++ panic("qman_enqueue() failed"); ++} ++ ++void qman_test_hotpotato(void) ++{ ++ if (cpumask_weight(cpu_online_mask) < 2) { ++ pr_info("qman_test_hotpotato, skip - only 1 CPU\n"); ++ return; ++ } ++ ++ pr_info("qman_test_hotpotato starting\n"); ++ ++ hp_cpu_list_length = 0; ++ loop_counter = 0; ++ hp_handler_slab = kmem_cache_create("hp_handler_slab", ++ sizeof(struct hp_handler), L1_CACHE_BYTES, ++ SLAB_HWCACHE_ALIGN, NULL); ++ if (!hp_handler_slab) ++ panic("kmem_cache_create() failed"); ++ ++ allocate_frame_data(); ++ ++ /* Init phase 1 */ ++ pr_info("Creating %d handlers per cpu...\n", HP_PER_CPU); ++ if (on_all_cpus(create_per_cpu_handlers)) ++ panic("on_each_cpu() failed"); ++ pr_info("Number of cpus: %d, total of %d handlers\n", ++ hp_cpu_list_length, hp_cpu_list_length * HP_PER_CPU); ++ ++ init_phase2(); ++ ++ init_phase3(); ++ ++ preempt_disable(); ++ if (special_handler->processor_id == smp_processor_id()) ++ send_first_frame(NULL); ++ else ++ smp_call_function_single(special_handler->processor_id, ++ send_first_frame, NULL, 1); ++ preempt_enable(); ++ ++ wait_event(queue, loop_counter == HP_LOOPS); ++ deallocate_frame_data(); ++ if (on_all_cpus(destroy_per_cpu_handlers)) ++ panic("on_each_cpu() failed"); ++ kmem_cache_destroy(hp_handler_slab); ++ pr_info("qman_test_hotpotato finished\n"); ++} +diff --git a/drivers/staging/fsl_qbman/qman_utility.c b/drivers/staging/fsl_qbman/qman_utility.c +new file mode 100644 +index 0000000..f1e3902 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/qman_utility.c +@@ -0,0 +1,129 @@ ++/* Copyright 2008-2011 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 "qman_private.h" ++ ++/* ----------------- */ ++/* --- FQID Pool --- */ ++ ++struct qman_fqid_pool { ++ /* Base and size of the FQID range */ ++ u32 fqid_base; ++ u32 total; ++ /* Number of FQIDs currently "allocated" */ ++ u32 used; ++ /* Allocation optimisation. When 'usedfqid_base = fqid_start; ++ pool->total = num; ++ pool->used = 0; ++ pool->next = 0; ++ pool->bits = kzalloc(QNUM_BYTES(num), GFP_KERNEL); ++ if (!pool->bits) { ++ kfree(pool); ++ return NULL; ++ } ++ /* If num is not an even multiple of QLONG_BITS (or even 8, for ++ * byte-oriented searching) then we fill the trailing bits with 1, to ++ * make them look allocated (permanently). */ ++ for (i = num + 1; i < QNUM_BITS(num); i++) ++ set_bit(i, pool->bits); ++ return pool; ++} ++EXPORT_SYMBOL(qman_fqid_pool_create); ++ ++int qman_fqid_pool_destroy(struct qman_fqid_pool *pool) ++{ ++ int ret = pool->used; ++ kfree(pool->bits); ++ kfree(pool); ++ return ret; ++} ++EXPORT_SYMBOL(qman_fqid_pool_destroy); ++ ++int qman_fqid_pool_alloc(struct qman_fqid_pool *pool, u32 *fqid) ++{ ++ int ret; ++ if (pool->used == pool->total) ++ return -ENOMEM; ++ *fqid = pool->fqid_base + pool->next; ++ ret = test_and_set_bit(pool->next, pool->bits); ++ BUG_ON(ret); ++ if (++pool->used == pool->total) ++ return 0; ++ pool->next = find_next_zero_bit(pool->bits, pool->total, pool->next); ++ if (pool->next >= pool->total) ++ pool->next = find_first_zero_bit(pool->bits, pool->total); ++ BUG_ON(pool->next >= pool->total); ++ return 0; ++} ++EXPORT_SYMBOL(qman_fqid_pool_alloc); ++ ++void qman_fqid_pool_free(struct qman_fqid_pool *pool, u32 fqid) ++{ ++ int ret; ++ ++ fqid -= pool->fqid_base; ++ ret = test_and_clear_bit(fqid, pool->bits); ++ BUG_ON(!ret); ++ if (pool->used-- == pool->total) ++ pool->next = fqid; ++} ++EXPORT_SYMBOL(qman_fqid_pool_free); ++ ++u32 qman_fqid_pool_used(struct qman_fqid_pool *pool) ++{ ++ return pool->used; ++} ++EXPORT_SYMBOL(qman_fqid_pool_used); +diff --git a/include/linux/fsl_bman.h b/include/linux/fsl_bman.h +new file mode 100644 +index 0000000..265d806 +--- /dev/null ++++ b/include/linux/fsl_bman.h +@@ -0,0 +1,519 @@ ++/* Copyright 2008-2012 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 FSL_BMAN_H ++#define FSL_BMAN_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* Last updated for v00.79 of the BG */ ++ ++/* Portal processing (interrupt) sources */ ++#define BM_PIRQ_RCRI 0x00000002 /* RCR Ring (below threshold) */ ++#define BM_PIRQ_BSCN 0x00000001 /* Buffer depletion State Change */ ++ ++/* This wrapper represents a bit-array for the depletion state of the 64 Bman ++ * buffer pools. */ ++struct bman_depletion { ++ u32 __state[2]; ++}; ++#define BMAN_DEPLETION_EMPTY { { 0x00000000, 0x00000000 } } ++#define BMAN_DEPLETION_FULL { { 0xffffffff, 0xffffffff } } ++#define __bmdep_word(x) ((x) >> 5) ++#define __bmdep_shift(x) ((x) & 0x1f) ++#define __bmdep_bit(x) (0x80000000 >> __bmdep_shift(x)) ++static inline void bman_depletion_init(struct bman_depletion *c) ++{ ++ c->__state[0] = c->__state[1] = 0; ++} ++static inline void bman_depletion_fill(struct bman_depletion *c) ++{ ++ c->__state[0] = c->__state[1] = ~0; ++} ++static inline int bman_depletion_get(const struct bman_depletion *c, u8 bpid) ++{ ++ return c->__state[__bmdep_word(bpid)] & __bmdep_bit(bpid); ++} ++static inline void bman_depletion_set(struct bman_depletion *c, u8 bpid) ++{ ++ c->__state[__bmdep_word(bpid)] |= __bmdep_bit(bpid); ++} ++static inline void bman_depletion_unset(struct bman_depletion *c, u8 bpid) ++{ ++ c->__state[__bmdep_word(bpid)] &= ~__bmdep_bit(bpid); ++} ++ ++/* ------------------------------------------------------- */ ++/* --- Bman data structures (and associated constants) --- */ ++ ++/* Represents s/w corenet portal mapped data structures */ ++struct bm_rcr_entry; /* RCR (Release Command Ring) entries */ ++struct bm_mc_command; /* MC (Management Command) command */ ++struct bm_mc_result; /* MC result */ ++ ++/* Code-reduction, define a wrapper for 48-bit buffers. In cases where a buffer ++ * pool id specific to this buffer is needed (BM_RCR_VERB_CMD_BPID_MULTI, ++ * BM_MCC_VERB_ACQUIRE), the 'bpid' field is used. */ ++struct bm_buffer { ++ union { ++ struct { ++ u8 __reserved1; ++ u8 bpid; ++ u16 hi; /* High 16-bits of 48-bit address */ ++ u32 lo; /* Low 32-bits of 48-bit address */ ++ }; ++ struct { ++ u64 __notaddress:16; ++ u64 addr:48; ++ }; ++ }; ++} __aligned(8); ++static inline u64 bm_buffer_get64(const struct bm_buffer *buf) ++{ ++ return buf->addr; ++} ++static inline dma_addr_t bm_buf_addr(const struct bm_buffer *buf) ++{ ++ return (dma_addr_t)buf->addr; ++} ++/* Macro, so we compile better if 'v' isn't always 64-bit */ ++#define bm_buffer_set64(buf, v) \ ++ do { \ ++ struct bm_buffer *__buf931 = (buf); \ ++ __buf931->hi = upper_32_bits(v); \ ++ __buf931->lo = lower_32_bits(v); \ ++ } while (0) ++ ++/* See 1.5.3.5.4: "Release Command" */ ++struct bm_rcr_entry { ++ union { ++ struct { ++ u8 __dont_write_directly__verb; ++ u8 bpid; /* used with BM_RCR_VERB_CMD_BPID_SINGLE */ ++ u8 __reserved1[62]; ++ }; ++ struct bm_buffer bufs[8]; ++ }; ++} __packed; ++#define BM_RCR_VERB_VBIT 0x80 ++#define BM_RCR_VERB_CMD_MASK 0x70 /* one of two values; */ ++#define BM_RCR_VERB_CMD_BPID_SINGLE 0x20 ++#define BM_RCR_VERB_CMD_BPID_MULTI 0x30 ++#define BM_RCR_VERB_BUFCOUNT_MASK 0x0f /* values 1..8 */ ++ ++/* See 1.5.3.1: "Acquire Command" */ ++/* See 1.5.3.2: "Query Command" */ ++struct bm_mcc_acquire { ++ u8 bpid; ++ u8 __reserved1[62]; ++} __packed; ++struct bm_mcc_query { ++ u8 __reserved2[63]; ++} __packed; ++struct bm_mc_command { ++ u8 __dont_write_directly__verb; ++ union { ++ struct bm_mcc_acquire acquire; ++ struct bm_mcc_query query; ++ }; ++} __packed; ++#define BM_MCC_VERB_VBIT 0x80 ++#define BM_MCC_VERB_CMD_MASK 0x70 /* where the verb contains; */ ++#define BM_MCC_VERB_CMD_ACQUIRE 0x10 ++#define BM_MCC_VERB_CMD_QUERY 0x40 ++#define BM_MCC_VERB_ACQUIRE_BUFCOUNT 0x0f /* values 1..8 go here */ ++ ++/* See 1.5.3.3: "Acquire Response" */ ++/* See 1.5.3.4: "Query Response" */ ++struct bm_pool_state { ++ u8 __reserved1[32]; ++ /* "availability state" and "depletion state" */ ++ struct { ++ u8 __reserved1[8]; ++ /* Access using bman_depletion_***() */ ++ struct bman_depletion state; ++ } as, ds; ++}; ++struct bm_mc_result { ++ union { ++ struct { ++ u8 verb; ++ u8 __reserved1[63]; ++ }; ++ union { ++ struct { ++ u8 __reserved1; ++ u8 bpid; ++ u8 __reserved2[62]; ++ }; ++ struct bm_buffer bufs[8]; ++ } acquire; ++ struct bm_pool_state query; ++ }; ++} __packed; ++#define BM_MCR_VERB_VBIT 0x80 ++#define BM_MCR_VERB_CMD_MASK BM_MCC_VERB_CMD_MASK ++#define BM_MCR_VERB_CMD_ACQUIRE BM_MCC_VERB_CMD_ACQUIRE ++#define BM_MCR_VERB_CMD_QUERY BM_MCC_VERB_CMD_QUERY ++#define BM_MCR_VERB_CMD_ERR_INVALID 0x60 ++#define BM_MCR_VERB_CMD_ERR_ECC 0x70 ++#define BM_MCR_VERB_ACQUIRE_BUFCOUNT BM_MCC_VERB_ACQUIRE_BUFCOUNT /* 0..8 */ ++/* Determine the "availability state" of pool 'p' from a query result 'r' */ ++#define BM_MCR_QUERY_AVAILABILITY(r, p) \ ++ bman_depletion_get(&r->query.as.state, p) ++/* Determine the "depletion state" of pool 'p' from a query result 'r' */ ++#define BM_MCR_QUERY_DEPLETION(r, p) \ ++ bman_depletion_get(&r->query.ds.state, p) ++ ++/*******************************************************************/ ++/* Managed (aka "shared" or "mux/demux") portal, high-level i/face */ ++/*******************************************************************/ ++ ++ /* Portal and Buffer Pools */ ++ /* ----------------------- */ ++/* Represents a managed portal */ ++struct bman_portal; ++ ++/* This object type represents Bman buffer pools. */ ++struct bman_pool; ++ ++struct bman_portal_config { ++ /* This is used for any "core-affine" portals, ie. default portals ++ * associated to the corresponding cpu. -1 implies that there is no core ++ * affinity configured. */ ++ int cpu; ++ /* portal interrupt line */ ++ int irq; ++ /* the unique index of this portal */ ++ u32 index; ++ /* Is this portal shared? (If so, it has coarser locking and demuxes ++ * processing on behalf of other CPUs.) */ ++ int is_shared; ++ /* These are the buffer pool IDs that may be used via this portal. */ ++ struct bman_depletion mask; ++}; ++ ++/* This callback type is used when handling pool depletion entry/exit. The ++ * 'cb_ctx' value is the opaque value associated with the pool object in ++ * bman_new_pool(). 'depleted' is non-zero on depletion-entry, and zero on ++ * depletion-exit. */ ++typedef void (*bman_cb_depletion)(struct bman_portal *bm, ++ struct bman_pool *pool, void *cb_ctx, int depleted); ++ ++/* This struct specifies parameters for a bman_pool object. */ ++struct bman_pool_params { ++ /* index of the buffer pool to encapsulate (0-63), ignored if ++ * BMAN_POOL_FLAG_DYNAMIC_BPID is set. */ ++ u32 bpid; ++ /* bit-mask of BMAN_POOL_FLAG_*** options */ ++ u32 flags; ++ /* depletion-entry/exit callback, if BMAN_POOL_FLAG_DEPLETION is set */ ++ bman_cb_depletion cb; ++ /* opaque user value passed as a parameter to 'cb' */ ++ void *cb_ctx; ++ /* depletion-entry/exit thresholds, if BMAN_POOL_FLAG_THRESH is set. NB: ++ * this is only allowed if BMAN_POOL_FLAG_DYNAMIC_BPID is used *and* ++ * when run in the control plane (which controls Bman CCSR). This array ++ * matches the definition of bm_pool_set(). */ ++ u32 thresholds[4]; ++}; ++ ++/* Flags to bman_new_pool() */ ++#define BMAN_POOL_FLAG_NO_RELEASE 0x00000001 /* can't release to pool */ ++#define BMAN_POOL_FLAG_ONLY_RELEASE 0x00000002 /* can only release to pool */ ++#define BMAN_POOL_FLAG_DEPLETION 0x00000004 /* track depletion entry/exit */ ++#define BMAN_POOL_FLAG_DYNAMIC_BPID 0x00000008 /* (de)allocate bpid */ ++#define BMAN_POOL_FLAG_THRESH 0x00000010 /* set depletion thresholds */ ++#define BMAN_POOL_FLAG_STOCKPILE 0x00000020 /* stockpile to reduce hw ops */ ++ ++/* Flags to bman_release() */ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++#define BMAN_RELEASE_FLAG_WAIT 0x00000001 /* wait if RCR is full */ ++#define BMAN_RELEASE_FLAG_WAIT_INT 0x00000002 /* if we wait, interruptible? */ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++#define BMAN_RELEASE_FLAG_WAIT_SYNC 0x00000004 /* if wait, until consumed? */ ++#endif ++#endif ++#define BMAN_RELEASE_FLAG_NOW 0x00000008 /* issue immediate release */ ++ ++/* Flags to bman_acquire() */ ++#define BMAN_ACQUIRE_FLAG_STOCKPILE 0x00000001 /* no hw op, stockpile only */ ++ ++ /* Portal Management */ ++ /* ----------------- */ ++/** ++ * bman_get_portal_config - get portal configuration settings ++ * ++ * This returns a read-only view of the current cpu's affine portal settings. ++ */ ++const struct bman_portal_config *bman_get_portal_config(void); ++ ++/** ++ * bman_irqsource_get - return the portal work that is interrupt-driven ++ * ++ * Returns a bitmask of BM_PIRQ_**I processing sources that are currently ++ * enabled for interrupt handling on the current cpu's affine portal. These ++ * sources will trigger the portal interrupt and the interrupt handler (or a ++ * tasklet/bottom-half it defers to) will perform the corresponding processing ++ * work. The bman_poll_***() functions will only process sources that are not in ++ * this bitmask. If the current CPU is sharing a portal hosted on another CPU, ++ * this always returns zero. ++ */ ++u32 bman_irqsource_get(void); ++ ++/** ++ * bman_irqsource_add - add processing sources to be interrupt-driven ++ * @bits: bitmask of BM_PIRQ_**I processing sources ++ * ++ * Adds processing sources that should be interrupt-driven (rather than ++ * processed via bman_poll_***() functions). Returns zero for success, or ++ * -EINVAL if the current CPU is sharing a portal hosted on another CPU. */ ++int bman_irqsource_add(u32 bits); ++ ++/** ++ * bman_irqsource_remove - remove processing sources from being interrupt-driven ++ * @bits: bitmask of BM_PIRQ_**I processing sources ++ * ++ * Removes processing sources from being interrupt-driven, so that they will ++ * instead be processed via bman_poll_***() functions. Returns zero for success, ++ * or -EINVAL if the current CPU is sharing a portal hosted on another CPU. */ ++int bman_irqsource_remove(u32 bits); ++ ++/** ++ * bman_affine_cpus - return a mask of cpus that have affine portals ++ */ ++const cpumask_t *bman_affine_cpus(void); ++ ++/** ++ * bman_poll_slow - process anything that isn't interrupt-driven. ++ * ++ * This function does any portal processing that isn't interrupt-driven. If the ++ * current CPU is sharing a portal hosted on another CPU, this function will ++ * return -EINVAL, otherwise the return value is a bitmask of BM_PIRQ_* sources ++ * indicating what interrupt sources were actually processed by the call. ++ * ++ * NB, unlike the legacy wrapper bman_poll(), this function will ++ * deterministically check for the presence of portal processing work and do it, ++ * which implies some latency even if there's nothing to do. The bman_poll() ++ * wrapper on the other hand (like the qman_poll() wrapper) attenuates this by ++ * checking for (and doing) portal processing infrequently. Ie. such that ++ * qman_poll() and bman_poll() can be called from core-processing loops. Use ++ * bman_poll_slow() when you yourself are deciding when to incur the overhead of ++ * processing. ++ */ ++u32 bman_poll_slow(void); ++ ++/** ++ * bman_poll - process anything that isn't interrupt-driven. ++ * ++ * Dispatcher logic on a cpu can use this to trigger any maintenance of the ++ * affine portal. This function does whatever processing is not triggered by ++ * interrupts. This is a legacy wrapper that can be used in core-processing ++ * loops but mitigates the performance overhead of portal processing by ++ * adaptively bypassing true portal processing most of the time. (Processing is ++ * done once every 10 calls if the previous processing revealed that work needed ++ * to be done, or once very 1000 calls if the previous processing revealed no ++ * work needed doing.) If you wish to control this yourself, call ++ * bman_poll_slow() instead, which always checks for portal processing work. ++ */ ++void bman_poll(void); ++ ++/** ++ * bman_rcr_is_empty - Determine if portal's RCR is empty ++ * ++ * For use in situations where a cpu-affine caller needs to determine when all ++ * releases for the local portal have been processed by Bman but can't use the ++ * BMAN_RELEASE_FLAG_WAIT_SYNC flag to do this from the final bman_release(). ++ * The function forces tracking of RCR consumption (which normally doesn't ++ * happen until release processing needs to find space to put new release ++ * commands), and returns zero if the ring still has unprocessed entries, ++ * non-zero if it is empty. ++ */ ++int bman_rcr_is_empty(void); ++ ++/** ++ * bman_alloc_bpid_range - Allocate a contiguous range of BPIDs ++ * @result: is set by the API to the base BPID of the allocated range ++ * @count: the number of BPIDs required ++ * @align: required alignment of the allocated range ++ * @partial: non-zero if the API can return fewer than @count BPIDs ++ * ++ * Returns the number of buffer pools allocated, or a negative error code. If ++ * @partial is non zero, the allocation request may return a smaller range of ++ * BPs than requested (though alignment will be as requested). If @partial is ++ * zero, the return value will either be 'count' or negative. ++ */ ++int bman_alloc_bpid_range(u32 *result, u32 count, u32 align, int partial); ++static inline int bman_alloc_bpid(u32 *result) ++{ ++ int ret = bman_alloc_bpid_range(result, 1, 0, 0); ++ return (ret > 0) ? 0 : ret; ++} ++ ++/** ++ * bman_release_bpid_range - Release the specified range of buffer pool IDs ++ * @bpid: the base BPID of the range to deallocate ++ * @count: the number of BPIDs in the range ++ * ++ * This function can also be used to seed the allocator with ranges of BPIDs ++ * that it can subsequently allocate from. ++ */ ++void bman_release_bpid_range(u32 bpid, unsigned int count); ++static inline void bman_release_bpid(u32 bpid) ++{ ++ bman_release_bpid_range(bpid, 1); ++} ++ ++int bman_reserve_bpid_range(u32 bpid, unsigned int count); ++static inline int bman_reserve_bpid(u32 bpid) ++{ ++ return bman_reserve_bpid_range(bpid, 1); ++} ++ ++void bman_seed_bpid_range(u32 bpid, unsigned int count); ++ ++ ++int bman_shutdown_pool(u32 bpid); ++ ++ /* Pool management */ ++ /* --------------- */ ++/** ++ * bman_new_pool - Allocates a Buffer Pool object ++ * @params: parameters specifying the buffer pool ID and behaviour ++ * ++ * Creates a pool object for the given @params. A portal and the depletion ++ * callback field of @params are only used if the BMAN_POOL_FLAG_DEPLETION flag ++ * is set. NB, the fields from @params are copied into the new pool object, so ++ * the structure provided by the caller can be released or reused after the ++ * function returns. ++ */ ++struct bman_pool *bman_new_pool(const struct bman_pool_params *params); ++ ++/** ++ * bman_free_pool - Deallocates a Buffer Pool object ++ * @pool: the pool object to release ++ * ++ */ ++void bman_free_pool(struct bman_pool *pool); ++ ++/** ++ * bman_get_params - Returns a pool object's parameters. ++ * @pool: the pool object ++ * ++ * The returned pointer refers to state within the pool object so must not be ++ * modified and can no longer be read once the pool object is destroyed. ++ */ ++const struct bman_pool_params *bman_get_params(const struct bman_pool *pool); ++ ++/** ++ * bman_release - Release buffer(s) to the buffer pool ++ * @pool: the buffer pool object to release to ++ * @bufs: an array of buffers to release ++ * @num: the number of buffers in @bufs (1-8) ++ * @flags: bit-mask of BMAN_RELEASE_FLAG_*** options ++ * ++ * Adds the given buffers to RCR entries. If the portal @p was created with the ++ * "COMPACT" flag, then it will be using a compaction algorithm to improve ++ * utilisation of RCR. As such, these buffers may join an existing ring entry ++ * and/or it may not be issued right away so as to allow future releases to join ++ * the same ring entry. Use the BMAN_RELEASE_FLAG_NOW flag to override this ++ * behaviour by committing the RCR entry (or entries) right away. If the RCR ++ * ring is full, the function will return -EBUSY unless BMAN_RELEASE_FLAG_WAIT ++ * is selected, in which case it will sleep waiting for space to become ++ * available in RCR. If the function receives a signal before such time (and ++ * BMAN_RELEASE_FLAG_WAIT_INT is set), the function returns -EINTR. Otherwise, ++ * it returns zero. ++ */ ++int bman_release(struct bman_pool *pool, const struct bm_buffer *bufs, u8 num, ++ u32 flags); ++ ++/** ++ * bman_acquire - Acquire buffer(s) from a buffer pool ++ * @pool: the buffer pool object to acquire from ++ * @bufs: array for storing the acquired buffers ++ * @num: the number of buffers desired (@bufs is at least this big) ++ * ++ * Issues an "Acquire" command via the portal's management command interface. ++ * The return value will be the number of buffers obtained from the pool, or a ++ * negative error code if a h/w error or pool starvation was encountered. In ++ * the latter case, the content of @bufs is undefined. ++ */ ++int bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, u8 num, ++ u32 flags); ++ ++/** ++ * bman_flush_stockpile - Flush stockpile buffer(s) to the buffer pool ++ * @pool: the buffer pool object the stockpile belongs ++ * @flags: bit-mask of BMAN_RELEASE_FLAG_*** options ++ * ++ * Adds stockpile buffers to RCR entries until the stockpile is empty. ++ * The return value will be a negative error code if a h/w error occurred. ++ * If BMAN_RELEASE_FLAG_NOW flag is passed and RCR ring is full, ++ * -EAGAIN will be returned. ++ */ ++int bman_flush_stockpile(struct bman_pool *pool, u32 flags); ++ ++/** ++ * bman_query_pools - Query all buffer pool states ++ * @state: storage for the queried availability and depletion states ++ */ ++int bman_query_pools(struct bm_pool_state *state); ++ ++#ifdef CONFIG_FSL_BMAN_CONFIG ++/** ++ * bman_query_free_buffers - Query how many free buffers are in buffer pool ++ * @pool: the buffer pool object to query ++ * ++ * Return the number of the free buffers ++ */ ++u32 bman_query_free_buffers(struct bman_pool *pool); ++ ++/** ++ * bman_update_pool_thresholds - Change the buffer pool's depletion thresholds ++ * @pool: the buffer pool object to which the thresholds will be set ++ * @thresholds: the new thresholds ++ */ ++int bman_update_pool_thresholds(struct bman_pool *pool, const u32 *thresholds); ++#endif ++ ++/** ++ * The below bman_p_***() variant might be called in a situation that the cpu ++ * which the portal affine to is not online yet. ++ * @bman_portal specifies which portal the API will use. ++*/ ++int bman_p_irqsource_add(struct bman_portal *p, __maybe_unused u32 bits); ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* FSL_BMAN_H */ +diff --git a/include/linux/fsl_qman.h b/include/linux/fsl_qman.h +new file mode 100644 +index 0000000..991729e +--- /dev/null ++++ b/include/linux/fsl_qman.h +@@ -0,0 +1,3464 @@ ++/* Copyright 2008-2012 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 FSL_QMAN_H ++#define FSL_QMAN_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* Last updated for v00.800 of the BG */ ++ ++/* Hardware constants */ ++#define QM_CHANNEL_SWPORTAL0 0 ++#define QMAN_CHANNEL_POOL1 0x21 ++#define QMAN_CHANNEL_CAAM 0x80 ++#define QMAN_CHANNEL_PME 0xa0 ++#define QMAN_CHANNEL_POOL1_REV3 0x401 ++#define QMAN_CHANNEL_CAAM_REV3 0x840 ++#define QMAN_CHANNEL_PME_REV3 0x860 ++#define QMAN_CHANNEL_DCE 0x8a0 ++#define QMAN_CHANNEL_DCE_QMANREV312 0x880 ++extern u16 qm_channel_pool1; ++extern u16 qm_channel_caam; ++extern u16 qm_channel_pme; ++extern u16 qm_channel_dce; ++enum qm_dc_portal { ++ qm_dc_portal_fman0 = 0, ++ qm_dc_portal_fman1 = 1, ++ qm_dc_portal_caam = 2, ++ qm_dc_portal_pme = 3, ++ qm_dc_portal_rman = 4, ++ qm_dc_portal_dce = 5 ++}; ++ ++/* Portal processing (interrupt) sources */ ++#define QM_PIRQ_CCSCI 0x00200000 /* CEETM Congestion State Change */ ++#define QM_PIRQ_CSCI 0x00100000 /* Congestion State Change */ ++#define QM_PIRQ_EQCI 0x00080000 /* Enqueue Command Committed */ ++#define QM_PIRQ_EQRI 0x00040000 /* EQCR Ring (below threshold) */ ++#define QM_PIRQ_DQRI 0x00020000 /* DQRR Ring (non-empty) */ ++#define QM_PIRQ_MRI 0x00010000 /* MR Ring (non-empty) */ ++/* This mask contains all the interrupt sources that need handling except DQRI, ++ * ie. that if present should trigger slow-path processing. */ ++#define QM_PIRQ_SLOW (QM_PIRQ_CSCI | QM_PIRQ_EQCI | QM_PIRQ_EQRI | \ ++ QM_PIRQ_MRI | QM_PIRQ_CCSCI) ++ ++/* --- Clock speed --- */ ++/* A qman driver instance may or may not know the current qman clock speed. ++ * However, certain CEETM calculations may not be possible if this is not known. ++ * The 'set' function will only succeed (return zero) if the driver did not ++ * already know the clock speed. Likewise, the 'get' function will only succeed ++ * if the driver does know the clock speed (either because it knew when booting, ++ * or was told via 'set'). In cases where software is running on a driver ++ * instance that does not know the clock speed (eg. on a hypervised data-plane), ++ * and the user can obtain the current qman clock speed by other means (eg. from ++ * a message sent from the control-plane), then the 'set' function can be used ++ * to enable rate-calculations in a driver where it would otherwise not be ++ * possible. */ ++int qm_get_clock(u64 *clock_hz); ++int qm_set_clock(u64 clock_hz); ++ ++/* For qman_static_dequeue_*** APIs */ ++#define QM_SDQCR_CHANNELS_POOL_MASK 0x00007fff ++/* for n in [1,15] */ ++#define QM_SDQCR_CHANNELS_POOL(n) (0x00008000 >> (n)) ++/* for conversion from n of qm_channel */ ++static inline u32 QM_SDQCR_CHANNELS_POOL_CONV(u16 channel) ++{ ++ return QM_SDQCR_CHANNELS_POOL(channel + 1 - qm_channel_pool1); ++} ++ ++/* For qman_volatile_dequeue(); Choose one PRECEDENCE. EXACT is optional. Use ++ * NUMFRAMES(n) (6-bit) or NUMFRAMES_TILLEMPTY to fill in the frame-count. Use ++ * FQID(n) to fill in the frame queue ID. */ ++#define QM_VDQCR_PRECEDENCE_VDQCR 0x0 ++#define QM_VDQCR_PRECEDENCE_SDQCR 0x80000000 ++#define QM_VDQCR_EXACT 0x40000000 ++#define QM_VDQCR_NUMFRAMES_MASK 0x3f000000 ++#define QM_VDQCR_NUMFRAMES_SET(n) (((n) & 0x3f) << 24) ++#define QM_VDQCR_NUMFRAMES_GET(n) (((n) >> 24) & 0x3f) ++#define QM_VDQCR_NUMFRAMES_TILLEMPTY QM_VDQCR_NUMFRAMES_SET(0) ++ ++ ++/* ------------------------------------------------------- */ ++/* --- Qman data structures (and associated constants) --- */ ++ ++/* Represents s/w corenet portal mapped data structures */ ++struct qm_eqcr_entry; /* EQCR (EnQueue Command Ring) entries */ ++struct qm_dqrr_entry; /* DQRR (DeQueue Response Ring) entries */ ++struct qm_mr_entry; /* MR (Message Ring) entries */ ++struct qm_mc_command; /* MC (Management Command) command */ ++struct qm_mc_result; /* MC result */ ++ ++/* See David Lapp's "Frame formats" document, "dpateam", Jan 07, 2008 */ ++#define QM_FD_FORMAT_SG 0x4 ++#define QM_FD_FORMAT_LONG 0x2 ++#define QM_FD_FORMAT_COMPOUND 0x1 ++enum qm_fd_format { ++ /* 'contig' implies a contiguous buffer, whereas 'sg' implies a ++ * scatter-gather table. 'big' implies a 29-bit length with no offset ++ * field, otherwise length is 20-bit and offset is 9-bit. 'compound' ++ * implies a s/g-like table, where each entry itself represents a frame ++ * (contiguous or scatter-gather) and the 29-bit "length" is ++ * interpreted purely for congestion calculations, ie. a "congestion ++ * weight". */ ++ qm_fd_contig = 0, ++ qm_fd_contig_big = QM_FD_FORMAT_LONG, ++ qm_fd_sg = QM_FD_FORMAT_SG, ++ qm_fd_sg_big = QM_FD_FORMAT_SG | QM_FD_FORMAT_LONG, ++ qm_fd_compound = QM_FD_FORMAT_COMPOUND ++}; ++ ++/* Capitalised versions are un-typed but can be used in static expressions */ ++#define QM_FD_CONTIG 0 ++#define QM_FD_CONTIG_BIG QM_FD_FORMAT_LONG ++#define QM_FD_SG QM_FD_FORMAT_SG ++#define QM_FD_SG_BIG (QM_FD_FORMAT_SG | QM_FD_FORMAT_LONG) ++#define QM_FD_COMPOUND QM_FD_FORMAT_COMPOUND ++ ++/* See 1.5.1.1: "Frame Descriptor (FD)" */ ++struct qm_fd { ++ union { ++ struct { ++ u8 dd:2; /* dynamic debug */ ++ u8 liodn_offset:6; ++ u8 bpid:8; /* Buffer Pool ID */ ++ u8 eliodn_offset:4; ++ u8 __reserved:4; ++ u8 addr_hi; /* high 8-bits of 40-bit address */ ++ u32 addr_lo; /* low 32-bits of 40-bit address */ ++ }; ++ struct { ++ u64 __notaddress:24; ++ /* More efficient address accessor */ ++ u64 addr:40; ++ }; ++ u64 opaque_addr; ++ }; ++ /* The 'format' field indicates the interpretation of the remaining 29 ++ * bits of the 32-bit word. For packing reasons, it is duplicated in the ++ * other union elements. Note, union'd structs are difficult to use with ++ * static initialisation under gcc, in which case use the "opaque" form ++ * with one of the macros. */ ++ union { ++ /* For easier/faster copying of this part of the fd (eg. from a ++ * DQRR entry to an EQCR entry) copy 'opaque' */ ++ u32 opaque; ++ /* If 'format' is _contig or _sg, 20b length and 9b offset */ ++ struct { ++ enum qm_fd_format format:3; ++ u16 offset:9; ++ u32 length20:20; ++ }; ++ /* If 'format' is _contig_big or _sg_big, 29b length */ ++ struct { ++ enum qm_fd_format _format1:3; ++ u32 length29:29; ++ }; ++ /* If 'format' is _compound, 29b "congestion weight" */ ++ struct { ++ enum qm_fd_format _format2:3; ++ u32 cong_weight:29; ++ }; ++ }; ++ union { ++ u32 cmd; ++ u32 status; ++ }; ++} __aligned(8); ++#define QM_FD_DD_NULL 0x00 ++#define QM_FD_PID_MASK 0x3f ++static inline u64 qm_fd_addr_get64(const struct qm_fd *fd) ++{ ++ return fd->addr; ++} ++ ++static inline dma_addr_t qm_fd_addr(const struct qm_fd *fd) ++{ ++ return (dma_addr_t)fd->addr; ++} ++/* Macro, so we compile better if 'v' isn't always 64-bit */ ++#define qm_fd_addr_set64(fd, v) \ ++ do { \ ++ struct qm_fd *__fd931 = (fd); \ ++ __fd931->addr = v; \ ++ } while (0) ++ ++/* For static initialisation of FDs (which is complicated by the use of unions ++ * in "struct qm_fd"), use the following macros. Note that; ++ * - 'dd', 'pid' and 'bpid' are ignored because there's no static initialisation ++ * use-case), ++ * - use capitalised QM_FD_*** formats for static initialisation. ++ */ ++#define QM_FD_FMT_20(cmd, addr_hi, addr_lo, fmt, off, len) \ ++ { 0, 0, 0, 0, 0, addr_hi, addr_lo, \ ++ { (((fmt)&0x7) << 29) | (((off)&0x1ff) << 20) | ((len)&0xfffff) }, \ ++ { cmd } } ++#define QM_FD_FMT_29(cmd, addr_hi, addr_lo, fmt, len) \ ++ { 0, 0, 0, 0, 0, addr_hi, addr_lo, \ ++ { (((fmt)&0x7) << 29) | ((len)&0x1fffffff) }, \ ++ { cmd } } ++ ++/* See 2.2.1.3 Multi-Core Datapath Acceleration Architecture */ ++#define QM_SG_OFFSET_MASK 0x1FFF ++struct qm_sg_entry { ++ union { ++ struct { ++ u8 __reserved1[3]; ++ u8 addr_hi; /* high 8-bits of 40-bit address */ ++ u32 addr_lo; /* low 32-bits of 40-bit address */ ++ }; ++ struct { ++ u64 __notaddress:24; ++ u64 addr:40; ++ }; ++ }; ++ u32 extension:1; /* Extension bit */ ++ u32 final:1; /* Final bit */ ++ u32 length:30; ++ u8 __reserved2; ++ u8 bpid; ++ u16 __reserved3:3; ++ u16 offset:13; ++} __packed; ++static inline u64 qm_sg_entry_get64(const struct qm_sg_entry *sg) ++{ ++ return sg->addr; ++} ++static inline dma_addr_t qm_sg_addr(const struct qm_sg_entry *sg) ++{ ++ return (dma_addr_t)sg->addr; ++} ++/* Macro, so we compile better if 'v' isn't always 64-bit */ ++#define qm_sg_entry_set64(sg, v) \ ++ do { \ ++ struct qm_sg_entry *__sg931 = (sg); \ ++ __sg931->addr = v; \ ++ } while (0) ++ ++/* See 1.5.8.1: "Enqueue Command" */ ++struct qm_eqcr_entry { ++ u8 __dont_write_directly__verb; ++ u8 dca; ++ u16 seqnum; ++ u32 orp; /* 24-bit */ ++ u32 fqid; /* 24-bit */ ++ u32 tag; ++ struct qm_fd fd; ++ u8 __reserved3[32]; ++} __packed; ++#define QM_EQCR_VERB_VBIT 0x80 ++#define QM_EQCR_VERB_CMD_MASK 0x61 /* but only one value; */ ++#define QM_EQCR_VERB_CMD_ENQUEUE 0x01 ++#define QM_EQCR_VERB_COLOUR_MASK 0x18 /* 4 possible values; */ ++#define QM_EQCR_VERB_COLOUR_GREEN 0x00 ++#define QM_EQCR_VERB_COLOUR_YELLOW 0x08 ++#define QM_EQCR_VERB_COLOUR_RED 0x10 ++#define QM_EQCR_VERB_COLOUR_OVERRIDE 0x18 ++#define QM_EQCR_VERB_INTERRUPT 0x04 /* on command consumption */ ++#define QM_EQCR_VERB_ORP 0x02 /* enable order restoration */ ++#define QM_EQCR_DCA_ENABLE 0x80 ++#define QM_EQCR_DCA_PARK 0x40 ++#define QM_EQCR_DCA_IDXMASK 0x0f /* "DQRR::idx" goes here */ ++#define QM_EQCR_SEQNUM_NESN 0x8000 /* Advance NESN */ ++#define QM_EQCR_SEQNUM_NLIS 0x4000 /* More fragments to come */ ++#define QM_EQCR_SEQNUM_SEQMASK 0x3fff /* sequence number goes here */ ++#define QM_EQCR_FQID_NULL 0 /* eg. for an ORP seqnum hole */ ++ ++/* See 1.5.8.2: "Frame Dequeue Response" */ ++struct qm_dqrr_entry { ++ u8 verb; ++ u8 stat; ++ u16 seqnum; /* 15-bit */ ++ u8 tok; ++ u8 __reserved2[3]; ++ u32 fqid; /* 24-bit */ ++ u32 contextB; ++ struct qm_fd fd; ++ u8 __reserved4[32]; ++}; ++#define QM_DQRR_VERB_VBIT 0x80 ++#define QM_DQRR_VERB_MASK 0x7f /* where the verb contains; */ ++#define QM_DQRR_VERB_FRAME_DEQUEUE 0x60 /* "this format" */ ++#define QM_DQRR_STAT_FQ_EMPTY 0x80 /* FQ empty */ ++#define QM_DQRR_STAT_FQ_HELDACTIVE 0x40 /* FQ held active */ ++#define QM_DQRR_STAT_FQ_FORCEELIGIBLE 0x20 /* FQ was force-eligible'd */ ++#define QM_DQRR_STAT_FD_VALID 0x10 /* has a non-NULL FD */ ++#define QM_DQRR_STAT_UNSCHEDULED 0x02 /* Unscheduled dequeue */ ++#define QM_DQRR_STAT_DQCR_EXPIRED 0x01 /* VDQCR or PDQCR expired*/ ++ ++/* See 1.5.8.3: "ERN Message Response" */ ++/* See 1.5.8.4: "FQ State Change Notification" */ ++struct qm_mr_entry { ++ u8 verb; ++ union { ++ struct { ++ u8 dca; ++ u16 seqnum; ++ u8 rc; /* Rejection Code */ ++ u32 orp:24; ++ u32 fqid; /* 24-bit */ ++ u32 tag; ++ struct qm_fd fd; ++ } __packed ern; ++ struct { ++ u8 colour:2; /* See QM_MR_DCERN_COLOUR_* */ ++ u8 __reserved1:3; ++ enum qm_dc_portal portal:3; ++ u16 __reserved2; ++ u8 rc; /* Rejection Code */ ++ u32 __reserved3:24; ++ u32 fqid; /* 24-bit */ ++ u32 tag; ++ struct qm_fd fd; ++ } __packed dcern; ++ struct { ++ u8 fqs; /* Frame Queue Status */ ++ u8 __reserved1[6]; ++ u32 fqid; /* 24-bit */ ++ u32 contextB; ++ u8 __reserved2[16]; ++ } __packed fq; /* FQRN/FQRNI/FQRL/FQPN */ ++ }; ++ u8 __reserved2[32]; ++} __packed; ++#define QM_MR_VERB_VBIT 0x80 ++/* The "ern" VERB bits match QM_EQCR_VERB_*** so aren't reproduced here. ERNs ++ * originating from direct-connect portals ("dcern") use 0x20 as a verb which ++ * would be invalid as a s/w enqueue verb. A s/w ERN can be distinguished from ++ * the other MR types by noting if the 0x20 bit is unset. */ ++#define QM_MR_VERB_TYPE_MASK 0x27 ++#define QM_MR_VERB_DC_ERN 0x20 ++#define QM_MR_VERB_FQRN 0x21 ++#define QM_MR_VERB_FQRNI 0x22 ++#define QM_MR_VERB_FQRL 0x23 ++#define QM_MR_VERB_FQPN 0x24 ++#define QM_MR_RC_MASK 0xf0 /* contains one of; */ ++#define QM_MR_RC_CGR_TAILDROP 0x00 ++#define QM_MR_RC_WRED 0x10 ++#define QM_MR_RC_ERROR 0x20 ++#define QM_MR_RC_ORPWINDOW_EARLY 0x30 ++#define QM_MR_RC_ORPWINDOW_LATE 0x40 ++#define QM_MR_RC_FQ_TAILDROP 0x50 ++#define QM_MR_RC_ORPWINDOW_RETIRED 0x60 ++#define QM_MR_RC_ORP_ZERO 0x70 ++#define QM_MR_FQS_ORLPRESENT 0x02 /* ORL fragments to come */ ++#define QM_MR_FQS_NOTEMPTY 0x01 /* FQ has enqueued frames */ ++#define QM_MR_DCERN_COLOUR_GREEN 0x00 ++#define QM_MR_DCERN_COLOUR_YELLOW 0x01 ++#define QM_MR_DCERN_COLOUR_RED 0x02 ++#define QM_MR_DCERN_COLOUR_OVERRIDE 0x03 ++ ++/* An identical structure of FQD fields is present in the "Init FQ" command and ++ * the "Query FQ" result, it's suctioned out into the "struct qm_fqd" type. ++ * Within that, the 'stashing' and 'taildrop' pieces are also factored out, the ++ * latter has two inlines to assist with converting to/from the mant+exp ++ * representation. */ ++struct qm_fqd_stashing { ++ /* See QM_STASHING_EXCL_<...> */ ++ u8 exclusive; ++ u8 __reserved1:2; ++ /* Numbers of cachelines */ ++ u8 annotation_cl:2; ++ u8 data_cl:2; ++ u8 context_cl:2; ++} __packed; ++struct qm_fqd_taildrop { ++ u16 __reserved1:3; ++ u16 mant:8; ++ u16 exp:5; ++} __packed; ++struct qm_fqd_oac { ++ /* See QM_OAC_<...> */ ++ u8 oac:2; /* "Overhead Accounting Control" */ ++ u8 __reserved1:6; ++ /* Two's-complement value (-128 to +127) */ ++ signed char oal; /* "Overhead Accounting Length" */ ++} __packed; ++struct qm_fqd { ++ union { ++ u8 orpc; ++ struct { ++ u8 __reserved1:2; ++ u8 orprws:3; ++ u8 oa:1; ++ u8 olws:2; ++ } __packed; ++ }; ++ u8 cgid; ++ u16 fq_ctrl; /* See QM_FQCTRL_<...> */ ++ union { ++ u16 dest_wq; ++ struct { ++ u16 channel:13; /* qm_channel */ ++ u16 wq:3; ++ } __packed dest; ++ }; ++ u16 __reserved2:1; ++ u16 ics_cred:15; ++ /* For "Initialize Frame Queue" commands, the write-enable mask ++ * determines whether 'td' or 'oac_init' is observed. For query ++ * commands, this field is always 'td', and 'oac_query' (below) reflects ++ * the Overhead ACcounting values. */ ++ union { ++ struct qm_fqd_taildrop td; ++ struct qm_fqd_oac oac_init; ++ }; ++ u32 context_b; ++ union { ++ /* Treat it as 64-bit opaque */ ++ u64 opaque; ++ struct { ++ u32 hi; ++ u32 lo; ++ }; ++ /* Treat it as s/w portal stashing config */ ++ /* See 1.5.6.7.1: "FQD Context_A field used for [...] */ ++ struct { ++ struct qm_fqd_stashing stashing; ++ /* 48-bit address of FQ context to ++ * stash, must be cacheline-aligned */ ++ u16 context_hi; ++ u32 context_lo; ++ } __packed; ++ } context_a; ++ struct qm_fqd_oac oac_query; ++} __packed; ++/* 64-bit converters for context_hi/lo */ ++static inline u64 qm_fqd_stashing_get64(const struct qm_fqd *fqd) ++{ ++ return ((u64)fqd->context_a.context_hi << 32) | ++ (u64)fqd->context_a.context_lo; ++} ++static inline dma_addr_t qm_fqd_stashing_addr(const struct qm_fqd *fqd) ++{ ++ return (dma_addr_t)qm_fqd_stashing_get64(fqd); ++} ++static inline u64 qm_fqd_context_a_get64(const struct qm_fqd *fqd) ++{ ++ return ((u64)fqd->context_a.hi << 32) | ++ (u64)fqd->context_a.lo; ++} ++/* Macro, so we compile better when 'v' isn't necessarily 64-bit */ ++#define qm_fqd_stashing_set64(fqd, v) \ ++ do { \ ++ struct qm_fqd *__fqd931 = (fqd); \ ++ __fqd931->context_a.context_hi = upper_32_bits(v); \ ++ __fqd931->context_a.context_lo = lower_32_bits(v); \ ++ } while (0) ++#define qm_fqd_context_a_set64(fqd, v) \ ++ do { \ ++ struct qm_fqd *__fqd931 = (fqd); \ ++ __fqd931->context_a.hi = upper_32_bits(v); \ ++ __fqd931->context_a.lo = lower_32_bits(v); \ ++ } while (0) ++/* convert a threshold value into mant+exp representation */ ++static inline int qm_fqd_taildrop_set(struct qm_fqd_taildrop *td, u32 val, ++ int roundup) ++{ ++ u32 e = 0; ++ int oddbit = 0; ++ if (val > 0xe0000000) ++ return -ERANGE; ++ while (val > 0xff) { ++ oddbit = val & 1; ++ val >>= 1; ++ e++; ++ if (roundup && oddbit) ++ val++; ++ } ++ td->exp = e; ++ td->mant = val; ++ return 0; ++} ++/* and the other direction */ ++static inline u32 qm_fqd_taildrop_get(const struct qm_fqd_taildrop *td) ++{ ++ return (u32)td->mant << td->exp; ++} ++ ++/* See 1.5.2.2: "Frame Queue Descriptor (FQD)" */ ++/* Frame Queue Descriptor (FQD) field 'fq_ctrl' uses these constants */ ++#define QM_FQCTRL_MASK 0x07ff /* 'fq_ctrl' flags; */ ++#define QM_FQCTRL_CGE 0x0400 /* Congestion Group Enable */ ++#define QM_FQCTRL_TDE 0x0200 /* Tail-Drop Enable */ ++#define QM_FQCTRL_ORP 0x0100 /* ORP Enable */ ++#define QM_FQCTRL_CTXASTASHING 0x0080 /* Context-A stashing */ ++#define QM_FQCTRL_CPCSTASH 0x0040 /* CPC Stash Enable */ ++#define QM_FQCTRL_FORCESFDR 0x0008 /* High-priority SFDRs */ ++#define QM_FQCTRL_AVOIDBLOCK 0x0004 /* Don't block active */ ++#define QM_FQCTRL_HOLDACTIVE 0x0002 /* Hold active in portal */ ++#define QM_FQCTRL_PREFERINCACHE 0x0001 /* Aggressively cache FQD */ ++#define QM_FQCTRL_LOCKINCACHE QM_FQCTRL_PREFERINCACHE /* older naming */ ++ ++/* See 1.5.6.7.1: "FQD Context_A field used for [...] */ ++/* Frame Queue Descriptor (FQD) field 'CONTEXT_A' uses these constants */ ++#define QM_STASHING_EXCL_ANNOTATION 0x04 ++#define QM_STASHING_EXCL_DATA 0x02 ++#define QM_STASHING_EXCL_CTX 0x01 ++ ++/* See 1.5.5.3: "Intra Class Scheduling" */ ++/* FQD field 'OAC' (Overhead ACcounting) uses these constants */ ++#define QM_OAC_ICS 0x2 /* Accounting for Intra-Class Scheduling */ ++#define QM_OAC_CG 0x1 /* Accounting for Congestion Groups */ ++ ++/* See 1.5.8.4: "FQ State Change Notification" */ ++/* This struct represents the 32-bit "WR_PARM_[GYR]" parameters in CGR fields ++ * and associated commands/responses. The WRED parameters are calculated from ++ * these fields as follows; ++ * MaxTH = MA * (2 ^ Mn) ++ * Slope = SA / (2 ^ Sn) ++ * MaxP = 4 * (Pn + 1) ++ */ ++struct qm_cgr_wr_parm { ++ union { ++ u32 word; ++ struct { ++ u32 MA:8; ++ u32 Mn:5; ++ u32 SA:7; /* must be between 64-127 */ ++ u32 Sn:6; ++ u32 Pn:6; ++ } __packed; ++ }; ++} __packed; ++/* This struct represents the 13-bit "CS_THRES" CGR field. In the corresponding ++ * management commands, this is padded to a 16-bit structure field, so that's ++ * how we represent it here. The congestion state threshold is calculated from ++ * these fields as follows; ++ * CS threshold = TA * (2 ^ Tn) ++ */ ++struct qm_cgr_cs_thres { ++ u16 __reserved:3; ++ u16 TA:8; ++ u16 Tn:5; ++} __packed; ++/* This identical structure of CGR fields is present in the "Init/Modify CGR" ++ * commands and the "Query CGR" result. It's suctioned out here into its own ++ * struct. */ ++struct __qm_mc_cgr { ++ struct qm_cgr_wr_parm wr_parm_g; ++ struct qm_cgr_wr_parm wr_parm_y; ++ struct qm_cgr_wr_parm wr_parm_r; ++ u8 wr_en_g; /* boolean, use QM_CGR_EN */ ++ u8 wr_en_y; /* boolean, use QM_CGR_EN */ ++ u8 wr_en_r; /* boolean, use QM_CGR_EN */ ++ u8 cscn_en; /* boolean, use QM_CGR_EN */ ++ union { ++ struct { ++ u16 cscn_targ_upd_ctrl; /* use QM_CSCN_TARG_UDP_ */ ++ u16 cscn_targ_dcp_low; /* CSCN_TARG_DCP low-16bits */ ++ }; ++ u32 cscn_targ; /* use QM_CGR_TARG_* */ ++ }; ++ u8 cstd_en; /* boolean, use QM_CGR_EN */ ++ u8 cs; /* boolean, only used in query response */ ++ struct qm_cgr_cs_thres cs_thres; /* use qm_cgr_cs_thres_set64() */ ++ u8 mode; /* QMAN_CGR_MODE_FRAME not supported in rev1.0 */ ++} __packed; ++#define QM_CGR_EN 0x01 /* For wr_en_*, cscn_en, cstd_en */ ++#define QM_CGR_TARG_UDP_CTRL_WRITE_BIT 0x8000 /* value written to portal bit*/ ++#define QM_CGR_TARG_UDP_CTRL_DCP 0x4000 /* 0: SWP, 1: DCP */ ++#define QM_CGR_TARG_PORTAL(n) (0x80000000 >> (n)) /* s/w portal, 0-9 */ ++#define QM_CGR_TARG_FMAN0 0x00200000 /* direct-connect portal: fman0 */ ++#define QM_CGR_TARG_FMAN1 0x00100000 /* : fman1 */ ++/* Convert CGR thresholds to/from "cs_thres" format */ ++static inline u64 qm_cgr_cs_thres_get64(const struct qm_cgr_cs_thres *th) ++{ ++ return (u64)th->TA << th->Tn; ++} ++static inline int qm_cgr_cs_thres_set64(struct qm_cgr_cs_thres *th, u64 val, ++ int roundup) ++{ ++ u32 e = 0; ++ int oddbit = 0; ++ while (val > 0xff) { ++ oddbit = val & 1; ++ val >>= 1; ++ e++; ++ if (roundup && oddbit) ++ val++; ++ } ++ th->Tn = e; ++ th->TA = val; ++ return 0; ++} ++ ++/* See 1.5.8.5.1: "Initialize FQ" */ ++/* See 1.5.8.5.2: "Query FQ" */ ++/* See 1.5.8.5.3: "Query FQ Non-Programmable Fields" */ ++/* See 1.5.8.5.4: "Alter FQ State Commands " */ ++/* See 1.5.8.6.1: "Initialize/Modify CGR" */ ++/* See 1.5.8.6.2: "CGR Test Write" */ ++/* See 1.5.8.6.3: "Query CGR" */ ++/* See 1.5.8.6.4: "Query Congestion Group State" */ ++struct qm_mcc_initfq { ++ u8 __reserved1; ++ u16 we_mask; /* Write Enable Mask */ ++ u32 fqid; /* 24-bit */ ++ u16 count; /* Initialises 'count+1' FQDs */ ++ struct qm_fqd fqd; /* the FQD fields go here */ ++ u8 __reserved3[30]; ++} __packed; ++struct qm_mcc_queryfq { ++ u8 __reserved1[3]; ++ u32 fqid; /* 24-bit */ ++ u8 __reserved2[56]; ++} __packed; ++struct qm_mcc_queryfq_np { ++ u8 __reserved1[3]; ++ u32 fqid; /* 24-bit */ ++ u8 __reserved2[56]; ++} __packed; ++struct qm_mcc_alterfq { ++ u8 __reserved1[3]; ++ u32 fqid; /* 24-bit */ ++ u8 __reserved2; ++ u8 count; /* number of consecutive FQID */ ++ u8 __reserved3[10]; ++ u32 context_b; /* frame queue context b */ ++ u8 __reserved4[40]; ++} __packed; ++struct qm_mcc_initcgr { ++ u8 __reserved1; ++ u16 we_mask; /* Write Enable Mask */ ++ struct __qm_mc_cgr cgr; /* CGR fields */ ++ u8 __reserved2[2]; ++ u8 cgid; ++ u8 __reserved4[32]; ++} __packed; ++struct qm_mcc_cgrtestwrite { ++ u8 __reserved1[2]; ++ u8 i_bcnt_hi:8;/* high 8-bits of 40-bit "Instant" */ ++ u32 i_bcnt_lo; /* low 32-bits of 40-bit */ ++ u8 __reserved2[23]; ++ u8 cgid; ++ u8 __reserved3[32]; ++} __packed; ++struct qm_mcc_querycgr { ++ u8 __reserved1[30]; ++ u8 cgid; ++ u8 __reserved2[32]; ++} __packed; ++struct qm_mcc_querycongestion { ++ u8 __reserved[63]; ++} __packed; ++struct qm_mcc_querywq { ++ u8 __reserved; ++ /* select channel if verb != QUERYWQ_DEDICATED */ ++ union { ++ u16 channel_wq; /* ignores wq (3 lsbits) */ ++ struct { ++ u16 id:13; /* qm_channel */ ++ u16 __reserved1:3; ++ } __packed channel; ++ }; ++ u8 __reserved2[60]; ++} __packed; ++ ++struct qm_mcc_ceetm_lfqmt_config { ++ u8 __reserved1[4]; ++ u32 lfqid:24; ++ u8 __reserved2[2]; ++ u16 cqid; ++ u8 __reserved3[2]; ++ u16 dctidx; ++ u8 __reserved4[48]; ++} __packed; ++ ++struct qm_mcc_ceetm_lfqmt_query { ++ u8 __reserved1[4]; ++ u32 lfqid:24; ++ u8 __reserved2[56]; ++} __packed; ++ ++struct qm_mcc_ceetm_cq_config { ++ u8 __reserved1; ++ u16 cqid; ++ u8 dcpid; ++ u8 __reserved2; ++ u16 ccgid; ++ u8 __reserved3[56]; ++} __packed; ++ ++struct qm_mcc_ceetm_cq_query { ++ u8 __reserved1; ++ u16 cqid; ++ u8 dcpid; ++ u8 __reserved2[59]; ++} __packed; ++ ++struct qm_mcc_ceetm_dct_config { ++ u8 __reserved1; ++ u16 dctidx; ++ u8 dcpid; ++ u8 __reserved2[15]; ++ u32 context_b; ++ u64 context_a; ++ u8 __reserved3[32]; ++} __packed; ++ ++struct qm_mcc_ceetm_dct_query { ++ u8 __reserved1; ++ u16 dctidx; ++ u8 dcpid; ++ u8 __reserved2[59]; ++} __packed; ++ ++struct qm_mcc_ceetm_class_scheduler_config { ++ u8 __reserved1; ++ u16 cqcid; ++ u8 dcpid; ++ u8 __reserved2[6]; ++ u8 gpc; ++ u16 crem; ++ u16 erem; ++ u8 w[8]; ++ u8 __reserved3[40]; ++} __packed; ++ ++struct qm_mcc_ceetm_class_scheduler_query { ++ u8 __reserved1; ++ u16 cqcid; ++ u8 dcpid; ++ u8 __reserved2[59]; ++} __packed; ++ ++#define CEETM_COMMAND_CHANNEL_MAPPING (0 << 12) ++#define CEETM_COMMAND_SP_MAPPING (1 << 12) ++#define CEETM_COMMAND_CHANNEL_SHAPER (2 << 12) ++#define CEETM_COMMAND_LNI_SHAPER (3 << 12) ++#define CEETM_COMMAND_TCFC (4 << 12) ++ ++#define CEETM_CCGRID_MASK 0x01FF ++#define CEETM_CCGR_CM_CONFIGURE (0 << 14) ++#define CEETM_CCGR_DN_CONFIGURE (1 << 14) ++#define CEETM_CCGR_TEST_WRITE (2 << 14) ++#define CEETM_CCGR_CM_QUERY (0 << 14) ++#define CEETM_CCGR_DN_QUERY (1 << 14) ++#define CEETM_CCGR_DN_QUERY_FLUSH (2 << 14) ++#define CEETM_QUERY_CONGESTION_STATE (3 << 14) ++ ++struct qm_mcc_ceetm_mapping_shaper_tcfc_config { ++ u8 __reserved1; ++ u16 cid; ++ u8 dcpid; ++ union { ++ struct { ++ u8 map; ++ u8 __reserved2[58]; ++ } __packed channel_mapping; ++ struct { ++ u8 map_reserved:5; ++ u8 map_lni_id:3; ++ u8 __reserved2[58]; ++ } __packed sp_mapping; ++ struct { ++ u8 cpl; ++ u32 crtcr:24; ++ u32 ertcr:24; ++ u16 crtbl; ++ u16 ertbl; ++ u8 mps; /* This will be hardcoded by driver with 60 */ ++ u8 __reserved2[47]; ++ } __packed shaper_config; ++ struct { ++ u8 __reserved2[11]; ++ u64 lnitcfcc; ++ u8 __reserved3[40]; ++ } __packed tcfc_config; ++ }; ++} __packed; ++ ++struct qm_mcc_ceetm_mapping_shaper_tcfc_query { ++ u8 __reserved1; ++ u16 cid; ++ u8 dcpid; ++ u8 __reserved2[59]; ++} __packed; ++ ++struct qm_mcc_ceetm_ccgr_config { ++ u8 __reserved1; ++ u16 ccgrid; ++ u8 dcpid; ++ u8 __reserved2; ++ u16 we_mask; ++ union { ++ struct { ++ u8 ctl; ++ u8 cdv; ++ u16 cscn_tupd; ++ u8 oal; ++ u8 __reserved3; ++ struct qm_cgr_cs_thres cs_thres; ++ struct qm_cgr_cs_thres cs_thres_x; ++ struct qm_cgr_cs_thres td_thres; ++ struct qm_cgr_wr_parm wr_parm_g; ++ struct qm_cgr_wr_parm wr_parm_y; ++ struct qm_cgr_wr_parm wr_parm_r; ++ } __packed cm_config; ++ struct { ++ u8 dnc; ++ u8 dn0; ++ u8 dn1; ++ u64 dnba:40; ++ u8 __reserved3[2]; ++ u16 dnth_0; ++ u8 __reserved4[2]; ++ u16 dnth_1; ++ u8 __reserved5[8]; ++ } __packed dn_config; ++ struct { ++ u8 __reserved3[3]; ++ u64 i_cnt:40; ++ u8 __reserved4[16]; ++ } __packed test_write; ++ }; ++ u8 __reserved5[32]; ++} __packed; ++ ++struct qm_mcc_ceetm_ccgr_query { ++ u8 __reserved1; ++ u16 ccgrid; ++ u8 dcpid; ++ u8 __reserved2[59]; ++} __packed; ++ ++struct qm_mcc_ceetm_cq_peek_pop_xsfdrread { ++ u8 __reserved1; ++ u16 cqid; ++ u8 dcpid; ++ u8 ct; ++ u16 xsfdr; ++ u8 __reserved2[56]; ++} __packed; ++ ++#define CEETM_QUERY_DEQUEUE_STATISTICS 0x00 ++#define CEETM_QUERY_DEQUEUE_CLEAR_STATISTICS 0x01 ++#define CEETM_WRITE_DEQUEUE_STATISTICS 0x02 ++#define CEETM_QUERY_REJECT_STATISTICS 0x03 ++#define CEETM_QUERY_REJECT_CLEAR_STATISTICS 0x04 ++#define CEETM_WRITE_REJECT_STATISTICS 0x05 ++struct qm_mcc_ceetm_statistics_query_write { ++ u8 __reserved1; ++ u16 cid; ++ u8 dcpid; ++ u8 ct; ++ u8 __reserved2[13]; ++ u64 frm_cnt:40; ++ u8 __reserved3[2]; ++ u64 byte_cnt:48; ++ u8 __reserved[32]; ++} __packed; ++ ++struct qm_mc_command { ++ u8 __dont_write_directly__verb; ++ union { ++ struct qm_mcc_initfq initfq; ++ struct qm_mcc_queryfq queryfq; ++ struct qm_mcc_queryfq_np queryfq_np; ++ struct qm_mcc_alterfq alterfq; ++ struct qm_mcc_initcgr initcgr; ++ struct qm_mcc_cgrtestwrite cgrtestwrite; ++ struct qm_mcc_querycgr querycgr; ++ struct qm_mcc_querycongestion querycongestion; ++ struct qm_mcc_querywq querywq; ++ struct qm_mcc_ceetm_lfqmt_config lfqmt_config; ++ struct qm_mcc_ceetm_lfqmt_query lfqmt_query; ++ struct qm_mcc_ceetm_cq_config cq_config; ++ struct qm_mcc_ceetm_cq_query cq_query; ++ struct qm_mcc_ceetm_dct_config dct_config; ++ struct qm_mcc_ceetm_dct_query dct_query; ++ struct qm_mcc_ceetm_class_scheduler_config csch_config; ++ struct qm_mcc_ceetm_class_scheduler_query csch_query; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_config mst_config; ++ struct qm_mcc_ceetm_mapping_shaper_tcfc_query mst_query; ++ struct qm_mcc_ceetm_ccgr_config ccgr_config; ++ struct qm_mcc_ceetm_ccgr_query ccgr_query; ++ struct qm_mcc_ceetm_cq_peek_pop_xsfdrread cq_ppxr; ++ struct qm_mcc_ceetm_statistics_query_write stats_query_write; ++ }; ++} __packed; ++#define QM_MCC_VERB_VBIT 0x80 ++#define QM_MCC_VERB_MASK 0x7f /* where the verb contains; */ ++#define QM_MCC_VERB_INITFQ_PARKED 0x40 ++#define QM_MCC_VERB_INITFQ_SCHED 0x41 ++#define QM_MCC_VERB_QUERYFQ 0x44 ++#define QM_MCC_VERB_QUERYFQ_NP 0x45 /* "non-programmable" fields */ ++#define QM_MCC_VERB_QUERYWQ 0x46 ++#define QM_MCC_VERB_QUERYWQ_DEDICATED 0x47 ++#define QM_MCC_VERB_ALTER_SCHED 0x48 /* Schedule FQ */ ++#define QM_MCC_VERB_ALTER_FE 0x49 /* Force Eligible FQ */ ++#define QM_MCC_VERB_ALTER_RETIRE 0x4a /* Retire FQ */ ++#define QM_MCC_VERB_ALTER_OOS 0x4b /* Take FQ out of service */ ++#define QM_MCC_VERB_ALTER_FQXON 0x4d /* FQ XON */ ++#define QM_MCC_VERB_ALTER_FQXOFF 0x4e /* FQ XOFF */ ++#define QM_MCC_VERB_INITCGR 0x50 ++#define QM_MCC_VERB_MODIFYCGR 0x51 ++#define QM_MCC_VERB_CGRTESTWRITE 0x52 ++#define QM_MCC_VERB_QUERYCGR 0x58 ++#define QM_MCC_VERB_QUERYCONGESTION 0x59 ++/* INITFQ-specific flags */ ++#define QM_INITFQ_WE_MASK 0x01ff /* 'Write Enable' flags; */ ++#define QM_INITFQ_WE_OAC 0x0100 ++#define QM_INITFQ_WE_ORPC 0x0080 ++#define QM_INITFQ_WE_CGID 0x0040 ++#define QM_INITFQ_WE_FQCTRL 0x0020 ++#define QM_INITFQ_WE_DESTWQ 0x0010 ++#define QM_INITFQ_WE_ICSCRED 0x0008 ++#define QM_INITFQ_WE_TDTHRESH 0x0004 ++#define QM_INITFQ_WE_CONTEXTB 0x0002 ++#define QM_INITFQ_WE_CONTEXTA 0x0001 ++/* INITCGR/MODIFYCGR-specific flags */ ++#define QM_CGR_WE_MASK 0x07ff /* 'Write Enable Mask'; */ ++#define QM_CGR_WE_WR_PARM_G 0x0400 ++#define QM_CGR_WE_WR_PARM_Y 0x0200 ++#define QM_CGR_WE_WR_PARM_R 0x0100 ++#define QM_CGR_WE_WR_EN_G 0x0080 ++#define QM_CGR_WE_WR_EN_Y 0x0040 ++#define QM_CGR_WE_WR_EN_R 0x0020 ++#define QM_CGR_WE_CSCN_EN 0x0010 ++#define QM_CGR_WE_CSCN_TARG 0x0008 ++#define QM_CGR_WE_CSTD_EN 0x0004 ++#define QM_CGR_WE_CS_THRES 0x0002 ++#define QM_CGR_WE_MODE 0x0001 ++ ++/* See 1.5.9.7 CEETM Management Commands */ ++#define QM_CEETM_VERB_LFQMT_CONFIG 0x70 ++#define QM_CEETM_VERB_LFQMT_QUERY 0x71 ++#define QM_CEETM_VERB_CQ_CONFIG 0x72 ++#define QM_CEETM_VERB_CQ_QUERY 0x73 ++#define QM_CEETM_VERB_DCT_CONFIG 0x74 ++#define QM_CEETM_VERB_DCT_QUERY 0x75 ++#define QM_CEETM_VERB_CLASS_SCHEDULER_CONFIG 0x76 ++#define QM_CEETM_VERB_CLASS_SCHEDULER_QUERY 0x77 ++#define QM_CEETM_VERB_MAPPING_SHAPER_TCFC_CONFIG 0x78 ++#define QM_CEETM_VERB_MAPPING_SHAPER_TCFC_QUERY 0x79 ++#define QM_CEETM_VERB_CCGR_CONFIG 0x7A ++#define QM_CEETM_VERB_CCGR_QUERY 0x7B ++#define QM_CEETM_VERB_CQ_PEEK_POP_XFDRREAD 0x7C ++#define QM_CEETM_VERB_STATISTICS_QUERY_WRITE 0x7D ++ ++/* See 1.5.8.5.1: "Initialize FQ" */ ++/* See 1.5.8.5.2: "Query FQ" */ ++/* See 1.5.8.5.3: "Query FQ Non-Programmable Fields" */ ++/* See 1.5.8.5.4: "Alter FQ State Commands " */ ++/* See 1.5.8.6.1: "Initialize/Modify CGR" */ ++/* See 1.5.8.6.2: "CGR Test Write" */ ++/* See 1.5.8.6.3: "Query CGR" */ ++/* See 1.5.8.6.4: "Query Congestion Group State" */ ++struct qm_mcr_initfq { ++ u8 __reserved1[62]; ++} __packed; ++struct qm_mcr_queryfq { ++ u8 __reserved1[8]; ++ struct qm_fqd fqd; /* the FQD fields are here */ ++ u8 __reserved2[30]; ++} __packed; ++struct qm_mcr_queryfq_np { ++ u8 __reserved1; ++ u8 state; /* QM_MCR_NP_STATE_*** */ ++ u8 __reserved2; ++ u32 fqd_link:24; ++ u16 __reserved3:2; ++ u16 odp_seq:14; ++ u16 __reserved4:2; ++ u16 orp_nesn:14; ++ u16 __reserved5:1; ++ u16 orp_ea_hseq:15; ++ u16 __reserved6:1; ++ u16 orp_ea_tseq:15; ++ u8 __reserved7; ++ u32 orp_ea_hptr:24; ++ u8 __reserved8; ++ u32 orp_ea_tptr:24; ++ u8 __reserved9; ++ u32 pfdr_hptr:24; ++ u8 __reserved10; ++ u32 pfdr_tptr:24; ++ u8 __reserved11[5]; ++ u8 __reserved12:7; ++ u8 is:1; ++ u16 ics_surp; ++ u32 byte_cnt; ++ u8 __reserved13; ++ u32 frm_cnt:24; ++ u32 __reserved14; ++ u16 ra1_sfdr; /* QM_MCR_NP_RA1_*** */ ++ u16 ra2_sfdr; /* QM_MCR_NP_RA2_*** */ ++ u16 __reserved15; ++ u16 od1_sfdr; /* QM_MCR_NP_OD1_*** */ ++ u16 od2_sfdr; /* QM_MCR_NP_OD2_*** */ ++ u16 od3_sfdr; /* QM_MCR_NP_OD3_*** */ ++} __packed; ++struct qm_mcr_alterfq { ++ u8 fqs; /* Frame Queue Status */ ++ u8 __reserved1[61]; ++} __packed; ++struct qm_mcr_initcgr { ++ u8 __reserved1[62]; ++} __packed; ++struct qm_mcr_cgrtestwrite { ++ u16 __reserved1; ++ struct __qm_mc_cgr cgr; /* CGR fields */ ++ u8 __reserved2[3]; ++ u32 __reserved3:24; ++ u32 i_bcnt_hi:8;/* high 8-bits of 40-bit "Instant" */ ++ u32 i_bcnt_lo; /* low 32-bits of 40-bit */ ++ u32 __reserved4:24; ++ u32 a_bcnt_hi:8;/* high 8-bits of 40-bit "Average" */ ++ u32 a_bcnt_lo; /* low 32-bits of 40-bit */ ++ u16 lgt; /* Last Group Tick */ ++ u16 wr_prob_g; ++ u16 wr_prob_y; ++ u16 wr_prob_r; ++ u8 __reserved5[8]; ++} __packed; ++struct qm_mcr_querycgr { ++ u16 __reserved1; ++ struct __qm_mc_cgr cgr; /* CGR fields */ ++ u8 __reserved2[3]; ++ u32 __reserved3:24; ++ u32 i_bcnt_hi:8;/* high 8-bits of 40-bit "Instant" */ ++ u32 i_bcnt_lo; /* low 32-bits of 40-bit */ ++ u32 __reserved4:24; ++ u32 a_bcnt_hi:8;/* high 8-bits of 40-bit "Average" */ ++ u32 a_bcnt_lo; /* low 32-bits of 40-bit */ ++ union { ++ u32 cscn_targ_swp[4]; ++ u8 __reserved5[16]; ++ }; ++} __packed; ++static inline u64 qm_mcr_querycgr_i_get64(const struct qm_mcr_querycgr *q) ++{ ++ return ((u64)q->i_bcnt_hi << 32) | (u64)q->i_bcnt_lo; ++} ++static inline u64 qm_mcr_querycgr_a_get64(const struct qm_mcr_querycgr *q) ++{ ++ return ((u64)q->a_bcnt_hi << 32) | (u64)q->a_bcnt_lo; ++} ++static inline u64 qm_mcr_cgrtestwrite_i_get64( ++ const struct qm_mcr_cgrtestwrite *q) ++{ ++ return ((u64)q->i_bcnt_hi << 32) | (u64)q->i_bcnt_lo; ++} ++static inline u64 qm_mcr_cgrtestwrite_a_get64( ++ const struct qm_mcr_cgrtestwrite *q) ++{ ++ return ((u64)q->a_bcnt_hi << 32) | (u64)q->a_bcnt_lo; ++} ++/* Macro, so we compile better if 'v' isn't always 64-bit */ ++#define qm_mcr_querycgr_i_set64(q, v) \ ++ do { \ ++ struct qm_mcr_querycgr *__q931 = (fd); \ ++ __q931->i_bcnt_hi = upper_32_bits(v); \ ++ __q931->i_bcnt_lo = lower_32_bits(v); \ ++ } while (0) ++#define qm_mcr_querycgr_a_set64(q, v) \ ++ do { \ ++ struct qm_mcr_querycgr *__q931 = (fd); \ ++ __q931->a_bcnt_hi = upper_32_bits(v); \ ++ __q931->a_bcnt_lo = lower_32_bits(v); \ ++ } while (0) ++struct __qm_mcr_querycongestion { ++ u32 __state[8]; ++}; ++struct qm_mcr_querycongestion { ++ u8 __reserved[30]; ++ /* Access this struct using QM_MCR_QUERYCONGESTION() */ ++ struct __qm_mcr_querycongestion state; ++} __packed; ++struct qm_mcr_querywq { ++ union { ++ u16 channel_wq; /* ignores wq (3 lsbits) */ ++ struct { ++ u16 id:13; /* qm_channel */ ++ u16 __reserved:3; ++ } __packed channel; ++ }; ++ u8 __reserved[28]; ++ u32 wq_len[8]; ++} __packed; ++ ++/* QMAN CEETM Management Command Response */ ++struct qm_mcr_ceetm_lfqmt_config { ++ u8 __reserved1[62]; ++} __packed; ++struct qm_mcr_ceetm_lfqmt_query { ++ u8 __reserved1[8]; ++ u16 cqid; ++ u8 __reserved2[2]; ++ u16 dctidx; ++ u8 __reserved3[2]; ++ u16 ccgid; ++ u8 __reserved4[44]; ++} __packed; ++ ++struct qm_mcr_ceetm_cq_config { ++ u8 __reserved1[62]; ++} __packed; ++ ++struct qm_mcr_ceetm_cq_query { ++ u8 __reserved1[4]; ++ u16 ccgid; ++ u16 state; ++ u32 pfdr_hptr:24; ++ u32 pfdr_tptr:24; ++ u16 od1_xsfdr; ++ u16 od2_xsfdr; ++ u16 od3_xsfdr; ++ u16 od4_xsfdr; ++ u16 od5_xsfdr; ++ u16 od6_xsfdr; ++ u16 ra1_xsfdr; ++ u16 ra2_xsfdr; ++ u8 __reserved2; ++ u32 frm_cnt:24; ++ u8 __reserved333[28]; ++} __packed; ++ ++struct qm_mcr_ceetm_dct_config { ++ u8 __reserved1[62]; ++} __packed; ++ ++struct qm_mcr_ceetm_dct_query { ++ u8 __reserved1[18]; ++ u32 context_b; ++ u64 context_a; ++ u8 __reserved2[32]; ++} __packed; ++ ++struct qm_mcr_ceetm_class_scheduler_config { ++ u8 __reserved1[62]; ++} __packed; ++ ++struct qm_mcr_ceetm_class_scheduler_query { ++ u8 __reserved1[9]; ++ u8 gpc; ++ u16 crem; ++ u16 erem; ++ u8 w[8]; ++ u8 __reserved2[5]; ++ u32 wbfslist:24; ++ u32 d8; ++ u32 d9; ++ u32 d10; ++ u32 d11; ++ u32 d12; ++ u32 d13; ++ u32 d14; ++ u32 d15; ++} __packed; ++ ++struct qm_mcr_ceetm_mapping_shaper_tcfc_config { ++ u16 cid; ++ u8 __reserved2[60]; ++} __packed; ++ ++struct qm_mcr_ceetm_mapping_shaper_tcfc_query { ++ u16 cid; ++ u8 __reserved1; ++ union { ++ struct { ++ u8 map; ++ u8 __reserved2[58]; ++ } __packed channel_mapping_query; ++ struct { ++ u8 map_reserved:5; ++ u8 map_lni_id:3; ++ u8 __reserved2[58]; ++ } __packed sp_mapping_query; ++ struct { ++ u8 cpl; ++ u32 crtcr:24; ++ u32 ertcr:24; ++ u16 crtbl; ++ u16 ertbl; ++ u8 mps; ++ u8 __reserved2[15]; ++ u32 crat; ++ u32 erat; ++ u8 __reserved3[24]; ++ } __packed shaper_query; ++ struct { ++ u8 __reserved1[11]; ++ u64 lnitcfcc; ++ u8 __reserved3[40]; ++ } __packed tcfc_query; ++ }; ++} __packed; ++ ++struct qm_mcr_ceetm_ccgr_config { ++ u8 __reserved1[46]; ++ union { ++ u8 __reserved2[8]; ++ struct { ++ u16 timestamp; ++ u16 wr_porb_g; ++ u16 wr_prob_y; ++ u16 wr_prob_r; ++ } __packed test_write; ++ }; ++ u8 __reserved3[8]; ++} __packed; ++ ++struct qm_mcr_ceetm_ccgr_query { ++ u8 __reserved1[6]; ++ union { ++ struct { ++ u8 ctl; ++ u8 cdv; ++ u8 __reserved2[2]; ++ u8 oal; ++ u8 __reserved3; ++ struct qm_cgr_cs_thres cs_thres; ++ struct qm_cgr_cs_thres cs_thres_x; ++ struct qm_cgr_cs_thres td_thres; ++ struct qm_cgr_wr_parm wr_parm_g; ++ struct qm_cgr_wr_parm wr_parm_y; ++ struct qm_cgr_wr_parm wr_parm_r; ++ u16 cscn_targ_dcp; ++ u8 dcp_lsn; ++ u64 i_cnt:40; ++ u8 __reserved4[3]; ++ u64 a_cnt:40; ++ u32 cscn_targ_swp[4]; ++ } __packed cm_query; ++ struct { ++ u8 dnc; ++ u8 dn0; ++ u8 dn1; ++ u64 dnba:40; ++ u8 __reserved2[2]; ++ u16 dnth_0; ++ u8 __reserved3[2]; ++ u16 dnth_1; ++ u8 __reserved4[10]; ++ u16 dnacc_0; ++ u8 __reserved5[2]; ++ u16 dnacc_1; ++ u8 __reserved6[24]; ++ } __packed dn_query; ++ struct { ++ u8 __reserved2[24]; ++ struct __qm_mcr_querycongestion state; ++ } __packed congestion_state; ++ ++ }; ++} __packed; ++ ++struct qm_mcr_ceetm_cq_peek_pop_xsfdrread { ++ u8 stat; ++ u8 __reserved1[11]; ++ u16 dctidx; ++ struct qm_fd fd; ++ u8 __reserved2[32]; ++} __packed; ++ ++struct qm_mcr_ceetm_statistics_query { ++ u8 __reserved1[17]; ++ u64 frm_cnt:40; ++ u8 __reserved2[2]; ++ u64 byte_cnt:48; ++ u8 __reserved3[32]; ++} __packed; ++ ++struct qm_mc_result { ++ u8 verb; ++ u8 result; ++ union { ++ struct qm_mcr_initfq initfq; ++ struct qm_mcr_queryfq queryfq; ++ struct qm_mcr_queryfq_np queryfq_np; ++ struct qm_mcr_alterfq alterfq; ++ struct qm_mcr_initcgr initcgr; ++ struct qm_mcr_cgrtestwrite cgrtestwrite; ++ struct qm_mcr_querycgr querycgr; ++ struct qm_mcr_querycongestion querycongestion; ++ struct qm_mcr_querywq querywq; ++ struct qm_mcr_ceetm_lfqmt_config lfqmt_config; ++ struct qm_mcr_ceetm_lfqmt_query lfqmt_query; ++ struct qm_mcr_ceetm_cq_config cq_config; ++ struct qm_mcr_ceetm_cq_query cq_query; ++ struct qm_mcr_ceetm_dct_config dct_config; ++ struct qm_mcr_ceetm_dct_query dct_query; ++ struct qm_mcr_ceetm_class_scheduler_config csch_config; ++ struct qm_mcr_ceetm_class_scheduler_query csch_query; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_config mst_config; ++ struct qm_mcr_ceetm_mapping_shaper_tcfc_query mst_query; ++ struct qm_mcr_ceetm_ccgr_config ccgr_config; ++ struct qm_mcr_ceetm_ccgr_query ccgr_query; ++ struct qm_mcr_ceetm_cq_peek_pop_xsfdrread cq_ppxr; ++ struct qm_mcr_ceetm_statistics_query stats_query; ++ }; ++} __packed; ++ ++#define QM_MCR_VERB_RRID 0x80 ++#define QM_MCR_VERB_MASK QM_MCC_VERB_MASK ++#define QM_MCR_VERB_INITFQ_PARKED QM_MCC_VERB_INITFQ_PARKED ++#define QM_MCR_VERB_INITFQ_SCHED QM_MCC_VERB_INITFQ_SCHED ++#define QM_MCR_VERB_QUERYFQ QM_MCC_VERB_QUERYFQ ++#define QM_MCR_VERB_QUERYFQ_NP QM_MCC_VERB_QUERYFQ_NP ++#define QM_MCR_VERB_QUERYWQ QM_MCC_VERB_QUERYWQ ++#define QM_MCR_VERB_QUERYWQ_DEDICATED QM_MCC_VERB_QUERYWQ_DEDICATED ++#define QM_MCR_VERB_ALTER_SCHED QM_MCC_VERB_ALTER_SCHED ++#define QM_MCR_VERB_ALTER_FE QM_MCC_VERB_ALTER_FE ++#define QM_MCR_VERB_ALTER_RETIRE QM_MCC_VERB_ALTER_RETIRE ++#define QM_MCR_VERB_ALTER_OOS QM_MCC_VERB_ALTER_OOS ++#define QM_MCR_RESULT_NULL 0x00 ++#define QM_MCR_RESULT_OK 0xf0 ++#define QM_MCR_RESULT_ERR_FQID 0xf1 ++#define QM_MCR_RESULT_ERR_FQSTATE 0xf2 ++#define QM_MCR_RESULT_ERR_NOTEMPTY 0xf3 /* OOS fails if FQ is !empty */ ++#define QM_MCR_RESULT_ERR_BADCHANNEL 0xf4 ++#define QM_MCR_RESULT_PENDING 0xf8 ++#define QM_MCR_RESULT_ERR_BADCOMMAND 0xff ++#define QM_MCR_NP_STATE_FE 0x10 ++#define QM_MCR_NP_STATE_R 0x08 ++#define QM_MCR_NP_STATE_MASK 0x07 /* Reads FQD::STATE; */ ++#define QM_MCR_NP_STATE_OOS 0x00 ++#define QM_MCR_NP_STATE_RETIRED 0x01 ++#define QM_MCR_NP_STATE_TEN_SCHED 0x02 ++#define QM_MCR_NP_STATE_TRU_SCHED 0x03 ++#define QM_MCR_NP_STATE_PARKED 0x04 ++#define QM_MCR_NP_STATE_ACTIVE 0x05 ++#define QM_MCR_NP_PTR_MASK 0x07ff /* for RA[12] & OD[123] */ ++#define QM_MCR_NP_RA1_NRA(v) (((v) >> 14) & 0x3) /* FQD::NRA */ ++#define QM_MCR_NP_RA2_IT(v) (((v) >> 14) & 0x1) /* FQD::IT */ ++#define QM_MCR_NP_OD1_NOD(v) (((v) >> 14) & 0x3) /* FQD::NOD */ ++#define QM_MCR_NP_OD3_NPC(v) (((v) >> 14) & 0x3) /* FQD::NPC */ ++#define QM_MCR_FQS_ORLPRESENT 0x02 /* ORL fragments to come */ ++#define QM_MCR_FQS_NOTEMPTY 0x01 /* FQ has enqueued frames */ ++/* This extracts the state for congestion group 'n' from a query response. ++ * Eg. ++ * u8 cgr = [...]; ++ * struct qm_mc_result *res = [...]; ++ * printf("congestion group %d congestion state: %d\n", cgr, ++ * QM_MCR_QUERYCONGESTION(&res->querycongestion.state, cgr)); ++ */ ++#define __CGR_WORD(num) (num >> 5) ++#define __CGR_SHIFT(num) (num & 0x1f) ++#define __CGR_NUM (sizeof(struct __qm_mcr_querycongestion) << 3) ++static inline int QM_MCR_QUERYCONGESTION(struct __qm_mcr_querycongestion *p, ++ u8 cgr) ++{ ++ return p->__state[__CGR_WORD(cgr)] & (0x80000000 >> __CGR_SHIFT(cgr)); ++} ++ ++ ++/*********************/ ++/* Utility interface */ ++/*********************/ ++ ++/* Represents an allocator over a range of FQIDs. NB, accesses are not locked, ++ * spinlock them yourself if needed. */ ++struct qman_fqid_pool; ++ ++/* Create/destroy a FQID pool, num must be a multiple of 32. NB, _destroy() ++ * always succeeds, but returns non-zero if there were "leaked" FQID ++ * allocations. */ ++struct qman_fqid_pool *qman_fqid_pool_create(u32 fqid_start, u32 num); ++int qman_fqid_pool_destroy(struct qman_fqid_pool *pool); ++/* Alloc/free a FQID from the range. _alloc() returns zero for success. */ ++int qman_fqid_pool_alloc(struct qman_fqid_pool *pool, u32 *fqid); ++void qman_fqid_pool_free(struct qman_fqid_pool *pool, u32 fqid); ++u32 qman_fqid_pool_used(struct qman_fqid_pool *pool); ++ ++/*******************************************************************/ ++/* Managed (aka "shared" or "mux/demux") portal, high-level i/face */ ++/*******************************************************************/ ++ ++ /* Portal and Frame Queues */ ++ /* ----------------------- */ ++/* Represents a managed portal */ ++struct qman_portal; ++ ++/* This object type represents Qman frame queue descriptors (FQD), it is ++ * cacheline-aligned, and initialised by qman_create_fq(). The structure is ++ * defined further down. */ ++struct qman_fq; ++ ++/* This object type represents a Qman congestion group, it is defined further ++ * down. */ ++struct qman_cgr; ++ ++struct qman_portal_config { ++ /* If the caller enables DQRR stashing (and thus wishes to operate the ++ * portal from only one cpu), this is the logical CPU that the portal ++ * will stash to. Whether stashing is enabled or not, this setting is ++ * also used for any "core-affine" portals, ie. default portals ++ * associated to the corresponding cpu. -1 implies that there is no core ++ * affinity configured. */ ++ int cpu; ++ /* portal interrupt line */ ++ int irq; ++ /* the unique index of this portal */ ++ u32 index; ++ /* Is this portal shared? (If so, it has coarser locking and demuxes ++ * processing on behalf of other CPUs.) */ ++ int is_shared; ++ /* The portal's dedicated channel id, use this value for initialising ++ * frame queues to target this portal when scheduled. */ ++ u16 channel; ++ /* A mask of which pool channels this portal has dequeue access to ++ * (using QM_SDQCR_CHANNELS_POOL(n) for the bitmask) */ ++ u32 pools; ++}; ++ ++/* This enum, and the callback type that returns it, are used when handling ++ * dequeued frames via DQRR. Note that for "null" callbacks registered with the ++ * portal object (for handling dequeues that do not demux because contextB is ++ * NULL), the return value *MUST* be qman_cb_dqrr_consume. */ ++enum qman_cb_dqrr_result { ++ /* DQRR entry can be consumed */ ++ qman_cb_dqrr_consume, ++ /* Like _consume, but requests parking - FQ must be held-active */ ++ qman_cb_dqrr_park, ++ /* Does not consume, for DCA mode only. This allows out-of-order ++ * consumes by explicit calls to qman_dca() and/or the use of implicit ++ * DCA via EQCR entries. */ ++ qman_cb_dqrr_defer, ++ /* Stop processing without consuming this ring entry. Exits the current ++ * qman_poll_dqrr() or interrupt-handling, as appropriate. If within an ++ * interrupt handler, the callback would typically call ++ * qman_irqsource_remove(QM_PIRQ_DQRI) before returning this value, ++ * otherwise the interrupt will reassert immediately. */ ++ qman_cb_dqrr_stop, ++ /* Like qman_cb_dqrr_stop, but consumes the current entry. */ ++ qman_cb_dqrr_consume_stop ++}; ++typedef enum qman_cb_dqrr_result (*qman_cb_dqrr)(struct qman_portal *qm, ++ struct qman_fq *fq, ++ const struct qm_dqrr_entry *dqrr); ++ ++/* This callback type is used when handling ERNs, FQRNs and FQRLs via MR. They ++ * are always consumed after the callback returns. */ ++typedef void (*qman_cb_mr)(struct qman_portal *qm, struct qman_fq *fq, ++ const struct qm_mr_entry *msg); ++ ++/* This callback type is used when handling DCP ERNs */ ++typedef void (*qman_cb_dc_ern)(struct qman_portal *qm, ++ const struct qm_mr_entry *msg); ++ ++/* s/w-visible states. Ie. tentatively scheduled + truly scheduled + active + ++ * held-active + held-suspended are just "sched". Things like "retired" will not ++ * be assumed until it is complete (ie. QMAN_FQ_STATE_CHANGING is set until ++ * then, to indicate it's completing and to gate attempts to retry the retire ++ * command). Note, park commands do not set QMAN_FQ_STATE_CHANGING because it's ++ * technically impossible in the case of enqueue DCAs (which refer to DQRR ring ++ * index rather than the FQ that ring entry corresponds to), so repeated park ++ * commands are allowed (if you're silly enough to try) but won't change FQ ++ * state, and the resulting park notifications move FQs from "sched" to ++ * "parked". */ ++enum qman_fq_state { ++ qman_fq_state_oos, ++ qman_fq_state_parked, ++ qman_fq_state_sched, ++ qman_fq_state_retired ++}; ++ ++/* Frame queue objects (struct qman_fq) are stored within memory passed to ++ * qman_create_fq(), as this allows stashing of caller-provided demux callback ++ * pointers at no extra cost to stashing of (driver-internal) FQ state. If the ++ * caller wishes to add per-FQ state and have it benefit from dequeue-stashing, ++ * they should; ++ * ++ * (a) extend the qman_fq structure with their state; eg. ++ * ++ * // myfq is allocated and driver_fq callbacks filled in; ++ * struct my_fq { ++ * struct qman_fq base; ++ * int an_extra_field; ++ * [ ... add other fields to be associated with each FQ ...] ++ * } *myfq = some_my_fq_allocator(); ++ * struct qman_fq *fq = qman_create_fq(fqid, flags, &myfq->base); ++ * ++ * // in a dequeue callback, access extra fields from 'fq' via a cast; ++ * struct my_fq *myfq = (struct my_fq *)fq; ++ * do_something_with(myfq->an_extra_field); ++ * [...] ++ * ++ * (b) when and if configuring the FQ for context stashing, specify how ever ++ * many cachelines are required to stash 'struct my_fq', to accelerate not ++ * only the Qman driver but the callback as well. ++ */ ++ ++struct qman_fq_cb { ++ qman_cb_dqrr dqrr; /* for dequeued frames */ ++ qman_cb_mr ern; /* for s/w ERNs */ ++ qman_cb_mr fqs; /* frame-queue state changes*/ ++}; ++ ++struct qman_fq { ++ /* Caller of qman_create_fq() provides these demux callbacks */ ++ struct qman_fq_cb cb; ++ /* These are internal to the driver, don't touch. In particular, they ++ * may change, be removed, or extended (so you shouldn't rely on ++ * sizeof(qman_fq) being a constant). */ ++ spinlock_t fqlock; ++ u32 fqid; ++ volatile unsigned long flags; ++ enum qman_fq_state state; ++ int cgr_groupid; ++ struct rb_node node; ++#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP ++ u32 key; ++#endif ++}; ++ ++/* This callback type is used when handling congestion group entry/exit. ++ * 'congested' is non-zero on congestion-entry, and zero on congestion-exit. */ ++typedef void (*qman_cb_cgr)(struct qman_portal *qm, ++ struct qman_cgr *cgr, int congested); ++ ++struct qman_cgr { ++ /* Set these prior to qman_create_cgr() */ ++ u32 cgrid; /* 0..255, but u32 to allow specials like -1, 256, etc.*/ ++ qman_cb_cgr cb; ++ /* These are private to the driver */ ++ u16 chan; /* portal channel this object is created on */ ++ struct list_head node; ++}; ++ ++/* Flags to qman_create_fq() */ ++#define QMAN_FQ_FLAG_NO_ENQUEUE 0x00000001 /* can't enqueue */ ++#define QMAN_FQ_FLAG_NO_MODIFY 0x00000002 /* can only enqueue */ ++#define QMAN_FQ_FLAG_TO_DCPORTAL 0x00000004 /* consumed by CAAM/PME/Fman */ ++#define QMAN_FQ_FLAG_LOCKED 0x00000008 /* multi-core locking */ ++#define QMAN_FQ_FLAG_AS_IS 0x00000010 /* query h/w state */ ++#define QMAN_FQ_FLAG_DYNAMIC_FQID 0x00000020 /* (de)allocate fqid */ ++ ++/* Flags to qman_destroy_fq() */ ++#define QMAN_FQ_DESTROY_PARKED 0x00000001 /* FQ can be parked or OOS */ ++ ++/* Flags from qman_fq_state() */ ++#define QMAN_FQ_STATE_CHANGING 0x80000000 /* 'state' is changing */ ++#define QMAN_FQ_STATE_NE 0x40000000 /* retired FQ isn't empty */ ++#define QMAN_FQ_STATE_ORL 0x20000000 /* retired FQ has ORL */ ++#define QMAN_FQ_STATE_BLOCKOOS 0xe0000000 /* if any are set, no OOS */ ++#define QMAN_FQ_STATE_CGR_EN 0x10000000 /* CGR enabled */ ++#define QMAN_FQ_STATE_VDQCR 0x08000000 /* being volatile dequeued */ ++ ++/* Flags to qman_init_fq() */ ++#define QMAN_INITFQ_FLAG_SCHED 0x00000001 /* schedule rather than park */ ++#define QMAN_INITFQ_FLAG_LOCAL 0x00000004 /* set dest portal */ ++ ++/* Flags to qman_volatile_dequeue() */ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++#define QMAN_VOLATILE_FLAG_WAIT 0x00000001 /* wait if VDQCR is in use */ ++#define QMAN_VOLATILE_FLAG_WAIT_INT 0x00000002 /* if wait, interruptible? */ ++#define QMAN_VOLATILE_FLAG_FINISH 0x00000004 /* wait till VDQCR completes */ ++#endif ++ ++/* Flags to qman_enqueue(). NB, the strange numbering is to align with hardware, ++ * bit-wise. (NB: the PME API is sensitive to these precise numberings too, so ++ * any change here should be audited in PME.) */ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT ++#define QMAN_ENQUEUE_FLAG_WAIT 0x00010000 /* wait if EQCR is full */ ++#define QMAN_ENQUEUE_FLAG_WAIT_INT 0x00020000 /* if wait, interruptible? */ ++#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC ++#define QMAN_ENQUEUE_FLAG_WAIT_SYNC 0x00000004 /* if wait, until consumed? */ ++#endif ++#endif ++#define QMAN_ENQUEUE_FLAG_WATCH_CGR 0x00080000 /* watch congestion state */ ++#define QMAN_ENQUEUE_FLAG_DCA 0x00008000 /* perform enqueue-DCA */ ++#define QMAN_ENQUEUE_FLAG_DCA_PARK 0x00004000 /* If DCA, requests park */ ++#define QMAN_ENQUEUE_FLAG_DCA_PTR(p) /* If DCA, p is DQRR entry */ \ ++ (((u32)(p) << 2) & 0x00000f00) ++#define QMAN_ENQUEUE_FLAG_C_GREEN 0x00000000 /* choose one C_*** flag */ ++#define QMAN_ENQUEUE_FLAG_C_YELLOW 0x00000008 ++#define QMAN_ENQUEUE_FLAG_C_RED 0x00000010 ++#define QMAN_ENQUEUE_FLAG_C_OVERRIDE 0x00000018 ++/* For the ORP-specific qman_enqueue_orp() variant; ++ * - this flag indicates "Not Last In Sequence", ie. all but the final fragment ++ * of a frame. */ ++#define QMAN_ENQUEUE_FLAG_NLIS 0x01000000 ++/* - this flag performs no enqueue but fills in an ORP sequence number that ++ * would otherwise block it (eg. if a frame has been dropped). */ ++#define QMAN_ENQUEUE_FLAG_HOLE 0x02000000 ++/* - this flag performs no enqueue but advances NESN to the given sequence ++ * number. */ ++#define QMAN_ENQUEUE_FLAG_NESN 0x04000000 ++ ++/* Flags to qman_modify_cgr() */ ++#define QMAN_CGR_FLAG_USE_INIT 0x00000001 ++#define QMAN_CGR_MODE_FRAME 0x00000001 ++ ++ /* Portal Management */ ++ /* ----------------- */ ++/** ++ * qman_get_portal_config - get portal configuration settings ++ * ++ * This returns a read-only view of the current cpu's affine portal settings. ++ */ ++const struct qman_portal_config *qman_get_portal_config(void); ++ ++/** ++ * qman_irqsource_get - return the portal work that is interrupt-driven ++ * ++ * Returns a bitmask of QM_PIRQ_**I processing sources that are currently ++ * enabled for interrupt handling on the current cpu's affine portal. These ++ * sources will trigger the portal interrupt and the interrupt handler (or a ++ * tasklet/bottom-half it defers to) will perform the corresponding processing ++ * work. The qman_poll_***() functions will only process sources that are not in ++ * this bitmask. If the current CPU is sharing a portal hosted on another CPU, ++ * this always returns zero. ++ */ ++u32 qman_irqsource_get(void); ++ ++/** ++ * qman_irqsource_add - add processing sources to be interrupt-driven ++ * @bits: bitmask of QM_PIRQ_**I processing sources ++ * ++ * Adds processing sources that should be interrupt-driven (rather than ++ * processed via qman_poll_***() functions). Returns zero for success, or ++ * -EINVAL if the current CPU is sharing a portal hosted on another CPU. ++ */ ++int qman_irqsource_add(u32 bits); ++ ++/** ++ * qman_irqsource_remove - remove processing sources from being interrupt-driven ++ * @bits: bitmask of QM_PIRQ_**I processing sources ++ * ++ * Removes processing sources from being interrupt-driven, so that they will ++ * instead be processed via qman_poll_***() functions. Returns zero for success, ++ * or -EINVAL if the current CPU is sharing a portal hosted on another CPU. ++ */ ++int qman_irqsource_remove(u32 bits); ++ ++/** ++ * qman_affine_cpus - return a mask of cpus that have affine portals ++ */ ++const cpumask_t *qman_affine_cpus(void); ++ ++/** ++ * qman_affine_channel - return the channel ID of an portal ++ * @cpu: the cpu whose affine portal is the subject of the query ++ * ++ * If @cpu is -1, the affine portal for the current CPU will be used. It is a ++ * bug to call this function for any value of @cpu (other than -1) that is not a ++ * member of the mask returned from qman_affine_cpus(). ++ */ ++u16 qman_affine_channel(int cpu); ++ ++/** ++ * qman_get_affine_portal - return the portal pointer affine to cpu ++ * @cpu: the cpu whose affine portal is the subject of the query ++ * ++ */ ++void *qman_get_affine_portal(int cpu); ++ ++/** ++ * qman_poll_dqrr - process DQRR (fast-path) entries ++ * @limit: the maximum number of DQRR entries to process ++ * ++ * Use of this function requires that DQRR processing not be interrupt-driven. ++ * Ie. the value returned by qman_irqsource_get() should not include ++ * QM_PIRQ_DQRI. If the current CPU is sharing a portal hosted on another CPU, ++ * this function will return -EINVAL, otherwise the return value is >=0 and ++ * represents the number of DQRR entries processed. ++ */ ++int qman_poll_dqrr(unsigned int limit); ++ ++/** ++ * qman_poll_slow - process anything (except DQRR) that isn't interrupt-driven. ++ * ++ * This function does any portal processing that isn't interrupt-driven. If the ++ * current CPU is sharing a portal hosted on another CPU, this function will ++ * return (u32)-1, otherwise the return value is a bitmask of QM_PIRQ_* sources ++ * indicating what interrupt sources were actually processed by the call. ++ */ ++u32 qman_poll_slow(void); ++ ++/** ++ * qman_poll - legacy wrapper for qman_poll_dqrr() and qman_poll_slow() ++ * ++ * Dispatcher logic on a cpu can use this to trigger any maintenance of the ++ * affine portal. There are two classes of portal processing in question; ++ * fast-path (which involves demuxing dequeue ring (DQRR) entries and tracking ++ * enqueue ring (EQCR) consumption), and slow-path (which involves EQCR ++ * thresholds, congestion state changes, etc). This function does whatever ++ * processing is not triggered by interrupts. ++ * ++ * Note, if DQRR and some slow-path processing are poll-driven (rather than ++ * interrupt-driven) then this function uses a heuristic to determine how often ++ * to run slow-path processing - as slow-path processing introduces at least a ++ * minimum latency each time it is run, whereas fast-path (DQRR) processing is ++ * close to zero-cost if there is no work to be done. Applications can tune this ++ * behaviour themselves by using qman_poll_dqrr() and qman_poll_slow() directly ++ * rather than going via this wrapper. ++ */ ++void qman_poll(void); ++ ++/** ++ * qman_stop_dequeues - Stop h/w dequeuing to the s/w portal ++ * ++ * Disables DQRR processing of the portal. This is reference-counted, so ++ * qman_start_dequeues() must be called as many times as qman_stop_dequeues() to ++ * truly re-enable dequeuing. ++ */ ++void qman_stop_dequeues(void); ++ ++/** ++ * qman_start_dequeues - (Re)start h/w dequeuing to the s/w portal ++ * ++ * Enables DQRR processing of the portal. This is reference-counted, so ++ * qman_start_dequeues() must be called as many times as qman_stop_dequeues() to ++ * truly re-enable dequeuing. ++ */ ++void qman_start_dequeues(void); ++ ++/** ++ * qman_static_dequeue_add - Add pool channels to the portal SDQCR ++ * @pools: bit-mask of pool channels, using QM_SDQCR_CHANNELS_POOL(n) ++ * ++ * Adds a set of pool channels to the portal's static dequeue command register ++ * (SDQCR). The requested pools are limited to those the portal has dequeue ++ * access to. ++ */ ++void qman_static_dequeue_add(u32 pools); ++ ++/** ++ * qman_static_dequeue_del - Remove pool channels from the portal SDQCR ++ * @pools: bit-mask of pool channels, using QM_SDQCR_CHANNELS_POOL(n) ++ * ++ * Removes a set of pool channels from the portal's static dequeue command ++ * register (SDQCR). The requested pools are limited to those the portal has ++ * dequeue access to. ++ */ ++void qman_static_dequeue_del(u32 pools); ++ ++/** ++ * qman_static_dequeue_get - return the portal's current SDQCR ++ * ++ * Returns the portal's current static dequeue command register (SDQCR). The ++ * entire register is returned, so if only the currently-enabled pool channels ++ * are desired, mask the return value with QM_SDQCR_CHANNELS_POOL_MASK. ++ */ ++u32 qman_static_dequeue_get(void); ++ ++/** ++ * qman_dca - Perform a Discrete Consumption Acknowledgement ++ * @dq: the DQRR entry to be consumed ++ * @park_request: indicates whether the held-active @fq should be parked ++ * ++ * Only allowed in DCA-mode portals, for DQRR entries whose handler callback had ++ * previously returned 'qman_cb_dqrr_defer'. NB, as with the other APIs, this ++ * does not take a 'portal' argument but implies the core affine portal from the ++ * cpu that is currently executing the function. For reasons of locking, this ++ * function must be called from the same CPU as that which processed the DQRR ++ * entry in the first place. ++ */ ++void qman_dca(struct qm_dqrr_entry *dq, int park_request); ++ ++/** ++ * qman_eqcr_is_empty - Determine if portal's EQCR is empty ++ * ++ * For use in situations where a cpu-affine caller needs to determine when all ++ * enqueues for the local portal have been processed by Qman but can't use the ++ * QMAN_ENQUEUE_FLAG_WAIT_SYNC flag to do this from the final qman_enqueue(). ++ * The function forces tracking of EQCR consumption (which normally doesn't ++ * happen until enqueue processing needs to find space to put new enqueue ++ * commands), and returns zero if the ring still has unprocessed entries, ++ * non-zero if it is empty. ++ */ ++int qman_eqcr_is_empty(void); ++ ++/** ++ * qman_set_dc_ern - Set the handler for DCP enqueue rejection notifications ++ * @handler: callback for processing DCP ERNs ++ * @affine: whether this handler is specific to the locally affine portal ++ * ++ * If a hardware block's interface to Qman (ie. its direct-connect portal, or ++ * DCP) is configured not to receive enqueue rejections, then any enqueues ++ * through that DCP that are rejected will be sent to a given software portal. ++ * If @affine is non-zero, then this handler will only be used for DCP ERNs ++ * received on the portal affine to the current CPU. If multiple CPUs share a ++ * portal and they all call this function, they will be setting the handler for ++ * the same portal! If @affine is zero, then this handler will be global to all ++ * portals handled by this instance of the driver. Only those portals that do ++ * not have their own affine handler will use the global handler. ++ */ ++void qman_set_dc_ern(qman_cb_dc_ern handler, int affine); ++ ++ /* FQ management */ ++ /* ------------- */ ++/** ++ * qman_create_fq - Allocates a FQ ++ * @fqid: the index of the FQD to encapsulate, must be "Out of Service" ++ * @flags: bit-mask of QMAN_FQ_FLAG_*** options ++ * @fq: memory for storing the 'fq', with callbacks filled in ++ * ++ * Creates a frame queue object for the given @fqid, unless the ++ * QMAN_FQ_FLAG_DYNAMIC_FQID flag is set in @flags, in which case a FQID is ++ * dynamically allocated (or the function fails if none are available). Once ++ * created, the caller should not touch the memory at 'fq' except as extended to ++ * adjacent memory for user-defined fields (see the definition of "struct ++ * qman_fq" for more info). NO_MODIFY is only intended for enqueuing to ++ * pre-existing frame-queues that aren't to be otherwise interfered with, it ++ * prevents all other modifications to the frame queue. The TO_DCPORTAL flag ++ * causes the driver to honour any contextB modifications requested in the ++ * qm_init_fq() API, as this indicates the frame queue will be consumed by a ++ * direct-connect portal (PME, CAAM, or Fman). When frame queues are consumed by ++ * software portals, the contextB field is controlled by the driver and can't be ++ * modified by the caller. If the AS_IS flag is specified, management commands ++ * will be used on portal @p to query state for frame queue @fqid and construct ++ * a frame queue object based on that, rather than assuming/requiring that it be ++ * Out of Service. ++ */ ++int qman_create_fq(u32 fqid, u32 flags, struct qman_fq *fq); ++ ++/** ++ * qman_destroy_fq - Deallocates a FQ ++ * @fq: the frame queue object to release ++ * @flags: bit-mask of QMAN_FQ_FREE_*** options ++ * ++ * The memory for this frame queue object ('fq' provided in qman_create_fq()) is ++ * not deallocated but the caller regains ownership, to do with as desired. The ++ * FQ must be in the 'out-of-service' state unless the QMAN_FQ_FREE_PARKED flag ++ * is specified, in which case it may also be in the 'parked' state. ++ */ ++void qman_destroy_fq(struct qman_fq *fq, u32 flags); ++ ++/** ++ * qman_fq_fqid - Queries the frame queue ID of a FQ object ++ * @fq: the frame queue object to query ++ */ ++u32 qman_fq_fqid(struct qman_fq *fq); ++ ++/** ++ * qman_fq_state - Queries the state of a FQ object ++ * @fq: the frame queue object to query ++ * @state: pointer to state enum to return the FQ scheduling state ++ * @flags: pointer to state flags to receive QMAN_FQ_STATE_*** bitmask ++ * ++ * Queries the state of the FQ object, without performing any h/w commands. ++ * This captures the state, as seen by the driver, at the time the function ++ * executes. ++ */ ++void qman_fq_state(struct qman_fq *fq, enum qman_fq_state *state, u32 *flags); ++ ++/** ++ * qman_init_fq - Initialises FQ fields, leaves the FQ "parked" or "scheduled" ++ * @fq: the frame queue object to modify, must be 'parked' or new. ++ * @flags: bit-mask of QMAN_INITFQ_FLAG_*** options ++ * @opts: the FQ-modification settings, as defined in the low-level API ++ * ++ * The @opts parameter comes from the low-level portal API. Select ++ * QMAN_INITFQ_FLAG_SCHED in @flags to cause the frame queue to be scheduled ++ * rather than parked. NB, @opts can be NULL. ++ * ++ * Note that some fields and options within @opts may be ignored or overwritten ++ * by the driver; ++ * 1. the 'count' and 'fqid' fields are always ignored (this operation only ++ * affects one frame queue: @fq). ++ * 2. the QM_INITFQ_WE_CONTEXTB option of the 'we_mask' field and the associated ++ * 'fqd' structure's 'context_b' field are sometimes overwritten; ++ * - if @fq was not created with QMAN_FQ_FLAG_TO_DCPORTAL, then context_b is ++ * initialised to a value used by the driver for demux. ++ * - if context_b is initialised for demux, so is context_a in case stashing ++ * is requested (see item 4). ++ * (So caller control of context_b is only possible for TO_DCPORTAL frame queue ++ * objects.) ++ * 3. if @flags contains QMAN_INITFQ_FLAG_LOCAL, the 'fqd' structure's ++ * 'dest::channel' field will be overwritten to match the portal used to issue ++ * the command. If the WE_DESTWQ write-enable bit had already been set by the ++ * caller, the channel workqueue will be left as-is, otherwise the write-enable ++ * bit is set and the workqueue is set to a default of 4. If the "LOCAL" flag ++ * isn't set, the destination channel/workqueue fields and the write-enable bit ++ * are left as-is. ++ * 4. if the driver overwrites context_a/b for demux, then if ++ * QM_INITFQ_WE_CONTEXTA is set, the driver will only overwrite ++ * context_a.address fields and will leave the stashing fields provided by the ++ * user alone, otherwise it will zero out the context_a.stashing fields. ++ */ ++int qman_init_fq(struct qman_fq *fq, u32 flags, struct qm_mcc_initfq *opts); ++ ++/** ++ * qman_schedule_fq - Schedules a FQ ++ * @fq: the frame queue object to schedule, must be 'parked' ++ * ++ * Schedules the frame queue, which must be Parked, which takes it to ++ * Tentatively-Scheduled or Truly-Scheduled depending on its fill-level. ++ */ ++int qman_schedule_fq(struct qman_fq *fq); ++ ++/** ++ * qman_retire_fq - Retires a FQ ++ * @fq: the frame queue object to retire ++ * @flags: FQ flags (as per qman_fq_state) if retirement completes immediately ++ * ++ * Retires the frame queue. This returns zero if it succeeds immediately, +1 if ++ * the retirement was started asynchronously, otherwise it returns negative for ++ * failure. When this function returns zero, @flags is set to indicate whether ++ * the retired FQ is empty and/or whether it has any ORL fragments (to show up ++ * as ERNs). Otherwise the corresponding flags will be known when a subsequent ++ * FQRN message shows up on the portal's message ring. ++ * ++ * NB, if the retirement is asynchronous (the FQ was in the Truly Scheduled or ++ * Active state), the completion will be via the message ring as a FQRN - but ++ * the corresponding callback may occur before this function returns!! Ie. the ++ * caller should be prepared to accept the callback as the function is called, ++ * not only once it has returned. ++ */ ++int qman_retire_fq(struct qman_fq *fq, u32 *flags); ++ ++/** ++ * qman_oos_fq - Puts a FQ "out of service" ++ * @fq: the frame queue object to be put out-of-service, must be 'retired' ++ * ++ * The frame queue must be retired and empty, and if any order restoration list ++ * was released as ERNs at the time of retirement, they must all be consumed. ++ */ ++int qman_oos_fq(struct qman_fq *fq); ++ ++/** ++ * qman_fq_flow_control - Set the XON/XOFF state of a FQ ++ * @fq: the frame queue object to be set to XON/XOFF state, must not be 'oos', ++ * or 'retired' or 'parked' state ++ * @xon: boolean to set fq in XON or XOFF state ++ * ++ * The frame should be in Tentatively Scheduled state or Truly Schedule sate, ++ * otherwise the IFSI interrupt will be asserted. ++ */ ++int qman_fq_flow_control(struct qman_fq *fq, int xon); ++ ++/** ++ * qman_query_fq - Queries FQD fields (via h/w query command) ++ * @fq: the frame queue object to be queried ++ * @fqd: storage for the queried FQD fields ++ */ ++int qman_query_fq(struct qman_fq *fq, struct qm_fqd *fqd); ++ ++/** ++ * qman_query_fq_np - Queries non-programmable FQD fields ++ * @fq: the frame queue object to be queried ++ * @np: storage for the queried FQD fields ++ */ ++int qman_query_fq_np(struct qman_fq *fq, struct qm_mcr_queryfq_np *np); ++ ++/** ++ * qman_query_wq - Queries work queue lengths ++ * @query_dedicated: If non-zero, query length of WQs in the channel dedicated ++ * to this software portal. Otherwise, query length of WQs in a ++ * channel specified in wq. ++ * @wq: storage for the queried WQs lengths. Also specified the channel to ++ * to query if query_dedicated is zero. ++ */ ++int qman_query_wq(u8 query_dedicated, struct qm_mcr_querywq *wq); ++ ++/** ++ * qman_volatile_dequeue - Issue a volatile dequeue command ++ * @fq: the frame queue object to dequeue from ++ * @flags: a bit-mask of QMAN_VOLATILE_FLAG_*** options ++ * @vdqcr: bit mask of QM_VDQCR_*** options, as per qm_dqrr_vdqcr_set() ++ * ++ * Attempts to lock access to the portal's VDQCR volatile dequeue functionality. ++ * The function will block and sleep if QMAN_VOLATILE_FLAG_WAIT is specified and ++ * the VDQCR is already in use, otherwise returns non-zero for failure. If ++ * QMAN_VOLATILE_FLAG_FINISH is specified, the function will only return once ++ * the VDQCR command has finished executing (ie. once the callback for the last ++ * DQRR entry resulting from the VDQCR command has been called). If not using ++ * the FINISH flag, completion can be determined either by detecting the ++ * presence of the QM_DQRR_STAT_UNSCHEDULED and QM_DQRR_STAT_DQCR_EXPIRED bits ++ * in the "stat" field of the "struct qm_dqrr_entry" passed to the FQ's dequeue ++ * callback, or by waiting for the QMAN_FQ_STATE_VDQCR bit to disappear from the ++ * "flags" retrieved from qman_fq_state(). ++ */ ++int qman_volatile_dequeue(struct qman_fq *fq, u32 flags, u32 vdqcr); ++ ++/** ++ * qman_enqueue - Enqueue a frame to a frame queue ++ * @fq: the frame queue object to enqueue to ++ * @fd: a descriptor of the frame to be enqueued ++ * @flags: bit-mask of QMAN_ENQUEUE_FLAG_*** options ++ * ++ * Fills an entry in the EQCR of portal @qm to enqueue the frame described by ++ * @fd. The descriptor details are copied from @fd to the EQCR entry, the 'pid' ++ * field is ignored. The return value is non-zero on error, such as ring full ++ * (and FLAG_WAIT not specified), congestion avoidance (FLAG_WATCH_CGR ++ * specified), etc. If the ring is full and FLAG_WAIT is specified, this ++ * function will block. If FLAG_INTERRUPT is set, the EQCI bit of the portal ++ * interrupt will assert when Qman consumes the EQCR entry (subject to "status ++ * disable", "enable", and "inhibit" registers). If FLAG_DCA is set, Qman will ++ * perform an implied "discrete consumption acknowledgement" on the dequeue ++ * ring's (DQRR) entry, at the ring index specified by the FLAG_DCA_IDX(x) ++ * macro. (As an alternative to issuing explicit DCA actions on DQRR entries, ++ * this implicit DCA can delay the release of a "held active" frame queue ++ * corresponding to a DQRR entry until Qman consumes the EQCR entry - providing ++ * order-preservation semantics in packet-forwarding scenarios.) If FLAG_DCA is ++ * set, then FLAG_DCA_PARK can also be set to imply that the DQRR consumption ++ * acknowledgement should "park request" the "held active" frame queue. Ie. ++ * when the portal eventually releases that frame queue, it will be left in the ++ * Parked state rather than Tentatively Scheduled or Truly Scheduled. If the ++ * portal is watching congestion groups, the QMAN_ENQUEUE_FLAG_WATCH_CGR flag ++ * is requested, and the FQ is a member of a congestion group, then this ++ * function returns -EAGAIN if the congestion group is currently congested. ++ * Note, this does not eliminate ERNs, as the async interface means we can be ++ * sending enqueue commands to an un-congested FQ that becomes congested before ++ * the enqueue commands are processed, but it does minimise needless thrashing ++ * of an already busy hardware resource by throttling many of the to-be-dropped ++ * enqueues "at the source". ++ */ ++int qman_enqueue(struct qman_fq *fq, const struct qm_fd *fd, u32 flags); ++ ++typedef int (*qman_cb_precommit) (void *arg); ++/** ++ * qman_enqueue_precommit - Enqueue a frame to a frame queue and call cb ++ * @fq: the frame queue object to enqueue to ++ * @fd: a descriptor of the frame to be enqueued ++ * @flags: bit-mask of QMAN_ENQUEUE_FLAG_*** options ++ * @cb: user supplied callback function to invoke before writing commit verb. ++ * @cb_arg: callback function argument ++ * ++ * This is similar to qman_enqueue except that it will invoke a user supplied ++ * callback function just before writng the commit verb. This is useful ++ * when the user want to do something *just before* enqueuing the request and ++ * the enqueue can't fail. ++ */ ++int qman_enqueue_precommit(struct qman_fq *fq, const struct qm_fd *fd, ++ u32 flags, qman_cb_precommit cb, void *cb_arg); ++ ++/** ++ * qman_enqueue_orp - Enqueue a frame to a frame queue using an ORP ++ * @fq: the frame queue object to enqueue to ++ * @fd: a descriptor of the frame to be enqueued ++ * @flags: bit-mask of QMAN_ENQUEUE_FLAG_*** options ++ * @orp: the frame queue object used as an order restoration point. ++ * @orp_seqnum: the sequence number of this frame in the order restoration path ++ * ++ * Similar to qman_enqueue(), but with the addition of an Order Restoration ++ * Point (@orp) and corresponding sequence number (@orp_seqnum) for this ++ * enqueue operation to employ order restoration. Each frame queue object acts ++ * as an Order Definition Point (ODP) by providing each frame dequeued from it ++ * with an incrementing sequence number, this value is generally ignored unless ++ * that sequence of dequeued frames will need order restoration later. Each ++ * frame queue object also encapsulates an Order Restoration Point (ORP), which ++ * is a re-assembly context for re-ordering frames relative to their sequence ++ * numbers as they are enqueued. The ORP does not have to be within the frame ++ * queue that receives the enqueued frame, in fact it is usually the frame ++ * queue from which the frames were originally dequeued. For the purposes of ++ * order restoration, multiple frames (or "fragments") can be enqueued for a ++ * single sequence number by setting the QMAN_ENQUEUE_FLAG_NLIS flag for all ++ * enqueues except the final fragment of a given sequence number. Ordering ++ * between sequence numbers is guaranteed, even if fragments of different ++ * sequence numbers are interlaced with one another. Fragments of the same ++ * sequence number will retain the order in which they are enqueued. If no ++ * enqueue is to performed, QMAN_ENQUEUE_FLAG_HOLE indicates that the given ++ * sequence number is to be "skipped" by the ORP logic (eg. if a frame has been ++ * dropped from a sequence), or QMAN_ENQUEUE_FLAG_NESN indicates that the given ++ * sequence number should become the ORP's "Next Expected Sequence Number". ++ * ++ * Side note: a frame queue object can be used purely as an ORP, without ++ * carrying any frames at all. Care should be taken not to deallocate a frame ++ * queue object that is being actively used as an ORP, as a future allocation ++ * of the frame queue object may start using the internal ORP before the ++ * previous use has finished. ++ */ ++int qman_enqueue_orp(struct qman_fq *fq, const struct qm_fd *fd, u32 flags, ++ struct qman_fq *orp, u16 orp_seqnum); ++ ++/** ++ * qman_alloc_fqid_range - Allocate a contiguous range of FQIDs ++ * @result: is set by the API to the base FQID of the allocated range ++ * @count: the number of FQIDs required ++ * @align: required alignment of the allocated range ++ * @partial: non-zero if the API can return fewer than @count FQIDs ++ * ++ * Returns the number of frame queues allocated, or a negative error code. If ++ * @partial is non zero, the allocation request may return a smaller range of ++ * FQs than requested (though alignment will be as requested). If @partial is ++ * zero, the return value will either be 'count' or negative. ++ */ ++int qman_alloc_fqid_range(u32 *result, u32 count, u32 align, int partial); ++static inline int qman_alloc_fqid(u32 *result) ++{ ++ int ret = qman_alloc_fqid_range(result, 1, 0, 0); ++ return (ret > 0) ? 0 : ret; ++} ++ ++/** ++ * qman_release_fqid_range - Release the specified range of frame queue IDs ++ * @fqid: the base FQID of the range to deallocate ++ * @count: the number of FQIDs in the range ++ * ++ * This function can also be used to seed the allocator with ranges of FQIDs ++ * that it can subsequently allocate from. ++ */ ++void qman_release_fqid_range(u32 fqid, unsigned int count); ++static inline void qman_release_fqid(u32 fqid) ++{ ++ qman_release_fqid_range(fqid, 1); ++} ++ ++void qman_seed_fqid_range(u32 fqid, unsigned int count); ++ ++ ++int qman_shutdown_fq(u32 fqid); ++ ++/** ++ * qman_reserve_fqid_range - Reserve the specified range of frame queue IDs ++ * @fqid: the base FQID of the range to deallocate ++ * @count: the number of FQIDs in the range ++ */ ++int qman_reserve_fqid_range(u32 fqid, unsigned int count); ++static inline int qman_reserve_fqid(u32 fqid) ++{ ++ return qman_reserve_fqid_range(fqid, 1); ++} ++ ++ /* Pool-channel management */ ++ /* ----------------------- */ ++/** ++ * qman_alloc_pool_range - Allocate a contiguous range of pool-channel IDs ++ * @result: is set by the API to the base pool-channel ID of the allocated range ++ * @count: the number of pool-channel IDs required ++ * @align: required alignment of the allocated range ++ * @partial: non-zero if the API can return fewer than @count ++ * ++ * Returns the number of pool-channel IDs allocated, or a negative error code. ++ * If @partial is non zero, the allocation request may return a smaller range of ++ * than requested (though alignment will be as requested). If @partial is zero, ++ * the return value will either be 'count' or negative. ++ */ ++int qman_alloc_pool_range(u32 *result, u32 count, u32 align, int partial); ++static inline int qman_alloc_pool(u32 *result) ++{ ++ int ret = qman_alloc_pool_range(result, 1, 0, 0); ++ return (ret > 0) ? 0 : ret; ++} ++ ++/** ++ * qman_release_pool_range - Release the specified range of pool-channel IDs ++ * @id: the base pool-channel ID of the range to deallocate ++ * @count: the number of pool-channel IDs in the range ++ */ ++void qman_release_pool_range(u32 id, unsigned int count); ++static inline void qman_release_pool(u32 id) ++{ ++ qman_release_pool_range(id, 1); ++} ++ ++/** ++ * qman_reserve_pool_range - Reserve the specified range of pool-channel IDs ++ * @id: the base pool-channel ID of the range to reserve ++ * @count: the number of pool-channel IDs in the range ++ */ ++int qman_reserve_pool_range(u32 id, unsigned int count); ++static inline int qman_reserve_pool(u32 id) ++{ ++ return qman_reserve_pool_range(id, 1); ++} ++ ++void qman_seed_pool_range(u32 id, unsigned int count); ++ ++ /* CGR management */ ++ /* -------------- */ ++/** ++ * qman_create_cgr - Register a congestion group object ++ * @cgr: the 'cgr' object, with fields filled in ++ * @flags: QMAN_CGR_FLAG_* values ++ * @opts: optional state of CGR settings ++ * ++ * Registers this object to receiving congestion entry/exit callbacks on the ++ * portal affine to the cpu portal on which this API is executed. If opts is ++ * NULL then only the callback (cgr->cb) function is registered. If @flags ++ * contains QMAN_CGR_FLAG_USE_INIT, then an init hw command (which will reset ++ * any unspecified parameters) will be used rather than a modify hw hardware ++ * (which only modifies the specified parameters). ++ */ ++int qman_create_cgr(struct qman_cgr *cgr, u32 flags, ++ struct qm_mcc_initcgr *opts); ++ ++/** ++ * qman_create_cgr_to_dcp - Register a congestion group object to DCP portal ++ * @cgr: the 'cgr' object, with fields filled in ++ * @flags: QMAN_CGR_FLAG_* values ++ * @dcp_portal: the DCP portal to which the cgr object is registered. ++ * @opts: optional state of CGR settings ++ * ++ */ ++int qman_create_cgr_to_dcp(struct qman_cgr *cgr, u32 flags, u16 dcp_portal, ++ struct qm_mcc_initcgr *opts); ++ ++/** ++ * qman_delete_cgr - Deregisters a congestion group object ++ * @cgr: the 'cgr' object to deregister ++ * ++ * "Unplugs" this CGR object from the portal affine to the cpu on which this API ++ * is executed. This must be excuted on the same affine portal on which it was ++ * created. ++ */ ++int qman_delete_cgr(struct qman_cgr *cgr); ++ ++/** ++ * qman_delete_cgr_safe - Deregisters a congestion group object from any CPU ++ * @cgr: the 'cgr' object to deregister ++ * ++ * This will select the proper CPU and run there qman_delete_cgr(). ++ */ ++void qman_delete_cgr_safe(struct qman_cgr *cgr); ++ ++/** ++ * qman_modify_cgr - Modify CGR fields ++ * @cgr: the 'cgr' object to modify ++ * @flags: QMAN_CGR_FLAG_* values ++ * @opts: the CGR-modification settings ++ * ++ * The @opts parameter comes from the low-level portal API, and can be NULL. ++ * Note that some fields and options within @opts may be ignored or overwritten ++ * by the driver, in particular the 'cgrid' field is ignored (this operation ++ * only affects the given CGR object). If @flags contains ++ * QMAN_CGR_FLAG_USE_INIT, then an init hw command (which will reset any ++ * unspecified parameters) will be used rather than a modify hw hardware (which ++ * only modifies the specified parameters). ++ */ ++int qman_modify_cgr(struct qman_cgr *cgr, u32 flags, ++ struct qm_mcc_initcgr *opts); ++ ++/** ++* qman_query_cgr - Queries CGR fields ++* @cgr: the 'cgr' object to query ++* @result: storage for the queried congestion group record ++*/ ++int qman_query_cgr(struct qman_cgr *cgr, struct qm_mcr_querycgr *result); ++ ++/** ++ * qman_query_congestion - Queries the state of all congestion groups ++ * @congestion: storage for the queried state of all congestion groups ++ */ ++int qman_query_congestion(struct qm_mcr_querycongestion *congestion); ++ ++/** ++ * qman_alloc_cgrid_range - Allocate a contiguous range of CGR IDs ++ * @result: is set by the API to the base CGR ID of the allocated range ++ * @count: the number of CGR IDs required ++ * @align: required alignment of the allocated range ++ * @partial: non-zero if the API can return fewer than @count ++ * ++ * Returns the number of CGR IDs allocated, or a negative error code. ++ * If @partial is non zero, the allocation request may return a smaller range of ++ * than requested (though alignment will be as requested). If @partial is zero, ++ * the return value will either be 'count' or negative. ++ */ ++int qman_alloc_cgrid_range(u32 *result, u32 count, u32 align, int partial); ++static inline int qman_alloc_cgrid(u32 *result) ++{ ++ int ret = qman_alloc_cgrid_range(result, 1, 0, 0); ++ return (ret > 0) ? 0 : ret; ++} ++ ++/** ++ * qman_release_cgrid_range - Release the specified range of CGR IDs ++ * @id: the base CGR ID of the range to deallocate ++ * @count: the number of CGR IDs in the range ++ */ ++void qman_release_cgrid_range(u32 id, unsigned int count); ++static inline void qman_release_cgrid(u32 id) ++{ ++ qman_release_cgrid_range(id, 1); ++} ++ ++/** ++ * qman_reserve_cgrid_range - Reserve the specified range of CGR ID ++ * @id: the base CGR ID of the range to reserve ++ * @count: the number of CGR IDs in the range ++ */ ++int qman_reserve_cgrid_range(u32 id, unsigned int count); ++static inline int qman_reserve_cgrid(u32 id) ++{ ++ return qman_reserve_cgrid_range(id, 1); ++} ++ ++void qman_seed_cgrid_range(u32 id, unsigned int count); ++ ++ ++ /* Helpers */ ++ /* ------- */ ++/** ++ * qman_poll_fq_for_init - Check if an FQ has been initialised from OOS ++ * @fqid: the FQID that will be initialised by other s/w ++ * ++ * In many situations, a FQID is provided for communication between s/w ++ * entities, and whilst the consumer is responsible for initialising and ++ * scheduling the FQ, the producer(s) generally create a wrapper FQ object using ++ * and only call qman_enqueue() (no FQ initialisation, scheduling, etc). Ie; ++ * qman_create_fq(..., QMAN_FQ_FLAG_NO_MODIFY, ...); ++ * However, data can not be enqueued to the FQ until it is initialised out of ++ * the OOS state - this function polls for that condition. It is particularly ++ * useful for users of IPC functions - each endpoint's Rx FQ is the other ++ * endpoint's Tx FQ, so each side can initialise and schedule their Rx FQ object ++ * and then use this API on the (NO_MODIFY) Tx FQ object in order to ++ * synchronise. The function returns zero for success, +1 if the FQ is still in ++ * the OOS state, or negative if there was an error. ++ */ ++static inline int qman_poll_fq_for_init(struct qman_fq *fq) ++{ ++ struct qm_mcr_queryfq_np np; ++ int err; ++ err = qman_query_fq_np(fq, &np); ++ if (err) ++ return err; ++ if ((np.state & QM_MCR_NP_STATE_MASK) == QM_MCR_NP_STATE_OOS) ++ return 1; ++ return 0; ++} ++ ++ /* -------------- */ ++ /* CEETM :: types */ ++ /* -------------- */ ++/** ++ * Token Rate Structure ++ * Shaping rates are based on a "credit" system and a pre-configured h/w ++ * internal timer. The following type represents a shaper "rate" parameter as a ++ * fractional number of "tokens". Here's how it works. This (fractional) number ++ * of tokens is added to the shaper's "credit" every time the h/w timer elapses ++ * (up to a limit which is set by another shaper parameter). Every time a frame ++ * is enqueued through a shaper, the shaper deducts as many tokens as there are ++ * bytes of data in the enqueued frame. A shaper will not allow itself to ++ * enqueue any frames if its token count is negative. As such; ++ * ++ * The rate at which data is enqueued is limited by the ++ * rate at which tokens are added. ++ * ++ * Therefore if the user knows the period between these h/w timer updates in ++ * seconds, they can calculate the maximum traffic rate of the shaper (in ++ * bytes-per-second) from the token rate. And vice versa, they can calculate ++ * the token rate to use in order to achieve a given traffic rate. ++ */ ++struct qm_ceetm_rate { ++ /* The token rate is; whole + (fraction/8192) */ ++ u32 whole:11; /* 0..2047 */ ++ u32 fraction:13; /* 0..8191 */ ++}; ++ ++struct qm_ceetm_weight_code { ++ /* The weight code is; 5 msbits + 3 lsbits */ ++ u8 y:5; ++ u8 x:3; ++}; ++ ++struct qm_ceetm { ++ unsigned int idx; ++ struct list_head sub_portals; ++ struct list_head lnis; ++ unsigned int sp_range[2]; ++ unsigned int lni_range[2]; ++}; ++ ++struct qm_ceetm_sp { ++ struct list_head node; ++ unsigned int idx; ++ unsigned int dcp_idx; ++ int is_claimed; ++ struct qm_ceetm_lni *lni; ++}; ++ ++/* Logical Network Interface */ ++struct qm_ceetm_lni { ++ struct list_head node; ++ unsigned int idx; ++ unsigned int dcp_idx; ++ int is_claimed; ++ struct qm_ceetm_sp *sp; ++ struct list_head channels; ++ int shaper_enable; ++ int shaper_couple; ++ int oal; ++ struct qm_ceetm_rate cr_token_rate; ++ struct qm_ceetm_rate er_token_rate; ++ u16 cr_token_bucket_limit; ++ u16 er_token_bucket_limit; ++}; ++ ++/* Class Queue Channel */ ++struct qm_ceetm_channel { ++ struct list_head node; ++ unsigned int idx; ++ unsigned int lni_idx; ++ unsigned int dcp_idx; ++ struct list_head class_queues; ++ struct list_head ccgs; ++ u8 shaper_enable; ++ u8 shaper_couple; ++ struct qm_ceetm_rate cr_token_rate; ++ struct qm_ceetm_rate er_token_rate; ++ u16 cr_token_bucket_limit; ++ u16 er_token_bucket_limit; ++}; ++ ++struct qm_ceetm_ccg; ++ ++/* This callback type is used when handling congestion entry/exit. The ++ * 'cb_ctx' value is the opaque value associated with ccg object. ++ * 'congested' is non-zero on congestion-entry, and zero on congestion-exit. ++ */ ++typedef void (*qman_cb_ccgr)(struct qm_ceetm_ccg *ccg, void *cb_ctx, ++ int congested); ++ ++/* Class Congestion Group */ ++struct qm_ceetm_ccg { ++ struct qm_ceetm_channel *parent; ++ struct list_head node; ++ struct list_head cb_node; ++ qman_cb_ccgr cb; ++ void *cb_ctx; ++ unsigned int idx; ++}; ++ ++/* Class Queue */ ++struct qm_ceetm_cq { ++ struct qm_ceetm_channel *parent; ++ struct qm_ceetm_ccg *ccg; ++ struct list_head node; ++ unsigned int idx; ++ int is_claimed; ++ struct list_head bound_lfqids; ++ struct list_head binding_node; ++}; ++ ++/* Logical Frame Queue */ ++struct qm_ceetm_lfq { ++ struct qm_ceetm_channel *parent; ++ struct list_head node; ++ unsigned int idx; ++ unsigned int dctidx; ++ u64 context_a; ++ u32 context_b; ++ qman_cb_mr ern; ++}; ++ ++/** ++ * qman_ceetm_bps2tokenrate - Given a desired rate 'bps' measured in bps ++ * (ie. bits-per-second), compute the 'token_rate' fraction that best ++ * approximates that rate. ++ * @bps: the desired shaper rate in bps. ++ * @token_rate: the output token rate computed with the given kbps. ++ * @rounding: dictates how to round if an exact conversion is not possible; if ++ * it is negative then 'token_rate' will round down to the highest value that ++ * does not exceed the desired rate, if it is positive then 'token_rate' will ++ * round up to the lowest value that is greater than or equal to the desired ++ * rate, and if it is zero then it will round to the nearest approximation, ++ * whether that be up or down. ++ * ++ * Return 0 for success, or -EINVAL if prescaler or qman clock is not available. ++ */ ++int qman_ceetm_bps2tokenrate(u64 bps, ++ struct qm_ceetm_rate *token_rate, ++ int rounding); ++ ++/** ++ * qman_ceetm_tokenrate2bps - Given a 'token_rate', compute the ++ * corresponding number of 'bps'. ++ * @token_rate: the input desired token_rate fraction. ++ * @bps: the output shaper rate in bps computed with the give token rate. ++ * @rounding: has the same semantics as the previous function. ++ * ++ * Return 0 for success, or -EINVAL if prescaler or qman clock is not available. ++ */ ++int qman_ceetm_tokenrate2bps(const struct qm_ceetm_rate *token_rate, ++ u64 *bps, ++ int rounding); ++ ++int qman_alloc_ceetm0_channel_range(u32 *result, u32 count, u32 align, ++ int partial); ++static inline int qman_alloc_ceetm0_channel(u32 *result) ++{ ++ int ret = qman_alloc_ceetm0_channel_range(result, 1, 0, 0); ++ return (ret > 0) ? 0 : ret; ++} ++void qman_release_ceetm0_channel_range(u32 channelid, u32 count); ++static inline void qman_release_ceetm0_channelid(u32 channelid) ++{ ++ qman_release_ceetm0_channel_range(channelid, 1); ++} ++ ++int qman_reserve_ceetm0_channel_range(u32 channelid, u32 count); ++static inline int qman_reserve_ceetm0_channelid(u32 channelid) ++{ ++ return qman_reserve_ceetm0_channel_range(channelid, 1); ++} ++ ++void qman_seed_ceetm0_channel_range(u32 channelid, u32 count); ++ ++ ++int qman_alloc_ceetm1_channel_range(u32 *result, u32 count, u32 align, ++ int partial); ++static inline int qman_alloc_ceetm1_channel(u32 *result) ++{ ++ int ret = qman_alloc_ceetm1_channel_range(result, 1, 0, 0); ++ return (ret > 0) ? 0 : ret; ++} ++void qman_release_ceetm1_channel_range(u32 channelid, u32 count); ++static inline void qman_release_ceetm1_channelid(u32 channelid) ++{ ++ qman_release_ceetm1_channel_range(channelid, 1); ++} ++int qman_reserve_ceetm1_channel_range(u32 channelid, u32 count); ++static inline int qman_reserve_ceetm1_channelid(u32 channelid) ++{ ++ return qman_reserve_ceetm1_channel_range(channelid, 1); ++} ++ ++void qman_seed_ceetm1_channel_range(u32 channelid, u32 count); ++ ++ ++int qman_alloc_ceetm0_lfqid_range(u32 *result, u32 count, u32 align, ++ int partial); ++static inline int qman_alloc_ceetm0_lfqid(u32 *result) ++{ ++ int ret = qman_alloc_ceetm0_lfqid_range(result, 1, 0, 0); ++ return (ret > 0) ? 0 : ret; ++} ++void qman_release_ceetm0_lfqid_range(u32 lfqid, u32 count); ++static inline void qman_release_ceetm0_lfqid(u32 lfqid) ++{ ++ qman_release_ceetm0_lfqid_range(lfqid, 1); ++} ++int qman_reserve_ceetm0_lfqid_range(u32 lfqid, u32 count); ++static inline int qman_reserve_ceetm0_lfqid(u32 lfqid) ++{ ++ return qman_reserve_ceetm0_lfqid_range(lfqid, 1); ++} ++ ++void qman_seed_ceetm0_lfqid_range(u32 lfqid, u32 count); ++ ++ ++int qman_alloc_ceetm1_lfqid_range(u32 *result, u32 count, u32 align, ++ int partial); ++static inline int qman_alloc_ceetm1_lfqid(u32 *result) ++{ ++ int ret = qman_alloc_ceetm1_lfqid_range(result, 1, 0, 0); ++ return (ret > 0) ? 0 : ret; ++} ++void qman_release_ceetm1_lfqid_range(u32 lfqid, u32 count); ++static inline void qman_release_ceetm1_lfqid(u32 lfqid) ++{ ++ qman_release_ceetm1_lfqid_range(lfqid, 1); ++} ++int qman_reserve_ceetm1_lfqid_range(u32 lfqid, u32 count); ++static inline int qman_reserve_ceetm1_lfqid(u32 lfqid) ++{ ++ return qman_reserve_ceetm1_lfqid_range(lfqid, 1); ++} ++ ++void qman_seed_ceetm1_lfqid_range(u32 lfqid, u32 count); ++ ++ ++ /* ----------------------------- */ ++ /* CEETM :: sub-portals */ ++ /* ----------------------------- */ ++ ++/** ++ * qman_ceetm_claim_sp - Claims the given sub-portal, provided it is available ++ * to us and configured for traffic-management. ++ * @sp: the returned sub-portal object, if successful. ++ * @dcp_id: specifies the desired Fman block (and thus the relevant CEETM ++ * instance), ++ * @sp_idx" is the desired sub-portal index from 0 to 15. ++ * ++ * Returns zero for success, or -ENODEV if the sub-portal is in use, or -EINVAL ++ * if the sp_idx is out of range. ++ * ++ * Note that if there are multiple driver domains (eg. a linux kernel versus ++ * user-space drivers in USDPAA, or multiple guests running under a hypervisor) ++ * then a sub-portal may be accessible by more than one instance of a qman ++ * driver and so it may be claimed multiple times. If this is the case, it is ++ * up to the system architect to prevent conflicting configuration actions ++ * coming from the different driver domains. The qman drivers do not have any ++ * behind-the-scenes coordination to prevent this from happening. ++ */ ++int qman_ceetm_sp_claim(struct qm_ceetm_sp **sp, ++ enum qm_dc_portal dcp_idx, ++ unsigned int sp_idx); ++ ++/** ++ * qman_ceetm_sp_release - Releases a previously claimed sub-portal. ++ * @sp: the sub-portal to be released. ++ * ++ * Returns 0 for success, or -EBUSY for failure if the dependencies are not ++ * released. ++ */ ++int qman_ceetm_sp_release(struct qm_ceetm_sp *sp); ++ ++ /* ----------------------------------- */ ++ /* CEETM :: logical network interfaces */ ++ /* ----------------------------------- */ ++ ++/** ++ * qman_ceetm_lni_claim - Claims an unclaimed LNI. ++ * @lni: the returned LNI object, if successful. ++ * @dcp_id: specifies the desired Fman block (and thus the relevant CEETM ++ * instance) ++ * @lni_idx: is the desired LNI index. ++ * ++ * Returns zero for success, or -EINVAL on failure, which will happen if the LNI ++ * is not available or has already been claimed (and not yet successfully ++ * released), or lni_dix is out of range. ++ * ++ * Note that there may be multiple driver domains (or instances) that need to ++ * transmit out the same LNI, so this claim is only guaranteeing exclusivity ++ * within the domain of the driver being called. See qman_ceetm_sp_claim() and ++ * qman_ceetm_sp_get_lni() for more information. ++ */ ++int qman_ceetm_lni_claim(struct qm_ceetm_lni **lni, ++ enum qm_dc_portal dcp_id, ++ unsigned int lni_idx); ++ ++/** ++ * qman_ceetm_lni_releaes - Releases a previously claimed LNI. ++ * @lni: the lni needs to be released. ++ * ++ * This will only succeed if all dependent objects have been released. ++ * Returns zero for success, or -EBUSY if the dependencies are not released. ++ */ ++int qman_ceetm_lni_release(struct qm_ceetm_lni *lni); ++ ++/** ++ * qman_ceetm_sp_set_lni ++ * qman_ceetm_sp_get_lni - Set/get the LNI that the sub-portal is currently ++ * mapped to. ++ * @sp: the given sub-portal. ++ * @lni(in "set"function): the LNI object which the sp will be mappaed to. ++ * @lni_idx(in "get" function): the LNI index which the sp is mapped to. ++ * ++ * Returns zero for success, or -EINVAL for the "set" function when this sp-lni ++ * mapping has been set, or configure mapping command returns error, and ++ * -EINVAL for "get" function when this sp-lni mapping is not set or the query ++ * mapping command returns error. ++ * ++ * This may be useful in situations where multiple driver domains have access ++ * to the same sub-portals in order to all be able to transmit out the same ++ * physical interface (perhaps they're on different IP addresses or VPNs, so ++ * Fman is splitting Rx traffic and here we need to converge Tx traffic). In ++ * that case, a control-plane is likely to use qman_ceetm_lni_claim() followed ++ * by qman_ceetm_sp_set_lni() to configure the sub-portal, and other domains ++ * are likely to use qman_ceetm_sp_get_lni() followed by qman_ceetm_lni_claim() ++ * in order to determine the LNI that the control-plane had assigned. This is ++ * why the "get" returns an index, whereas the "set" takes an (already claimed) ++ * LNI object. ++ */ ++int qman_ceetm_sp_set_lni(struct qm_ceetm_sp *sp, ++ struct qm_ceetm_lni *lni); ++int qman_ceetm_sp_get_lni(struct qm_ceetm_sp *sp, ++ unsigned int *lni_idx); ++ ++/** ++ * qman_ceetm_lni_enable_shaper ++ * qman_ceetm_lni_disable_shaper - Enables/disables shaping on the LNI. ++ * @lni: the given LNI. ++ * @coupled: indicates whether CR and ER are coupled. ++ * @oal: the overhead accounting length which is added to the actual length of ++ * each frame when performing shaper calculations. ++ * ++ * When the number of (unused) committed-rate tokens reach the committed-rate ++ * token limit, 'coupled' indicates whether surplus tokens should be added to ++ * the excess-rate token count (up to the excess-rate token limit). ++ * When LNI is claimed, the shaper is disabled by default. The enable function ++ * will turn on this shaper for this lni. ++ * Whenever a claimed LNI is first enabled for shaping, its committed and ++ * excess token rates and limits are zero, so will need to be changed to do ++ * anything useful. The shaper can subsequently be enabled/disabled without ++ * resetting the shaping parameters, but the shaping parameters will be reset ++ * when the LNI is released. ++ * ++ * Returns zero for success, or errno for "enable" function in the cases as: ++ * a) -EINVAL if the shaper is already enabled, ++ * b) -EIO if the configure shaper command returns error. ++ * For "disable" function, returns: ++ * a) -EINVAL if the shaper is has already disabled. ++ * b) -EIO if calling configure shaper command returns error. ++ */ ++int qman_ceetm_lni_enable_shaper(struct qm_ceetm_lni *lni, int coupled, ++ int oal); ++int qman_ceetm_lni_disable_shaper(struct qm_ceetm_lni *lni); ++ ++/** ++ * qman_ceetm_lni_is_shaper_enabled - Check LNI shaper status ++ * @lni: the give LNI ++ */ ++int qman_ceetm_lni_is_shaper_enabled(struct qm_ceetm_lni *lni); ++ ++/** ++ * qman_ceetm_lni_set_commit_rate ++ * qman_ceetm_lni_get_commit_rate ++ * qman_ceetm_lni_set_excess_rate ++ * qman_ceetm_lni_get_excess_rate - Set/get the shaper CR/ER token rate and ++ * token limit for the given LNI. ++ * @lni: the given LNI. ++ * @token_rate: the desired token rate for "set" fuction, or the token rate of ++ * the LNI queried by "get" function. ++ * @token_limit: the desired token bucket limit for "set" function, or the token ++ * limit of the given LNI queried by "get" function. ++ * ++ * Returns zero for success. The "set" function returns -EINVAL if the given ++ * LNI is unshapped or -EIO if the configure shaper command returns error. ++ * The "get" function returns -EINVAL if the token rate or the token limit is ++ * not set or the query command returns error. ++ */ ++int qman_ceetm_lni_set_commit_rate(struct qm_ceetm_lni *lni, ++ const struct qm_ceetm_rate *token_rate, ++ u16 token_limit); ++int qman_ceetm_lni_get_commit_rate(struct qm_ceetm_lni *lni, ++ struct qm_ceetm_rate *token_rate, ++ u16 *token_limit); ++int qman_ceetm_lni_set_excess_rate(struct qm_ceetm_lni *lni, ++ const struct qm_ceetm_rate *token_rate, ++ u16 token_limit); ++int qman_ceetm_lni_get_excess_rate(struct qm_ceetm_lni *lni, ++ struct qm_ceetm_rate *token_rate, ++ u16 *token_limit); ++/** ++ * qman_ceetm_lni_set_commit_rate_bps ++ * qman_ceetm_lni_get_commit_rate_bps ++ * qman_ceetm_lni_set_excess_rate_bps ++ * qman_ceetm_lni_get_excess_rate_bps - Set/get the shaper CR/ER rate ++ * and token limit for the given LNI. ++ * @lni: the given LNI. ++ * @bps: the desired shaping rate in bps for "set" fuction, or the shaping rate ++ * of the LNI queried by "get" function. ++ * @token_limit: the desired token bucket limit for "set" function, or the token ++ * limit of the given LNI queried by "get" function. ++ * ++ * Returns zero for success. The "set" function returns -EINVAL if the given ++ * LNI is unshapped or -EIO if the configure shaper command returns error. ++ * The "get" function returns -EINVAL if the token rate or the token limit is ++ * not set or the query command returns error. ++ */ ++int qman_ceetm_lni_set_commit_rate_bps(struct qm_ceetm_lni *lni, ++ u64 bps, ++ u16 token_limit); ++int qman_ceetm_lni_get_commit_rate_bps(struct qm_ceetm_lni *lni, ++ u64 *bps, u16 *token_limit); ++int qman_ceetm_lni_set_excess_rate_bps(struct qm_ceetm_lni *lni, ++ u64 bps, ++ u16 token_limit); ++int qman_ceetm_lni_get_excess_rate_bps(struct qm_ceetm_lni *lni, ++ u64 *bps, u16 *token_limit); ++ ++/** ++ * qman_ceetm_lni_set_tcfcc ++ * qman_ceetm_lni_get_tcfcc - Configure/query "Traffic Class Flow Control". ++ * @lni: the given LNI. ++ * @cq_level: is between 0 and 15, representing individual class queue levels ++ * (CQ0 to CQ7 for every channel) and grouped class queue levels (CQ8 to CQ15 ++ * for every channel). ++ * @traffic_class: is between 0 and 7 when associating a given class queue level ++ * to a traffic class, or -1 when disabling traffic class flow control for this ++ * class queue level. ++ * ++ * Return zero for success, or -EINVAL if the cq_level or traffic_class is out ++ * of range as indicated above, or -EIO if the configure/query tcfcc command ++ * returns error. ++ * ++ * Refer to the section of QMan CEETM traffic class flow control in the ++ * Reference Manual. ++ */ ++int qman_ceetm_lni_set_tcfcc(struct qm_ceetm_lni *lni, ++ unsigned int cq_level, ++ int traffic_class); ++int qman_ceetm_lni_get_tcfcc(struct qm_ceetm_lni *lni, ++ unsigned int cq_level, ++ int *traffic_class); ++ ++ /* ----------------------------- */ ++ /* CEETM :: class queue channels */ ++ /* ----------------------------- */ ++ ++/** ++ * qman_ceetm_channel_claim - Claims an unclaimed CQ channel that is mapped to ++ * the given LNI. ++ * @channel: the returned class queue channel object, if successful. ++ * @lni: the LNI that the channel belongs to. ++ * ++ * Channels are always initially "unshaped". ++ * ++ * Return zero for success, or -ENODEV if there is no channel available(all 32 ++ * channels are claimed) or -EINVAL if the channel mapping command returns ++ * error. ++ */ ++int qman_ceetm_channel_claim(struct qm_ceetm_channel **channel, ++ struct qm_ceetm_lni *lni); ++ ++/** ++ * qman_ceetm_channel_release - Releases a previously claimed CQ channel. ++ * @channel: the channel needs to be released. ++ * ++ * Returns zero for success, or -EBUSY if the dependencies are still in use. ++ * ++ * Note any shaping of the channel will be cleared to leave it in an unshaped ++ * state. ++ */ ++int qman_ceetm_channel_release(struct qm_ceetm_channel *channel); ++ ++/** ++ * qman_ceetm_channel_enable_shaper ++ * qman_ceetm_channel_disable_shaper - Enables/disables shaping on the channel. ++ * @channel: the given channel. ++ * @coupled: indicates whether surplus CR tokens should be added to the ++ * excess-rate token count (up to the excess-rate token limit) when the number ++ * of (unused) committed-rate tokens reach the committed_rate token limit. ++ * ++ * Whenever a claimed channel is first enabled for shaping, its committed and ++ * excess token rates and limits are zero, so will need to be changed to do ++ * anything useful. The shaper can subsequently be enabled/disabled without ++ * resetting the shaping parameters, but the shaping parameters will be reset ++ * when the channel is released. ++ * ++ * Return 0 for success, or -EINVAL for failure, in the case that the channel ++ * shaper has been enabled/disabled or the management command returns error. ++ */ ++int qman_ceetm_channel_enable_shaper(struct qm_ceetm_channel *channel, ++ int coupled); ++int qman_ceetm_channel_disable_shaper(struct qm_ceetm_channel *channel); ++ ++/** ++ * qman_ceetm_channel_is_shaper_enabled - Check channel shaper status. ++ * @channel: the give channel. ++ */ ++int qman_ceetm_channel_is_shaper_enabled(struct qm_ceetm_channel *channel); ++ ++/** ++ * qman_ceetm_channel_set_commit_rate ++ * qman_ceetm_channel_get_commit_rate ++ * qman_ceetm_channel_set_excess_rate ++ * qman_ceetm_channel_get_excess_rate - Set/get channel CR/ER shaper parameters. ++ * @channel: the given channel. ++ * @token_rate: the desired token rate for "set" function, or the queried token ++ * rate for "get" function. ++ * @token_limit: the desired token limit for "set" function, or the queried ++ * token limit for "get" function. ++ * ++ * Return zero for success. The "set" function returns -EINVAL if the channel ++ * is unshaped, or -EIO if the configure shapper command returns error. The ++ * "get" function returns -EINVAL if token rate of token limit is not set, or ++ * the query shaper command returns error. ++ */ ++int qman_ceetm_channel_set_commit_rate(struct qm_ceetm_channel *channel, ++ const struct qm_ceetm_rate *token_rate, ++ u16 token_limit); ++int qman_ceetm_channel_get_commit_rate(struct qm_ceetm_channel *channel, ++ struct qm_ceetm_rate *token_rate, ++ u16 *token_limit); ++int qman_ceetm_channel_set_excess_rate(struct qm_ceetm_channel *channel, ++ const struct qm_ceetm_rate *token_rate, ++ u16 token_limit); ++int qman_ceetm_channel_get_excess_rate(struct qm_ceetm_channel *channel, ++ struct qm_ceetm_rate *token_rate, ++ u16 *token_limit); ++/** ++ * qman_ceetm_channel_set_commit_rate_bps ++ * qman_ceetm_channel_get_commit_rate_bps ++ * qman_ceetm_channel_set_excess_rate_bps ++ * qman_ceetm_channel_get_excess_rate_bps - Set/get channel CR/ER shaper ++ * parameters. ++ * @channel: the given channel. ++ * @token_rate: the desired shaper rate in bps for "set" function, or the ++ * shaper rate in bps for "get" function. ++ * @token_limit: the desired token limit for "set" function, or the queried ++ * token limit for "get" function. ++ * ++ * Return zero for success. The "set" function returns -EINVAL if the channel ++ * is unshaped, or -EIO if the configure shapper command returns error. The ++ * "get" function returns -EINVAL if token rate of token limit is not set, or ++ * the query shaper command returns error. ++ */ ++int qman_ceetm_channel_set_commit_rate_bps(struct qm_ceetm_channel *channel, ++ u64 bps, u16 token_limit); ++int qman_ceetm_channel_get_commit_rate_bps(struct qm_ceetm_channel *channel, ++ u64 *bps, u16 *token_limit); ++int qman_ceetm_channel_set_excess_rate_bps(struct qm_ceetm_channel *channel, ++ u64 bps, u16 token_limit); ++int qman_ceetm_channel_get_excess_rate_bps(struct qm_ceetm_channel *channel, ++ u64 *bps, u16 *token_limit); ++ ++/** ++ * qman_ceetm_channel_set_weight ++ * qman_ceetm_channel_get_weight - Set/get the weight for unshaped channel ++ * @channel: the given channel. ++ * @token_limit: the desired token limit as the weight of the unshaped channel ++ * for "set" function, or the queried token limit for "get" function. ++ * ++ * The algorithm of unshaped fair queuing (uFQ) is used for unshaped channel. ++ * It allows the unshaped channels to be included in the CR time eligible list, ++ * and thus use the configured CR token limit value as their fair queuing ++ * weight. ++ * ++ * Return zero for success, or -EINVAL if the channel is a shaped channel or ++ * the management command returns error. ++ */ ++int qman_ceetm_channel_set_weight(struct qm_ceetm_channel *channel, ++ u16 token_limit); ++int qman_ceetm_channel_get_weight(struct qm_ceetm_channel *channel, ++ u16 *token_limit); ++ ++/** ++ * qman_ceetm_channel_set_group ++ * qman_ceetm_channel_get_group - Set/get the grouping of the class scheduler. ++ * @channel: the given channel. ++ * @group_b: indicates whether there is group B in this channel. ++ * @prio_a: the priority of group A. ++ * @prio_b: the priority of group B. ++ * ++ * There are 8 individual class queues (CQ0-CQ7), and 8 grouped class queues ++ * (CQ8-CQ15). If 'group_b' is zero, then all the grouped class queues are in ++ * group A, otherwise they are split into group A (CQ8-11) and group B ++ * (CQ12-C15). The individual class queues and the group(s) are in strict ++ * priority order relative to each other. Within the group(s), the scheduling ++ * is not strict priority order, but the result of scheduling within a group ++ * is in strict priority order relative to the other class queues in the ++ * channel. 'prio_a' and 'prio_b' control the priority order of the groups ++ * relative to the individual class queues, and take values from 0-7. Eg. if ++ * 'group_b' is non-zero, 'prio_a' is 2 and 'prio_b' is 6, then the strict ++ * priority order would be; ++ * CQ0, CQ1, CQ2, GROUPA, CQ3, CQ4, CQ5, CQ6, GROUPB, CQ7 ++ * ++ * Return 0 for success. For "set" function, returns -EINVAL if prio_a or ++ * prio_b are out of the range 1 - 7 (priority of group A or group B can not ++ * be 0, CQ0 is always the highest class queue in this channel.), or -EIO if ++ * the configure scheduler command returns error. For "get" function, return ++ * -EINVAL if the query scheduler command returns error. ++ */ ++int qman_ceetm_channel_set_group(struct qm_ceetm_channel *channel, ++ int group_b, ++ unsigned int prio_a, ++ unsigned int prio_b); ++int qman_ceetm_channel_get_group(struct qm_ceetm_channel *channel, ++ int *group_b, ++ unsigned int *prio_a, ++ unsigned int *prio_b); ++ ++/** ++ * qman_ceetm_channel_set_group_cr_eligibility ++ * qman_ceetm_channel_set_group_er_eligibility - Set channel group eligibility ++ * @channel: the given channel object ++ * @group_b: indicates whether there is group B in this channel. ++ * @cre: the commit rate eligibility, 1 for enable, 0 for disable. ++ * ++ * Return zero for success, or -EINVAL if eligibility setting fails. ++*/ ++int qman_ceetm_channel_set_group_cr_eligibility(struct qm_ceetm_channel ++ *channel, int group_b, int cre); ++int qman_ceetm_channel_set_group_er_eligibility(struct qm_ceetm_channel ++ *channel, int group_b, int ere); ++ ++/** ++ * qman_ceetm_channel_set_cq_cr_eligibility ++ * qman_ceetm_channel_set_cq_er_eligibility - Set channel cq eligibility ++ * @channel: the given channel object ++ * @idx: is from 0 to 7 (representing CQ0 to CQ7). ++ * @cre: the commit rate eligibility, 1 for enable, 0 for disable. ++ * ++ * Return zero for success, or -EINVAL if eligibility setting fails. ++*/ ++int qman_ceetm_channel_set_cq_cr_eligibility(struct qm_ceetm_channel *channel, ++ unsigned int idx, int cre); ++int qman_ceetm_channel_set_cq_er_eligibility(struct qm_ceetm_channel *channel, ++ unsigned int idx, int ere); ++ ++ /* --------------------- */ ++ /* CEETM :: class queues */ ++ /* --------------------- */ ++ ++/** ++ * qman_ceetm_cq_claim - Claims an individual class queue. ++ * @cq: the returned class queue object, if successful. ++ * @channel: the class queue channel. ++ * @idx: is from 0 to 7 (representing CQ0 to CQ7). ++ * @ccg: represents the class congestion group that this class queue should be ++ * subscribed to, or NULL if no congestion group membership is desired. ++ * ++ * Returns zero for success, or -EINVAL if @idx is out of range 0 - 7 or ++ * if this class queue has been claimed, or configure class queue command ++ * returns error, or returns -ENOMEM if allocating CQ memory fails. ++ */ ++int qman_ceetm_cq_claim(struct qm_ceetm_cq **cq, ++ struct qm_ceetm_channel *channel, ++ unsigned int idx, ++ struct qm_ceetm_ccg *ccg); ++ ++/** ++ * qman_ceetm_cq_claim_A - Claims a class queue group A. ++ * @cq: the returned class queue object, if successful. ++ * @channel: the class queue channel. ++ * @idx: is from 8 to 15 if only group A exits, otherwise, it is from 8 to 11. ++ * @ccg: represents the class congestion group that this class queue should be ++ * subscribed to, or NULL if no congestion group membership is desired. ++ * ++ * Return zero for success, or -EINVAL if @idx is out the range or if ++ * this class queue has been claimed or configure class queue command returns ++ * error, or returns -ENOMEM if allocating CQ memory fails. ++ */ ++int qman_ceetm_cq_claim_A(struct qm_ceetm_cq **cq, ++ struct qm_ceetm_channel *channel, ++ unsigned int idx, ++ struct qm_ceetm_ccg *ccg); ++ ++/** ++ * qman_ceetm_cq_claim_B - Claims a class queue group B. ++ * @cq: the returned class queue object, if successful. ++ * @channel: the class queue channel. ++ * @idx: is from 0 to 3 (CQ12 to CQ15). ++ * @ccg: represents the class congestion group that this class queue should be ++ * subscribed to, or NULL if no congestion group membership is desired. ++ * ++ * Return zero for success, or -EINVAL if @idx is out the range or if ++ * this class queue has been claimed or configure class queue command returns ++ * error, or returns -ENOMEM if allocating CQ memory fails. ++ */ ++int qman_ceetm_cq_claim_B(struct qm_ceetm_cq **cq, ++ struct qm_ceetm_channel *channel, ++ unsigned int idx, ++ struct qm_ceetm_ccg *ccg); ++ ++/** ++ * qman_ceetm_cq_release - Releases a previously claimed class queue. ++ * @cq: The class queue to be released. ++ * ++ * Return zero for success, or -EBUSY if the dependent objects (eg. logical ++ * FQIDs) have not been released. ++ */ ++int qman_ceetm_cq_release(struct qm_ceetm_cq *cq); ++ ++/** ++ * qman_ceetm_set_queue_weight ++ * qman_ceetm_get_queue_weight - Configure/query the weight of a grouped class ++ * queue. ++ * @cq: the given class queue. ++ * @weight_code: the desired weight code to set for the given class queue for ++ * "set" function or the queired weight code for "get" function. ++ * ++ * Grouped class queues have a default weight code of zero, which corresponds to ++ * a scheduler weighting of 1. This function can be used to modify a grouped ++ * class queue to another weight, (Use the helpers qman_ceetm_wbfs2ratio() ++ * and qman_ceetm_ratio2wbfs() to convert between these 'weight_code' values ++ * and the corresponding sharing weight.) ++ * ++ * Returns zero for success, or -EIO if the configure weight command returns ++ * error for "set" function, or -EINVAL if the query command returns ++ * error for "get" function. ++ * See section "CEETM Weighted Scheduling among Grouped Classes" in Reference ++ * Manual for weight and weight code. ++ */ ++int qman_ceetm_set_queue_weight(struct qm_ceetm_cq *cq, ++ struct qm_ceetm_weight_code *weight_code); ++int qman_ceetm_get_queue_weight(struct qm_ceetm_cq *cq, ++ struct qm_ceetm_weight_code *weight_code); ++ ++/** ++ * qman_ceetm_set_queue_weight_in_ratio ++ * qman_ceetm_get_queue_weight_in_ratio - Configure/query the weight of a ++ * grouped class queue. ++ * @cq: the given class queue. ++ * @ratio: the weight in ratio. It should be the real ratio number multiplied ++ * by 100 to get rid of fraction. ++ * ++ * Returns zero for success, or -EIO if the configure weight command returns ++ * error for "set" function, or -EINVAL if the query command returns ++ * error for "get" function. ++ */ ++int qman_ceetm_set_queue_weight_in_ratio(struct qm_ceetm_cq *cq, u32 ratio); ++int qman_ceetm_get_queue_weight_in_ratio(struct qm_ceetm_cq *cq, u32 *ratio); ++ ++/* Weights are encoded using a pseudo-exponential scheme. The weight codes 0, ++ * 32, 64, [...] correspond to weights of 1, 2, 4, [...]. The weights ++ * corresponding to intermediate weight codes are calculated using linear ++ * interpolation on the inverted values. Or put another way, the inverse weights ++ * for each 32nd weight code are 1, 1/2, 1/4, [...], and so the intervals ++ * between these are divided linearly into 32 intermediate values, the inverses ++ * of which form the remaining weight codes. ++ * ++ * The Weighted Bandwidth Fair Scheduling (WBFS) algorithm provides a form of ++ * scheduling within a group of class queues (group A or B). Weights are used to ++ * normalise the class queues to an underlying BFS algorithm where all class ++ * queues are assumed to require "equal bandwidth". So the weights referred to ++ * by the weight codes act as divisors on the size of frames being enqueued. Ie. ++ * one class queue in a group is assigned a weight of 2 whilst the other class ++ * queues in the group keep the default weight of 1, then the WBFS scheduler ++ * will effectively treat all frames enqueued on the weight-2 class queue as ++ * having half the number of bytes they really have. Ie. if all other things are ++ * equal, that class queue would get twice as much bytes-per-second bandwidth as ++ * the others. So weights should be chosen to provide bandwidth ratios between ++ * members of the same class queue group. These weights have no bearing on ++ * behaviour outside that group's WBFS mechanism though. ++ */ ++ ++/** ++ * qman_ceetm_wbfs2ratio - Given a weight code ('wbfs'), an accurate fractional ++ * representation of the corresponding weight is given (in order to not lose ++ * any precision). ++ * @weight_code: The given weight code in WBFS. ++ * @numerator: the numerator part of the weight computed by the weight code. ++ * @denominator: the denominator part of the weight computed by the weight code ++ * ++ * Returns zero for success or -EINVAL if the given weight code is illegal. ++ */ ++int qman_ceetm_wbfs2ratio(struct qm_ceetm_weight_code *weight_code, ++ u32 *numerator, ++ u32 *denominator); ++/** ++ * qman_ceetm_ratio2wbfs - Given a weight, find the nearest possible weight code ++ * If the user needs to know how close this is, convert the resulting weight ++ * code back to a weight and compare. ++ * @numerator: numerator part of the given weight. ++ * @denominator: denominator part of the given weight. ++ * @weight_code: the weight code computed from the given weight. ++ * ++ * Returns zero for success, or -ERANGE if "numerator/denominator" is outside ++ * the range of weights. ++ */ ++int qman_ceetm_ratio2wbfs(u32 numerator, ++ u32 denominator, ++ struct qm_ceetm_weight_code *weight_code, ++ int rounding); ++ ++#define QMAN_CEETM_FLAG_CLEAR_STATISTICS_COUNTER 0x1 ++/** ++ * qman_ceetm_cq_get_dequeue_statistics - Get the statistics provided by CEETM ++ * CQ counters. ++ * @cq: the given CQ object. ++ * @flags: indicates whether the statistics counter will be cleared after query. ++ * @frame_count: The number of the frames that have been counted since the ++ * counter was cleared last time. ++ * @byte_count: the number of bytes in all frames that have been counted. ++ * ++ * Return zero for success or -EINVAL if query statistics command returns error. ++ * ++ */ ++int qman_ceetm_cq_get_dequeue_statistics(struct qm_ceetm_cq *cq, u32 flags, ++ u64 *frame_count, u64 *byte_count); ++ ++/** ++ * qman_ceetm_drain_cq - drain the CQ till it is empty. ++ * @cq: the give CQ object. ++ * Return 0 for success or -EINVAL for unsuccessful command to empty CQ. ++ */ ++int qman_ceetm_drain_cq(struct qm_ceetm_cq *cq); ++ ++ /* ---------------------- */ ++ /* CEETM :: logical FQIDs */ ++ /* ---------------------- */ ++/** ++ * qman_ceetm_lfq_claim - Claims an unused logical FQID, associates it with ++ * the given class queue. ++ * @lfq: the returned lfq object, if successful. ++ * @cq: the class queue which needs to claim a LFQID. ++ * ++ * Return zero for success, or -ENODEV if no LFQID is available or -ENOMEM if ++ * allocating memory for lfq fails, or -EINVAL if configuring LFQMT fails. ++ */ ++int qman_ceetm_lfq_claim(struct qm_ceetm_lfq **lfq, ++ struct qm_ceetm_cq *cq); ++ ++/** ++ * qman_ceetm_lfq_release - Releases a previously claimed logical FQID. ++ * @lfq: the lfq to be released. ++ * ++ * Return zero for success. ++ */ ++int qman_ceetm_lfq_release(struct qm_ceetm_lfq *lfq); ++ ++/** ++ * qman_ceetm_lfq_set_context ++ * qman_ceetm_lfq_get_context - Set/get the context_a/context_b pair to the ++ * "dequeue context table" associated with the logical FQID. ++ * @lfq: the given logical FQ object. ++ * @context_a: contextA of the dequeue context. ++ * @context_b: contextB of the dequeue context. ++ * ++ * Returns zero for success, or -EINVAL if there is error to set/get the ++ * context pair. ++ */ ++int qman_ceetm_lfq_set_context(struct qm_ceetm_lfq *lfq, ++ u64 context_a, ++ u32 context_b); ++int qman_ceetm_lfq_get_context(struct qm_ceetm_lfq *lfq, ++ u64 *context_a, ++ u32 *context_b); ++ ++/** ++ * qman_ceetm_create_fq - Initialise a FQ object for the LFQ. ++ * @lfq: the given logic fq. ++ * @fq: the fq object created for the given logic fq. ++ * ++ * The FQ object can be used in qman_enqueue() and qman_enqueue_orp() APIs to ++ * target a logical FQID (and the class queue it is associated with). ++ * Note that this FQ object can only be used for enqueues, and ++ * in the case of qman_enqueue_orp() it can not be used as the 'orp' parameter, ++ * only as 'fq'. This FQ object can not (and shouldn't) be destroyed, it is only ++ * valid as long as the underlying 'lfq' remains claimed. It is the user's ++ * responsibility to ensure that the underlying 'lfq' is not released until any ++ * enqueues to this FQ object have completed. The only field the user needs to ++ * fill in is fq->cb.ern, as that enqueue rejection handler is the callback that ++ * could conceivably be called on this FQ object. This API can be called ++ * multiple times to create multiple FQ objects referring to the same logical ++ * FQID, and any enqueue rejections will respect the callback of the object that ++ * issued the enqueue (and will identify the object via the parameter passed to ++ * the callback too). There is no 'flags' parameter to this API as there is for ++ * qman_create_fq() - the created FQ object behaves as though qman_create_fq() ++ * had been called with the single flag QMAN_FQ_FLAG_NO_MODIFY. ++ * ++ * Returns 0 for success. ++ */ ++int qman_ceetm_create_fq(struct qm_ceetm_lfq *lfq, struct qman_fq *fq); ++ ++ /* -------------------------------- */ ++ /* CEETM :: class congestion groups */ ++ /* -------------------------------- */ ++ ++/** ++ * qman_ceetm_ccg_claim - Claims an unused CCG. ++ * @ccg: the returned CCG object, if successful. ++ * @channel: the given class queue channel ++ * @cscn: the callback function of this CCG. ++ * @cb_ctx: the corresponding context to be used used if state change ++ * notifications are later enabled for this CCG. ++ * ++ * The congestion group is local to the given class queue channel, so only ++ * class queues within the channel can be associated with that congestion group. ++ * The association of class queues to congestion groups occurs when the class ++ * queues are claimed, see qman_ceetm_cq_claim() and related functions. ++ * Congestion groups are in a "zero" state when initially claimed, and they are ++ * returned to that state when released. ++ * ++ * Return zero for success, or -EINVAL if no CCG in the channel is available. ++ */ ++int qman_ceetm_ccg_claim(struct qm_ceetm_ccg **ccg, ++ struct qm_ceetm_channel *channel, ++ unsigned int idx, ++ void (*cscn)(struct qm_ceetm_ccg *, ++ void *cb_ctx, ++ int congested), ++ void *cb_ctx); ++ ++/** ++ * qman_ceetm_ccg_release - Releases a previously claimed CCG. ++ * @ccg: the given ccg. ++ * ++ * Returns zero for success, or -EBUSY if the given ccg's dependent objects ++ * (class queues that are associated with the CCG) have not been released. ++ */ ++int qman_ceetm_ccg_release(struct qm_ceetm_ccg *ccg); ++ ++/* This struct is used to specify attributes for a CCG. The 'we_mask' field ++ * controls which CCG attributes are to be updated, and the remainder specify ++ * the values for those attributes. A CCG counts either frames or the bytes ++ * within those frames, but not both ('mode'). A CCG can optionally cause ++ * enqueues to be rejected, due to tail-drop or WRED, or both (they are ++ * independent options, 'td_en' and 'wr_en_g,wr_en_y,wr_en_r'). Tail-drop can be ++ * level-triggered due to a single threshold ('td_thres') or edge-triggered due ++ * to a "congestion state", but not both ('td_mode'). Congestion state has ++ * distinct entry and exit thresholds ('cs_thres_in' and 'cs_thres_out'), and ++ * notifications can be sent to software the CCG goes in to and out of this ++ * congested state ('cscn_en'). */ ++struct qm_ceetm_ccg_params { ++ /* Boolean fields together in a single bitfield struct */ ++ struct { ++ /* Whether to count bytes or frames. 1==frames */ ++ u8 mode:1; ++ /* En/disable tail-drop. 1==enable */ ++ u8 td_en:1; ++ /* Tail-drop on congestion-state or threshold. 1=threshold */ ++ u8 td_mode:1; ++ /* Generate congestion state change notifications. 1==enable */ ++ u8 cscn_en:1; ++ /* Enable WRED rejections (per colour). 1==enable */ ++ u8 wr_en_g:1; ++ u8 wr_en_y:1; ++ u8 wr_en_r:1; ++ } __packed; ++ /* Tail-drop threshold. See qm_cgr_thres_[gs]et64(). */ ++ struct qm_cgr_cs_thres td_thres; ++ /* Congestion state thresholds, for entry and exit. */ ++ struct qm_cgr_cs_thres cs_thres_in; ++ struct qm_cgr_cs_thres cs_thres_out; ++ /* Overhead accounting length. Per-packet "tax", from -128 to +127 */ ++ signed char oal; ++ /* Congestion state change notification for DCP portal, virtual CCGID*/ ++ /* WRED parameters. */ ++ struct qm_cgr_wr_parm wr_parm_g; ++ struct qm_cgr_wr_parm wr_parm_y; ++ struct qm_cgr_wr_parm wr_parm_r; ++}; ++/* Bits used in 'we_mask' to qman_ceetm_ccg_set(), controls which attributes of ++ * the CCGR are to be updated. */ ++#define QM_CCGR_WE_CDV 0x0000 /* cdv */ ++#define QM_CCGR_WE_MODE 0x0001 /* mode (bytes/frames) */ ++#define QM_CCGR_WE_CS_THRES_IN 0x0002 /* congestion state entry threshold */ ++#define QM_CCGR_WE_TD_EN 0x0004 /* congestion state tail-drop enable */ ++#define QM_CCGR_WE_CSCN_TUPD 0x0008 /* CSCN target update */ ++#define QM_CCGR_WE_CSCN_EN 0x0010 /* congestion notification enable */ ++#define QM_CCGR_WE_WR_EN_R 0x0020 /* WRED enable - red */ ++#define QM_CCGR_WE_WR_EN_Y 0x0040 /* WRED enable - yellow */ ++#define QM_CCGR_WE_WR_EN_G 0x0080 /* WRED enable - green */ ++#define QM_CCGR_WE_WR_PARM_R 0x0100 /* WRED parameters - red */ ++#define QM_CCGR_WE_WR_PARM_Y 0x0200 /* WRED parameters - yellow */ ++#define QM_CCGR_WE_WR_PARM_G 0x0400 /* WRED parameters - green */ ++#define QM_CCGR_WE_OAL 0x0800 /* overhead accounting length */ ++#define QM_CCGR_WE_CS_THRES_OUT 0x1000 /* congestion state exit threshold */ ++#define QM_CCGR_WE_TD_THRES 0x2000 /* tail-drop threshold */ ++#define QM_CCGR_WE_TD_MODE 0x4000 /* tail-drop mode (state/threshold) */ ++ ++/** ++ * qman_ceetm_ccg_set ++ * qman_ceetm_ccg_get - Configure/query a subset of CCG attributes. ++ * @ccg: the given CCG object. ++ * @we_mask: the write enable mask. ++ * @params: the parameters setting for this ccg ++ * ++ * Return 0 for success, or -EIO if configure ccg command returns error for ++ * "set" function, or -EINVAL if query ccg command returns error for "get" ++ * function. ++ */ ++int qman_ceetm_ccg_set(struct qm_ceetm_ccg *ccg, ++ u16 we_mask, ++ const struct qm_ceetm_ccg_params *params); ++int qman_ceetm_ccg_get(struct qm_ceetm_ccg *ccg, ++ struct qm_ceetm_ccg_params *params); ++ ++/** qman_ceetm_cscn_swp_set - Add or remove a software portal from the target ++ * mask. ++ * qman_ceetm_cscn_swp_get - Query whether a given software portal index is ++ * in the cscn target mask. ++ * @ccg: the give CCG object. ++ * @swp_idx: the index of the software portal. ++ * @cscn_enabled: 1: Set the swp to be cscn target. 0: remove the swp from ++ * the target mask. ++ * @we_mask: the write enable mask. ++ * @params: the parameters setting for this ccg ++ * ++ * Return 0 for success, or -EINVAL if command in set/get function fails. ++ */ ++int qman_ceetm_cscn_swp_set(struct qm_ceetm_ccg *ccg, ++ u16 swp_idx, ++ unsigned int cscn_enabled, ++ u16 we_mask, ++ const struct qm_ceetm_ccg_params *params); ++int qman_ceetm_cscn_swp_get(struct qm_ceetm_ccg *ccg, ++ u16 swp_idx, ++ unsigned int *cscn_enabled); ++ ++/** qman_ceetm_cscn_dcp_set - Add or remove a direct connect portal from the\ ++ * target mask. ++ * qman_ceetm_cscn_swp_get - Query whether a given direct connect portal index ++ * is in the cscn target mask. ++ * @ccg: the give CCG object. ++ * @dcp_idx: the index of the direct connect portal. ++ * @vcgid: congestion state change notification for dcp portal, virtual CGID. ++ * @cscn_enabled: 1: Set the dcp to be cscn target. 0: remove the dcp from ++ * the target mask. ++ * @we_mask: the write enable mask. ++ * @params: the parameters setting for this ccg ++ * ++ * Return 0 for success, or -EINVAL if command in set/get function fails. ++ */ ++int qman_ceetm_cscn_dcp_set(struct qm_ceetm_ccg *ccg, ++ u16 dcp_idx, ++ u8 vcgid, ++ unsigned int cscn_enabled, ++ u16 we_mask, ++ const struct qm_ceetm_ccg_params *params); ++int qman_ceetm_cscn_dcp_get(struct qm_ceetm_ccg *ccg, ++ u16 dcp_idx, ++ u8 *vcgid, ++ unsigned int *cscn_enabled); ++ ++/** ++ * qman_ceetm_ccg_get_reject_statistics - Get the statistics provided by ++ * CEETM CCG counters. ++ * @ccg: the given CCG object. ++ * @flags: indicates whether the statistics counter will be cleared after query. ++ * @frame_count: The number of the frames that have been counted since the ++ * counter was cleared last time. ++ * @byte_count: the number of bytes in all frames that have been counted. ++ * ++ * Return zero for success or -EINVAL if query statistics command returns error. ++ * ++ */ ++int qman_ceetm_ccg_get_reject_statistics(struct qm_ceetm_ccg *ccg, u32 flags, ++ u64 *frame_count, u64 *byte_count); ++ ++/** ++ * qman_set_wpm - Set waterfall power management ++ * ++ * @wpm_enable: boolean, 1 = enable wpm, 0 = disable wpm. ++ * ++ * Return 0 for success, return -ENODEV if QMan misc_cfg register is not ++ * accessible. ++ */ ++int qman_set_wpm(int wpm_enable); ++ ++/** ++ * qman_get_swp - Query the waterfall power management setting ++ * ++ * @wpm_enable: boolean, 1 = enable wpm, 0 = disable wpm. ++ * ++ * Return 0 for success, return -ENODEV if QMan misc_cfg register is not ++ * accessible. ++ */ ++int qman_get_wpm(int *wpm_enable); ++ ++/* The below qman_p_***() variants might be called in a migration situation ++ * (e.g. cpu hotplug). They are used to continue accessing the portal that ++ * execution was affine to prior to migration. ++ * @qman_portal specifies which portal the APIs will use. ++*/ ++const struct qman_portal_config *qman_p_get_portal_config(struct qman_portal ++ *p); ++int qman_p_irqsource_add(struct qman_portal *p, u32 bits); ++int qman_p_irqsource_remove(struct qman_portal *p, u32 bits); ++int qman_p_poll_dqrr(struct qman_portal *p, unsigned int limit); ++u32 qman_p_poll_slow(struct qman_portal *p); ++void qman_p_poll(struct qman_portal *p); ++void qman_p_stop_dequeues(struct qman_portal *p); ++void qman_p_start_dequeues(struct qman_portal *p); ++void qman_p_static_dequeue_add(struct qman_portal *p, u32 pools); ++void qman_p_static_dequeue_del(struct qman_portal *p, u32 pools); ++u32 qman_p_static_dequeue_get(struct qman_portal *p); ++void qman_p_dca(struct qman_portal *p, struct qm_dqrr_entry *dq, ++ int park_request); ++int qman_p_volatile_dequeue(struct qman_portal *p, struct qman_fq *fq, ++ u32 flags __maybe_unused, u32 vdqcr); ++int qman_p_enqueue(struct qman_portal *p, struct qman_fq *fq, ++ const struct qm_fd *fd, u32 flags); ++int qman_p_enqueue_orp(struct qman_portal *p, struct qman_fq *fq, ++ const struct qm_fd *fd, u32 flags, ++ struct qman_fq *orp, u16 orp_seqnum); ++int qman_p_enqueue_precommit(struct qman_portal *p, struct qman_fq *fq, ++ const struct qm_fd *fd, u32 flags, ++ qman_cb_precommit cb, void *cb_arg); ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* FSL_QMAN_H */ +diff --git a/include/linux/fsl_usdpaa.h b/include/linux/fsl_usdpaa.h +new file mode 100644 +index 0000000..896c03a +--- /dev/null ++++ b/include/linux/fsl_usdpaa.h +@@ -0,0 +1,372 @@ ++/* Copyright 2011-2012 Freescale Semiconductor, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#ifndef FSL_USDPAA_H ++#define FSL_USDPAA_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include ++#include ++#include /* For "enum qm_channel" */ ++#include ++ ++#ifdef CONFIG_FSL_USDPAA ++ ++/******************************/ ++/* Allocation of resource IDs */ ++/******************************/ ++ ++/* This enum is used to distinguish between the type of underlying object being ++ * manipulated. */ ++enum usdpaa_id_type { ++ usdpaa_id_fqid, ++ usdpaa_id_bpid, ++ usdpaa_id_qpool, ++ usdpaa_id_cgrid, ++ usdpaa_id_ceetm0_lfqid, ++ usdpaa_id_ceetm0_channelid, ++ usdpaa_id_ceetm1_lfqid, ++ usdpaa_id_ceetm1_channelid, ++ usdpaa_id_max /* <-- not a valid type, represents the number of types */ ++}; ++#define USDPAA_IOCTL_MAGIC 'u' ++struct usdpaa_ioctl_id_alloc { ++ uint32_t base; /* Return value, the start of the allocated range */ ++ enum usdpaa_id_type id_type; /* what kind of resource(s) to allocate */ ++ uint32_t num; /* how many IDs to allocate (and return value) */ ++ uint32_t align; /* must be a power of 2, 0 is treated like 1 */ ++ int partial; /* whether to allow less than 'num' */ ++}; ++struct usdpaa_ioctl_id_release { ++ /* Input; */ ++ enum usdpaa_id_type id_type; ++ uint32_t base; ++ uint32_t num; ++}; ++struct usdpaa_ioctl_id_reserve { ++ enum usdpaa_id_type id_type; ++ uint32_t base; ++ uint32_t num; ++}; ++ ++ ++/* ioctl() commands */ ++#define USDPAA_IOCTL_ID_ALLOC \ ++ _IOWR(USDPAA_IOCTL_MAGIC, 0x01, struct usdpaa_ioctl_id_alloc) ++#define USDPAA_IOCTL_ID_RELEASE \ ++ _IOW(USDPAA_IOCTL_MAGIC, 0x02, struct usdpaa_ioctl_id_release) ++#define USDPAA_IOCTL_ID_RESERVE \ ++ _IOW(USDPAA_IOCTL_MAGIC, 0x0A, struct usdpaa_ioctl_id_reserve) ++ ++/**********************/ ++/* Mapping DMA memory */ ++/**********************/ ++ ++/* Maximum length for a map name, including NULL-terminator */ ++#define USDPAA_DMA_NAME_MAX 16 ++/* Flags for requesting DMA maps. Maps are private+unnamed or sharable+named. ++ * For a sharable and named map, specify _SHARED (whether creating one or ++ * binding to an existing one). If _SHARED is specified and _CREATE is not, then ++ * the mapping must already exist. If _SHARED and _CREATE are specified and the ++ * mapping doesn't already exist, it will be created. If _SHARED and _CREATE are ++ * specified and the mapping already exists, the mapping will fail unless _LAZY ++ * is specified. When mapping to a pre-existing sharable map, the length must be ++ * an exact match. Lengths must be a power-of-4 multiple of page size. ++ * ++ * Note that this does not actually map the memory to user-space, that is done ++ * by a subsequent mmap() using the page offset returned from this ioctl(). The ++ * ioctl() is what gives the process permission to do this, and a page-offset ++ * with which to do so. ++ */ ++#define USDPAA_DMA_FLAG_SHARE 0x01 ++#define USDPAA_DMA_FLAG_CREATE 0x02 ++#define USDPAA_DMA_FLAG_LAZY 0x04 ++#define USDPAA_DMA_FLAG_RDONLY 0x08 ++struct usdpaa_ioctl_dma_map { ++ /* Output parameters - virtual and physical addresses */ ++ void *ptr; ++ uint64_t phys_addr; ++ /* Input parameter, the length of the region to be created (or if ++ * mapping an existing region, this must match it). Must be a power-of-4 ++ * multiple of page size. */ ++ uint64_t len; ++ /* Input parameter, the USDPAA_DMA_FLAG_* settings. */ ++ uint32_t flags; ++ /* If _FLAG_SHARE is specified, the name of the region to be created (or ++ * of the existing mapping to use). */ ++ char name[USDPAA_DMA_NAME_MAX]; ++ /* If this ioctl() creates the mapping, this is an input parameter ++ * stating whether the region supports locking. If mapping an existing ++ * region, this is a return value indicating the same thing. */ ++ int has_locking; ++ /* In the case of a successful map with _CREATE and _LAZY, this return ++ * value indicates whether we created the mapped region or whether it ++ * already existed. */ ++ int did_create; ++}; ++ ++#ifdef CONFIG_COMPAT ++struct usdpaa_ioctl_dma_map_compat { ++ /* Output parameters - virtual and physical addresses */ ++ compat_uptr_t ptr; ++ uint64_t phys_addr; ++ /* Input parameter, the length of the region to be created (or if ++ * mapping an existing region, this must match it). Must be a power-of-4 ++ * multiple of page size. */ ++ uint64_t len; ++ /* Input parameter, the USDPAA_DMA_FLAG_* settings. */ ++ uint32_t flags; ++ /* If _FLAG_SHARE is specified, the name of the region to be created (or ++ * of the existing mapping to use). */ ++ char name[USDPAA_DMA_NAME_MAX]; ++ /* If this ioctl() creates the mapping, this is an input parameter ++ * stating whether the region supports locking. If mapping an existing ++ * region, this is a return value indicating the same thing. */ ++ int has_locking; ++ /* In the case of a successful map with _CREATE and _LAZY, this return ++ * value indicates whether we created the mapped region or whether it ++ * already existed. */ ++ int did_create; ++}; ++ ++#define USDPAA_IOCTL_DMA_MAP_COMPAT \ ++ _IOWR(USDPAA_IOCTL_MAGIC, 0x03, struct usdpaa_ioctl_dma_map_compat) ++#endif ++ ++ ++#define USDPAA_IOCTL_DMA_MAP \ ++ _IOWR(USDPAA_IOCTL_MAGIC, 0x03, struct usdpaa_ioctl_dma_map) ++/* munmap() does not remove the DMA map, just the user-space mapping to it. ++ * This ioctl will do both (though you can munmap() before calling the ioctl ++ * too). */ ++#define USDPAA_IOCTL_DMA_UNMAP \ ++ _IOW(USDPAA_IOCTL_MAGIC, 0x04, unsigned char) ++/* We implement a cross-process locking scheme per DMA map. Call this ioctl() ++ * with a mmap()'d address, and the process will (interruptible) sleep if the ++ * lock is already held by another process. Process destruction will ++ * automatically clean up any held locks. */ ++#define USDPAA_IOCTL_DMA_LOCK \ ++ _IOW(USDPAA_IOCTL_MAGIC, 0x05, unsigned char) ++#define USDPAA_IOCTL_DMA_UNLOCK \ ++ _IOW(USDPAA_IOCTL_MAGIC, 0x06, unsigned char) ++ ++/***************************************/ ++/* Mapping and using QMan/BMan portals */ ++/***************************************/ ++enum usdpaa_portal_type { ++ usdpaa_portal_qman, ++ usdpaa_portal_bman, ++}; ++ ++#define QBMAN_ANY_PORTAL_IDX 0xffffffff ++ ++struct usdpaa_ioctl_portal_map { ++ /* Input parameter, is a qman or bman portal required. */ ++ ++ enum usdpaa_portal_type type; ++ /* Specifes a specific portal index to map or QBMAN_ANY_PORTAL_IDX ++ for don't care. The portal index will be populated by the ++ driver when the ioctl() successfully completes */ ++ uint32_t index; ++ ++ /* Return value if the map succeeds, this gives the mapped ++ * cache-inhibited (cinh) and cache-enabled (cena) addresses. */ ++ struct usdpaa_portal_map { ++ void *cinh; ++ void *cena; ++ } addr; ++ /* Qman-specific return values */ ++ uint16_t channel; ++ uint32_t pools; ++}; ++ ++#ifdef CONFIG_COMPAT ++struct compat_usdpaa_ioctl_portal_map { ++ /* Input parameter, is a qman or bman portal required. */ ++ enum usdpaa_portal_type type; ++ /* Specifes a specific portal index to map or QBMAN_ANY_PORTAL_IDX ++ for don't care. The portal index will be populated by the ++ driver when the ioctl() successfully completes */ ++ uint32_t index; ++ /* Return value if the map succeeds, this gives the mapped ++ * cache-inhibited (cinh) and cache-enabled (cena) addresses. */ ++ struct usdpaa_portal_map_compat { ++ compat_uptr_t cinh; ++ compat_uptr_t cena; ++ } addr; ++ /* Qman-specific return values */ ++ uint16_t channel; ++ uint32_t pools; ++}; ++#define USDPAA_IOCTL_PORTAL_MAP_COMPAT \ ++ _IOWR(USDPAA_IOCTL_MAGIC, 0x07, struct compat_usdpaa_ioctl_portal_map) ++#define USDPAA_IOCTL_PORTAL_UNMAP_COMPAT \ ++ _IOW(USDPAA_IOCTL_MAGIC, 0x08, struct usdpaa_portal_map_compat) ++#endif ++ ++#define USDPAA_IOCTL_PORTAL_MAP \ ++ _IOWR(USDPAA_IOCTL_MAGIC, 0x07, struct usdpaa_ioctl_portal_map) ++#define USDPAA_IOCTL_PORTAL_UNMAP \ ++ _IOW(USDPAA_IOCTL_MAGIC, 0x08, struct usdpaa_portal_map) ++ ++struct usdpaa_ioctl_irq_map { ++ enum usdpaa_portal_type type; /* Type of portal to map */ ++ int fd; /* File descriptor that contains the portal */ ++ void *portal_cinh; /* Cache inhibited area to identify the portal */ ++}; ++ ++#define USDPAA_IOCTL_PORTAL_IRQ_MAP \ ++ _IOW(USDPAA_IOCTL_MAGIC, 0x09, struct usdpaa_ioctl_irq_map) ++ ++#ifdef CONFIG_COMPAT ++ ++struct compat_ioctl_irq_map { ++ enum usdpaa_portal_type type; /* Type of portal to map */ ++ compat_int_t fd; /* File descriptor that contains the portal */ ++ compat_uptr_t portal_cinh; /* Used identify the portal */}; ++ ++#define USDPAA_IOCTL_PORTAL_IRQ_MAP_COMPAT \ ++ _IOW(USDPAA_IOCTL_MAGIC, 0x09, struct compat_ioctl_irq_map) ++#endif ++ ++/* ioctl to query the amount of DMA memory used in the system */ ++struct usdpaa_ioctl_dma_used { ++ uint64_t free_bytes; ++ uint64_t total_bytes; ++}; ++#define USDPAA_IOCTL_DMA_USED \ ++ _IOR(USDPAA_IOCTL_MAGIC, 0x0B, struct usdpaa_ioctl_dma_used) ++ ++/* ioctl to allocate a raw portal */ ++struct usdpaa_ioctl_raw_portal { ++ /* inputs */ ++ enum usdpaa_portal_type type; /* Type of portal to allocate */ ++ ++ /* set to non zero to turn on stashing */ ++ uint8_t enable_stash; ++ /* Stashing attributes for the portal */ ++ uint32_t cpu; ++ uint32_t cache; ++ uint32_t window; ++ ++ /* Specifies the stash request queue this portal should use */ ++ uint8_t sdest; ++ ++ /* Specifes a specific portal index to map or QBMAN_ANY_PORTAL_IDX ++ * for don't care. The portal index will be populated by the ++ * driver when the ioctl() successfully completes */ ++ uint32_t index; ++ ++ /* outputs */ ++ uint64_t cinh; ++ uint64_t cena; ++}; ++ ++#define USDPAA_IOCTL_ALLOC_RAW_PORTAL \ ++ _IOWR(USDPAA_IOCTL_MAGIC, 0x0C, struct usdpaa_ioctl_raw_portal) ++ ++#define USDPAA_IOCTL_FREE_RAW_PORTAL \ ++ _IOR(USDPAA_IOCTL_MAGIC, 0x0D, struct usdpaa_ioctl_raw_portal) ++ ++#ifdef CONFIG_COMPAT ++ ++struct compat_ioctl_raw_portal { ++ /* inputs */ ++ enum usdpaa_portal_type type; /* Type of portal to allocate */ ++ ++ /* set to non zero to turn on stashing */ ++ uint8_t enable_stash; ++ /* Stashing attributes for the portal */ ++ uint32_t cpu; ++ uint32_t cache; ++ uint32_t window; ++ /* Specifies the stash request queue this portal should use */ ++ uint8_t sdest; ++ ++ /* Specifes a specific portal index to map or QBMAN_ANY_PORTAL_IDX ++ * for don't care. The portal index will be populated by the ++ * driver when the ioctl() successfully completes */ ++ uint32_t index; ++ ++ /* outputs */ ++ uint64_t cinh; ++ uint64_t cena; ++}; ++ ++#define USDPAA_IOCTL_ALLOC_RAW_PORTAL_COMPAT \ ++ _IOWR(USDPAA_IOCTL_MAGIC, 0x0C, struct compat_ioctl_raw_portal) ++ ++#define USDPAA_IOCTL_FREE_RAW_PORTAL_COMPAT \ ++ _IOR(USDPAA_IOCTL_MAGIC, 0x0D, struct compat_ioctl_raw_portal) ++ ++#endif ++ ++#ifdef __KERNEL__ ++ ++/* Early-boot hook */ ++void __init fsl_usdpaa_init_early(void); ++ ++/* Fault-handling in arch/powerpc/mm/mem.c gives USDPAA an opportunity to detect ++ * faults within its ranges via this hook. */ ++int usdpaa_test_fault(unsigned long pfn, u64 *phys_addr, u64 *size); ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* CONFIG_FSL_USDPAA */ ++ ++#ifdef __KERNEL__ ++/* This interface is needed in a few places and though it's not specific to ++ * USDPAA as such, creating a new header for it doesn't make any sense. The ++ * qbman kernel driver implements this interface and uses it as the backend for ++ * both the FQID and BPID allocators. The fsl_usdpaa driver also uses this ++ * interface for tracking per-process allocations handed out to user-space. */ ++struct dpa_alloc { ++ struct list_head free; ++ spinlock_t lock; ++ struct list_head used; ++}; ++#define DECLARE_DPA_ALLOC(name) \ ++ struct dpa_alloc name = { \ ++ .free = { \ ++ .prev = &name.free, \ ++ .next = &name.free \ ++ }, \ ++ .lock = __SPIN_LOCK_UNLOCKED(name.lock), \ ++ .used = { \ ++ .prev = &name.used, \ ++ .next = &name.used \ ++ } \ ++ } ++static inline void dpa_alloc_init(struct dpa_alloc *alloc) ++{ ++ INIT_LIST_HEAD(&alloc->free); ++ INIT_LIST_HEAD(&alloc->used); ++ spin_lock_init(&alloc->lock); ++} ++int dpa_alloc_new(struct dpa_alloc *alloc, u32 *result, u32 count, u32 align, ++ int partial); ++void dpa_alloc_free(struct dpa_alloc *alloc, u32 base_id, u32 count); ++void dpa_alloc_seed(struct dpa_alloc *alloc, u32 fqid, u32 count); ++ ++/* Like 'new' but specifies the desired range, returns -ENOMEM if the entire ++ * desired range is not available, or 0 for success. */ ++int dpa_alloc_reserve(struct dpa_alloc *alloc, u32 base_id, u32 count); ++/* Pops and returns contiguous ranges from the allocator. Returns -ENOMEM when ++ * 'alloc' is empty. */ ++int dpa_alloc_pop(struct dpa_alloc *alloc, u32 *result, u32 *count); ++/* Returns 1 if the specified id is alloced, 0 otherwise */ ++int dpa_alloc_check(struct dpa_alloc *list, u32 id); ++#endif /* __KERNEL__ */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* FSL_USDPAA_H */ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0053-fsl_qman-Add-invalidation-in-case-PAMU-is-not-enable.patch b/target/linux/layerscape-64b/patches-4.1/0053-fsl_qman-Add-invalidation-in-case-PAMU-is-not-enable.patch new file mode 100644 index 0000000..33afd96 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0053-fsl_qman-Add-invalidation-in-case-PAMU-is-not-enable.patch @@ -0,0 +1,55 @@ +From eb2593ac51070f8c34414cfed1f0b7816f984a85 Mon Sep 17 00:00:00 2001 +From: Roy Pledge +Date: Thu, 14 Jan 2016 16:20:41 -0500 +Subject: [PATCH 053/151] fsl_qman: Add invalidation in case PAMU is not + enabled + +Signed-off-by: Roy Pledge +--- + drivers/staging/fsl_qbman/qman_high.c | 9 +++++++-- + drivers/staging/fsl_qbman/qman_low.h | 9 +++++++++ + 2 files changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/fsl_qbman/qman_high.c b/drivers/staging/fsl_qbman/qman_high.c +index c50828b..580adb0 100644 +--- a/drivers/staging/fsl_qbman/qman_high.c ++++ b/drivers/staging/fsl_qbman/qman_high.c +@@ -416,8 +416,13 @@ struct qman_portal *qman_create_portal( + + __p = &portal->p; + +- portal->use_eqcr_ci_stashing = ((qman_ip_rev >= QMAN_REV30) ? +- 1 : 0); ++#ifdef CONFIG_FSL_PAMU ++ /* PAMU is required for stashing */ ++ portal->use_eqcr_ci_stashing = ((qman_ip_rev >= QMAN_REV30) ? ++ 1 : 0); ++#else ++ portal->use_eqcr_ci_stashing = 0; ++#endif + + /* prep the low-level portal struct with the mapped addresses from the + * config, everything that follows depends on it and "config" is more +diff --git a/drivers/staging/fsl_qbman/qman_low.h b/drivers/staging/fsl_qbman/qman_low.h +index 407a82c..6ac7ecd 100644 +--- a/drivers/staging/fsl_qbman/qman_low.h ++++ b/drivers/staging/fsl_qbman/qman_low.h +@@ -694,6 +694,15 @@ static inline void qm_dqrr_pvb_update(struct qm_portal *portal) + register struct qm_dqrr *dqrr = &portal->dqrr; + const struct qm_dqrr_entry *res = qm_cl(dqrr->ring, dqrr->pi); + DPA_ASSERT(dqrr->pmode == qm_dqrr_pvb); ++#ifndef CONFIG_FSL_PAMU ++ /* ++ * If PAMU is not available we need to invalidate the cache. ++ * When PAMU is available the cache is updated by stash ++ */ ++ dcbi(res); ++ dcbt_ro(res); ++#endif ++ + /* when accessing 'verb', use __raw_readb() to ensure that compiler + * inlining doesn't try to optimise out "excess reads". */ + if ((__raw_readb(&res->verb) & QM_DQRR_VERB_VBIT) == dqrr->vbit) { +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0054-fsl_qbman-Use-do_div-when-dividing.patch b/target/linux/layerscape-64b/patches-4.1/0054-fsl_qbman-Use-do_div-when-dividing.patch new file mode 100644 index 0000000..92086d7 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0054-fsl_qbman-Use-do_div-when-dividing.patch @@ -0,0 +1,30 @@ +From fdbfccf9929bbf807721ee540f044fa55cc7ef19 Mon Sep 17 00:00:00 2001 +From: Roy Pledge +Date: Tue, 2 Feb 2016 06:41:01 -0500 +Subject: [PATCH 054/151] fsl_qbman: Use do_div() when dividing + +The do_div() function must be used for division inside the kernel. + +Signed-off-by: Roy Pledge +--- + drivers/staging/fsl_qbman/qman_config.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/fsl_qbman/qman_config.c b/drivers/staging/fsl_qbman/qman_config.c +index 6a6225e..2ce3255 100644 +--- a/drivers/staging/fsl_qbman/qman_config.c ++++ b/drivers/staging/fsl_qbman/qman_config.c +@@ -824,8 +824,8 @@ int qman_ceetm_set_prescaler(enum qm_dc_portal portal) + temp = 0x400000 * 100; + do_div(temp, CONFIG_QMAN_CEETM_UPDATE_PERIOD); + temp *= 10000000; +- pres = (u16)(temp / qman_clk); +- ++ do_div(temp, qman_clk); ++ pres = (u16) temp; + qm_out(CEETM_CFG_IDX, portal); + qm_out(CEETM_CFG_PRES, pres); + return 0; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0055-arm64-Add-pdev_archdata-for-dmamask.patch b/target/linux/layerscape-64b/patches-4.1/0055-arm64-Add-pdev_archdata-for-dmamask.patch new file mode 100644 index 0000000..bde0095 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0055-arm64-Add-pdev_archdata-for-dmamask.patch @@ -0,0 +1,58 @@ +From c3cbcedb2490949aa54a260f9656b8f2680d3497 Mon Sep 17 00:00:00 2001 +From: Cristian Sovaiala +Date: Thu, 4 Jun 2015 18:27:20 +0300 +Subject: [PATCH 055/151] arm64: Add pdev_archdata for dmamask + +The dma_mask for a device structure is a pointer. This pointer +needs to be set up before the dma mask can actually be set. Most +frameworks in the kernel take care of setting this up properly but +platform devices that don't follow a regular bus structure may not +ever have this set. As a result, checks such as dma_capable will +always return false on a raw platform device and dma_set_mask will +always return -EIO. Fix this by adding a dma_mask in the +platform_device archdata and setting it to be the dma_mask. Devices +used in other frameworks can change this as needed. + +Signed-off-by: Laura Abbott +--- + arch/arm64/include/asm/device.h | 1 + + arch/arm64/kernel/setup.c | 7 +++++++ + 2 files changed, 8 insertions(+) + +diff --git a/arch/arm64/include/asm/device.h b/arch/arm64/include/asm/device.h +index 243ef25..eb4f47d 100644 +--- a/arch/arm64/include/asm/device.h ++++ b/arch/arm64/include/asm/device.h +@@ -25,6 +25,7 @@ struct dev_archdata { + }; + + struct pdev_archdata { ++ u64 dma_mask; + }; + + #endif +diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c +index bbdb53b..66f2382 100644 +--- a/arch/arm64/kernel/setup.c ++++ b/arch/arm64/kernel/setup.c +@@ -46,6 +46,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -583,3 +584,9 @@ const struct seq_operations cpuinfo_op = { + .stop = c_stop, + .show = c_show + }; ++ ++void arch_setup_pdev_archdata(struct platform_device *pdev) ++{ ++ pdev->archdata.dma_mask = DMA_BIT_MASK(32); ++ pdev->dev.dma_mask = &pdev->archdata.dma_mask; ++} +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0056-fsl_qbman-Update-QBMan-drivers-to-support-little-end.patch b/target/linux/layerscape-64b/patches-4.1/0056-fsl_qbman-Update-QBMan-drivers-to-support-little-end.patch new file mode 100644 index 0000000..3b6177e --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0056-fsl_qbman-Update-QBMan-drivers-to-support-little-end.patch @@ -0,0 +1,2549 @@ +From 4d90a8df18f916be5e0e7ee4acd767f654dbacd2 Mon Sep 17 00:00:00 2001 +From: Roy Pledge +Date: Tue, 19 Apr 2016 15:05:08 +0800 +Subject: [PATCH 056/151] fsl_qbman: Update QBMan drivers to support little + endian CPUs + +commit 66ba9d4429d1b2ab4cfe87f78584768f88d6a992 +[doesn't apply arch/powerpc/platforms/85xx/corenet_generic.c] + +This patch adds support for little endian CPUs and the ARM64 +platform for the QBMan device (which is inherently big endian). + +Signed-off-by: Roy Pledge +Integrated-by: Zhao Qiang +--- + drivers/staging/fsl_qbman/Kconfig | 2 + + drivers/staging/fsl_qbman/bman_config.c | 79 ++------ + drivers/staging/fsl_qbman/bman_driver.c | 40 ++-- + drivers/staging/fsl_qbman/bman_high.c | 40 ++-- + drivers/staging/fsl_qbman/bman_low.h | 43 ++++- + drivers/staging/fsl_qbman/dpa_sys.h | 60 +----- + drivers/staging/fsl_qbman/dpa_sys_arm64.h | 102 ++++++++++ + drivers/staging/fsl_qbman/dpa_sys_ppc32.h | 70 +++++++ + drivers/staging/fsl_qbman/dpa_sys_ppc64.h | 79 ++++++++ + drivers/staging/fsl_qbman/fsl_usdpaa.c | 31 ++- + drivers/staging/fsl_qbman/fsl_usdpaa_irq.c | 7 +- + drivers/staging/fsl_qbman/qbman_driver.c | 2 + + drivers/staging/fsl_qbman/qman_config.c | 88 +++++---- + drivers/staging/fsl_qbman/qman_driver.c | 96 +++++---- + drivers/staging/fsl_qbman/qman_high.c | 247 +++++++++++++++++++++--- + drivers/staging/fsl_qbman/qman_low.h | 74 +++++-- + drivers/staging/fsl_qbman/qman_private.h | 5 + + drivers/staging/fsl_qbman/qman_test.h | 1 + + drivers/staging/fsl_qbman/qman_test_high.c | 2 + + drivers/staging/fsl_qbman/qman_test_hotpotato.c | 2 + + include/linux/fsl_bman.h | 13 ++ + include/linux/fsl_qman.h | 159 ++++++++++++++- + include/linux/fsl_usdpaa.h | 2 +- + 23 files changed, 970 insertions(+), 274 deletions(-) + create mode 100644 drivers/staging/fsl_qbman/dpa_sys_arm64.h + create mode 100644 drivers/staging/fsl_qbman/dpa_sys_ppc32.h + create mode 100644 drivers/staging/fsl_qbman/dpa_sys_ppc64.h + +diff --git a/drivers/staging/fsl_qbman/Kconfig b/drivers/staging/fsl_qbman/Kconfig +index c857514..959d537 100644 +--- a/drivers/staging/fsl_qbman/Kconfig ++++ b/drivers/staging/fsl_qbman/Kconfig +@@ -3,6 +3,8 @@ config FSL_DPA + depends on HAS_FSL_QBMAN + default y + select FSL_QMAN_FQ_LOOKUP if PPC64 ++ select FSL_QMAN_FQ_LOOKUP if ARM64 ++ + + menu "Freescale Datapath QMan/BMan options" + depends on FSL_DPA +diff --git a/drivers/staging/fsl_qbman/bman_config.c b/drivers/staging/fsl_qbman/bman_config.c +index 136e22d..5d80d1d 100644 +--- a/drivers/staging/fsl_qbman/bman_config.c ++++ b/drivers/staging/fsl_qbman/bman_config.c +@@ -31,6 +31,7 @@ + + #include + #include "bman_private.h" ++#include + + /* Last updated for v00.79 of the BG */ + +@@ -248,61 +249,16 @@ static struct device_node *bm_node; + static dma_addr_t fbpr_a; + static size_t fbpr_sz = DEFAULT_FBPR_SZ; + +-/* Parse the property to extract the memory location and size and +- * memblock_reserve() it. If it isn't supplied, memblock_alloc() the default +- * size. Also flush this memory range from data cache so that BMAN originated +- * transactions for this memory region could be marked non-coherent. +- */ +-static __init int parse_mem_property(struct device_node *node, const char *name, +- dma_addr_t *addr, size_t *sz, int zero) ++static int bman_fbpr(struct reserved_mem *rmem) + { +- const u32 *pint; +- int ret; +- unsigned long vaddr; +- +- pint = of_get_property(node, name, &ret); +- if (!pint || (ret != 16)) { +- pr_info("No %s property '%s', using memblock_alloc(%016zx)\n", +- node->full_name, name, *sz); +- *addr = memblock_alloc(*sz, *sz); +- vaddr = (unsigned long)phys_to_virt(*addr); +- if (zero) +- memset((void *)vaddr, 0, *sz); +- flush_dcache_range(vaddr, vaddr + *sz); +- return 0; +- } +- pr_info("Using %s property '%s'\n", node->full_name, name); +- /* If using a "zero-pma", don't try to zero it, even if you asked */ +- if (zero && of_find_property(node, "zero-pma", &ret)) { +- pr_info(" it's a 'zero-pma', not zeroing from s/w\n"); +- zero = 0; +- } +- *addr = ((u64)pint[0] << 32) | (u64)pint[1]; +- *sz = ((u64)pint[2] << 32) | (u64)pint[3]; +- /* Keep things simple, it's either all in the DRAM range or it's all +- * outside. */ +- if (*addr < memblock_end_of_DRAM()) { +- BUG_ON((u64)*addr + (u64)*sz > memblock_end_of_DRAM()); +- if (memblock_reserve(*addr, *sz) < 0) { +- pr_err("Failed to reserve %s\n", name); +- return -ENOMEM; +- } +- vaddr = (unsigned long)phys_to_virt(*addr); +- if (zero) +- memset((void *)vaddr, 0, *sz); +- flush_dcache_range(vaddr, vaddr + *sz); +- } else if (zero) { +- /* map as cacheable, non-guarded */ +- void __iomem *tmpp = ioremap_prot(*addr, *sz, 0); +- if (!tmpp) +- return -ENOMEM; +- memset_io(tmpp, 0, *sz); +- vaddr = (unsigned long)tmpp; +- flush_dcache_range(vaddr, vaddr + *sz); +- iounmap(tmpp); +- } ++ fbpr_a = rmem->base; ++ fbpr_sz = rmem->size; ++ ++ WARN_ON(!(fbpr_a && fbpr_sz)); ++ + return 0; + } ++RESERVEDMEM_OF_DECLARE(bman_fbpr, "fsl,bman-fbpr", bman_fbpr); + + static int __init fsl_bman_init(struct device_node *node) + { +@@ -322,11 +278,6 @@ static int __init fsl_bman_init(struct device_node *node) + s = of_get_property(node, "fsl,hv-claimable", &ret); + if (s && !strcmp(s, "standby")) + standby = 1; +- if (!standby) { +- ret = parse_mem_property(node, "fsl,bman-fbpr", +- &fbpr_a, &fbpr_sz, 0); +- BUG_ON(ret); +- } + /* Global configuration */ + regs = ioremap(res.start, res.end - res.start + 1); + bm = bm_create(regs); +@@ -363,13 +314,14 @@ int bm_pool_set(u32 bpid, const u32 *thresholds) + { + if (!bm) + return -ENODEV; +- bm_set_pool(bm, bpid, thresholds[0], thresholds[1], +- thresholds[2], thresholds[3]); ++ bm_set_pool(bm, bpid, thresholds[0], ++ thresholds[1], thresholds[2], ++ thresholds[3]); + return 0; + } + EXPORT_SYMBOL(bm_pool_set); + +-__init void bman_init_early(void) ++__init int bman_init_early(void) + { + struct device_node *dn; + int ret; +@@ -386,7 +338,10 @@ __init void bman_init_early(void) + BUG_ON(ret); + } + } ++ return 0; + } ++postcore_initcall_sync(bman_init_early); ++ + + static void log_edata_bits(u32 bit_count) + { +@@ -464,7 +419,7 @@ static int __bind_irq(void) + int ret, err_irq; + + err_irq = of_irq_to_resource(bm_node, 0, NULL); +- if (err_irq == NO_IRQ) { ++ if (err_irq == 0) { + pr_info("Can't get %s property '%s'\n", bm_node->full_name, + "interrupts"); + return -ENODEV; +@@ -494,6 +449,8 @@ int bman_init_ccsr(struct device_node *node) + return -EINVAL; + /* FBPR memory */ + bm_set_memory(bm, fbpr_a, 0, fbpr_sz); ++ pr_info("bman-fbpr addr 0x%llx size 0x%zx\n", fbpr_a, fbpr_sz); ++ + ret = __bind_irq(); + if (ret) + return ret; +diff --git a/drivers/staging/fsl_qbman/bman_driver.c b/drivers/staging/fsl_qbman/bman_driver.c +index 980a7d3..94053f8 100644 +--- a/drivers/staging/fsl_qbman/bman_driver.c ++++ b/drivers/staging/fsl_qbman/bman_driver.c +@@ -28,7 +28,7 @@ + * (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 "bman_private.h" ++#include "bman_low.h" + #ifdef CONFIG_HOTPLUG_CPU + #include + #endif +@@ -70,7 +70,7 @@ static int __init fsl_bpool_init(struct device_node *node) + } + if (thresh) { + #ifdef CONFIG_FSL_BMAN_CONFIG +- ret = bm_pool_set(*bpid, thresh); ++ ret = bm_pool_set(be32_to_cpu(*bpid), thresh); + if (ret) + pr_err("No CCSR node for %s property '%s'\n", + node->full_name, "fsl,bpool-thresholds"); +@@ -97,9 +97,9 @@ static int __init fsl_bpid_range_init(struct device_node *node) + node->full_name); + return -EINVAL; + } +- bman_seed_bpid_range(range[0], range[1]); ++ bman_seed_bpid_range(be32_to_cpu(range[0]), be32_to_cpu(range[1])); + pr_info("Bman: BPID allocator includes range %d:%d\n", +- range[0], range[1]); ++ be32_to_cpu(range[0]), be32_to_cpu(range[1])); + return 0; + } + +@@ -142,6 +142,12 @@ static struct bm_portal_config * __init parse_pcfg(struct device_node *node) + bman_ip_rev = BMAN_REV21; + bman_pool_max = 64; + bman_portal_max = 10; ++ } else { ++ pr_warn("unknown BMan version in portal node," ++ "default to rev1.0\n"); ++ bman_ip_rev = BMAN_REV10; ++ bman_pool_max = 64; ++ bman_portal_max = 10; + } + + ret = of_address_to_resource(node, DPA_PORTAL_CE, +@@ -163,24 +169,36 @@ static struct bm_portal_config * __init parse_pcfg(struct device_node *node) + "cell-index"); + goto err; + } +- if (*index >= bman_portal_max) ++ if (be32_to_cpu(*index) >= bman_portal_max) { ++ pr_err("BMan portal cell index %d out of range, max %d\n", ++ be32_to_cpu(*index), bman_portal_max); + goto err; ++ } + + pcfg->public_cfg.cpu = -1; + + irq = irq_of_parse_and_map(node, 0); +- if (irq == NO_IRQ) { ++ if (irq == 0) { + pr_err("Can't get %s property 'interrupts'\n", node->full_name); + goto err; + } + pcfg->public_cfg.irq = irq; +- pcfg->public_cfg.index = *index; ++ pcfg->public_cfg.index = be32_to_cpu(*index); + bman_depletion_fill(&pcfg->public_cfg.mask); + + len = resource_size(&pcfg->addr_phys[DPA_PORTAL_CE]); + if (len != (unsigned long)len) + goto err; + ++#ifdef CONFIG_ARM64 ++ pcfg->addr_virt[DPA_PORTAL_CE] = ioremap_cache_ns( ++ pcfg->addr_phys[DPA_PORTAL_CE].start, ++ resource_size(&pcfg->addr_phys[DPA_PORTAL_CE])); ++ pcfg->addr_virt[DPA_PORTAL_CI] = ioremap( ++ pcfg->addr_phys[DPA_PORTAL_CI].start, ++ resource_size(&pcfg->addr_phys[DPA_PORTAL_CI])); ++ ++#else + pcfg->addr_virt[DPA_PORTAL_CE] = ioremap_prot( + pcfg->addr_phys[DPA_PORTAL_CE].start, + (unsigned long)len, +@@ -189,10 +207,10 @@ static struct bm_portal_config * __init parse_pcfg(struct device_node *node) + pcfg->addr_phys[DPA_PORTAL_CI].start, + resource_size(&pcfg->addr_phys[DPA_PORTAL_CI]), + _PAGE_GUARDED | _PAGE_NO_CACHE); +- ++#endif + /* disable bp depletion */ +- __raw_writel(0x0, pcfg->addr_virt[DPA_PORTAL_CI] + 0x200); +- __raw_writel(0x0, pcfg->addr_virt[DPA_PORTAL_CI] + 0x204); ++ __raw_writel(0x0, pcfg->addr_virt[DPA_PORTAL_CI] + BM_REG_SCN(0)); ++ __raw_writel(0x0, pcfg->addr_virt[DPA_PORTAL_CI] + BM_REG_SCN(1)); + return pcfg; + err: + kfree(pcfg); +@@ -433,7 +451,7 @@ __init int bman_init(void) + } + if (list_empty(&shared_pcfgs) && list_empty(&unshared_pcfgs)) { + /* Default, give an unshared portal to each online cpu */ +- for_each_possible_cpu(cpu) { ++ for_each_online_cpu(cpu) { + pcfg = get_pcfg(&unused_pcfgs); + if (!pcfg) + break; +diff --git a/drivers/staging/fsl_qbman/bman_high.c b/drivers/staging/fsl_qbman/bman_high.c +index 9986120..2ece0f3 100644 +--- a/drivers/staging/fsl_qbman/bman_high.c ++++ b/drivers/staging/fsl_qbman/bman_high.c +@@ -316,7 +316,7 @@ struct bman_portal *bman_create_portal( + irq_can_set_affinity(config->public_cfg.irq) && + irq_set_affinity(config->public_cfg.irq, + cpumask_of(config->public_cfg.cpu))) { +- pr_err("irq_set_affinity() failed\n"); ++ pr_err("irq_set_affinity() failed %s\n", portal->irqname); + goto fail_affinity; + } + +@@ -460,6 +460,8 @@ static u32 __poll_portal_slow(struct bman_portal *p, u32 is) + while (!(mcr = bm_mc_result(&p->p))) + cpu_relax(); + tmp = mcr->query.ds.state; ++ tmp.__state[0] = be32_to_cpu(tmp.__state[0]); ++ tmp.__state[1] = be32_to_cpu(tmp.__state[1]); + PORTAL_IRQ_UNLOCK(p, irqflags); + for (i = 0; i < 2; i++) { + int idx = i * 32; +@@ -831,21 +833,11 @@ static noinline struct bm_rcr_entry *wait_rel_start(struct bman_portal **p, + } + #endif + +-/* to facilitate better copying of bufs into the ring without either (a) copying +- * noise into the first byte (prematurely triggering the command), nor (b) being +- * very inefficient by copying small fields using read-modify-write */ +-struct overlay_bm_buffer { +- u32 first; +- u32 second; +-}; +- + static inline int __bman_release(struct bman_pool *pool, + const struct bm_buffer *bufs, u8 num, u32 flags) + { + struct bman_portal *p; + struct bm_rcr_entry *r; +- struct overlay_bm_buffer *o_dest; +- struct overlay_bm_buffer *o_src = (struct overlay_bm_buffer *)&bufs[0]; + __maybe_unused unsigned long irqflags; + u32 i = num - 1; + +@@ -861,12 +853,16 @@ static inline int __bman_release(struct bman_pool *pool, + return -EBUSY; + /* We can copy all but the first entry, as this can trigger badness + * with the valid-bit. Use the overlay to mask the verb byte. */ +- o_dest = (struct overlay_bm_buffer *)&r->bufs[0]; +- o_dest->first = (o_src->first & 0x0000ffff) | +- (((u32)pool->params.bpid << 16) & 0x00ff0000); +- o_dest->second = o_src->second; +- if (i) +- copy_words(&r->bufs[1], &bufs[1], i * sizeof(bufs[0])); ++ r->bufs[0].opaque = ++ ((cpu_to_be64((bufs[0].opaque | ++ ((u64)pool->params.bpid<<48)) ++ & 0x00ffffffffffffff))); ++ if (i) { ++ for (i = 1; i < num; i++) ++ r->bufs[i].opaque = ++ cpu_to_be64(bufs[i].opaque); ++ } ++ + bm_rcr_pvb_commit(&p->p, BM_RCR_VERB_CMD_BPID_SINGLE | + (num & BM_RCR_VERB_BUFCOUNT_MASK)); + #ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC +@@ -962,7 +958,7 @@ static inline int __bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, + struct bm_mc_command *mcc; + struct bm_mc_result *mcr; + __maybe_unused unsigned long irqflags; +- int ret; ++ int ret, i; + + PORTAL_IRQ_LOCK(p, irqflags); + mcc = bm_mc_start(&p->p); +@@ -972,9 +968,11 @@ static inline int __bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, + while (!(mcr = bm_mc_result(&p->p))) + cpu_relax(); + ret = mcr->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT; +- if (bufs) +- copy_words(&bufs[0], &mcr->acquire.bufs[0], +- num * sizeof(bufs[0])); ++ if (bufs) { ++ for (i = 0; i < num; i++) ++ bufs[i].opaque = ++ be64_to_cpu(mcr->acquire.bufs[i].opaque); ++ } + PORTAL_IRQ_UNLOCK(p, irqflags); + put_affine_portal(); + if (ret != num) +diff --git a/drivers/staging/fsl_qbman/bman_low.h b/drivers/staging/fsl_qbman/bman_low.h +index e4ab771..7dc9d54 100644 +--- a/drivers/staging/fsl_qbman/bman_low.h ++++ b/drivers/staging/fsl_qbman/bman_low.h +@@ -35,6 +35,8 @@ + /* Portal register assists */ + /***************************/ + ++#if defined(CONFIG_PPC32) || defined(CONFIG_PPC64) ++ + /* Cache-inhibited register offsets */ + #define BM_REG_RCR_PI_CINH 0x0000 + #define BM_REG_RCR_CI_CINH 0x0004 +@@ -52,6 +54,29 @@ + #define BM_CL_RCR_PI_CENA 0x3000 + #define BM_CL_RCR_CI_CENA 0x3100 + ++#endif ++ ++#if defined(CONFIG_ARM64) ++ ++/* Cache-inhibited register offsets */ ++#define BM_REG_RCR_PI_CINH 0x3000 ++#define BM_REG_RCR_CI_CINH 0x3100 ++#define BM_REG_RCR_ITR 0x3200 ++#define BM_REG_CFG 0x3300 ++#define BM_REG_SCN(n) (0x3400 + ((n) << 6)) ++#define BM_REG_ISR 0x3e00 ++#define BM_REG_IIR 0x3ec0 ++ ++/* Cache-enabled register offsets */ ++#define BM_CL_CR 0x0000 ++#define BM_CL_RR0 0x0100 ++#define BM_CL_RR1 0x0140 ++#define BM_CL_RCR 0x1000 ++#define BM_CL_RCR_PI_CENA 0x3000 ++#define BM_CL_RCR_CI_CENA 0x3100 ++ ++#endif ++ + /* BTW, the drivers (and h/w programming model) already obtain the required + * synchronisation for portal accesses via lwsync(), hwsync(), and + * data-dependencies. Use of barrier()s or other order-preserving primitives +@@ -60,19 +85,20 @@ + * non-coherent). */ + + /* Cache-inhibited register access. */ +-#define __bm_in(bm, o) __raw_readl((bm)->addr_ci + (o)) +-#define __bm_out(bm, o, val) __raw_writel((val), (bm)->addr_ci + (o)) ++#define __bm_in(bm, o) be32_to_cpu(__raw_readl((bm)->addr_ci + (o))) ++#define __bm_out(bm, o, val) __raw_writel(cpu_to_be32(val), \ ++ (bm)->addr_ci + (o)); + #define bm_in(reg) __bm_in(&portal->addr, BM_REG_##reg) + #define bm_out(reg, val) __bm_out(&portal->addr, BM_REG_##reg, val) + + /* Cache-enabled (index) register access */ + #define __bm_cl_touch_ro(bm, o) dcbt_ro((bm)->addr_ce + (o)) + #define __bm_cl_touch_rw(bm, o) dcbt_rw((bm)->addr_ce + (o)) +-#define __bm_cl_in(bm, o) __raw_readl((bm)->addr_ce + (o)) ++#define __bm_cl_in(bm, o) be32_to_cpu(__raw_readl((bm)->addr_ce + (o))) + #define __bm_cl_out(bm, o, val) \ + do { \ + u32 *__tmpclout = (bm)->addr_ce + (o); \ +- __raw_writel((val), __tmpclout); \ ++ __raw_writel(cpu_to_be32(val), __tmpclout); \ + dcbf(__tmpclout); \ + } while (0) + #define __bm_cl_invalidate(bm, o) dcbi((bm)->addr_ce + (o)) +@@ -196,6 +222,7 @@ static inline int bm_rcr_init(struct bm_portal *portal, enum bm_rcr_pmode pmode, + + rcr->ring = portal->addr.addr_ce + BM_CL_RCR; + rcr->ci = bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1); ++ + pi = bm_in(RCR_PI_CINH) & (BM_RCR_SIZE - 1); + rcr->cursor = rcr->ring + pi; + rcr->vbit = (bm_in(RCR_PI_CINH) & BM_RCR_SIZE) ? BM_RCR_VERB_VBIT : 0; +@@ -487,13 +514,21 @@ static inline void bm_isr_bscn_mask(struct bm_portal *portal, u8 bpid, + + static inline u32 __bm_isr_read(struct bm_portal *portal, enum bm_isr_reg n) + { ++#if defined(CONFIG_ARM64) ++ return __bm_in(&portal->addr, BM_REG_ISR + (n << 6)); ++#else + return __bm_in(&portal->addr, BM_REG_ISR + (n << 2)); ++#endif + } + + static inline void __bm_isr_write(struct bm_portal *portal, enum bm_isr_reg n, + u32 val) + { ++#if defined(CONFIG_ARM64) ++ __bm_out(&portal->addr, BM_REG_ISR + (n << 6), val); ++#else + __bm_out(&portal->addr, BM_REG_ISR + (n << 2), val); ++#endif + } + + /* Buffer Pool Cleanup */ +diff --git a/drivers/staging/fsl_qbman/dpa_sys.h b/drivers/staging/fsl_qbman/dpa_sys.h +index 7dd0640..afa2613 100644 +--- a/drivers/staging/fsl_qbman/dpa_sys.h ++++ b/drivers/staging/fsl_qbman/dpa_sys.h +@@ -58,11 +58,11 @@ + #include + #include + #include +-#include + #include + #include + #include + #include ++#include + + #include + +@@ -77,58 +77,14 @@ + /* Misc inline assists */ + /***********************/ + +-/* TODO: NB, we currently assume that hwsync() and lwsync() imply compiler +- * barriers and that dcb*() won't fall victim to compiler or execution +- * reordering with respect to other code/instructions that manipulate the same +- * cacheline. */ +-#define hwsync() __asm__ __volatile__ ("sync" : : : "memory") +-#define lwsync()__asm__ __volatile__ (stringify_in_c(LWSYNC) : : : "memory") +-#define dcbf(p) __asm__ __volatile__ ("dcbf 0,%0" : : "r" (p) : "memory") +-#define dcbt_ro(p) __asm__ __volatile__ ("dcbt 0,%0" : : "r" (p)) +-#define dcbt_rw(p) __asm__ __volatile__ ("dcbtst 0,%0" : : "r" (p)) +-#define dcbi(p) dcbf(p) +-#ifdef CONFIG_PPC_E500MC +-#define dcbzl(p) __asm__ __volatile__ ("dcbzl 0,%0" : : "r" (p)) +-#define dcbz_64(p) dcbzl(p) +-#define dcbf_64(p) dcbf(p) +-/* Commonly used combo */ +-#define dcbit_ro(p) \ +- do { \ +- dcbi(p); \ +- dcbt_ro(p); \ +- } while (0) +-#else +-#define dcbz(p)__asm__ __volatile__ ("dcbz 0,%0" : : "r" (p)) +-#define dcbz_64(p) \ +- do { \ +- dcbz((u32)p + 32); \ +- dcbz(p); \ +- } while (0) +-#define dcbf_64(p) \ +- do { \ +- dcbf((u32)p + 32); \ +- dcbf(p); \ +- } while (0) +-/* Commonly used combo */ +-#define dcbit_ro(p) \ +- do { \ +- dcbi(p); \ +- dcbi((u32)p + 32); \ +- dcbt_ro(p); \ +- dcbt_ro((u32)p + 32); \ +- } while (0) +-#endif /* CONFIG_PPC_E500MC */ ++#if defined CONFIG_PPC32 ++#include "dpa_sys_ppc32.h" ++#elif defined CONFIG_PPC64 ++#include "dpa_sys_ppc64.h" ++#elif defined CONFIG_ARM64 ++#include "dpa_sys_arm64.h" ++#endif + +-static inline u64 mfatb(void) +-{ +- u32 hi, lo, chk; +- do { +- hi = mfspr(SPRN_ATBU); +- lo = mfspr(SPRN_ATBL); +- chk = mfspr(SPRN_ATBU); +- } while (unlikely(hi != chk)); +- return ((u64)hi << 32) | (u64)lo; +-} + + #ifdef CONFIG_FSL_DPA_CHECKING + #define DPA_ASSERT(x) \ +diff --git a/drivers/staging/fsl_qbman/dpa_sys_arm64.h b/drivers/staging/fsl_qbman/dpa_sys_arm64.h +new file mode 100644 +index 0000000..b119095 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/dpa_sys_arm64.h +@@ -0,0 +1,102 @@ ++/* Copyright 2014 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 DPA_SYS_ARM64_H ++#define DPA_SYS_ARM64_H ++ ++#include ++#include ++ ++/* Implementation of ARM 64 bit specific routines */ ++ ++/* TODO: NB, we currently assume that hwsync() and lwsync() imply compiler ++ * barriers and that dcb*() won't fall victim to compiler or execution ++ * reordering with respect to other code/instructions that manipulate the same ++ * cacheline. */ ++#define hwsync() { asm volatile("dmb st" : : : "memory"); } ++#define lwsync() { asm volatile("dmb st" : : : "memory"); } ++#define dcbf(p) { asm volatile("dc cvac, %0;" : : "r" (p) : "memory"); } ++#define dcbt_ro(p) { asm volatile("prfm pldl1keep, [%0, #64]" : : "r" (p)); } ++#define dcbt_rw(p) { asm volatile("prfm pldl1keep, [%0, #64]" : : "r" (p)); } ++#define dcbi(p) { asm volatile("dc ivac, %0" : : "r"(p) : "memory"); } ++#define dcbz(p) { asm volatile("dc zva, %0" : : "r" (p) : "memory"); } ++ ++#define dcbz_64(p) \ ++ do { \ ++ dcbz(p); \ ++ } while (0) ++ ++#define dcbf_64(p) \ ++ do { \ ++ dcbf(p); \ ++ } while (0) ++/* Commonly used combo */ ++#define dcbit_ro(p) \ ++ do { \ ++ dcbi(p); \ ++ dcbt_ro(p); \ ++ } while (0) ++ ++static inline u64 mfatb(void) ++{ ++ return get_cycles(); ++} ++ ++static inline u32 in_be32(volatile void *addr) ++{ ++ return be32_to_cpu(*((volatile u32 *) addr)); ++} ++ ++static inline void out_be32(void *addr, u32 val) ++{ ++ *((u32 *) addr) = cpu_to_be32(val); ++} ++ ++ ++static inline void set_bits(unsigned long mask, volatile unsigned long *p) ++{ ++ *p |= mask; ++} ++static inline void clear_bits(unsigned long mask, volatile unsigned long *p) ++{ ++ *p &= ~mask; ++} ++ ++static inline void flush_dcache_range(unsigned long start, unsigned long stop) ++{ ++ __flush_dcache_area((void *) start, stop - start + 1); ++} ++ ++#define hard_smp_processor_id() raw_smp_processor_id() ++ ++ ++ ++#endif +diff --git a/drivers/staging/fsl_qbman/dpa_sys_ppc32.h b/drivers/staging/fsl_qbman/dpa_sys_ppc32.h +new file mode 100644 +index 0000000..874616d +--- /dev/null ++++ b/drivers/staging/fsl_qbman/dpa_sys_ppc32.h +@@ -0,0 +1,70 @@ ++/* Copyright 2014 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 DPA_SYS_PPC32_H ++#define DPA_SYS_PPC32_H ++ ++/* Implementation of PowerPC 32 bit specific routines */ ++ ++/* TODO: NB, we currently assume that hwsync() and lwsync() imply compiler ++ * barriers and that dcb*() won't fall victim to compiler or execution ++ * reordering with respect to other code/instructions that manipulate the same ++ * cacheline. */ ++#define hwsync() __asm__ __volatile__ ("sync" : : : "memory") ++#define lwsync() __asm__ __volatile__ (stringify_in_c(LWSYNC) : : : "memory") ++#define dcbf(p) __asm__ __volatile__ ("dcbf 0,%0" : : "r" (p) : "memory") ++#define dcbt_ro(p) __asm__ __volatile__ ("dcbt 0,%0" : : "r" (p)) ++#define dcbt_rw(p) __asm__ __volatile__ ("dcbtst 0,%0" : : "r" (p)) ++#define dcbi(p) dcbf(p) ++ ++#define dcbzl(p) __asm__ __volatile__ ("dcbzl 0,%0" : : "r" (p)) ++#define dcbz_64(p) dcbzl(p) ++#define dcbf_64(p) dcbf(p) ++ ++/* Commonly used combo */ ++#define dcbit_ro(p) \ ++ do { \ ++ dcbi(p); \ ++ dcbt_ro(p); \ ++ } while (0) ++ ++static inline u64 mfatb(void) ++{ ++ u32 hi, lo, chk; ++ do { ++ hi = mfspr(SPRN_ATBU); ++ lo = mfspr(SPRN_ATBL); ++ chk = mfspr(SPRN_ATBU); ++ } while (unlikely(hi != chk)); ++ return ((u64)hi << 32) | (u64)lo; ++} ++ ++#endif +diff --git a/drivers/staging/fsl_qbman/dpa_sys_ppc64.h b/drivers/staging/fsl_qbman/dpa_sys_ppc64.h +new file mode 100644 +index 0000000..d980319 +--- /dev/null ++++ b/drivers/staging/fsl_qbman/dpa_sys_ppc64.h +@@ -0,0 +1,79 @@ ++/* Copyright 2014 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 DPA_SYS_PPC64_H ++#define DPA_SYS_PPC64_H ++ ++/* Implementation of PowerPC 64 bit specific routines */ ++ ++/* TODO: NB, we currently assume that hwsync() and lwsync() imply compiler ++ * barriers and that dcb*() won't fall victim to compiler or execution ++ * reordering with respect to other code/instructions that manipulate the same ++ * cacheline. */ ++#define hwsync() __asm__ __volatile__ ("sync" : : : "memory") ++#define lwsync() __asm__ __volatile__ (stringify_in_c(LWSYNC) : : : "memory") ++#define dcbf(p) __asm__ __volatile__ ("dcbf 0,%0" : : "r" (p) : "memory") ++#define dcbt_ro(p) __asm__ __volatile__ ("dcbt 0,%0" : : "r" (p)) ++#define dcbt_rw(p) __asm__ __volatile__ ("dcbtst 0,%0" : : "r" (p)) ++#define dcbi(p) dcbf(p) ++ ++#define dcbz(p) __asm__ __volatile__ ("dcbz 0,%0" : : "r" (p)) ++#define dcbz_64(p) \ ++ do { \ ++ dcbz((void*)p + 32); \ ++ dcbz(p); \ ++ } while (0) ++#define dcbf_64(p) \ ++ do { \ ++ dcbf((void*)p + 32); \ ++ dcbf(p); \ ++ } while (0) ++/* Commonly used combo */ ++#define dcbit_ro(p) \ ++ do { \ ++ dcbi(p); \ ++ dcbi((void*)p + 32); \ ++ dcbt_ro(p); \ ++ dcbt_ro((void*)p + 32); \ ++ } while (0) ++ ++static inline u64 mfatb(void) ++{ ++ u32 hi, lo, chk; ++ do { ++ hi = mfspr(SPRN_ATBU); ++ lo = mfspr(SPRN_ATBL); ++ chk = mfspr(SPRN_ATBU); ++ } while (unlikely(hi != chk)); ++ return ((u64)hi << 32) | (u64)lo; ++} ++ ++#endif +diff --git a/drivers/staging/fsl_qbman/fsl_usdpaa.c b/drivers/staging/fsl_qbman/fsl_usdpaa.c +index 955b345..9386402 100644 +--- a/drivers/staging/fsl_qbman/fsl_usdpaa.c ++++ b/drivers/staging/fsl_qbman/fsl_usdpaa.c +@@ -8,9 +8,6 @@ + * kind, whether express or implied. + */ + +-#include +-#include "bman_low.h" +-#include "qman_low.h" + + #include + #include +@@ -20,7 +17,15 @@ + #include + #include + #include ++ ++#ifndef CONFIG_ARM64 + #include ++#endif ++ ++#include "dpa_sys.h" ++#include ++#include "bman_low.h" ++#include "qman_low.h" + + /* Physical address range of the memory reservation, exported for mm/mem.c */ + static u64 phys_start; +@@ -728,7 +733,11 @@ static int check_mmap_portal(struct ctx *ctx, struct vm_area_struct *vma, + match, pfn); + if (*match) { + vma->vm_page_prot = ++#ifdef CONFIG_ARM64 ++ pgprot_cached_ns(vma->vm_page_prot); ++#else + pgprot_cached_noncoherent(vma->vm_page_prot); ++#endif + return ret; + } + ret = check_mmap_resource(&portal->phys[DPA_PORTAL_CI], vma, +@@ -1167,6 +1176,7 @@ map_match: + for (i = 0; i < map->frag_count; i++) { + DPA_ASSERT(current_frag->refs > 0); + --current_frag->refs; ++#ifndef CONFIG_ARM64 + /* + * Make sure we invalidate the TLB entry for + * this fragment, otherwise a remap of a different +@@ -1174,7 +1184,7 @@ map_match: + * incorrect piece of memory + */ + cleartlbcam(vaddr, mfspr(SPRN_PID)); +- ++#endif + vaddr += current_frag->len; + current_frag = list_entry(current_frag->list.prev, + struct mem_fragment, list); +@@ -1855,16 +1865,16 @@ static __init int usdpaa_mem(char *arg) + } + early_param("usdpaa_mem", usdpaa_mem); + +-__init void fsl_usdpaa_init_early(void) ++__init int fsl_usdpaa_init_early(void) + { + if (!phys_size) { + pr_info("No USDPAA memory, no 'usdpaa_mem' bootarg\n"); +- return; ++ return 0; + } + if (phys_size % PAGE_SIZE) { + pr_err("'usdpaa_mem' bootarg must be a multiple of page size\n"); + phys_size = 0; +- return; ++ return 0; + } + phys_start = __memblock_alloc_base(phys_size, + largest_page_size(phys_size), +@@ -1872,15 +1882,20 @@ __init void fsl_usdpaa_init_early(void) + if (!phys_start) { + pr_err("Failed to reserve USDPAA region (sz:%llx)\n", + phys_size); +- return; ++ return 0; + } + pfn_start = phys_start >> PAGE_SHIFT; + pfn_size = phys_size >> PAGE_SHIFT; ++#ifdef CONFIG_PPC + first_tlb = current_tlb = tlbcam_index; + tlbcam_index += num_tlb; ++#endif + pr_info("USDPAA region at %llx:%llx(%lx:%lx), %d TLB1 entries)\n", + phys_start, phys_size, pfn_start, pfn_size, num_tlb); ++ return 0; + } ++subsys_initcall(fsl_usdpaa_init_early); ++ + + static int __init usdpaa_init(void) + { +diff --git a/drivers/staging/fsl_qbman/fsl_usdpaa_irq.c b/drivers/staging/fsl_qbman/fsl_usdpaa_irq.c +index 1f8260b..b13ba32 100644 +--- a/drivers/staging/fsl_qbman/fsl_usdpaa_irq.c ++++ b/drivers/staging/fsl_qbman/fsl_usdpaa_irq.c +@@ -59,6 +59,7 @@ struct usdpaa_irq_ctx { + spinlock_t lock; + void *inhibit_addr; /* inhibit register address */ + struct file *usdpaa_filp; ++ char irq_name[128]; + }; + + static int usdpaa_irq_open(struct inode *inode, struct file *filp) +@@ -101,6 +102,7 @@ static irqreturn_t usdpaa_irq_handler(int irq, void *_ctx) + /* Set the inhibit register. This will be reenabled + once the USDPAA code handles the IRQ */ + out_be32(ctx->inhibit_addr, 0x1); ++ pr_info("Inhibit at %p count %d", ctx->inhibit_addr, ctx->irq_count); + return IRQ_HANDLED; + } + +@@ -131,8 +133,11 @@ static int map_irq(struct file *fp, struct usdpaa_ioctl_irq_map *irq_map) + + ctx->irq_set = 1; + ++ snprintf(ctx->irq_name, sizeof(ctx->irq_name), ++ "usdpaa_irq %d", ctx->irq_num); ++ + ret = request_irq(ctx->irq_num, usdpaa_irq_handler, 0, +- "usdpaa_irq", ctx); ++ ctx->irq_name, ctx); + if (ret) { + pr_err("USDPAA request_irq(%d) failed, ret= %d\n", + ctx->irq_num, ret); +diff --git a/drivers/staging/fsl_qbman/qbman_driver.c b/drivers/staging/fsl_qbman/qbman_driver.c +index a2904bd..ab487d5 100644 +--- a/drivers/staging/fsl_qbman/qbman_driver.c ++++ b/drivers/staging/fsl_qbman/qbman_driver.c +@@ -32,6 +32,8 @@ + #include + #include "qman_private.h" + #include "bman_private.h" ++__init void qman_init_early(void); ++__init void bman_init_early(void); + + static __init int qbman_init(void) + { +diff --git a/drivers/staging/fsl_qbman/qman_config.c b/drivers/staging/fsl_qbman/qman_config.c +index 2ce3255..c2ba677 100644 +--- a/drivers/staging/fsl_qbman/qman_config.c ++++ b/drivers/staging/fsl_qbman/qman_config.c +@@ -31,6 +31,8 @@ + + #include + #include "qman_private.h" ++#include ++#include + + /* Last updated for v00.800 of the BG */ + +@@ -428,6 +430,28 @@ static struct device_node *qm_node; + static dma_addr_t fqd_a, pfdr_a; + static size_t fqd_sz = DEFAULT_FQD_SZ, pfdr_sz = DEFAULT_PFDR_SZ; + ++static int qman_fqd(struct reserved_mem *rmem) ++{ ++ fqd_a = rmem->base; ++ fqd_sz = rmem->size; ++ ++ WARN_ON(!(fqd_a && fqd_sz)); ++ ++ return 0; ++} ++RESERVEDMEM_OF_DECLARE(qman_fqd, "fsl,qman-fqd", qman_fqd); ++ ++static int qman_pfdr(struct reserved_mem *rmem) ++{ ++ pfdr_a = rmem->base; ++ pfdr_sz = rmem->size; ++ ++ WARN_ON(!(pfdr_a && pfdr_sz)); ++ ++ return 0; ++} ++RESERVEDMEM_OF_DECLARE(qman_fbpr, "fsl,qman-pfdr", qman_pfdr); ++ + /* Parse the property to extract the memory location and size and + * memblock_reserve() it. If it isn't supplied, memblock_alloc() the default + * size. Also flush this memory range from data cache so that QMAN originated +@@ -436,51 +460,30 @@ static size_t fqd_sz = DEFAULT_FQD_SZ, pfdr_sz = DEFAULT_PFDR_SZ; + static __init int parse_mem_property(struct device_node *node, const char *name, + dma_addr_t *addr, size_t *sz, int zero) + { +- const u32 *pint; + int ret; +- unsigned long vaddr; +- +- pint = of_get_property(node, name, &ret); +- if (!pint || (ret != 16)) { +- pr_info("No %s property '%s', using memblock_alloc(%016zx)\n", +- node->full_name, name, *sz); +- *addr = memblock_alloc(*sz, *sz); +- vaddr = (unsigned long)phys_to_virt(*addr); +- if (zero) +- memset((void *)vaddr, 0, *sz); +- flush_dcache_range(vaddr, vaddr + *sz); +- return 0; +- } +- pr_info("Using %s property '%s'\n", node->full_name, name); ++ + /* If using a "zero-pma", don't try to zero it, even if you asked */ + if (zero && of_find_property(node, "zero-pma", &ret)) { + pr_info(" it's a 'zero-pma', not zeroing from s/w\n"); + zero = 0; + } +- *addr = ((u64)pint[0] << 32) | (u64)pint[1]; +- *sz = ((u64)pint[2] << 32) | (u64)pint[3]; +- /* Keep things simple, it's either all in the DRAM range or it's all +- * outside. */ +- if (*addr < memblock_end_of_DRAM()) { +- BUG_ON((u64)*addr + (u64)*sz > memblock_end_of_DRAM()); +- if (memblock_reserve(*addr, *sz) < 0) { +- pr_err("Failed to reserve %s\n", name); +- return -ENOMEM; +- } +- vaddr = (unsigned long)phys_to_virt(*addr); +- if (zero) +- memset(phys_to_virt(*addr), 0, *sz); +- flush_dcache_range(vaddr, vaddr + *sz); +- } else if (zero) { ++ ++ if (zero) { + /* map as cacheable, non-guarded */ +- void __iomem *tmpp = ioremap_prot(*addr, *sz, 0); ++#ifdef CONFIG_ARM64 ++ void __iomem *tmpp = ioremap_cache(*addr, *sz); ++#else ++ void __iomem *tmpp = ioremap(*addr, *sz); ++#endif ++ + if (!tmpp) + return -ENOMEM; + memset_io(tmpp, 0, *sz); +- vaddr = (unsigned long)tmpp; +- flush_dcache_range(vaddr, vaddr + *sz); ++ flush_dcache_range((unsigned long)tmpp, ++ (unsigned long)tmpp + *sz); + iounmap(tmpp); + } ++ + return 0; + } + +@@ -509,9 +512,11 @@ static int __init fsl_qman_init(struct device_node *node) + if (!standby) { + ret = parse_mem_property(node, "fsl,qman-fqd", + &fqd_a, &fqd_sz, 1); ++ pr_info("qman-fqd addr 0x%llx size 0x%zx\n", fqd_a, fqd_sz); + BUG_ON(ret); + ret = parse_mem_property(node, "fsl,qman-pfdr", + &pfdr_a, &pfdr_sz, 0); ++ pr_info("qman-pfdr addr 0x%llx size 0x%zx\n", pfdr_a, pfdr_sz); + BUG_ON(ret); + } + /* Global configuration */ +@@ -538,6 +543,8 @@ static int __init fsl_qman_init(struct device_node *node) + qman_ip_rev = QMAN_REV30; + else if ((major == 3) && (minor == 1)) + qman_ip_rev = QMAN_REV31; ++ else if ((major == 3) && (minor == 2)) ++ qman_ip_rev = QMAN_REV32; + else { + pr_warn("unknown Qman version, default to rev1.1\n"); + qman_ip_rev = QMAN_REV11; +@@ -557,7 +564,7 @@ int qman_have_ccsr(void) + return qm ? 1 : 0; + } + +-__init void qman_init_early(void) ++__init int qman_init_early(void) + { + struct device_node *dn; + int ret; +@@ -574,7 +581,9 @@ __init void qman_init_early(void) + BUG_ON(ret); + } + } ++ return 0; + } ++postcore_initcall_sync(qman_init_early); + + static void log_edata_bits(u32 bit_count) + { +@@ -679,7 +688,7 @@ static int __bind_irq(void) + int ret, err_irq; + + err_irq = of_irq_to_resource(qm_node, 0, NULL); +- if (err_irq == NO_IRQ) { ++ if (err_irq == 0) { + pr_info("Can't get %s property '%s'\n", qm_node->full_name, + "interrupts"); + return -ENODEV; +@@ -705,6 +714,11 @@ int qman_init_ccsr(struct device_node *node) + return 0; + if (node != qm_node) + return -EINVAL; ++#ifdef CONFIG_ARM64 ++ /* TEMP for LS1043 : should be done in uboot */ ++ qm_out(QCSP_BARE, 0x5); ++ qm_out(QCSP_BAR, 0x0); ++#endif + /* FQD memory */ + qm_set_memory(qm, qm_memory_fqd, fqd_a, 1, 0, 0, fqd_sz); + /* PFDR memory */ +@@ -766,6 +780,10 @@ int qman_set_sdest(u16 channel, unsigned int cpu_idx) + + if (!qman_have_ccsr()) + return -ENODEV; ++ if ((qman_ip_rev & 0xFF00) == QMAN_REV31) { ++ /* LS1043A - only one L2 cache */ ++ cpu_idx = 0; ++ } + + if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) { + before = qm_in(REV3_QCSP_IO_CFG(idx)); +diff --git a/drivers/staging/fsl_qbman/qman_driver.c b/drivers/staging/fsl_qbman/qman_driver.c +index c3e5718..3c347f9 100644 +--- a/drivers/staging/fsl_qbman/qman_driver.c ++++ b/drivers/staging/fsl_qbman/qman_driver.c +@@ -93,9 +93,9 @@ static __init int fsl_fqid_range_init(struct device_node *node) + pr_err(STR_ERR_CELL, STR_FQID_RANGE, 2, node->full_name); + return -EINVAL; + } +- qman_seed_fqid_range(range[0], range[1]); ++ qman_seed_fqid_range(be32_to_cpu(range[0]), be32_to_cpu(range[1])); + pr_info("Qman: FQID allocator includes range %d:%d\n", +- range[0], range[1]); ++ be32_to_cpu(range[0]), be32_to_cpu(range[1])); + return 0; + } + +@@ -112,8 +112,8 @@ static __init int fsl_pool_channel_range_sdqcr(struct device_node *node) + pr_err(STR_ERR_CELL, STR_POOL_CHAN_RANGE, 1, node->full_name); + return -EINVAL; + } +- for (ret = 0; ret < chanid[1]; ret++) +- pools_sdqcr |= QM_SDQCR_CHANNELS_POOL_CONV(chanid[0] + ret); ++ for (ret = 0; ret < be32_to_cpu(chanid[1]); ret++) ++ pools_sdqcr |= QM_SDQCR_CHANNELS_POOL_CONV(be32_to_cpu(chanid[0]) + ret); + return 0; + } + +@@ -130,9 +130,9 @@ static __init int fsl_pool_channel_range_init(struct device_node *node) + pr_err(STR_ERR_CELL, STR_POOL_CHAN_RANGE, 1, node->full_name); + return -EINVAL; + } +- qman_seed_pool_range(chanid[0], chanid[1]); ++ qman_seed_pool_range(be32_to_cpu(chanid[0]), be32_to_cpu(chanid[1])); + pr_info("Qman: pool channel allocator includes range %d:%d\n", +- chanid[0], chanid[1]); ++ be32_to_cpu(chanid[0]), be32_to_cpu(chanid[1])); + return 0; + } + +@@ -150,9 +150,9 @@ static __init int fsl_cgrid_range_init(struct device_node *node) + pr_err(STR_ERR_CELL, STR_CGRID_RANGE, 2, node->full_name); + return -EINVAL; + } +- qman_seed_cgrid_range(range[0], range[1]); ++ qman_seed_cgrid_range(be32_to_cpu(range[0]), be32_to_cpu(range[1])); + pr_info("Qman: CGRID allocator includes range %d:%d\n", +- range[0], range[1]); ++ be32_to_cpu(range[0]), be32_to_cpu(range[1])); + for (cgr.cgrid = 0; cgr.cgrid < __CGR_NUM; cgr.cgrid++) { + ret = qman_modify_cgr(&cgr, QMAN_CGR_FLAG_USE_INIT, NULL); + if (ret) +@@ -185,18 +185,18 @@ static __init int fsl_ceetm_init(struct device_node *node) + return -EINVAL; + } + +- dcp_portal = (range[0] & 0x0F0000) >> 16; ++ dcp_portal = (be32_to_cpu(range[0]) & 0x0F0000) >> 16; + if (dcp_portal > qm_dc_portal_fman1) { + pr_err("The DCP portal %d doesn't support CEETM\n", dcp_portal); + return -EINVAL; + } + + if (dcp_portal == qm_dc_portal_fman0) +- qman_seed_ceetm0_lfqid_range(range[0], range[1]); ++ qman_seed_ceetm0_lfqid_range(be32_to_cpu(range[0]), be32_to_cpu(range[1])); + if (dcp_portal == qm_dc_portal_fman1) +- qman_seed_ceetm1_lfqid_range(range[0], range[1]); ++ qman_seed_ceetm1_lfqid_range(be32_to_cpu(range[0]), be32_to_cpu(range[1])); + pr_debug("Qman: The lfqid allocator of CEETM %d includes range" +- " 0x%x:0x%x\n", dcp_portal, range[0], range[1]); ++ " 0x%x:0x%x\n", dcp_portal, be32_to_cpu(range[0]), be32_to_cpu(range[1])); + + qman_ceetms[dcp_portal].idx = dcp_portal; + INIT_LIST_HEAD(&qman_ceetms[dcp_portal].sub_portals); +@@ -221,16 +221,16 @@ static __init int fsl_ceetm_init(struct device_node *node) + range[0] + i); + return -ENOMEM; + } +- sp->idx = range[0] + i; ++ sp->idx = be32_to_cpu(range[0]) + i; + sp->dcp_idx = dcp_portal; + sp->is_claimed = 0; + list_add_tail(&sp->node, &qman_ceetms[dcp_portal].sub_portals); + sp++; + } + pr_debug("Qman: Reserve sub-portal %d:%d for CEETM %d\n", +- range[0], range[1], dcp_portal); +- qman_ceetms[dcp_portal].sp_range[0] = range[0]; +- qman_ceetms[dcp_portal].sp_range[1] = range[1]; ++ be32_to_cpu(range[0]), be32_to_cpu(range[1]), dcp_portal); ++ qman_ceetms[dcp_portal].sp_range[0] = be32_to_cpu(range[0]); ++ qman_ceetms[dcp_portal].sp_range[1] = be32_to_cpu(range[1]); + + /* Find LNI range */ + range = of_get_property(node, "fsl,ceetm-lni-range", &ret); +@@ -251,7 +251,7 @@ static __init int fsl_ceetm_init(struct device_node *node) + range[0] + i); + return -ENOMEM; + } +- lni->idx = range[0] + i; ++ lni->idx = be32_to_cpu(range[0]) + i; + lni->dcp_idx = dcp_portal; + lni->is_claimed = 0; + INIT_LIST_HEAD(&lni->channels); +@@ -259,9 +259,9 @@ static __init int fsl_ceetm_init(struct device_node *node) + lni++; + } + pr_debug("Qman: Reserve LNI %d:%d for CEETM %d\n", +- range[0], range[1], dcp_portal); +- qman_ceetms[dcp_portal].lni_range[0] = range[0]; +- qman_ceetms[dcp_portal].lni_range[1] = range[1]; ++ be32_to_cpu(range[0]), be32_to_cpu(range[1]), dcp_portal); ++ qman_ceetms[dcp_portal].lni_range[0] = be32_to_cpu(range[0]); ++ qman_ceetms[dcp_portal].lni_range[1] = be32_to_cpu(range[1]); + + /* Find CEETM channel range */ + range = of_get_property(node, "fsl,ceetm-channel-range", &ret); +@@ -277,11 +277,11 @@ static __init int fsl_ceetm_init(struct device_node *node) + } + + if (dcp_portal == qm_dc_portal_fman0) +- qman_seed_ceetm0_channel_range(range[0], range[1]); ++ qman_seed_ceetm0_channel_range(be32_to_cpu(range[0]), be32_to_cpu(range[1])); + if (dcp_portal == qm_dc_portal_fman1) +- qman_seed_ceetm1_channel_range(range[0], range[1]); ++ qman_seed_ceetm1_channel_range(be32_to_cpu(range[0]), be32_to_cpu(range[1])); + pr_debug("Qman: The channel allocator of CEETM %d includes" +- " range %d:%d\n", dcp_portal, range[0], range[1]); ++ " range %d:%d\n", dcp_portal, be32_to_cpu(range[0]), be32_to_cpu(range[1])); + + /* Set CEETM PRES register */ + ret = qman_ceetm_set_prescaler(dcp_portal); +@@ -341,6 +341,11 @@ static void qman_get_ip_revision(struct device_node *dn) + ip_rev = QMAN_REV31; + qman_portal_max = 10; + ip_cfg = QMAN_REV_CFG_3; ++ } else if (of_device_is_compatible(dn, ++ "fsl,qman-portal-3.2.0")) { ++ ip_rev = QMAN_REV32; ++ qman_portal_max = 10; ++ ip_cfg = QMAN_REV_CFG_3; // TODO: Verify for ls1043 + } else { + pr_warn("unknown QMan version in portal node," + "default to rev1.1\n"); +@@ -373,7 +378,8 @@ static void qman_get_ip_revision(struct device_node *dn) + static struct qm_portal_config * __init parse_pcfg(struct device_node *node) + { + struct qm_portal_config *pcfg; +- const u32 *index, *channel; ++ const u32 *index_p, *channel_p; ++ u32 index, channel; + int irq, ret; + resource_size_t len; + +@@ -393,7 +399,7 @@ static struct qm_portal_config * __init parse_pcfg(struct device_node *node) + */ + pcfg->dev.bus = &platform_bus_type; + pcfg->dev.of_node = node; +-#ifdef CONFIG_IOMMU_API ++#ifdef CONFIG_FSL_PAMU + pcfg->dev.archdata.iommu_domain = NULL; + #endif + +@@ -411,34 +417,39 @@ static struct qm_portal_config * __init parse_pcfg(struct device_node *node) + "reg::CI"); + goto err; + } +- index = of_get_property(node, "cell-index", &ret); +- if (!index || (ret != 4)) { ++ index_p = of_get_property(node, "cell-index", &ret); ++ if (!index_p || (ret != 4)) { + pr_err("Can't get %s property '%s'\n", node->full_name, + "cell-index"); + goto err; + } +- if (*index >= qman_portal_max) ++ index = be32_to_cpu(*index_p); ++ if (index >= qman_portal_max) { ++ pr_err("QMan portal index %d is beyond max (%d)\n", ++ index, qman_portal_max); + goto err; ++ } + +- channel = of_get_property(node, "fsl,qman-channel-id", &ret); +- if (!channel || (ret != 4)) { ++ channel_p = of_get_property(node, "fsl,qman-channel-id", &ret); ++ if (!channel_p || (ret != 4)) { + pr_err("Can't get %s property '%s'\n", node->full_name, + "fsl,qman-channel-id"); + goto err; + } +- if (*channel != (*index + QM_CHANNEL_SWPORTAL0)) ++ channel = be32_to_cpu(*channel_p); ++ if (channel != (index + QM_CHANNEL_SWPORTAL0)) + pr_err("Warning: node %s has mismatched %s and %s\n", + node->full_name, "cell-index", "fsl,qman-channel-id"); +- pcfg->public_cfg.channel = *channel; ++ pcfg->public_cfg.channel = channel; + pcfg->public_cfg.cpu = -1; + irq = irq_of_parse_and_map(node, 0); +- if (irq == NO_IRQ) { ++ if (irq == 0) { + pr_err("Can't get %s property '%s'\n", node->full_name, + "interrupts"); + goto err; + } + pcfg->public_cfg.irq = irq; +- pcfg->public_cfg.index = *index; ++ pcfg->public_cfg.index = index; + #ifdef CONFIG_FSL_QMAN_CONFIG + /* We need the same LIODN offset for all portals */ + qman_liodn_fixup(pcfg->public_cfg.channel); +@@ -447,6 +458,16 @@ static struct qm_portal_config * __init parse_pcfg(struct device_node *node) + len = resource_size(&pcfg->addr_phys[DPA_PORTAL_CE]); + if (len != (unsigned long)len) + goto err; ++ ++#ifdef CONFIG_ARM64 ++ pcfg->addr_virt[DPA_PORTAL_CE] = ioremap_cache_ns( ++ pcfg->addr_phys[DPA_PORTAL_CE].start, ++ resource_size(&pcfg->addr_phys[DPA_PORTAL_CE])); ++ ++ pcfg->addr_virt[DPA_PORTAL_CI] = ioremap( ++ pcfg->addr_phys[DPA_PORTAL_CI].start, ++ resource_size(&pcfg->addr_phys[DPA_PORTAL_CI])); ++#else + pcfg->addr_virt[DPA_PORTAL_CE] = ioremap_prot( + pcfg->addr_phys[DPA_PORTAL_CE].start, + (unsigned long)len, +@@ -455,7 +476,7 @@ static struct qm_portal_config * __init parse_pcfg(struct device_node *node) + pcfg->addr_phys[DPA_PORTAL_CI].start, + resource_size(&pcfg->addr_phys[DPA_PORTAL_CI]), + _PAGE_GUARDED | _PAGE_NO_CACHE); +- ++#endif + return pcfg; + err: + kfree(pcfg); +@@ -674,9 +695,9 @@ static void qman_portal_update_sdest(const struct qm_portal_config *pcfg, + return; + } + } ++#endif + #ifdef CONFIG_FSL_QMAN_CONFIG + if (qman_set_sdest(pcfg->public_cfg.channel, cpu)) +-#endif + pr_warn("Failed to update portal's stash request queue\n"); + #endif + } +@@ -775,6 +796,7 @@ __init int qman_init(void) + qm_channel_caam = QMAN_CHANNEL_CAAM_REV3; + qm_channel_pme = QMAN_CHANNEL_PME_REV3; + } ++ + if ((qman_ip_rev == QMAN_REV31) && (qman_ip_cfg == QMAN_REV_CFG_2)) + qm_channel_dce = QMAN_CHANNEL_DCE_QMANREV312; + +@@ -827,7 +849,7 @@ __init int qman_init(void) + } + } + if (list_empty(&shared_pcfgs) && list_empty(&unshared_pcfgs)) { +- for_each_possible_cpu(cpu) { ++ for_each_online_cpu(cpu) { + pcfg = get_pcfg(&unused_pcfgs); + if (!pcfg) + break; +diff --git a/drivers/staging/fsl_qbman/qman_high.c b/drivers/staging/fsl_qbman/qman_high.c +index 580adb0..c13d0ee 100644 +--- a/drivers/staging/fsl_qbman/qman_high.c ++++ b/drivers/staging/fsl_qbman/qman_high.c +@@ -125,6 +125,15 @@ struct qman_portal { + u8 alloced; + /* power management data */ + u32 save_isdr; ++#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ++ /* Keep a shadow copy of the DQRR on LE systems ++ as the SW needs to do byteswaps of read only ++ memory. Must be aligned to the size of the ++ ring to ensure easy index calcualtions based ++ on address */ ++ struct qm_dqrr_entry shadow_dqrr[QM_DQRR_SIZE] ++ __attribute__((aligned(512))); ++#endif + }; + + #ifdef CONFIG_FSL_DPA_PORTAL_SHARE +@@ -281,6 +290,103 @@ static inline struct qman_fq *get_fq_table_entry(u32 entry) + } + #endif + ++static inline void cpu_to_hw_fqd(struct qm_fqd *fqd) ++{ ++ /* Byteswap the FQD to HW format */ ++ fqd->fq_ctrl = cpu_to_be16(fqd->fq_ctrl); ++ fqd->dest_wq = cpu_to_be16(fqd->dest_wq); ++ fqd->ics_cred = cpu_to_be16(fqd->ics_cred); ++ fqd->context_b = cpu_to_be32(fqd->context_b); ++ fqd->context_a.opaque = cpu_to_be64(fqd->context_a.opaque); ++} ++ ++static inline void hw_fqd_to_cpu(struct qm_fqd *fqd) ++{ ++ /* Byteswap the FQD to CPU format */ ++ fqd->fq_ctrl = be16_to_cpu(fqd->fq_ctrl); ++ fqd->dest_wq = be16_to_cpu(fqd->dest_wq); ++ fqd->ics_cred = be16_to_cpu(fqd->ics_cred); ++ fqd->context_b = be32_to_cpu(fqd->context_b); ++ fqd->context_a.opaque = be64_to_cpu(fqd->context_a.opaque); ++} ++ ++/* Swap a 40 bit address */ ++static inline u64 cpu_to_be40(u64 in) ++{ ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++ return in; ++#else ++ u64 out = 0; ++ u8 *p = (u8 *) &out; ++ p[0] = in >> 32; ++ p[1] = in >> 24; ++ p[2] = in >> 16; ++ p[3] = in >> 8; ++ p[4] = in >> 0; ++ return out; ++#endif ++} ++static inline u64 be40_to_cpu(u64 in) ++{ ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++ return in; ++#else ++ u64 out = 0; ++ u8 *pout = (u8 *) &out; ++ u8 *pin = (u8 *) ∈ ++ pout[0] = pin[4]; ++ pout[1] = pin[3]; ++ pout[2] = pin[2]; ++ pout[3] = pin[1]; ++ pout[4] = pin[0]; ++ return out; ++#endif ++} ++ ++/* Swap a 24 bit value */ ++static inline u32 cpu_to_be24(u32 in) ++{ ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++ return in; ++#else ++ u32 out = 0; ++ u8 *p = (u8 *) &out; ++ p[0] = in >> 16; ++ p[1] = in >> 8; ++ p[2] = in >> 0; ++ return out; ++#endif ++} ++ ++static inline u32 be24_to_cpu(u32 in) ++{ ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++ return in; ++#else ++ u32 out = 0; ++ u8 *pout = (u8 *) &out; ++ u8 *pin = (u8 *) ∈ ++ pout[0] = pin[2]; ++ pout[1] = pin[1]; ++ pout[2] = pin[0]; ++ return out; ++#endif ++} ++ ++static inline void cpu_to_hw_fd(struct qm_fd *fd) ++{ ++ fd->addr = cpu_to_be40(fd->addr); ++ fd->status = cpu_to_be32(fd->status); ++ fd->opaque = cpu_to_be32(fd->opaque); ++} ++ ++static inline void hw_fd_to_cpu(struct qm_fd *fd) ++{ ++ fd->addr = be40_to_cpu(fd->addr); ++ fd->status = be32_to_cpu(fd->status); ++ fd->opaque = be32_to_cpu(fd->opaque); ++} ++ + /* In the case that slow- and fast-path handling are both done by qman_poll() + * (ie. because there is no interrupt handling), we ought to balance how often + * we do the fast-path poll versus the slow-path poll. We'll use two decrementer +@@ -500,15 +606,21 @@ struct qman_portal *qman_create_portal( + portal->cb_dc_ern = NULL; + sprintf(buf, "qportal-%d", config->public_cfg.channel); + portal->pdev = platform_device_alloc(buf, -1); +- if (!portal->pdev) ++ if (!portal->pdev) { ++ pr_err("qman_portal - platform_device_alloc() failed\n"); + goto fail_devalloc; +- if (dma_set_mask(&portal->pdev->dev, DMA_BIT_MASK(40))) ++ } ++ if (dma_set_mask(&portal->pdev->dev, DMA_BIT_MASK(40))) { ++ pr_err("qman_portal - dma_set_mask() failed\n"); + goto fail_devadd; ++ } + portal->pdev->dev.pm_domain = &qman_portal_device_pm_domain; + portal->pdev->dev.platform_data = portal; + ret = platform_device_add(portal->pdev); +- if (ret) ++ if (ret) { ++ pr_err("qman_portal - platform_device_add() failed\n"); + goto fail_devadd; ++ } + dpa_rbtree_init(&portal->retire_table); + isdr = 0xffffffff; + qm_isr_disable_write(__p, isdr); +@@ -858,7 +970,7 @@ mr_loop: + case QM_MR_VERB_FQRN: + case QM_MR_VERB_FQRL: + /* Lookup in the retirement table */ +- fq = table_find_fq(p, msg->fq.fqid); ++ fq = table_find_fq(p, be32_to_cpu(msg->fq.fqid)); + BUG_ON(!fq); + fq_state_change(p, fq, msg, verb); + if (fq->cb.fqs) +@@ -867,9 +979,11 @@ mr_loop: + case QM_MR_VERB_FQPN: + /* Parked */ + #ifdef CONFIG_FSL_QMAN_FQ_LOOKUP +- fq = get_fq_table_entry(msg->fq.contextB); ++ fq = get_fq_table_entry( ++ be32_to_cpu(msg->fq.contextB)); + #else +- fq = (void *)(uintptr_t)msg->fq.contextB; ++ fq = (void *)(uintptr_t) ++ be32_to_cpu(msg->fq.contextB); + #endif + fq_state_change(p, fq, msg, verb); + if (fq->cb.fqs) +@@ -895,9 +1009,10 @@ mr_loop: + } else { + /* Its a software ERN */ + #ifdef CONFIG_FSL_QMAN_FQ_LOOKUP +- fq = get_fq_table_entry(msg->ern.tag); ++ pr_info("ROY\n"); ++ fq = get_fq_table_entry(be32_to_cpu(msg->ern.tag)); + #else +- fq = (void *)(uintptr_t)msg->ern.tag; ++ fq = (void *)(uintptr_t)be32_to_cpu(msg->ern.tag); + #endif + fq->cb.ern(p, fq, msg); + } +@@ -960,12 +1075,27 @@ static inline unsigned int __poll_portal_fast(struct qman_portal *p, + struct qman_fq *fq; + enum qman_cb_dqrr_result res; + unsigned int limit = 0; +- ++#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ++ struct qm_dqrr_entry *shadow; ++#endif + loop: + qm_dqrr_pvb_update(&p->p); + dq = qm_dqrr_current(&p->p); + if (!dq) + goto done; ++#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ++ /* If running on an LE system the fields of the ++ dequeue entry must be swapped. Because the ++ QMan HW will ignore writes the DQRR entry is ++ copied and the index stored within the copy */ ++ shadow = &p->shadow_dqrr[DQRR_PTR2IDX(dq)]; ++ *shadow = *dq; ++ dq = shadow; ++ shadow->fqid = be32_to_cpu(shadow->fqid); ++ shadow->contextB = be32_to_cpu(shadow->contextB); ++ shadow->seqnum = be16_to_cpu(shadow->seqnum); ++ hw_fd_to_cpu(&shadow->fd); ++#endif + if (dq->stat & QM_DQRR_STAT_UNSCHEDULED) { + /* VDQCR: don't trust contextB as the FQ may have been + * configured for h/w consumption and we're draining it +@@ -994,6 +1124,7 @@ loop: + #endif + /* Now let the callback do its stuff */ + res = fq->cb.dqrr(p, fq, dq); ++ + /* The callback can request that we exit without consuming this + * entry nor advancing; */ + if (res == qman_cb_dqrr_stop) +@@ -1082,6 +1213,7 @@ int qman_p_irqsource_remove(struct qman_portal *p, u32 bits) + bits &= QM_PIRQ_VISIBLE; + clear_bits(bits, &p->irq_sources); + qm_isr_enable_write(&p->p, p->irq_sources); ++ + ier = qm_isr_enable_read(&p->p); + /* Using "~ier" (rather than "bits" or "~p->irq_sources") creates a + * data-dependency, ie. to protect against re-ordering. */ +@@ -1368,7 +1500,7 @@ int qman_create_fq(u32 fqid, u32 flags, struct qman_fq *fq) + p = get_affine_portal(); + PORTAL_IRQ_LOCK(p, irqflags); + mcc = qm_mc_start(&p->p); +- mcc->queryfq.fqid = fqid; ++ mcc->queryfq.fqid = cpu_to_be32(fqid); + qm_mc_commit(&p->p, QM_MCC_VERB_QUERYFQ); + while (!(mcr = qm_mc_result(&p->p))) + cpu_relax(); +@@ -1378,8 +1510,9 @@ int qman_create_fq(u32 fqid, u32 flags, struct qman_fq *fq) + goto err; + } + fqd = mcr->queryfq.fqd; ++ hw_fqd_to_cpu(&fqd); + mcc = qm_mc_start(&p->p); +- mcc->queryfq_np.fqid = fqid; ++ mcc->queryfq_np.fqid = cpu_to_be32(fqid); + qm_mc_commit(&p->p, QM_MCC_VERB_QUERYFQ_NP); + while (!(mcr = qm_mc_result(&p->p))) + cpu_relax(); +@@ -1500,8 +1633,9 @@ int qman_init_fq(struct qman_fq *fq, u32 flags, struct qm_mcc_initfq *opts) + mcc = qm_mc_start(&p->p); + if (opts) + mcc->initfq = *opts; +- mcc->initfq.fqid = fq->fqid; ++ mcc->initfq.fqid = cpu_to_be32(fq->fqid); + mcc->initfq.count = 0; ++ + /* If the FQ does *not* have the TO_DCPORTAL flag, contextB is set as a + * demux pointer. Otherwise, the caller-provided value is allowed to + * stand, don't overwrite it. */ +@@ -1532,6 +1666,8 @@ int qman_init_fq(struct qman_fq *fq, u32 flags, struct qm_mcc_initfq *opts) + mcc->initfq.fqd.dest.wq = 4; + } + } ++ mcc->initfq.we_mask = cpu_to_be16(mcc->initfq.we_mask); ++ cpu_to_hw_fqd(&mcc->initfq.fqd); + qm_mc_commit(&p->p, myverb); + while (!(mcr = qm_mc_result(&p->p))) + cpu_relax(); +@@ -1587,7 +1723,7 @@ int qman_schedule_fq(struct qman_fq *fq) + goto out; + } + mcc = qm_mc_start(&p->p); +- mcc->alterfq.fqid = fq->fqid; ++ mcc->alterfq.fqid = cpu_to_be32(fq->fqid); + qm_mc_commit(&p->p, QM_MCC_VERB_ALTER_SCHED); + while (!(mcr = qm_mc_result(&p->p))) + cpu_relax(); +@@ -1635,7 +1771,7 @@ int qman_retire_fq(struct qman_fq *fq, u32 *flags) + if (rval) + goto out; + mcc = qm_mc_start(&p->p); +- mcc->alterfq.fqid = fq->fqid; ++ mcc->alterfq.fqid = cpu_to_be32(fq->fqid); + qm_mc_commit(&p->p, QM_MCC_VERB_ALTER_RETIRE); + while (!(mcr = qm_mc_result(&p->p))) + cpu_relax(); +@@ -1718,7 +1854,7 @@ int qman_oos_fq(struct qman_fq *fq) + goto out; + } + mcc = qm_mc_start(&p->p); +- mcc->alterfq.fqid = fq->fqid; ++ mcc->alterfq.fqid = cpu_to_be32(fq->fqid); + qm_mc_commit(&p->p, QM_MCC_VERB_ALTER_OOS); + while (!(mcr = qm_mc_result(&p->p))) + cpu_relax(); +@@ -1800,14 +1936,15 @@ int qman_query_fq(struct qman_fq *fq, struct qm_fqd *fqd) + + PORTAL_IRQ_LOCK(p, irqflags); + mcc = qm_mc_start(&p->p); +- mcc->queryfq.fqid = fq->fqid; ++ mcc->queryfq.fqid = cpu_to_be32(fq->fqid); + qm_mc_commit(&p->p, QM_MCC_VERB_QUERYFQ); + while (!(mcr = qm_mc_result(&p->p))) + cpu_relax(); + DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ); + res = mcr->result; + if (res == QM_MCR_RESULT_OK) +- *fqd = mcr->queryfq.fqd; ++ memcpy_fromio(fqd, &mcr->queryfq.fqd, sizeof(*fqd)); ++ hw_fqd_to_cpu(fqd); + PORTAL_IRQ_UNLOCK(p, irqflags); + put_affine_portal(); + if (res != QM_MCR_RESULT_OK) +@@ -1826,14 +1963,35 @@ int qman_query_fq_np(struct qman_fq *fq, struct qm_mcr_queryfq_np *np) + + PORTAL_IRQ_LOCK(p, irqflags); + mcc = qm_mc_start(&p->p); +- mcc->queryfq.fqid = fq->fqid; ++ mcc->queryfq.fqid = cpu_to_be32(fq->fqid); + qm_mc_commit(&p->p, QM_MCC_VERB_QUERYFQ_NP); + while (!(mcr = qm_mc_result(&p->p))) + cpu_relax(); + DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ_NP); + res = mcr->result; +- if (res == QM_MCR_RESULT_OK) +- *np = mcr->queryfq_np; ++ if (res == QM_MCR_RESULT_OK) { ++ memcpy_fromio(np, &mcr->queryfq_np, sizeof(*np)); ++ np->fqd_link = be24_to_cpu(np->fqd_link); ++ np->odp_seq = be16_to_cpu(np->odp_seq); ++ np->orp_nesn = be16_to_cpu(np->orp_nesn); ++ np->orp_ea_hseq = be16_to_cpu(np->orp_ea_hseq); ++ np->orp_ea_tseq = be16_to_cpu(np->orp_ea_tseq); ++ np->orp_ea_hptr = be24_to_cpu(np->orp_ea_hptr); ++ np->orp_ea_tptr = be24_to_cpu(np->orp_ea_tptr); ++ np->pfdr_hptr = be24_to_cpu(np->pfdr_hptr); ++ np->pfdr_tptr = be24_to_cpu(np->pfdr_tptr); ++ np->ics_surp = be16_to_cpu(np->ics_surp); ++ np->byte_cnt = be32_to_cpu(np->byte_cnt); ++ np->frm_cnt = be24_to_cpu(np->frm_cnt); ++ np->ra1_sfdr = be16_to_cpu(np->ra1_sfdr); ++ np->ra2_sfdr = be16_to_cpu(np->ra2_sfdr); ++ np->od1_sfdr = be16_to_cpu(np->od1_sfdr); ++ np->od2_sfdr = be16_to_cpu(np->od2_sfdr); ++ np->od3_sfdr = be16_to_cpu(np->od3_sfdr); ++ ++ ++ } ++ + PORTAL_IRQ_UNLOCK(p, irqflags); + put_affine_portal(); + if (res == QM_MCR_RESULT_ERR_FQID) +@@ -1863,7 +2021,7 @@ int qman_query_wq(u8 query_dedicated, struct qm_mcr_querywq *wq) + DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == myverb); + res = mcr->result; + if (res == QM_MCR_RESULT_OK) +- *wq = mcr->querywq; ++ memcpy_fromio(wq, &mcr->querywq, sizeof(*wq)); + PORTAL_IRQ_UNLOCK(p, irqflags); + put_affine_portal(); + if (res != QM_MCR_RESULT_OK) { +@@ -1894,7 +2052,7 @@ int qman_testwrite_cgr(struct qman_cgr *cgr, u64 i_bcnt, + DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_CGRTESTWRITE); + res = mcr->result; + if (res == QM_MCR_RESULT_OK) +- *result = mcr->cgrtestwrite; ++ memcpy_fromio(result, &mcr->cgrtestwrite, sizeof(*result)); + PORTAL_IRQ_UNLOCK(p, irqflags); + put_affine_portal(); + if (res != QM_MCR_RESULT_OK) { +@@ -1912,6 +2070,7 @@ int qman_query_cgr(struct qman_cgr *cgr, struct qm_mcr_querycgr *cgrd) + struct qman_portal *p = get_affine_portal(); + unsigned long irqflags __maybe_unused; + u8 res; ++ int i; + + PORTAL_IRQ_LOCK(p, irqflags); + mcc = qm_mc_start(&p->p); +@@ -1922,13 +2081,23 @@ int qman_query_cgr(struct qman_cgr *cgr, struct qm_mcr_querycgr *cgrd) + DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYCGR); + res = mcr->result; + if (res == QM_MCR_RESULT_OK) +- *cgrd = mcr->querycgr; ++ memcpy_fromio(cgrd, &mcr->querycgr, sizeof(*cgrd)); + PORTAL_IRQ_UNLOCK(p, irqflags); + put_affine_portal(); + if (res != QM_MCR_RESULT_OK) { + pr_err("QUERY_CGR failed: %s\n", mcr_result_str(res)); + return -EIO; + } ++ cgrd->cgr.wr_parm_g.word = ++ be32_to_cpu(cgrd->cgr.wr_parm_g.word); ++ cgrd->cgr.wr_parm_y.word = ++ be32_to_cpu(cgrd->cgr.wr_parm_y.word); ++ cgrd->cgr.wr_parm_r.word = ++ be32_to_cpu(cgrd->cgr.wr_parm_r.word); ++ cgrd->cgr.cscn_targ = be32_to_cpu(cgrd->cgr.cscn_targ); ++ cgrd->cgr.__cs_thres = be16_to_cpu(cgrd->cgr.__cs_thres); ++ for (i = 0; i < ARRAY_SIZE(cgrd->cscn_targ_swp); i++) ++ be32_to_cpus(&cgrd->cscn_targ_swp[i]); + return 0; + } + EXPORT_SYMBOL(qman_query_cgr); +@@ -1939,6 +2108,7 @@ int qman_query_congestion(struct qm_mcr_querycongestion *congestion) + struct qman_portal *p = get_affine_portal(); + unsigned long irqflags __maybe_unused; + u8 res; ++ int i; + + PORTAL_IRQ_LOCK(p, irqflags); + qm_mc_start(&p->p); +@@ -1949,13 +2119,17 @@ int qman_query_congestion(struct qm_mcr_querycongestion *congestion) + QM_MCC_VERB_QUERYCONGESTION); + res = mcr->result; + if (res == QM_MCR_RESULT_OK) +- *congestion = mcr->querycongestion; ++ memcpy_fromio(congestion, &mcr->querycongestion, ++ sizeof(*congestion)); + PORTAL_IRQ_UNLOCK(p, irqflags); + put_affine_portal(); + if (res != QM_MCR_RESULT_OK) { + pr_err("QUERY_CONGESTION failed: %s\n", mcr_result_str(res)); + return -EIO; + } ++ ++ for (i = 0; i < ARRAY_SIZE(congestion->state.__state); i++) ++ be32_to_cpus(&congestion->state.__state[i]); + return 0; + } + EXPORT_SYMBOL(qman_query_congestion); +@@ -2185,13 +2359,14 @@ static inline struct qm_eqcr_entry *try_p_eq_start(struct qman_portal *p, + ((flags & QMAN_ENQUEUE_FLAG_DCA_PARK) ? + QM_EQCR_DCA_PARK : 0) | + ((flags >> 8) & QM_EQCR_DCA_IDXMASK); +- eq->fqid = fq->fqid; ++ eq->fqid = cpu_to_be32(fq->fqid); + #ifdef CONFIG_FSL_QMAN_FQ_LOOKUP +- eq->tag = fq->key; ++ eq->tag = cpu_to_be32(fq->key); + #else +- eq->tag = (u32)(uintptr_t)fq; ++ eq->tag = cpu_to_be32((u32)(uintptr_t)fq); + #endif + eq->fd = *fd; ++ cpu_to_hw_fd(&eq->fd); + return eq; + } + +@@ -2365,8 +2540,8 @@ int qman_p_enqueue_orp(struct qman_portal *p, struct qman_fq *fq, + /* No need to check 4 QMAN_ENQUEUE_FLAG_HOLE */ + orp_seqnum &= ~QM_EQCR_SEQNUM_NESN; + } +- eq->seqnum = orp_seqnum; +- eq->orp = orp->fqid; ++ eq->seqnum = cpu_to_be16(orp_seqnum); ++ eq->orp = cpu_to_be32(orp->fqid); + /* Note: QM_EQCR_VERB_INTERRUPT == QMAN_ENQUEUE_FLAG_WAIT_SYNC */ + qm_eqcr_pvb_commit(&p->p, QM_EQCR_VERB_ORP | + ((flags & (QMAN_ENQUEUE_FLAG_HOLE | QMAN_ENQUEUE_FLAG_NESN)) ? +@@ -2415,8 +2590,8 @@ int qman_enqueue_orp(struct qman_fq *fq, const struct qm_fd *fd, u32 flags, + /* No need to check 4 QMAN_ENQUEUE_FLAG_HOLE */ + orp_seqnum &= ~QM_EQCR_SEQNUM_NESN; + } +- eq->seqnum = orp_seqnum; +- eq->orp = orp->fqid; ++ eq->seqnum = cpu_to_be16(orp_seqnum); ++ eq->orp = cpu_to_be32(orp->fqid); + /* Note: QM_EQCR_VERB_INTERRUPT == QMAN_ENQUEUE_FLAG_WAIT_SYNC */ + qm_eqcr_pvb_commit(&p->p, QM_EQCR_VERB_ORP | + ((flags & (QMAN_ENQUEUE_FLAG_HOLE | QMAN_ENQUEUE_FLAG_NESN)) ? +@@ -2538,6 +2713,16 @@ int qman_modify_cgr(struct qman_cgr *cgr, u32 flags, + mcc = qm_mc_start(&p->p); + if (opts) + mcc->initcgr = *opts; ++ mcc->initcgr.we_mask = cpu_to_be16(mcc->initcgr.we_mask); ++ mcc->initcgr.cgr.wr_parm_g.word = ++ cpu_to_be32(mcc->initcgr.cgr.wr_parm_g.word); ++ mcc->initcgr.cgr.wr_parm_y.word = ++ cpu_to_be32(mcc->initcgr.cgr.wr_parm_y.word); ++ mcc->initcgr.cgr.wr_parm_r.word = ++ cpu_to_be32(mcc->initcgr.cgr.wr_parm_r.word); ++ mcc->initcgr.cgr.cscn_targ = cpu_to_be32(mcc->initcgr.cgr.cscn_targ); ++ mcc->initcgr.cgr.__cs_thres = cpu_to_be16(mcc->initcgr.cgr.__cs_thres); ++ + mcc->initcgr.cgid = cgr->cgrid; + if (flags & QMAN_CGR_FLAG_USE_INIT) + verb = QM_MCC_VERB_INITCGR; +diff --git a/drivers/staging/fsl_qbman/qman_low.h b/drivers/staging/fsl_qbman/qman_low.h +index 6ac7ecd..9b76b56 100644 +--- a/drivers/staging/fsl_qbman/qman_low.h ++++ b/drivers/staging/fsl_qbman/qman_low.h +@@ -36,6 +36,8 @@ + /***************************/ + + /* Cache-inhibited register offsets */ ++#if defined(CONFIG_PPC32) || defined(CONFIG_PPC64) ++ + #define QM_REG_EQCR_PI_CINH 0x0000 + #define QM_REG_EQCR_CI_CINH 0x0004 + #define QM_REG_EQCR_ITR 0x0008 +@@ -68,6 +70,45 @@ + #define QM_CL_RR0 0x3900 + #define QM_CL_RR1 0x3940 + ++#endif ++ ++#if defined(CONFIG_ARM64) ++ ++#define QM_REG_EQCR_PI_CINH 0x3000 ++#define QM_REG_EQCR_CI_CINH 0x3040 ++#define QM_REG_EQCR_ITR 0x3080 ++#define QM_REG_DQRR_PI_CINH 0x3100 ++#define QM_REG_DQRR_CI_CINH 0x3140 ++#define QM_REG_DQRR_ITR 0x3180 ++#define QM_REG_DQRR_DCAP 0x31C0 ++#define QM_REG_DQRR_SDQCR 0x3200 ++#define QM_REG_DQRR_VDQCR 0x3240 ++#define QM_REG_DQRR_PDQCR 0x3280 ++#define QM_REG_MR_PI_CINH 0x3300 ++#define QM_REG_MR_CI_CINH 0x3340 ++#define QM_REG_MR_ITR 0x3380 ++#define QM_REG_CFG 0x3500 ++#define QM_REG_ISR 0x3600 ++#define QM_REG_IIR 0x36C0 ++#define QM_REG_ITPR 0x3740 ++ ++/* Cache-enabled register offsets */ ++#define QM_CL_EQCR 0x0000 ++#define QM_CL_DQRR 0x1000 ++#define QM_CL_MR 0x2000 ++#define QM_CL_EQCR_PI_CENA 0x3000 ++#define QM_CL_EQCR_CI_CENA 0x3040 ++#define QM_CL_DQRR_PI_CENA 0x3100 ++#define QM_CL_DQRR_CI_CENA 0x3140 ++#define QM_CL_MR_PI_CENA 0x3300 ++#define QM_CL_MR_CI_CENA 0x3340 ++#define QM_CL_CR 0x3800 ++#define QM_CL_RR0 0x3900 ++#define QM_CL_RR1 0x3940 ++ ++#endif ++ ++ + /* BTW, the drivers (and h/w programming model) already obtain the required + * synchronisation for portal accesses via lwsync(), hwsync(), and + * data-dependencies. Use of barrier()s or other order-preserving primitives +@@ -76,19 +117,20 @@ + * non-coherent). */ + + /* Cache-inhibited register access. */ +-#define __qm_in(qm, o) __raw_readl((qm)->addr_ci + (o)) +-#define __qm_out(qm, o, val) __raw_writel((val), (qm)->addr_ci + (o)) ++#define __qm_in(qm, o) be32_to_cpu(__raw_readl((qm)->addr_ci + (o))) ++#define __qm_out(qm, o, val) __raw_writel((cpu_to_be32(val)), \ ++ (qm)->addr_ci + (o)); + #define qm_in(reg) __qm_in(&portal->addr, QM_REG_##reg) + #define qm_out(reg, val) __qm_out(&portal->addr, QM_REG_##reg, val) + + /* Cache-enabled (index) register access */ + #define __qm_cl_touch_ro(qm, o) dcbt_ro((qm)->addr_ce + (o)) + #define __qm_cl_touch_rw(qm, o) dcbt_rw((qm)->addr_ce + (o)) +-#define __qm_cl_in(qm, o) __raw_readl((qm)->addr_ce + (o)) ++#define __qm_cl_in(qm, o) be32_to_cpu(__raw_readl((qm)->addr_ce + (o))) + #define __qm_cl_out(qm, o, val) \ + do { \ + u32 *__tmpclout = (qm)->addr_ce + (o); \ +- __raw_writel((val), __tmpclout); \ ++ __raw_writel(cpu_to_be32(val), __tmpclout); \ + dcbf(__tmpclout); \ + } while (0) + #define __qm_cl_invalidate(qm, o) dcbi((qm)->addr_ce + (o)) +@@ -1131,13 +1173,21 @@ static inline void qm_isr_set_iperiod(struct qm_portal *portal, u16 iperiod) + + static inline u32 __qm_isr_read(struct qm_portal *portal, enum qm_isr_reg n) + { ++#if defined(CONFIG_ARM64) ++ return __qm_in(&portal->addr, QM_REG_ISR + (n << 6)); ++#else + return __qm_in(&portal->addr, QM_REG_ISR + (n << 2)); ++#endif + } + + static inline void __qm_isr_write(struct qm_portal *portal, enum qm_isr_reg n, + u32 val) + { ++#if defined(CONFIG_ARM64) ++ __qm_out(&portal->addr, QM_REG_ISR + (n << 6), val); ++#else + __qm_out(&portal->addr, QM_REG_ISR + (n << 2), val); ++#endif + } + + /* Cleanup FQs */ +@@ -1151,10 +1201,11 @@ static inline int qm_shutdown_fq(struct qm_portal **portal, int portal_count, + int orl_empty, fq_empty, i, drain = 0; + u32 result; + u32 channel, wq; ++ u16 dest_wq; + + /* Determine the state of the FQID */ + mcc = qm_mc_start(portal[0]); +- mcc->queryfq_np.fqid = fqid; ++ mcc->queryfq_np.fqid = cpu_to_be32(fqid); + qm_mc_commit(portal[0], QM_MCC_VERB_QUERYFQ_NP); + while (!(mcr = qm_mc_result(portal[0]))) + cpu_relax(); +@@ -1165,15 +1216,16 @@ static inline int qm_shutdown_fq(struct qm_portal **portal, int portal_count, + + /* Query which channel the FQ is using */ + mcc = qm_mc_start(portal[0]); +- mcc->queryfq.fqid = fqid; ++ mcc->queryfq.fqid = cpu_to_be32(fqid); + qm_mc_commit(portal[0], QM_MCC_VERB_QUERYFQ); + while (!(mcr = qm_mc_result(portal[0]))) + cpu_relax(); + DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ); + + /* Need to store these since the MCR gets reused */ +- channel = mcr->queryfq.fqd.dest.channel; +- wq = mcr->queryfq.fqd.dest.wq; ++ dest_wq = be16_to_cpu(mcr->queryfq.fqd.dest_wq); ++ channel = dest_wq & 0x7; ++ wq = dest_wq>>3; + + switch (state) { + case QM_MCR_NP_STATE_TEN_SCHED: +@@ -1182,7 +1234,7 @@ static inline int qm_shutdown_fq(struct qm_portal **portal, int portal_count, + case QM_MCR_NP_STATE_PARKED: + orl_empty = 0; + mcc = qm_mc_start(portal[0]); +- mcc->alterfq.fqid = fqid; ++ mcc->alterfq.fqid = cpu_to_be32(fqid); + qm_mc_commit(portal[0], QM_MCC_VERB_ALTER_RETIRE); + while (!(mcr = qm_mc_result(portal[0]))) + cpu_relax(); +@@ -1324,7 +1376,7 @@ static inline int qm_shutdown_fq(struct qm_portal **portal, int portal_count, + cpu_relax(); + } + mcc = qm_mc_start(portal[0]); +- mcc->alterfq.fqid = fqid; ++ mcc->alterfq.fqid = cpu_to_be32(fqid); + qm_mc_commit(portal[0], QM_MCC_VERB_ALTER_OOS); + while (!(mcr = qm_mc_result(portal[0]))) + cpu_relax(); +@@ -1339,7 +1391,7 @@ static inline int qm_shutdown_fq(struct qm_portal **portal, int portal_count, + case QM_MCR_NP_STATE_RETIRED: + /* Send OOS Command */ + mcc = qm_mc_start(portal[0]); +- mcc->alterfq.fqid = fqid; ++ mcc->alterfq.fqid = cpu_to_be32(fqid); + qm_mc_commit(portal[0], QM_MCC_VERB_ALTER_OOS); + while (!(mcr = qm_mc_result(portal[0]))) + cpu_relax(); +diff --git a/drivers/staging/fsl_qbman/qman_private.h b/drivers/staging/fsl_qbman/qman_private.h +index e9f60d5..e35a5bb 100644 +--- a/drivers/staging/fsl_qbman/qman_private.h ++++ b/drivers/staging/fsl_qbman/qman_private.h +@@ -32,7 +32,10 @@ + #include "dpa_sys.h" + #include + #include ++ ++#if defined(CONFIG_FSL_PAMU) + #include ++#endif + + #if !defined(CONFIG_FSL_QMAN_FQ_LOOKUP) && defined(CONFIG_PPC64) + #error "_PPC64 requires _FSL_QMAN_FQ_LOOKUP" +@@ -193,6 +196,8 @@ struct qm_portal_config { + #define QMAN_REV20 0x0200 + #define QMAN_REV30 0x0300 + #define QMAN_REV31 0x0301 ++#define QMAN_REV32 0x0302 ++ + /* QMan REV_2 register contains the Cfg option */ + #define QMAN_REV_CFG_0 0x0 + #define QMAN_REV_CFG_1 0x1 +diff --git a/drivers/staging/fsl_qbman/qman_test.h b/drivers/staging/fsl_qbman/qman_test.h +index 49c5679..8c4181c 100644 +--- a/drivers/staging/fsl_qbman/qman_test.h ++++ b/drivers/staging/fsl_qbman/qman_test.h +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + #include + +diff --git a/drivers/staging/fsl_qbman/qman_test_high.c b/drivers/staging/fsl_qbman/qman_test_high.c +index 45a459b..a9462f1 100644 +--- a/drivers/staging/fsl_qbman/qman_test_high.c ++++ b/drivers/staging/fsl_qbman/qman_test_high.c +@@ -185,6 +185,8 @@ static enum qman_cb_dqrr_result cb_dqrr(struct qman_portal *p, + { + if (fd_cmp(&fd_dq, &dq->fd)) { + pr_err("BADNESS: dequeued frame doesn't match;\n"); ++ pr_err("Expected 0x%llx, got 0x%llx\n", ++ fd_dq.length29, dq->fd.length29); + BUG(); + } + fd_inc(&fd_dq); +diff --git a/drivers/staging/fsl_qbman/qman_test_hotpotato.c b/drivers/staging/fsl_qbman/qman_test_hotpotato.c +index 05b744d..145a480 100644 +--- a/drivers/staging/fsl_qbman/qman_test_hotpotato.c ++++ b/drivers/staging/fsl_qbman/qman_test_hotpotato.c +@@ -290,6 +290,7 @@ static void create_per_cpu_handlers(void) + handler->frame_ptr = frame_ptr; + list_add_tail(&handler->node, &hp_cpu->handlers); + } ++ put_cpu_var(hp_cpus); + } + + static void destroy_per_cpu_handlers(void) +@@ -315,6 +316,7 @@ static void destroy_per_cpu_handlers(void) + list_del(&handler->node); + kmem_cache_free(hp_handler_slab, handler); + } ++ put_cpu_var(hp_cpus); + } + + static inline u8 num_cachelines(u32 offset) +diff --git a/include/linux/fsl_bman.h b/include/linux/fsl_bman.h +index 265d806..4394222 100644 +--- a/include/linux/fsl_bman.h ++++ b/include/linux/fsl_bman.h +@@ -87,15 +87,28 @@ struct bm_mc_result; /* MC result */ + struct bm_buffer { + union { + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u8 __reserved1; + u8 bpid; + u16 hi; /* High 16-bits of 48-bit address */ + u32 lo; /* Low 32-bits of 48-bit address */ ++#else ++ u32 lo; ++ u16 hi; ++ u8 bpid; ++ u8 __reserved; ++#endif + }; + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u64 __notaddress:16; + u64 addr:48; ++#else ++ u64 addr:48; ++ u64 __notaddress:16; ++#endif + }; ++ u64 opaque; + }; + } __aligned(8); + static inline u64 bm_buffer_get64(const struct bm_buffer *buf) +diff --git a/include/linux/fsl_qman.h b/include/linux/fsl_qman.h +index 991729e..0c54e0a 100644 +--- a/include/linux/fsl_qman.h ++++ b/include/linux/fsl_qman.h +@@ -150,6 +150,7 @@ enum qm_fd_format { + struct qm_fd { + union { + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u8 dd:2; /* dynamic debug */ + u8 liodn_offset:6; + u8 bpid:8; /* Buffer Pool ID */ +@@ -157,6 +158,15 @@ struct qm_fd { + u8 __reserved:4; + u8 addr_hi; /* high 8-bits of 40-bit address */ + u32 addr_lo; /* low 32-bits of 40-bit address */ ++#else ++ u8 liodn_offset:6; ++ u8 dd:2; /* dynamic debug */ ++ u8 bpid:8; /* Buffer Pool ID */ ++ u8 __reserved:4; ++ u8 eliodn_offset:4; ++ u8 addr_hi; /* high 8-bits of 40-bit address */ ++ u32 addr_lo; /* low 32-bits of 40-bit address */ ++#endif + }; + struct { + u64 __notaddress:24; +@@ -239,17 +249,33 @@ struct qm_sg_entry { + u32 addr_lo; /* low 32-bits of 40-bit address */ + }; + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u64 __notaddress:24; + u64 addr:40; ++#else ++ u64 addr:40; ++ u64 __notaddress:24; ++#endif + }; + }; ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u32 extension:1; /* Extension bit */ + u32 final:1; /* Final bit */ + u32 length:30; ++#else ++ u32 length:30; ++ u32 final:1; /* Final bit */ ++ u32 extension:1; /* Extension bit */ ++#endif + u8 __reserved2; + u8 bpid; ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u16 __reserved3:3; + u16 offset:13; ++#else ++ u16 offset:13; ++ u16 __reserved3:3; ++#endif + } __packed; + static inline u64 qm_sg_entry_get64(const struct qm_sg_entry *sg) + { +@@ -332,9 +358,15 @@ struct qm_mr_entry { + struct qm_fd fd; + } __packed ern; + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u8 colour:2; /* See QM_MR_DCERN_COLOUR_* */ + u8 __reserved1:3; + enum qm_dc_portal portal:3; ++#else ++ enum qm_dc_portal portal:3; ++ u8 __reserved1:3; ++ u8 colour:2; /* See QM_MR_DCERN_COLOUR_* */ ++#endif + u16 __reserved2; + u8 rc; /* Rejection Code */ + u32 __reserved3:24; +@@ -387,21 +419,39 @@ struct qm_mr_entry { + struct qm_fqd_stashing { + /* See QM_STASHING_EXCL_<...> */ + u8 exclusive; ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u8 __reserved1:2; + /* Numbers of cachelines */ + u8 annotation_cl:2; + u8 data_cl:2; + u8 context_cl:2; ++#else ++ u8 context_cl:2; ++ u8 data_cl:2; ++ u8 annotation_cl:2; ++ u8 __reserved1:2; ++#endif + } __packed; + struct qm_fqd_taildrop { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u16 __reserved1:3; + u16 mant:8; + u16 exp:5; ++#else ++ u16 exp:5; ++ u16 mant:8; ++ u16 __reserved1:3; ++#endif + } __packed; + struct qm_fqd_oac { + /* See QM_OAC_<...> */ ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u8 oac:2; /* "Overhead Accounting Control" */ + u8 __reserved1:6; ++#else ++ u8 __reserved1:6; ++ u8 oac:2; /* "Overhead Accounting Control" */ ++#endif + /* Two's-complement value (-128 to +127) */ + signed char oal; /* "Overhead Accounting Length" */ + } __packed; +@@ -409,10 +459,17 @@ struct qm_fqd { + union { + u8 orpc; + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u8 __reserved1:2; + u8 orprws:3; + u8 oa:1; + u8 olws:2; ++#else ++ u8 olws:2; ++ u8 oa:1; ++ u8 orprws:3; ++ u8 __reserved1:2; ++#endif + } __packed; + }; + u8 cgid; +@@ -420,12 +477,22 @@ struct qm_fqd { + union { + u16 dest_wq; + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u16 channel:13; /* qm_channel */ + u16 wq:3; ++#else ++ u16 wq:3; ++ u16 channel:13; /* qm_channel */ ++#endif + } __packed dest; + }; ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u16 __reserved2:1; + u16 ics_cred:15; ++#else ++ u16 __reserved2:1; ++ u16 ics_cred:15; ++#endif + /* For "Initialize Frame Queue" commands, the write-enable mask + * determines whether 'td' or 'oac_init' is observed. For query + * commands, this field is always 'td', and 'oac_query' (below) reflects +@@ -439,17 +506,28 @@ struct qm_fqd { + /* Treat it as 64-bit opaque */ + u64 opaque; + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u32 hi; + u32 lo; ++#else ++ u32 lo; ++ u32 hi; ++#endif + }; + /* Treat it as s/w portal stashing config */ + /* See 1.5.6.7.1: "FQD Context_A field used for [...] */ + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + struct qm_fqd_stashing stashing; + /* 48-bit address of FQ context to + * stash, must be cacheline-aligned */ + u16 context_hi; + u32 context_lo; ++#else ++ u32 context_lo; ++ u16 context_hi; ++ struct qm_fqd_stashing stashing; ++#endif + } __packed; + } context_a; + struct qm_fqd_oac oac_query; +@@ -544,11 +622,19 @@ struct qm_cgr_wr_parm { + union { + u32 word; + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u32 MA:8; + u32 Mn:5; + u32 SA:7; /* must be between 64-127 */ + u32 Sn:6; + u32 Pn:6; ++#else ++ u32 Pn:6; ++ u32 Sn:6; ++ u32 SA:7; /* must be between 64-127 */ ++ u32 Mn:5; ++ u32 MA:8; ++#endif + } __packed; + }; + } __packed; +@@ -559,9 +645,15 @@ struct qm_cgr_wr_parm { + * CS threshold = TA * (2 ^ Tn) + */ + struct qm_cgr_cs_thres { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u16 __reserved:3; + u16 TA:8; + u16 Tn:5; ++#else ++ u16 Tn:5; ++ u16 TA:8; ++ u16 __reserved:3; ++#endif + } __packed; + /* This identical structure of CGR fields is present in the "Init/Modify CGR" + * commands and the "Query CGR" result. It's suctioned out here into its own +@@ -576,14 +668,23 @@ struct __qm_mc_cgr { + u8 cscn_en; /* boolean, use QM_CGR_EN */ + union { + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u16 cscn_targ_upd_ctrl; /* use QM_CSCN_TARG_UDP_ */ + u16 cscn_targ_dcp_low; /* CSCN_TARG_DCP low-16bits */ ++#else ++ u16 cscn_targ_dcp_low; /* CSCN_TARG_DCP low-16bits */ ++ u16 cscn_targ_upd_ctrl; /* use QM_CSCN_TARG_UDP_ */ ++#endif + }; + u32 cscn_targ; /* use QM_CGR_TARG_* */ + }; + u8 cstd_en; /* boolean, use QM_CGR_EN */ + u8 cs; /* boolean, only used in query response */ +- struct qm_cgr_cs_thres cs_thres; /* use qm_cgr_cs_thres_set64() */ ++ union { ++ /* use qm_cgr_cs_thres_set64() */ ++ struct qm_cgr_cs_thres cs_thres; ++ u16 __cs_thres; ++ }; + u8 mode; /* QMAN_CGR_MODE_FRAME not supported in rev1.0 */ + } __packed; + #define QM_CGR_EN 0x01 /* For wr_en_*, cscn_en, cstd_en */ +@@ -679,8 +780,13 @@ struct qm_mcc_querywq { + union { + u16 channel_wq; /* ignores wq (3 lsbits) */ + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u16 id:13; /* qm_channel */ + u16 __reserved1:3; ++#else ++ u16 __reserved1:3; ++ u16 id:13; /* qm_channel */ ++#endif + } __packed channel; + }; + u8 __reserved2[60]; +@@ -779,8 +885,13 @@ struct qm_mcc_ceetm_mapping_shaper_tcfc_config { + u8 __reserved2[58]; + } __packed channel_mapping; + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u8 map_reserved:5; + u8 map_lni_id:3; ++#else ++ u8 map_lni_id:3; ++ u8 map_reserved:5; ++#endif + u8 __reserved2[58]; + } __packed sp_mapping; + struct { +@@ -988,6 +1099,7 @@ struct qm_mcr_queryfq { + struct qm_mcr_queryfq_np { + u8 __reserved1; + u8 state; /* QM_MCR_NP_STATE_*** */ ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u8 __reserved2; + u32 fqd_link:24; + u16 __reserved3:2; +@@ -1020,7 +1132,52 @@ struct qm_mcr_queryfq_np { + u16 od1_sfdr; /* QM_MCR_NP_OD1_*** */ + u16 od2_sfdr; /* QM_MCR_NP_OD2_*** */ + u16 od3_sfdr; /* QM_MCR_NP_OD3_*** */ ++#else ++ u8 __reserved2; ++ u32 fqd_link:24; ++ ++ u16 odp_seq:14; ++ u16 __reserved3:2; ++ ++ u16 orp_nesn:14; ++ u16 __reserved4:2; ++ ++ u16 orp_ea_hseq:15; ++ u16 __reserved5:1; ++ ++ u16 orp_ea_tseq:15; ++ u16 __reserved6:1; ++ ++ u8 __reserved7; ++ u32 orp_ea_hptr:24; ++ ++ u8 __reserved8; ++ u32 orp_ea_tptr:24; ++ ++ u8 __reserved9; ++ u32 pfdr_hptr:24; ++ ++ u8 __reserved10; ++ u32 pfdr_tptr:24; ++ ++ u8 __reserved11[5]; ++ u8 is:1; ++ u8 __reserved12:7; ++ u16 ics_surp; ++ u32 byte_cnt; ++ u8 __reserved13; ++ u32 frm_cnt:24; ++ u32 __reserved14; ++ u16 ra1_sfdr; /* QM_MCR_NP_RA1_*** */ ++ u16 ra2_sfdr; /* QM_MCR_NP_RA2_*** */ ++ u16 __reserved15; ++ u16 od1_sfdr; /* QM_MCR_NP_OD1_*** */ ++ u16 od2_sfdr; /* QM_MCR_NP_OD2_*** */ ++ u16 od3_sfdr; /* QM_MCR_NP_OD3_*** */ ++#endif + } __packed; ++ ++ + struct qm_mcr_alterfq { + u8 fqs; /* Frame Queue Status */ + u8 __reserved1[61]; +diff --git a/include/linux/fsl_usdpaa.h b/include/linux/fsl_usdpaa.h +index 896c03a..381853d 100644 +--- a/include/linux/fsl_usdpaa.h ++++ b/include/linux/fsl_usdpaa.h +@@ -311,7 +311,7 @@ struct compat_ioctl_raw_portal { + #ifdef __KERNEL__ + + /* Early-boot hook */ +-void __init fsl_usdpaa_init_early(void); ++int __init fsl_usdpaa_init_early(void); + + /* Fault-handling in arch/powerpc/mm/mem.c gives USDPAA an opportunity to detect + * faults within its ranges via this hook. */ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0057-fsl_qbman-Enable-DPAA1-QBMan-for-ARM64-platforms.patch b/target/linux/layerscape-64b/patches-4.1/0057-fsl_qbman-Enable-DPAA1-QBMan-for-ARM64-platforms.patch new file mode 100644 index 0000000..35a1ef2 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0057-fsl_qbman-Enable-DPAA1-QBMan-for-ARM64-platforms.patch @@ -0,0 +1,36 @@ +From 73a76a3be4204d279a098d0b14ffb1817139e4a8 Mon Sep 17 00:00:00 2001 +From: Roy Pledge +Date: Thu, 14 Apr 2016 10:21:02 +0800 +Subject: [PATCH 057/151] fsl_qbman: Enable DPAA1 QBMan for ARM64 platforms + +commit ddb0ae0f9d638efc70402d4fb570bca3a3178091 +[context adjustment] + +Enable the QBMan device for ARM64 platofrms. This is needed for +ARM based SoCs that have DPAA1 such as the LS1043A + +Signed-off-by: Roy Pledge +Integrated-by: Zhao Qiang +--- + arch/arm64/Kconfig | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index bf4c50b..c7314c2 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -263,6 +263,11 @@ endmenu + + menu "Bus support" + ++config HAS_FSL_QBMAN ++ bool "Datapath Acceleration Queue and Buffer management" ++ help ++ Datapath Acceleration Queue and Buffer management ++ + config PCI + bool "PCI support" + help +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0058-dpaa_eth-fix-the-bitfields-of-a-FD.patch b/target/linux/layerscape-64b/patches-4.1/0058-dpaa_eth-fix-the-bitfields-of-a-FD.patch new file mode 100644 index 0000000..be7a293 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0058-dpaa_eth-fix-the-bitfields-of-a-FD.patch @@ -0,0 +1,67 @@ +From d05261bf23709e727a5d633f9beebf13f799a390 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Tue, 17 Feb 2015 18:15:29 +0200 +Subject: [PATCH 058/151] dpaa_eth: fix the bitfields of a FD + +In LE architectures the bitfields are switched also. Therefore the order of the +bitfields is dependent on the architecture. + +There is no need to set high and low addresses separately. arm64 will fetch only +the first 40 bits anyway. + +Signed-off-by: Marian-Cristian Rotariu +Change-Id: I2434c245ac30f7f024f5225c316dfb486c25045a +Reviewed-on: http://git.am.freescale.net:8181/31273 +Reviewed-by: Yang Li +Tested-by: Yang Li + +Conflicts: + + drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c +--- + include/linux/fsl_qman.h | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/include/linux/fsl_qman.h b/include/linux/fsl_qman.h +index 0c54e0a..bc4ee50 100644 +--- a/include/linux/fsl_qman.h ++++ b/include/linux/fsl_qman.h +@@ -186,19 +186,35 @@ struct qm_fd { + u32 opaque; + /* If 'format' is _contig or _sg, 20b length and 9b offset */ + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + enum qm_fd_format format:3; + u16 offset:9; + u32 length20:20; ++#else ++ u32 length20:20; ++ u16 offset:9; ++ enum qm_fd_format format:3; ++#endif + }; + /* If 'format' is _contig_big or _sg_big, 29b length */ + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + enum qm_fd_format _format1:3; + u32 length29:29; ++#else ++ u32 length29:29; ++ enum qm_fd_format _format1:3; ++#endif + }; + /* If 'format' is _compound, 29b "congestion weight" */ + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + enum qm_fd_format _format2:3; + u32 cong_weight:29; ++#else ++ u32 cong_weight:29; ++ enum qm_fd_format _format2:3; ++#endif + }; + }; + union { +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0059-dpaa_eth-fix-S-G-for-ARM.patch b/target/linux/layerscape-64b/patches-4.1/0059-dpaa_eth-fix-S-G-for-ARM.patch new file mode 100644 index 0000000..3d3006e --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0059-dpaa_eth-fix-S-G-for-ARM.patch @@ -0,0 +1,56 @@ +From 414dd2e27e2fd52f16d8b57d040251cfe78c6172 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Mon, 11 May 2015 17:45:48 +0300 +Subject: [PATCH 059/151] dpaa_eth: fix S/G for ARM + +This patch makes the endianness conversion needed for ARM's LE data processing +of the S/G tables. + +A new union was created in the S/G Table structure for easy reference to the +32bit concatenated field. + +Change-Id: I7d21da325596530528805845acad92d7f9a707df +Signed-off-by: Marian-Cristian Rotariu + +Conflicts: + + drivers/net/ethernet/freescale/dpa/dpaa_eth_common.c + drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c +--- + include/linux/fsl_qman.h | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/include/linux/fsl_qman.h b/include/linux/fsl_qman.h +index bc4ee50..b8c89b9 100644 +--- a/include/linux/fsl_qman.h ++++ b/include/linux/fsl_qman.h +@@ -274,15 +274,20 @@ struct qm_sg_entry { + #endif + }; + }; ++ union { ++ struct { + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +- u32 extension:1; /* Extension bit */ +- u32 final:1; /* Final bit */ +- u32 length:30; ++ u32 extension:1; /* Extension bit */ ++ u32 final:1; /* Final bit */ ++ u32 length:30; + #else +- u32 length:30; +- u32 final:1; /* Final bit */ +- u32 extension:1; /* Extension bit */ ++ u32 length:30; ++ u32 final:1; /* Final bit */ ++ u32 extension:1; /* Extension bit */ + #endif ++ }; ++ u32 sgt_efl; ++ }; + u8 __reserved2; + u8 bpid; + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0060-fsl_qbman-Convenient-accessors-for-S-G-structure.patch b/target/linux/layerscape-64b/patches-4.1/0060-fsl_qbman-Convenient-accessors-for-S-G-structure.patch new file mode 100644 index 0000000..a3cc097 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0060-fsl_qbman-Convenient-accessors-for-S-G-structure.patch @@ -0,0 +1,168 @@ +From 8ee984f3c3d620ace1022fd5c17b1fe8a3b755db Mon Sep 17 00:00:00 2001 +From: Cristian Sovaiala +Date: Thu, 9 Jul 2015 17:37:48 +0300 +Subject: [PATCH 060/151] fsl_qbman: Convenient accessors for S/G structure + +Signed-off-by: Cristian Sovaiala +Change-Id: Iebaacc3477b9b88187afd178c9b35567b60ce6fd +--- + include/linux/fsl_qman.h | 113 +++++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 99 insertions(+), 14 deletions(-) + +diff --git a/include/linux/fsl_qman.h b/include/linux/fsl_qman.h +index b8c89b9..2a154eb 100644 +--- a/include/linux/fsl_qman.h ++++ b/include/linux/fsl_qman.h +@@ -265,14 +265,10 @@ struct qm_sg_entry { + u32 addr_lo; /* low 32-bits of 40-bit address */ + }; + struct { +-#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u64 __notaddress:24; + u64 addr:40; +-#else +- u64 addr:40; +- u64 __notaddress:24; +-#endif + }; ++ u64 opaque; + }; + union { + struct { +@@ -282,35 +278,124 @@ struct qm_sg_entry { + u32 length:30; + #else + u32 length:30; +- u32 final:1; /* Final bit */ +- u32 extension:1; /* Extension bit */ ++ u32 final:1; /* Final bit */ ++ u32 extension:1; /* Extension bit */ + #endif + }; + u32 sgt_efl; + }; + u8 __reserved2; + u8 bpid; ++ union { ++ struct { + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +- u16 __reserved3:3; +- u16 offset:13; ++ u16 __reserved3:3; ++ u16 offset:13; + #else +- u16 offset:13; +- u16 __reserved3:3; ++ u16 offset:13; ++ u16 __reserved3:3; + #endif ++ }; ++ u16 opaque_offset; ++ }; + } __packed; ++union qm_sg_efl { ++ struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++ u32 extension:1; /* Extension bit */ ++ u32 final:1; /* Final bit */ ++ u32 length:30; ++#else ++ u32 length:30; ++ u32 final:1; /* Final bit */ ++ u32 extension:1; /* Extension bit */ ++#endif ++ }; ++ u32 efl; ++}; + static inline u64 qm_sg_entry_get64(const struct qm_sg_entry *sg) + { +- return sg->addr; ++ u64 addr = (u64)sg->addr_hi << 32; ++ ++ addr |= be32_to_cpu(sg->addr_lo); ++ return addr; + } + static inline dma_addr_t qm_sg_addr(const struct qm_sg_entry *sg) + { +- return (dma_addr_t)sg->addr; ++ u64 addr = (u64)sg->addr_hi << 32; ++ ++ addr |= be32_to_cpu(sg->addr_lo); ++ return (dma_addr_t)addr; ++} ++static inline u8 qm_sg_entry_get_ext(const struct qm_sg_entry *sg) ++{ ++ union qm_sg_efl u; ++ ++ u.efl = be32_to_cpu(sg->sgt_efl); ++ return u.extension; + } ++static inline u8 qm_sg_entry_get_final(const struct qm_sg_entry *sg) ++{ ++ union qm_sg_efl u; ++ ++ u.efl = be32_to_cpu(sg->sgt_efl); ++ return u.final; ++} ++static inline u32 qm_sg_entry_get_len(const struct qm_sg_entry *sg) ++{ ++ union qm_sg_efl u; ++ ++ u.efl = be32_to_cpu(sg->sgt_efl); ++ return u.length; ++} ++static inline u8 qm_sg_entry_get_bpid(const struct qm_sg_entry *sg) ++{ ++ return sg->bpid; ++} ++static inline u16 qm_sg_entry_get_offset(const struct qm_sg_entry *sg) ++{ ++ u32 opaque_offset = be16_to_cpu(sg->opaque_offset); ++ ++ return opaque_offset & 0x1fff; ++} ++ + /* Macro, so we compile better if 'v' isn't always 64-bit */ + #define qm_sg_entry_set64(sg, v) \ + do { \ + struct qm_sg_entry *__sg931 = (sg); \ +- __sg931->addr = v; \ ++ __sg931->addr_hi = (uint8_t)upper_32_bits(v); \ ++ __sg931->addr_lo = cpu_to_be32(lower_32_bits(v)); \ ++ } while (0) ++#define qm_sg_entry_set_ext(sg, v) \ ++ do { \ ++ union qm_sg_efl __u932; \ ++ __u932.efl = be32_to_cpu((sg)->sgt_efl); \ ++ __u932.extension = v; \ ++ (sg)->sgt_efl = cpu_to_be32(__u932.efl); \ ++ } while (0) ++#define qm_sg_entry_set_final(sg, v) \ ++ do { \ ++ union qm_sg_efl __u933; \ ++ __u933.efl = be32_to_cpu((sg)->sgt_efl); \ ++ __u933.final = v; \ ++ (sg)->sgt_efl = cpu_to_be32(__u933.efl); \ ++ } while (0) ++#define qm_sg_entry_set_len(sg, v) \ ++ do { \ ++ union qm_sg_efl __u934; \ ++ __u934.efl = be32_to_cpu((sg)->sgt_efl); \ ++ __u934.length = v; \ ++ (sg)->sgt_efl = cpu_to_be32(__u934.efl); \ ++ } while (0) ++#define qm_sg_entry_set_bpid(sg, v) \ ++ do { \ ++ struct qm_sg_entry *__u935 = (sg); \ ++ __u935->bpid = v; \ ++ } while (0) ++#define qm_sg_entry_set_offset(sg, v) \ ++ do { \ ++ struct qm_sg_entry *__u936 = (sg); \ ++ __u936->opaque_offset = cpu_to_be16(v); \ + } while (0) + + /* See 1.5.8.1: "Enqueue Command" */ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0061-fsl_qman-fix-CGR-congestion-indication-processing.patch b/target/linux/layerscape-64b/patches-4.1/0061-fsl_qman-fix-CGR-congestion-indication-processing.patch new file mode 100644 index 0000000..88a2f2d --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0061-fsl_qman-fix-CGR-congestion-indication-processing.patch @@ -0,0 +1,40 @@ +From 342ec5d07a3237623c6b5bc446e58b11a9c3cbe6 Mon Sep 17 00:00:00 2001 +From: Alex Porosanu +Date: Tue, 4 Aug 2015 23:32:48 +0300 +Subject: [PATCH 061/151] fsl_qman: fix CGR congestion indication processing + +QM_MCR_QUERYCONGESTION macro checks if the corresponding bit for +the CGR is set in the "query congestion" command response. If +the corresponding bit is set (meaning that the respective CGR +is in a congested state), then the corresponding callback +is called. +The bit-checking must be done by taking into account the difference +between the DPAA block's and the core's endianness. + +Note: improper functioning of CGR callback (i.e. not being called +even if congestion is present) leads to packets being accumulated +in one or more FQs which will eventually lead in the end to +exhausting all the system memory (OOM) + +Signed-off-by: Alex Porosanu +--- + include/linux/fsl_qman.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/linux/fsl_qman.h b/include/linux/fsl_qman.h +index 2a154eb..1ea11d4 100644 +--- a/include/linux/fsl_qman.h ++++ b/include/linux/fsl_qman.h +@@ -1635,7 +1635,8 @@ struct qm_mc_result { + static inline int QM_MCR_QUERYCONGESTION(struct __qm_mcr_querycongestion *p, + u8 cgr) + { +- return p->__state[__CGR_WORD(cgr)] & (0x80000000 >> __CGR_SHIFT(cgr)); ++ return be32_to_cpu(p->__state[__CGR_WORD(cgr)]) & ++ (0x80000000 >> __CGR_SHIFT(cgr)); + } + + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0062-qbman-fix-qm_sg_entry-structure.patch b/target/linux/layerscape-64b/patches-4.1/0062-qbman-fix-qm_sg_entry-structure.patch new file mode 100644 index 0000000..443f0eb --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0062-qbman-fix-qm_sg_entry-structure.patch @@ -0,0 +1,77 @@ +From 3c66305afa34f6dc8f95ef719e3c20bc2f5c10e9 Mon Sep 17 00:00:00 2001 +From: Alex Porosanu +Date: Fri, 7 Aug 2015 18:16:43 +0300 +Subject: [PATCH 062/151] qbman: fix qm_sg_entry structure. + +The address-related members of the qm_sg_entry structure +were not updated to take into account LE systems and BE +DPAA block. This patch updates the structure and performs +the necessary changes to the relevant accessors. + +Signed-off-by: Alex Porosanu +--- + include/linux/fsl_qman.h | 24 ++++++++++++++---------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +diff --git a/include/linux/fsl_qman.h b/include/linux/fsl_qman.h +index 1ea11d4..5850455 100644 +--- a/include/linux/fsl_qman.h ++++ b/include/linux/fsl_qman.h +@@ -260,13 +260,24 @@ static inline dma_addr_t qm_fd_addr(const struct qm_fd *fd) + struct qm_sg_entry { + union { + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u8 __reserved1[3]; + u8 addr_hi; /* high 8-bits of 40-bit address */ + u32 addr_lo; /* low 32-bits of 40-bit address */ ++#else ++ u32 addr_lo; /* low 32-bits of 40-bit address */ ++ u8 addr_hi; /* high 8-bits of 40-bit address */ ++ u8 __reserved1[3]; ++#endif + }; + struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + u64 __notaddress:24; + u64 addr:40; ++#else ++ u64 addr:40; ++ u64 __notaddress:24; ++#endif + }; + u64 opaque; + }; +@@ -315,17 +326,11 @@ union qm_sg_efl { + }; + static inline u64 qm_sg_entry_get64(const struct qm_sg_entry *sg) + { +- u64 addr = (u64)sg->addr_hi << 32; +- +- addr |= be32_to_cpu(sg->addr_lo); +- return addr; ++ return be64_to_cpu(sg->opaque); + } + static inline dma_addr_t qm_sg_addr(const struct qm_sg_entry *sg) + { +- u64 addr = (u64)sg->addr_hi << 32; +- +- addr |= be32_to_cpu(sg->addr_lo); +- return (dma_addr_t)addr; ++ return (dma_addr_t)be64_to_cpu(sg->opaque); + } + static inline u8 qm_sg_entry_get_ext(const struct qm_sg_entry *sg) + { +@@ -363,8 +368,7 @@ static inline u16 qm_sg_entry_get_offset(const struct qm_sg_entry *sg) + #define qm_sg_entry_set64(sg, v) \ + do { \ + struct qm_sg_entry *__sg931 = (sg); \ +- __sg931->addr_hi = (uint8_t)upper_32_bits(v); \ +- __sg931->addr_lo = cpu_to_be32(lower_32_bits(v)); \ ++ __sg931->opaque = cpu_to_be64(v); \ + } while (0) + #define qm_sg_entry_set_ext(sg, v) \ + do { \ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0063-fsl_qbman-fix-CGR-average-instantaneous-byte-counts.patch b/target/linux/layerscape-64b/patches-4.1/0063-fsl_qbman-fix-CGR-average-instantaneous-byte-counts.patch new file mode 100644 index 0000000..db1b4d5 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0063-fsl_qbman-fix-CGR-average-instantaneous-byte-counts.patch @@ -0,0 +1,85 @@ +From 251d675ce822b252013139d97cbc54f99ab95e43 Mon Sep 17 00:00:00 2001 +From: Alex Porosanu +Date: Tue, 11 Aug 2015 12:39:28 +0300 +Subject: [PATCH 063/151] fsl_qbman: fix CGR average & instantaneous byte + counts + +Signed-off-by: Alex Porosanu +--- + include/linux/fsl_qman.h | 42 ++++++++++++++++++++++++++++++++---------- + 1 file changed, 32 insertions(+), 10 deletions(-) + +diff --git a/include/linux/fsl_qman.h b/include/linux/fsl_qman.h +index 5850455..6dd7b48 100644 +--- a/include/linux/fsl_qman.h ++++ b/include/linux/fsl_qman.h +@@ -1315,12 +1315,34 @@ struct qm_mcr_querycgr { + u16 __reserved1; + struct __qm_mc_cgr cgr; /* CGR fields */ + u8 __reserved2[3]; +- u32 __reserved3:24; +- u32 i_bcnt_hi:8;/* high 8-bits of 40-bit "Instant" */ +- u32 i_bcnt_lo; /* low 32-bits of 40-bit */ +- u32 __reserved4:24; +- u32 a_bcnt_hi:8;/* high 8-bits of 40-bit "Average" */ +- u32 a_bcnt_lo; /* low 32-bits of 40-bit */ ++ union { ++ struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++ u32 __reserved3:24; ++ u32 i_bcnt_hi:8;/* high 8-bits of 40-bit "Instant" */ ++ u32 i_bcnt_lo; /* low 32-bits of 40-bit */ ++#else ++ u32 i_bcnt_lo; /* low 32-bits of 40-bit */ ++ u32 i_bcnt_hi:8;/* high 8-bits of 40-bit "Instant" */ ++ u32 __reserved3:24; ++#endif ++ }; ++ u64 i_bcnt; ++ }; ++ union { ++ struct { ++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++ u32 __reserved4:24; ++ u32 a_bcnt_hi:8;/* high 8-bits of 40-bit "Average" */ ++ u32 a_bcnt_lo; /* low 32-bits of 40-bit */ ++#else ++ u32 a_bcnt_lo; /* low 32-bits of 40-bit */ ++ u32 a_bcnt_hi:8;/* high 8-bits of 40-bit "Average" */ ++ u32 __reserved4:24; ++#endif ++ }; ++ u64 a_bcnt; ++ }; + union { + u32 cscn_targ_swp[4]; + u8 __reserved5[16]; +@@ -1328,21 +1350,21 @@ struct qm_mcr_querycgr { + } __packed; + static inline u64 qm_mcr_querycgr_i_get64(const struct qm_mcr_querycgr *q) + { +- return ((u64)q->i_bcnt_hi << 32) | (u64)q->i_bcnt_lo; ++ return be64_to_cpu(q->i_bcnt); + } + static inline u64 qm_mcr_querycgr_a_get64(const struct qm_mcr_querycgr *q) + { +- return ((u64)q->a_bcnt_hi << 32) | (u64)q->a_bcnt_lo; ++ return be64_to_cpu(q->a_bcnt); + } + static inline u64 qm_mcr_cgrtestwrite_i_get64( + const struct qm_mcr_cgrtestwrite *q) + { +- return ((u64)q->i_bcnt_hi << 32) | (u64)q->i_bcnt_lo; ++ return be64_to_cpu(((u64)q->i_bcnt_hi << 32) | (u64)q->i_bcnt_lo); + } + static inline u64 qm_mcr_cgrtestwrite_a_get64( + const struct qm_mcr_cgrtestwrite *q) + { +- return ((u64)q->a_bcnt_hi << 32) | (u64)q->a_bcnt_lo; ++ return be64_to_cpu(((u64)q->a_bcnt_hi << 32) | (u64)q->a_bcnt_lo); + } + /* Macro, so we compile better if 'v' isn't always 64-bit */ + #define qm_mcr_querycgr_i_set64(q, v) \ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0064-fsl_qbman-Fix-Frame-Queue-Stash-setup.patch b/target/linux/layerscape-64b/patches-4.1/0064-fsl_qbman-Fix-Frame-Queue-Stash-setup.patch new file mode 100644 index 0000000..0ff77cc --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0064-fsl_qbman-Fix-Frame-Queue-Stash-setup.patch @@ -0,0 +1,38 @@ +From 6167be60437d17bca61acef3dd84b37a0ee3c41b Mon Sep 17 00:00:00 2001 +From: Roy Pledge +Date: Wed, 2 Sep 2015 17:00:54 -0400 +Subject: [PATCH 064/151] fsl_qbman: Fix Frame Queue Stash setup + +The stashing subfields of the FQD context_a need to be populated so +that they are in proper byteorder once the entire context is swapped + +Signed-off-by: Roy Pledge +--- + include/linux/fsl_qman.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/linux/fsl_qman.h b/include/linux/fsl_qman.h +index 6dd7b48..5a68042 100644 +--- a/include/linux/fsl_qman.h ++++ b/include/linux/fsl_qman.h +@@ -528,8 +528,8 @@ struct qm_mr_entry { + * representation. */ + struct qm_fqd_stashing { + /* See QM_STASHING_EXCL_<...> */ +- u8 exclusive; + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++ u8 exclusive; + u8 __reserved1:2; + /* Numbers of cachelines */ + u8 annotation_cl:2; +@@ -540,6 +540,7 @@ struct qm_fqd_stashing { + u8 data_cl:2; + u8 annotation_cl:2; + u8 __reserved1:2; ++ u8 exclusive; + #endif + } __packed; + struct qm_fqd_taildrop { +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0065-bman-fix-stockpile-logic.patch b/target/linux/layerscape-64b/patches-4.1/0065-bman-fix-stockpile-logic.patch new file mode 100644 index 0000000..96a32cd --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0065-bman-fix-stockpile-logic.patch @@ -0,0 +1,196 @@ +From 1affbdb51f25ccbcb0c7f73c598f0bced27d8291 Mon Sep 17 00:00:00 2001 +From: Ahmed Mansour +Date: Wed, 16 Mar 2016 10:16:28 -0400 +Subject: [PATCH 065/151] bman: fix stockpile logic + +Array overruns had been observed in the stockpile logic, and upon +further examination the code appears poorly structured in addition to +being buggy (mea culpa). + +Signed-off-by: Geoff Thorpe + +Signed-off-by: Ahmed Mansour +--- + drivers/staging/fsl_qbman/bman_high.c | 137 +++++++++++++++++++++------------- + 1 file changed, 84 insertions(+), 53 deletions(-) + +diff --git a/drivers/staging/fsl_qbman/bman_high.c b/drivers/staging/fsl_qbman/bman_high.c +index 2ece0f3..254987f 100644 +--- a/drivers/staging/fsl_qbman/bman_high.c ++++ b/drivers/staging/fsl_qbman/bman_high.c +@@ -895,7 +895,7 @@ static inline int __bman_release(struct bman_pool *pool, + int bman_release(struct bman_pool *pool, const struct bm_buffer *bufs, u8 num, + u32 flags) + { +- int ret = 0; ++ int ret; + #ifdef CONFIG_FSL_DPA_CHECKING + if (!num || (num > 8)) + return -EINVAL; +@@ -911,38 +911,50 @@ int bman_release(struct bman_pool *pool, const struct bm_buffer *bufs, u8 num, + panic("only one instance of bman_released/acquired allowed"); + } + #endif +- /* This needs some explanation. Adding the given buffers may take the +- * stockpile over the threshold, but in fact the stockpile may already +- * *be* over the threshold if a previous release-to-hw attempt had +- * failed. So we have 3 cases to cover; +- * 1. we add to the stockpile and don't hit the threshold, +- * 2. we add to the stockpile, hit the threshold and release-to-hw, +- * 3. we have to release-to-hw before adding to the stockpile +- * (not enough room in the stockpile for case 2). +- * Our constraints on thresholds guarantee that in case 3, there must be +- * at least 8 bufs already in the stockpile, so all release-to-hw ops +- * are for 8 bufs. Despite all this, the API must indicate whether the +- * given buffers were taken off the caller's hands, irrespective of +- * whether a release-to-hw was attempted. */ +- while (num) { +- /* Add buffers to stockpile if they fit */ +- if ((pool->sp_fill + num) < BMAN_STOCKPILE_SZ) { +- copy_words(pool->sp + pool->sp_fill, bufs, +- sizeof(struct bm_buffer) * num); +- pool->sp_fill += num; +- num = 0; /* --> will return success no matter what */ ++ /* Two movements of buffers are possible, and can occur in either order. ++ * A: moving buffers from the caller to the stockpile. ++ * B: moving buffers from the stockpile to hardware. ++ * Order 1: if there is already enough space in the stockpile for A ++ * then we want to do A first, and only do B if we trigger the ++ * stockpile-high threshold. ++ * Order 2: if there is not enough space in the stockpile for A, then ++ * we want to do B first, then do A if B had succeeded. However in this ++ * case B is dependent on how many buffers the user needs to release, ++ * not the stockpile-high threshold. ++ * Due to the different handling of B between the two cases, putting A ++ * and B in a while() loop would require quite obscure logic, so handle ++ * the different sequences explicitly. */ ++ if ((pool->sp_fill + num) <= BMAN_STOCKPILE_SZ) { ++ /* Order 1: do A */ ++ copy_words(pool->sp + pool->sp_fill, bufs, ++ sizeof(struct bm_buffer) * num); ++ pool->sp_fill += num; ++ /* do B relative to STOCKPILE_HIGH */ ++ while (pool->sp_fill >= BMAN_STOCKPILE_HIGH) { ++ ret = __bman_release(pool, ++ pool->sp + (pool->sp_fill - 8), 8, ++ flags); ++ if (ret >= 0) ++ pool->sp_fill -= 8; + } +- /* Do hw op if hitting the high-water threshold */ +- if ((pool->sp_fill + num) >= BMAN_STOCKPILE_HIGH) { ++ } else { ++ /* Order 2: do B relative to 'num' */ ++ do { + ret = __bman_release(pool, +- pool->sp + (pool->sp_fill - 8), 8, flags); +- if (ret) { +- ret = (num ? ret : 0); ++ pool->sp + (pool->sp_fill - 8), 8, ++ flags); ++ if (ret < 0) ++ /* failure */ + goto release_done; +- } + pool->sp_fill -= 8; +- } ++ } while ((pool->sp_fill + num) > BMAN_STOCKPILE_SZ); ++ /* do A */ ++ copy_words(pool->sp + pool->sp_fill, bufs, ++ sizeof(struct bm_buffer) * num); ++ pool->sp_fill += num; + } ++ /* success */ ++ ret = 0; + release_done: + #ifdef CONFIG_FSL_DPA_CHECKING + atomic_inc(&pool->in_use); +@@ -983,7 +995,7 @@ static inline int __bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, + int bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, u8 num, + u32 flags) + { +- int ret = 0; ++ int ret; + #ifdef CONFIG_FSL_DPA_CHECKING + if (!num || (num > 8)) + return -EINVAL; +@@ -999,33 +1011,52 @@ int bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, u8 num, + panic("only one instance of bman_released/acquired allowed"); + } + #endif +- /* Only need a h/w op if we'll hit the low-water thresh */ +- if (!(flags & BMAN_ACQUIRE_FLAG_STOCKPILE) && +- (pool->sp_fill <= (BMAN_STOCKPILE_LOW + num))) { +- /* refill stockpile with max amount, but if max amount +- * isn't available, try amount the user wants */ +- int bufcount = 8; +- ret = __bman_acquire(pool, pool->sp + pool->sp_fill, bufcount); +- if (ret < 0 && bufcount != num) { +- bufcount = num; +- /* Maybe buffer pool has less than 8 */ +- ret = __bman_acquire(pool, pool->sp + pool->sp_fill, +- bufcount); ++ /* Two movements of buffers are possible, and can occur in either order. ++ * A: moving buffers from stockpile to the caller. ++ * B: moving buffers from hardware to the stockpile. ++ * Order 1: if there are already enough buffers in the stockpile for A ++ * then we want to do A first, and only do B if we trigger the ++ * stockpile-low threshold. ++ * Order 2: if there are not enough buffers in the stockpile for A, ++ * then we want to do B first, then do A if B had succeeded. However in ++ * this case B is dependent on how many buffers the user needs, not the ++ * stockpile-low threshold. ++ * Due to the different handling of B between the two cases, putting A ++ * and B in a while() loop would require quite obscure logic, so handle ++ * the different sequences explicitly. */ ++ if (num <= pool->sp_fill) { ++ /* Order 1: do A */ ++ copy_words(bufs, pool->sp + (pool->sp_fill - num), ++ sizeof(struct bm_buffer) * num); ++ pool->sp_fill -= num; ++ /* do B relative to STOCKPILE_LOW */ ++ while (pool->sp_fill <= BMAN_STOCKPILE_LOW) { ++ ret = __bman_acquire(pool, pool->sp + pool->sp_fill, 8); ++ if (ret < 0) ++ ret = __bman_acquire(pool, ++ pool->sp + pool->sp_fill, 1); ++ if (ret < 0) ++ break; ++ pool->sp_fill += ret; + } +- if (ret < 0) +- goto hw_starved; +- DPA_ASSERT(ret == bufcount); +- pool->sp_fill += bufcount; + } else { +-hw_starved: +- if (pool->sp_fill < num) { +- ret = -ENOMEM; +- goto acquire_done; +- } ++ /* Order 2: do B relative to 'num' */ ++ do { ++ ret = __bman_acquire(pool, pool->sp + pool->sp_fill, 8); ++ if (ret < 0) ++ ret = __bman_acquire(pool, ++ pool->sp + pool->sp_fill, 1); ++ if (ret < 0) ++ /* failure */ ++ goto acquire_done; ++ pool->sp_fill += ret; ++ } while (pool->sp_fill < num); ++ /* do A */ ++ copy_words(bufs, pool->sp + (pool->sp_fill - num), ++ sizeof(struct bm_buffer) * num); ++ pool->sp_fill -= num; + } +- copy_words(bufs, pool->sp + (pool->sp_fill - num), +- sizeof(struct bm_buffer) * num); +- pool->sp_fill -= num; ++ /* success */ + ret = num; + acquire_done: + #ifdef CONFIG_FSL_DPA_CHECKING +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0066-fmd-add-LS1043-support.patch b/target/linux/layerscape-64b/patches-4.1/0066-fmd-add-LS1043-support.patch new file mode 100644 index 0000000..b2ae5d9 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0066-fmd-add-LS1043-support.patch @@ -0,0 +1,3599 @@ +From 92d7e7ed2150c9bd8fb785c19efe60f7ebb6d097 Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Tue, 16 Feb 2016 10:47:05 +0200 +Subject: [PATCH 066/151] fmd: add LS1043 support + +Signed-off-by: Madalin Bucur +--- + drivers/net/ethernet/freescale/sdk_fman/Kconfig | 11 +- + .../freescale/sdk_fman/Peripherals/FM/MAC/Makefile | 3 + + .../Peripherals/FM/MACSEC/fm_macsec_master.c | 4 +- + .../freescale/sdk_fman/Peripherals/FM/Pcd/Makefile | 3 + + .../freescale/sdk_fman/Peripherals/FM/Pcd/fm_cc.c | 103 +-- + .../sdk_fman/Peripherals/FM/Pcd/fm_manip.c | 61 +- + .../sdk_fman/Peripherals/FM/Pcd/fm_manip.h | 2 + + .../freescale/sdk_fman/Peripherals/FM/Pcd/fm_prs.c | 10 +- + .../freescale/sdk_fman/Peripherals/FM/fm.c | 4 + + .../net/ethernet/freescale/sdk_fman/etc/memcpy.c | 19 + + .../sdk_fman/inc/Peripherals/fm_pcd_ext.h | 6 +- + .../net/ethernet/freescale/sdk_fman/inc/core_ext.h | 8 +- + .../freescale/sdk_fman/inc/cores/arm_ext.h | 55 ++ + .../ethernet/freescale/sdk_fman/inc/error_ext.h | 2 +- + .../freescale/sdk_fman/inc/etc/memcpy_ext.h | 34 + + .../freescale/sdk_fman/inc/flib/common/general.h | 3 +- + .../inc/integrations/LS1043/dpaa_integration_ext.h | 291 +++++++ + .../sdk_fman/inc/integrations/LS1043/part_ext.h | 64 ++ + .../inc/integrations/LS1043/part_integration_ext.h | 185 +++++ + .../ethernet/freescale/sdk_fman/inc/types_ext.h | 42 - + .../ethernet/freescale/sdk_fman/ls1043_dflags.h | 56 ++ + .../net/ethernet/freescale/sdk_fman/ncsw_config.mk | 6 + + .../freescale/sdk_fman/src/inc/types_linux.h | 8 + + .../freescale/sdk_fman/src/wrapper/lnxwrp_fm.c | 70 +- + .../sdk_fman/src/wrapper/lnxwrp_fm_port.c | 161 +++- + .../sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c | 19 +- + .../sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.c | 2 + + .../ethernet/freescale/sdk_fman/src/xx/Makefile | 9 +- + .../freescale/sdk_fman/src/xx/xx_arm_linux.c | 905 +++++++++++++++++++++ + .../ethernet/freescale/sdk_fman/src/xx/xx_linux.c | 37 +- + 30 files changed, 1982 insertions(+), 201 deletions(-) + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/cores/arm_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/integrations/LS1043/dpaa_integration_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/integrations/LS1043/part_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/inc/integrations/LS1043/part_integration_ext.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/ls1043_dflags.h + create mode 100644 drivers/net/ethernet/freescale/sdk_fman/src/xx/xx_arm_linux.c + +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Kconfig b/drivers/net/ethernet/freescale/sdk_fman/Kconfig +index e56e3ec..0b3e581 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/Kconfig ++++ b/drivers/net/ethernet/freescale/sdk_fman/Kconfig +@@ -2,7 +2,7 @@ menu "Frame Manager support" + + menuconfig FSL_SDK_FMAN + bool "Freescale Frame Manager (datapath) support - SDK driver" +- depends on FSL_SOC && FSL_BMAN && FSL_QMAN ++ depends on (FSL_SOC || ARM64) && FSL_BMAN && FSL_QMAN + default y + ---help--- + If unsure, say Y. +@@ -21,6 +21,13 @@ choice + depends on FSL_SDK_FMAN + prompt "Processor Type" + ++config FMAN_ARM ++ bool "LS1043" ++ depends on ARM64 ++ ---help--- ++ Choose "LS1043" for the ARM platforms: ++ LS1043 ++ + config FMAN_P3040_P4080_P5020 + bool "P3040 P4080 5020" + +@@ -100,7 +107,7 @@ config FSL_FM_RX_EXTRA_HEADROOM + + config FMAN_PFC + bool "FMan PFC support (EXPERIMENTAL)" +- depends on ( FMAN_V3H || FMAN_V3L ) && FSL_SDK_FMAN ++ depends on ( FMAN_V3H || FMAN_V3L || FMAN_ARM) && FSL_SDK_FMAN + default n + ---help--- + This option enables PFC support on FMan v3 ports. +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/Makefile b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/Makefile +index 823f6ad..f6b090d 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/Makefile ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MAC/Makefile +@@ -22,4 +22,7 @@ endif + ifeq ($(CONFIG_FMAN_V3L),y) + fsl-ncsw-MAC-objs += memac.o memac_mii_acc.o fman_memac_mii_acc.o + endif ++ifeq ($(CONFIG_FMAN_ARM),y) ++fsl-ncsw-MAC-objs += memac.o memac_mii_acc.o fman_memac_mii_acc.o ++endif + +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_master.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_master.c +index 79260c8..623612a 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_master.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/MACSEC/fm_macsec_master.c +@@ -715,7 +715,7 @@ t_Error FmMacsecCreateRxSa(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId, ma + WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->rxsca, scId); + WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecRxScSa[saId].rxsanpn, DEFAULT_initNextPn); + WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecRxScSa[saId].rxsalpn, lowestPn); +- Mem2IOCpy32((void*)p_FmMacsec->p_FmMacsecRegs->fmMacsecRxScSa[saId].rxsak, key, sizeof(macsecSAKey_t)); ++ MemCpy8((void*)p_FmMacsec->p_FmMacsecRegs->fmMacsecRxScSa[saId].rxsak, key, sizeof(macsecSAKey_t)); + + tmpReg |= RX_SACFG_ACTIVE; + tmpReg |= ((an << RX_SACFG_AN_SHIFT) & RX_SACFG_AN_MASK); +@@ -740,7 +740,7 @@ t_Error FmMacsecCreateTxSa(t_Handle h_FmMacsec, uint32_t scId, e_ScSaId saId, ma + + WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->txsca, scId); + WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecTxScSa[saId].txsanpn, DEFAULT_initNextPn); +- Mem2IOCpy32((void*)p_FmMacsec->p_FmMacsecRegs->fmMacsecTxScSa[saId].txsak, key, sizeof(macsecSAKey_t)); ++ MemCpy8((void*)p_FmMacsec->p_FmMacsecRegs->fmMacsecTxScSa[saId].txsak, key, sizeof(macsecSAKey_t)); + + tmpReg |= TX_SACFG_ACTIVE; + WRITE_UINT32(p_FmMacsec->p_FmMacsecRegs->fmMacsecTxScSa[saId].txsacs, tmpReg); +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/Makefile b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/Makefile +index 880c0e1..62fbd73 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/Makefile ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/Makefile +@@ -20,4 +20,7 @@ endif + ifeq ($(CONFIG_FMAN_V3L),y) + fsl-ncsw-Pcd-objs += fm_replic.o + endif ++ifeq ($(CONFIG_FMAN_ARM),y) ++fsl-ncsw-Pcd-objs += fm_replic.o ++endif + +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_cc.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_cc.c +index 51df898..b0e045b 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_cc.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_cc.c +@@ -165,7 +165,7 @@ static t_FmPcdStatsObj* GetStatsObj(t_FmPcdCcNode *p_CcNode) + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics ADs")); + return NULL; + } +- IOMemSet32(p_StatsObj->h_StatsAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ MemSet8(p_StatsObj->h_StatsAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); + + p_StatsObj->h_StatsCounters = (t_Handle)FM_MURAM_AllocMem( + h_FmMuram, p_CcNode->countersArraySize, +@@ -177,7 +177,7 @@ static t_FmPcdStatsObj* GetStatsObj(t_FmPcdCcNode *p_CcNode) + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics counters")); + return NULL; + } +- IOMemSet32(p_StatsObj->h_StatsCounters, 0, p_CcNode->countersArraySize); ++ MemSet8(p_StatsObj->h_StatsCounters, 0, p_CcNode->countersArraySize); + } + + return p_StatsObj; +@@ -195,7 +195,7 @@ static void PutStatsObj(t_FmPcdCcNode *p_CcNode, t_FmPcdStatsObj *p_StatsObj) + if (p_CcNode->maxNumOfKeys) + { + /* Nullify counters */ +- IOMemSet32(p_StatsObj->h_StatsCounters, 0, p_CcNode->countersArraySize); ++ MemSet8(p_StatsObj->h_StatsCounters, 0, p_CcNode->countersArraySize); + + EnqueueStatsObj(&p_CcNode->availableStatsLst, p_StatsObj); + } +@@ -367,8 +367,8 @@ static void FillAdOfTypeContLookup(t_Handle h_Ad, + tmpReg32 |= p_Node->parseCode; + WRITE_UINT32(p_AdContLookup->pcAndOffsets, tmpReg32); + +- Mem2IOCpy32((void*)&p_AdContLookup->gmask, p_Node->p_GlblMask, +- CC_GLBL_MASK_SIZE); ++ MemCpy8((void*)&p_AdContLookup->gmask, p_Node->p_GlblMask, ++ CC_GLBL_MASK_SIZE); + } + } + +@@ -396,7 +396,7 @@ static t_Error AllocAndFillAdForContLookupManip(t_Handle h_CcNode) + RETURN_ERROR(MAJOR, E_NO_MEMORY, + ("MURAM allocation for CC action descriptor")); + +- IOMemSet32(p_CcNode->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ MemSet8(p_CcNode->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); + + FillAdOfTypeContLookup(p_CcNode->h_Ad, NULL, p_CcNode->h_FmPcd, + p_CcNode, NULL, NULL); +@@ -1005,11 +1005,11 @@ static t_Error DoDynamicChange( + else + keySize = p_CcNode->ccKeySizeAccExtraction; + +- IO2IOCpy32(p_AdditionalParams->p_KeysMatchTableOld, ++ MemCpy8(p_AdditionalParams->p_KeysMatchTableOld, + p_AdditionalParams->p_KeysMatchTableNew, + p_CcNode->maxNumOfKeys * keySize * sizeof(uint8_t)); + +- IO2IOCpy32( ++ MemCpy8( + p_AdditionalParams->p_AdTableOld, + p_AdditionalParams->p_AdTableNew, + (uint32_t)((p_CcNode->maxNumOfKeys + 1) +@@ -1032,8 +1032,8 @@ static t_Error DoDynamicChange( + /* HC to copy from the new Ad (old updated structures) to current Ad (uses shadow structures) */ + err = DynamicChangeHc(h_FmPcd, h_OldPointersLst, h_NewPointersLst, + p_AdditionalParams, useShadowStructs); +- if (err) +- RETURN_ERROR(MAJOR, err, NO_MSG); ++ if (err) ++ RETURN_ERROR(MAJOR, err, NO_MSG); + } + } + +@@ -2515,12 +2515,12 @@ static t_Error BuildNewNodeCommonPart( + ("MURAM allocation for CC node key match table")); + } + +- IOMemSet32( ++ MemSet8( + (uint8_t*)p_AdditionalInfo->p_AdTableNew, + 0, + (uint32_t)((p_AdditionalInfo->numOfKeys + 1) + * FM_PCD_CC_AD_ENTRY_SIZE)); +- IOMemSet32((uint8_t*)p_AdditionalInfo->p_KeysMatchTableNew, 0, ++ MemSet8((uint8_t*)p_AdditionalInfo->p_KeysMatchTableNew, 0, + *size * sizeof(uint8_t) * (p_AdditionalInfo->numOfKeys + 1)); + } + else +@@ -2542,12 +2542,12 @@ static t_Error BuildNewNodeCommonPart( + p_AdditionalInfo->p_AdTableNew = + PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, p_CcNode->keysMatchTableMaxSize); + +- IOMemSet32( ++ MemSet8( + (uint8_t*)p_AdditionalInfo->p_AdTableNew, + 0, + (uint32_t)((p_CcNode->maxNumOfKeys + 1) + * FM_PCD_CC_AD_ENTRY_SIZE)); +- IOMemSet32((uint8_t*)p_AdditionalInfo->p_KeysMatchTableNew, 0, ++ MemSet8((uint8_t*)p_AdditionalInfo->p_KeysMatchTableNew, 0, + (*size) * sizeof(uint8_t) * (p_CcNode->maxNumOfKeys)); + } + +@@ -2685,7 +2685,7 @@ static t_Error BuildNewNodeAddOrMdfyKeyAndNextEngine( + p_KeysMatchTableNewTmp = + PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j*size*sizeof(uint8_t)); + +- Mem2IOCpy32((void*)p_KeysMatchTableNewTmp, p_KeyParams->p_Key, ++ MemCpy8((void*)p_KeysMatchTableNewTmp, p_KeyParams->p_Key, + p_CcNode->userSizeOfExtraction); + + /* Update mask for the received new key */ +@@ -2693,7 +2693,7 @@ static t_Error BuildNewNodeAddOrMdfyKeyAndNextEngine( + { + if (p_KeyParams->p_Mask) + { +- Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ MemCpy8(PTR_MOVE(p_KeysMatchTableNewTmp, + p_CcNode->ccKeySizeAccExtraction), + p_KeyParams->p_Mask, + p_CcNode->userSizeOfExtraction); +@@ -2701,13 +2701,13 @@ static t_Error BuildNewNodeAddOrMdfyKeyAndNextEngine( + else + if (p_CcNode->ccKeySizeAccExtraction > 4) + { +- IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ MemSet8(PTR_MOVE(p_KeysMatchTableNewTmp, + p_CcNode->ccKeySizeAccExtraction), + 0xff, p_CcNode->userSizeOfExtraction); + } + else + { +- Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ MemCpy8(PTR_MOVE(p_KeysMatchTableNewTmp, + p_CcNode->ccKeySizeAccExtraction), + p_CcNode->p_GlblMask, + p_CcNode->userSizeOfExtraction); +@@ -2723,7 +2723,7 @@ static t_Error BuildNewNodeAddOrMdfyKeyAndNextEngine( + /* Copy existing action descriptors to the newly allocated Ad table */ + p_AdTableOldTmp = + PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i*FM_PCD_CC_AD_ENTRY_SIZE); +- IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, ++ MemCpy8(p_AdTableNewTmp, p_AdTableOldTmp, + FM_PCD_CC_AD_ENTRY_SIZE); + + /* Copy existing keys and their masks to the newly allocated keys match table */ +@@ -2736,7 +2736,7 @@ static t_Error BuildNewNodeAddOrMdfyKeyAndNextEngine( + { + if (prvLclMask) + { +- IO2IOCpy32( ++ MemCpy8( + PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction), + PTR_MOVE(p_KeysMatchTableOldTmp, p_CcNode->ccKeySizeAccExtraction), + p_CcNode->ccKeySizeAccExtraction); +@@ -2749,13 +2749,13 @@ static t_Error BuildNewNodeAddOrMdfyKeyAndNextEngine( + + if (p_CcNode->ccKeySizeAccExtraction > 4) + { +- IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ MemSet8(PTR_MOVE(p_KeysMatchTableNewTmp, + p_CcNode->ccKeySizeAccExtraction), + 0xff, p_CcNode->userSizeOfExtraction); + } + else + { +- IO2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ MemCpy8(PTR_MOVE(p_KeysMatchTableNewTmp, + p_CcNode->ccKeySizeAccExtraction), + p_CcNode->p_GlblMask, + p_CcNode->userSizeOfExtraction); +@@ -2763,7 +2763,7 @@ static t_Error BuildNewNodeAddOrMdfyKeyAndNextEngine( + } + } + +- IO2IOCpy32(p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp, ++ MemCpy8(p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp, + p_CcNode->ccKeySizeAccExtraction); + + i++; +@@ -2775,7 +2775,7 @@ static t_Error BuildNewNodeAddOrMdfyKeyAndNextEngine( + PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j * FM_PCD_CC_AD_ENTRY_SIZE); + p_AdTableOldTmp = + PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i * FM_PCD_CC_AD_ENTRY_SIZE); +- IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ MemCpy8(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); + + if (!LIST_IsEmpty(&p_CcNode->ccTreesLst)) + { +@@ -2888,13 +2888,13 @@ static t_Error BuildNewNodeRemoveKey( + PTR_MOVE(p_AdditionalInfo->p_AdTableNew, i * FM_PCD_CC_AD_ENTRY_SIZE); + p_AdTableOldTmp = + PTR_MOVE(p_AdditionalInfo->p_AdTableOld, j * FM_PCD_CC_AD_ENTRY_SIZE); +- IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ MemCpy8(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); + + p_KeysMatchTableOldTmp = + PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableOld, j * size * sizeof(uint8_t)); + p_KeysMatchTableNewTmp = + PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, i * size * sizeof(uint8_t)); +- IO2IOCpy32(p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp, ++ MemCpy8(p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp, + size * sizeof(uint8_t)); + } + +@@ -2902,7 +2902,7 @@ static t_Error BuildNewNodeRemoveKey( + PTR_MOVE(p_AdditionalInfo->p_AdTableNew, i * FM_PCD_CC_AD_ENTRY_SIZE); + p_AdTableOldTmp = + PTR_MOVE(p_AdditionalInfo->p_AdTableOld, j * FM_PCD_CC_AD_ENTRY_SIZE); +- IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ MemCpy8(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); + + if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine + == e_FM_PCD_CC) +@@ -2976,7 +2976,7 @@ static t_Error BuildNewNodeModifyKey( + p_AdTableOldTmp = + PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i*FM_PCD_CC_AD_ENTRY_SIZE); + +- IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ MemCpy8(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); + + if (j == keyIndex) + { +@@ -3019,22 +3019,22 @@ static t_Error BuildNewNodeModifyKey( + p_KeysMatchTableNewTmp = + PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j * size * sizeof(uint8_t)); + +- Mem2IOCpy32(p_KeysMatchTableNewTmp, p_Key, ++ MemCpy8(p_KeysMatchTableNewTmp, p_Key, + p_CcNode->userSizeOfExtraction); + + if (p_CcNode->lclMask) + { + if (p_Mask) +- Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ MemCpy8(PTR_MOVE(p_KeysMatchTableNewTmp, + p_CcNode->ccKeySizeAccExtraction), + p_Mask, p_CcNode->userSizeOfExtraction); + else + if (p_CcNode->ccKeySizeAccExtraction > 4) +- IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ MemSet8(PTR_MOVE(p_KeysMatchTableNewTmp, + p_CcNode->ccKeySizeAccExtraction), + 0xff, p_CcNode->userSizeOfExtraction); + else +- Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ MemCpy8(PTR_MOVE(p_KeysMatchTableNewTmp, + p_CcNode->ccKeySizeAccExtraction), + p_CcNode->p_GlblMask, + p_CcNode->userSizeOfExtraction); +@@ -3050,7 +3050,7 @@ static t_Error BuildNewNodeModifyKey( + if (p_CcNode->lclMask) + { + if (prvLclMask) +- IO2IOCpy32( ++ MemCpy8( + PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction), + PTR_MOVE(p_KeysMatchTableOldTmp, p_CcNode->ccKeySizeAccExtraction), + p_CcNode->userSizeOfExtraction); +@@ -3061,17 +3061,17 @@ static t_Error BuildNewNodeModifyKey( + i * (int)p_CcNode->ccKeySizeAccExtraction * sizeof(uint8_t)); + + if (p_CcNode->ccKeySizeAccExtraction > 4) +- IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp, ++ MemSet8(PTR_MOVE(p_KeysMatchTableNewTmp, + p_CcNode->ccKeySizeAccExtraction), + 0xff, p_CcNode->userSizeOfExtraction); + else +- IO2IOCpy32( ++ MemCpy8( + PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction), + p_CcNode->p_GlblMask, + p_CcNode->userSizeOfExtraction); + } + } +- IO2IOCpy32((void*)p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp, ++ MemCpy8((void*)p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp, + p_CcNode->ccKeySizeAccExtraction); + } + } +@@ -3080,7 +3080,7 @@ static t_Error BuildNewNodeModifyKey( + PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j * FM_PCD_CC_AD_ENTRY_SIZE); + p_AdTableOldTmp = PTR_MOVE(p_CcNode->h_AdTable, i * FM_PCD_CC_AD_ENTRY_SIZE); + +- IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); ++ MemCpy8(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE); + + return E_OK; + } +@@ -3203,7 +3203,7 @@ static t_Error BuildNewNodeModifyNextEngine( + if (!p_Ad) + RETURN_ERROR(MAJOR, E_NO_MEMORY, + ("MURAM allocation for CC node action descriptor")); +- IOMemSet32((uint8_t *)p_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ MemSet8((uint8_t *)p_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); + + /* If statistics were not enabled before, but requested now - Allocate a statistics + object that holds statistics AD and counters. */ +@@ -3568,7 +3568,7 @@ static t_Error UpdatePtrWhichPointOnCrntMdfNode( + h_NewAd = GetNewAd(p_CcNode, FALSE); + if (!h_NewAd) + RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); +- IOMemSet32(h_NewAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ MemSet8(h_NewAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); + + h_OrigAd = p_CcNode->h_Ad; + BuildNewAd(h_NewAd, p_FmPcdModifyCcKeyAdditionalParams, p_CcNode, +@@ -4054,6 +4054,7 @@ static t_Error IcHashIndexedCheckParams(t_Handle h_FmPcd, + } + + *isKeyTblAlloc = FALSE; ++ cpu_to_be16s(&glblMask); + memcpy(PTR_MOVE(p_CcNode->p_GlblMask, 2), &glblMask, 2); + + return E_OK; +@@ -4251,7 +4252,7 @@ static t_Error AllocStatsObjs(t_FmPcdCcNode *p_CcNode) + RETURN_ERROR(MAJOR, E_NO_MEMORY, + ("MURAM allocation for statistics ADs")); + } +- IOMemSet32(h_StatsAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ MemSet8(h_StatsAd, 0, FM_PCD_CC_AD_ENTRY_SIZE); + + /* Allocate statistics counters from MURAM */ + h_StatsCounters = (t_Handle)FM_MURAM_AllocMem( +@@ -4265,7 +4266,7 @@ static t_Error AllocStatsObjs(t_FmPcdCcNode *p_CcNode) + RETURN_ERROR(MAJOR, E_NO_MEMORY, + ("MURAM allocation for statistics counters")); + } +- IOMemSet32(h_StatsCounters, 0, p_CcNode->countersArraySize); ++ MemSet8(h_StatsCounters, 0, p_CcNode->countersArraySize); + + p_StatsObj->h_StatsAd = h_StatsAd; + p_StatsObj->h_StatsCounters = h_StatsCounters; +@@ -4668,11 +4669,14 @@ static t_Error MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNode *p_CcNode, + /* Initialize using value received from the user */ + for (tmp = 0; tmp < p_CcNode->numOfStatsFLRs; tmp++) + { ++ uint16_t flr = ++ cpu_to_be16(p_CcNodeParam->keysParams.frameLengthRanges[tmp]); ++ + h_StatsFLRs = + PTR_MOVE(p_CcNode->h_StatsFLRs, tmp * FM_PCD_CC_STATS_FLR_SIZE); + +- Mem2IOCpy32(h_StatsFLRs, +- &(p_CcNodeParam->keysParams.frameLengthRanges[tmp]), ++ MemCpy8(h_StatsFLRs, ++ &flr, + FM_PCD_CC_STATS_FLR_SIZE); + } + break; +@@ -4694,7 +4698,7 @@ static t_Error MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNode *p_CcNode, + RETURN_ERROR(MAJOR, E_NO_MEMORY, + ("MURAM allocation for CC node key match table")); + } +- IOMemSet32((uint8_t *)p_CcNode->h_KeysMatchTable, 0, matchTableSize); ++ MemSet8((uint8_t *)p_CcNode->h_KeysMatchTable, 0, matchTableSize); + } + + /* Allocate action descriptors table */ +@@ -4706,7 +4710,7 @@ static t_Error MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNode *p_CcNode, + RETURN_ERROR(MAJOR, E_NO_MEMORY, + ("MURAM allocation for CC node action descriptors table")); + } +- IOMemSet32((uint8_t *)p_CcNode->h_AdTable, 0, adTableSize); ++ MemSet8((uint8_t *)p_CcNode->h_AdTable, 0, adTableSize); + + p_KeysMatchTblTmp = p_CcNode->h_KeysMatchTable; + p_AdTableTmp = p_CcNode->h_AdTable; +@@ -4719,20 +4723,20 @@ static t_Error MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNode *p_CcNode, + if (p_KeysMatchTblTmp) + { + /* Copy the key */ +- Mem2IOCpy32((void*)p_KeysMatchTblTmp, p_KeyParams->p_Key, ++ MemCpy8((void*)p_KeysMatchTblTmp, p_KeyParams->p_Key, + p_CcNode->sizeOfExtraction); + + /* Copy the key mask or initialize it to 0xFF..F */ + if (p_CcNode->lclMask && p_KeyParams->p_Mask) + { +- Mem2IOCpy32(PTR_MOVE(p_KeysMatchTblTmp, ++ MemCpy8(PTR_MOVE(p_KeysMatchTblTmp, + p_CcNode->ccKeySizeAccExtraction), /* User's size of extraction rounded up to a valid matching table entry size */ + p_KeyParams->p_Mask, p_CcNode->sizeOfExtraction); /* Exact size of extraction as received from the user */ + } + else + if (p_CcNode->lclMask) + { +- IOMemSet32(PTR_MOVE(p_KeysMatchTblTmp, ++ MemSet8(PTR_MOVE(p_KeysMatchTblTmp, + p_CcNode->ccKeySizeAccExtraction), /* User's size of extraction rounded up to a valid matching table entry size */ + 0xff, p_CcNode->sizeOfExtraction); /* Exact size of extraction as received from the user */ + } +@@ -6174,7 +6178,7 @@ t_Handle FM_PCD_CcRootBuild(t_Handle h_FmPcd, + REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree")); + return NULL; + } +- IOMemSet32( ++ MemSet8( + UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr), 0, + (uint32_t)(FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE)); + +@@ -7079,6 +7083,7 @@ t_Error FM_PCD_MatchTableGetIndexedHashBucket(t_Handle h_CcNode, + SANITY_CHECK_RETURN_ERROR(p_CcNodeBucketHandle, E_NULL_POINTER); + + memcpy(&glblMask, PTR_MOVE(p_CcNode->p_GlblMask, 2), 2); ++ be16_to_cpus(&glblMask); + + crc64 = crc64_init(); + crc64 = crc64_compute(p_Key, keySize, crc64); +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_manip.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_manip.c +index e980320..113777e 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_manip.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_manip.c +@@ -182,6 +182,7 @@ static t_Error CalculateTableSize(t_FmPcdManipParams *p_FmPcdManipParams, + switch (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.specificL2) + { + case (e_FM_PCD_MANIP_HDR_INSRT_MPLS): ++ case (e_FM_PCD_MANIP_HDR_INSRT_PPPOE): + dataSize += + p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.size; + break; +@@ -472,6 +473,9 @@ static t_Error BuildHmct(t_FmPcdManip *p_Manip, + case (e_FM_PCD_MANIP_HDR_RMV_MPLS): + hmcdOpt = HMCD_RMV_L2_MPLS; + break; ++ case (e_FM_PCD_MANIP_HDR_RMV_PPPOE): ++ hmcdOpt = HMCD_RMV_L2_PPPOE; ++ break; + default: + RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); + } +@@ -556,8 +560,8 @@ static t_Error BuildHmct(t_FmPcdManip *p_Manip, + p_LocalData = (uint32_t*)p_UsrData; + + /* initialize data and advance pointer to next command */ +- for (i = 0; i < size / 4; i++, p_TmpHmct += HMCD_BASIC_SIZE / 4) +- WRITE_UINT32(*p_TmpHmct, *(p_LocalData+i)); ++ MemCpy8(p_TmpHmct, p_LocalData, size); ++ p_TmpHmct += size / sizeof(uint32_t); + + if (remain) + XX_Free(p_LocalData); +@@ -585,6 +589,9 @@ static t_Error BuildHmct(t_FmPcdManip *p_Manip, + else + hmcdOpt = HMCD_INSRT_L2_MPLS; + break; ++ case (e_FM_PCD_MANIP_HDR_INSRT_PPPOE): ++ hmcdOpt = HMCD_INSRT_L2_PPPOE; ++ break; + default: + RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG); + } +@@ -601,7 +608,7 @@ static t_Error BuildHmct(t_FmPcdManip *p_Manip, + (uint8_t)p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.size; + + ASSERT_COND(p_TmpData); +- Mem2IOCpy32( ++ MemCpy8( + p_TmpData, + p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.p_Data, + size); +@@ -654,7 +661,7 @@ static t_Error BuildHmct(t_FmPcdManip *p_Manip, + WRITE_UINT8(*p_TmpHmct, p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.lastDstOffset); + p_TmpHmct += HMCD_PARAM_SIZE / 4; + +- Mem2IOCpy32( ++ MemCpy8( + p_TmpHmct, + p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.insrt.p_Data, + p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.ipParams.insrt.size); +@@ -675,7 +682,7 @@ static t_Error BuildHmct(t_FmPcdManip *p_Manip, + + p_TmpHmct += HMCD_BASIC_SIZE / 4; + +- Mem2IOCpy32( ++ MemCpy8( + p_TmpHmct, + p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.p_Data, + p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.size); +@@ -695,7 +702,7 @@ static t_Error BuildHmct(t_FmPcdManip *p_Manip, + + p_TmpHmct += HMCD_BASIC_SIZE / 4; + +- Mem2IOCpy32( ++ MemCpy8( + p_TmpHmct, + p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.p_Data, + p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.insrt.size); +@@ -989,7 +996,7 @@ static t_Error BuildHmct(t_FmPcdManip *p_Manip, + size = + p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdrSize; + ASSERT_COND(p_TmpData); +- Mem2IOCpy32( ++ MemCpy8( + p_TmpData, + p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdr, + size); +@@ -1738,7 +1745,7 @@ static t_Error UpdateInitCapwapReasm(t_Handle h_FmPcd, + if (!p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl) + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly frame buffer index pool table")); + +- IOMemSet32(p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl, 0, (uint32_t)(size + 1)); ++ MemSet8(p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl, 0, (uint32_t)(size + 1)); + + for ( i = 0; i < size; i++) + WRITE_UINT8(*(uint8_t *)PTR_MOVE(p_Manip->capwapFragParams.p_ReassmFrmDescrIndxPoolTbl, i), (uint8_t)(i+1)); +@@ -1756,7 +1763,7 @@ static t_Error UpdateInitCapwapReasm(t_Handle h_FmPcd, + if (!p_Manip->capwapFragParams.p_ReassmFrmDescrPoolTbl) + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly frame buffer pool table")); + +- IOMemSet32(p_Manip->capwapFragParams.p_ReassmFrmDescrPoolTbl, 0, (uint32_t)((size +1)* FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE)); ++ MemSet8(p_Manip->capwapFragParams.p_ReassmFrmDescrPoolTbl, 0, (uint32_t)((size +1)* FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE)); + + tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->capwapFragParams.p_ReassmFrmDescrPoolTbl) - p_FmPcd->physicalMuramBase); + +@@ -1772,7 +1779,7 @@ static t_Error UpdateInitCapwapReasm(t_Handle h_FmPcd, + if (!p_Manip->capwapFragParams.p_TimeOutTbl) + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly timeout table")); + +- IOMemSet32(p_Manip->capwapFragParams.p_TimeOutTbl, 0, (uint16_t)((size + 1)*FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE)); ++ MemSet8(p_Manip->capwapFragParams.p_TimeOutTbl, 0, (uint16_t)((size + 1)*FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE)); + + tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->capwapFragParams.p_TimeOutTbl) - p_FmPcd->physicalMuramBase); + WRITE_UINT32(p_ReassmTbl->timeOutTblPtr, tmpReg32); +@@ -1922,7 +1929,7 @@ static t_Error CreateReassCommonTable(t_FmPcdManip *p_Manip) + RETURN_ERROR(MAJOR, E_NO_MEMORY, + ("MURAM alloc for Reassembly common parameters table")); + +- IOMemSet32(p_Manip->reassmParams.p_ReassCommonTbl, 0, ++ MemSet8(p_Manip->reassmParams.p_ReassCommonTbl, 0, + FM_PCD_MANIP_REASM_COMMON_PARAM_TABLE_SIZE); + + /* Setting the TimeOut Mode.*/ +@@ -1950,7 +1957,7 @@ static t_Error CreateReassCommonTable(t_FmPcdManip *p_Manip) + MAJOR, E_NO_MEMORY, + ("MURAM alloc for Reassembly frame descriptor indexes pool")); + +- IOMemSet32(UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrIndxPoolTblAddr), ++ MemSet8(UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrIndxPoolTblAddr), + 0, (uint32_t)(size * 2)); + + /* The entries in IP Reassembly Frame Descriptor Indexes Pool contains indexes starting with 1 up to +@@ -1977,7 +1984,7 @@ static t_Error CreateReassCommonTable(t_FmPcdManip *p_Manip) + if (!p_Manip->reassmParams.reassFrmDescrPoolTblAddr) + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED")); + +- IOMemSet32(UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrPoolTblAddr), 0, ++ MemSet8(UINT_TO_PTR(p_Manip->reassmParams.reassFrmDescrPoolTblAddr), 0, + (uint32_t)(size * 64)); + + /* Sets the Reassembly Frame Descriptors Pool and liodn offset*/ +@@ -2005,7 +2012,7 @@ static t_Error CreateReassCommonTable(t_FmPcdManip *p_Manip) + RETURN_ERROR(MAJOR, E_NO_MEMORY, + ("MURAM alloc for Reassembly timeout table")); + +- IOMemSet32(UINT_TO_PTR(p_Manip->reassmParams.timeOutTblAddr), 0, ++ MemSet8(UINT_TO_PTR(p_Manip->reassmParams.timeOutTblAddr), 0, + (uint16_t)(size * 8)); + + /* Sets the TimeOut table offset from MURAM */ +@@ -2144,7 +2151,7 @@ static t_Error CreateReassTable(t_FmPcdManip *p_Manip, e_NetHeaderType hdr) + *p_ReassTbl = NULL; + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED")); + } +- IOMemSet32(UINT_TO_PTR(*p_AutoLearnHashTblAddr), 0, autoLearnHashTblSize); ++ MemSet8(UINT_TO_PTR(*p_AutoLearnHashTblAddr), 0, autoLearnHashTblSize); + + /* Sets the Reassembly Automatic Learning Hash Table and liodn offset */ + tmpReg64 = ((uint64_t)(p_Manip->reassmParams.dataLiodnOffset +@@ -2171,7 +2178,7 @@ static t_Error CreateReassTable(t_FmPcdManip *p_Manip, e_NetHeaderType hdr) + *p_AutoLearnHashTblAddr = 0; + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED")); + } +- IOMemSet32(UINT_TO_PTR(*p_AutoLearnSetLockTblAddr), 0, (numOfSets * 4)); ++ MemSet8(UINT_TO_PTR(*p_AutoLearnSetLockTblAddr), 0, (numOfSets * 4)); + + /* sets Set Lock table pointer and liodn offset*/ + tmpReg64 = ((uint64_t)(p_Manip->reassmParams.dataLiodnOffset +@@ -2266,7 +2273,7 @@ static t_Error UpdateInitReasm(t_Handle h_FmPcd, t_Handle h_PcdParams, + RETURN_ERROR( + MAJOR, E_NO_MEMORY, + ("MURAM alloc for Reassembly internal buffers pool")); +- IOMemSet32( ++ MemSet8( + UINT_TO_PTR(p_Manip->reassmParams.internalBufferPoolAddr), + 0, (uint32_t)(totalNumOfTnums * BMI_FIFO_UNITS)); + +@@ -2961,7 +2968,7 @@ static t_Error UpdateIndxStats(t_Handle h_FmPcd, + if (!p_Manip->p_StatsTbl) + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Manipulation indexed statistics table")); + +- IOMemSet32(p_Manip->p_StatsTbl, 0, (uint32_t)(p_Manip->owner * 4)); ++ MemSet8(p_Manip->p_StatsTbl, 0, (uint32_t)(p_Manip->owner * 4)); + + tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->p_StatsTbl) - p_FmPcd->physicalMuramBase); + +@@ -3122,7 +3129,7 @@ static t_Error CapwapReassembly(t_CapwapReassemblyParams *p_ManipParams, + if (!p_Manip->h_Frag) + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc CAPWAP reassembly parameters table")); + +- IOMemSet32(p_Manip->h_Frag, 0, FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE); ++ MemSet8(p_Manip->h_Frag, 0, FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE); + + p_Table = (t_CapwapReasmPram *)p_Manip->h_Frag; + +@@ -3134,7 +3141,7 @@ static t_Error CapwapReassembly(t_CapwapReassemblyParams *p_ManipParams, + if (!p_Manip->capwapFragParams.p_AutoLearnHashTbl) + RETURN_ERROR(MAJOR, E_NO_MEMORY,("MURAM alloc for CAPWAP automatic learning hash table")); + +- IOMemSet32(p_Manip->capwapFragParams.p_AutoLearnHashTbl, 0, (uint32_t)(p_ManipParams->maxNumFramesInProcess * 2 * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE)); ++ MemSet8(p_Manip->capwapFragParams.p_AutoLearnHashTbl, 0, (uint32_t)(p_ManipParams->maxNumFramesInProcess * 2 * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE)); + + tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->capwapFragParams.p_AutoLearnHashTbl) - p_FmPcd->physicalMuramBase); + +@@ -3204,7 +3211,7 @@ static t_Error CapwapFragmentation(t_CapwapFragmentationParams *p_ManipParams, + if (!p_Manip->h_Frag) + RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP fragmentation table descriptor")); + +- IOMemSet32(p_Manip->h_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ MemSet8(p_Manip->h_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE); + + p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Frag; + +@@ -3422,7 +3429,7 @@ static t_Error InsrtHdrByTempl(t_FmPcdManipHdrInsrtParams *p_ManipParams, t_FmPc + p_Template[14] = tmpReg8; + } + +- Mem2IOCpy32(p_Manip->p_Template, p_Template, p_InsrtByTemplate->size); ++ MemCpy8(p_Manip->p_Template, p_Template, p_InsrtByTemplate->size); + + XX_Free(p_Template); + } +@@ -3899,7 +3906,7 @@ static t_Error IpFragmentation(t_FmPcdManipFragIpParams *p_ManipParams, + if (!p_Manip->fragParams.p_Frag) + RETURN_ERROR(MAJOR, E_NO_MEMORY, + ("MURAM alloc for Fragmentation table descriptor")); +- IOMemSet32(p_Manip->fragParams.p_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ MemSet8(p_Manip->fragParams.p_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE); + + /* Prepare the third Ad register (pcAndOffsets)- OperationCode */ + pcAndOffsetsReg = (uint32_t)HMAN_OC_IP_FRAGMENTATION; +@@ -4288,7 +4295,7 @@ static t_Error CapwapFragmentation(t_FmPcdManipFragCapwapParams *p_ManipParams, + if (!p_Manip->fragParams.p_Frag) + RETURN_ERROR(MAJOR, E_NO_MEMORY, + ("MURAM alloc for Fragmentation table descriptor")); +- IOMemSet32(p_Manip->fragParams.p_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ MemSet8(p_Manip->fragParams.p_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE); + + /* Prepare the third Ad register (pcAndOffsets)- OperationCode */ + pcAndOffsetsReg = (uint32_t)HMAN_OC_CAPWAP_FRAGMENTATION; +@@ -4464,7 +4471,7 @@ static t_Handle ManipOrStatsSetNode(t_Handle h_FmPcd, t_Handle *p_Params, + return NULL; + } + +- IOMemSet32(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ MemSet8(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); + } + else + { +@@ -4538,7 +4545,7 @@ static void BuildHmtd(uint8_t *p_Dest, uint8_t *p_Src, uint8_t *p_Hmcd, + t_Error err; + + /* Copy the HMTD */ +- IO2IOCpy32(p_Dest, (uint8_t*)p_Src, 16); ++ MemCpy8(p_Dest, (uint8_t*)p_Src, 16); + /* Replace the HMCT table pointer */ + WRITE_UINT32( + ((t_Hmtd *)p_Dest)->hmcdBasePtr, +@@ -4975,7 +4982,7 @@ void FmPcdManipUpdateAdContLookupForCc(t_Handle h_Manip, t_Handle p_Ad, + #endif /* (defined(FM_CAPWAP_SUPPORT) && (DPAA_VERSION == 10)) */ + case (HMAN_OC): + /* Initialize HMTD within the match table*/ +- IOMemSet32(p_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); ++ MemSet8(p_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE); + /* copy the existing HMTD *//* ask Alla - memcpy??? */ + memcpy((uint8_t*)p_Ad, p_Manip->h_Ad, sizeof(t_Hmtd)); + /* update NADEN to be "1"*/ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_manip.h b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_manip.h +index ebafd63..853bb83 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_manip.h ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_manip.h +@@ -222,9 +222,11 @@ + #define HMCD_RMV_L2_STACKED_QTAGS 1 + #define HMCD_RMV_L2_ETHERNET_AND_MPLS 2 + #define HMCD_RMV_L2_MPLS 3 ++#define HMCD_RMV_L2_PPPOE 4 + + #define HMCD_INSRT_L2_MPLS 0 + #define HMCD_INSRT_N_UPDATE_L2_MPLS 1 ++#define HMCD_INSRT_L2_PPPOE 2 + #define HMCD_INSRT_L2_SIZE_SHIFT 24 + + #define HMCD_L2_MODE_SHIFT 16 +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_prs.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_prs.c +index da2fccf..a21b104 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_prs.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/Pcd/fm_prs.c +@@ -160,8 +160,8 @@ t_Error PrsInit(t_FmPcd *p_FmPcd) + FmEnableRamsEcc(p_FmPcd->h_Fm); + + /* load sw parser Ip-Frag patch */ +- for (i=0; ip_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4; +- for(i=0; isize,4); i++) +- WRITE_UINT32(p_LoadTarget[i], p_TmpCode[i]); ++ ++ for(i=0; isize, 4); i++) ++ WRITE_UINT32(p_LoadTarget[i], GET_UINT32(p_TmpCode[i])); ++ + p_FmPcd->p_FmPcdPrs->p_CurrSwPrs = + p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4 + ROUND_UP(p_SwPrs->size,4); + +diff --git a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.c b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.c +index 71ef3a2..f5040c7 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/Peripherals/FM/fm.c +@@ -47,7 +47,9 @@ + #include "fm_common.h" + #include "fm_ipc.h" + #include "fm.h" ++#ifndef CONFIG_ARM64 + #include ++#endif + #include "fsl_fman.h" + + +@@ -3530,6 +3532,7 @@ t_Error FM_Init(t_Handle h_Fm) + if ((err = FwNotResetErratumBugzilla6173WA(p_Fm)) != E_OK) + RETURN_ERROR(MAJOR, err, NO_MSG); + #else /* not FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */ ++#ifndef CONFIG_FMAN_ARM + { + u32 svr = mfspr(SPRN_SVR); + +@@ -3547,6 +3550,7 @@ t_Error FM_Init(t_Handle h_Fm) + XX_UDelay(100); + } + } ++#endif + if (fman_is_qmi_halt_not_busy_state(p_Fm->p_FmQmiRegs)) + { + fman_resume(p_Fm->p_FmFpmRegs); +diff --git a/drivers/net/ethernet/freescale/sdk_fman/etc/memcpy.c b/drivers/net/ethernet/freescale/sdk_fman/etc/memcpy.c +index 02973e5..fa203ec 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/etc/memcpy.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/etc/memcpy.c +@@ -36,6 +36,25 @@ + #include "xx_ext.h" + #include "memcpy_ext.h" + ++void * MemCpy8(void* pDst, void* pSrc, uint32_t size) ++{ ++ int i; ++ ++ for(i = 0; i < size; ++i) ++ *(((uint8_t*)(pDst)) + i) = *(((uint8_t*)(pSrc)) + i); ++ ++ return pDst; ++} ++ ++void * MemSet8(void* pDst, int c, uint32_t size) ++{ ++ int i; ++ ++ for(i = 0; i < size; ++i) ++ *(((uint8_t*)(pDst)) + i) = (uint8_t)(c); ++ ++ return pDst; ++} + + void * MemCpy32(void* pDst,void* pSrc, uint32_t size) + { +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_pcd_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_pcd_ext.h +index a9e4a24..8d1c3d8 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_pcd_ext.h ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/Peripherals/fm_pcd_ext.h +@@ -1121,7 +1121,8 @@ typedef enum e_FmPcdManipHdrRmvSpecificL2 { + e_FM_PCD_MANIP_HDR_RMV_STACKED_QTAGS, /**< stacked QTags */ + e_FM_PCD_MANIP_HDR_RMV_ETHERNET_AND_MPLS, /**< MPLS and Ethernet/802.3 MAC header until + the header which follows the MPLS header */ +- e_FM_PCD_MANIP_HDR_RMV_MPLS /**< Remove MPLS header (Unlimited MPLS labels) */ ++ e_FM_PCD_MANIP_HDR_RMV_MPLS, /**< Remove MPLS header (Unlimited MPLS labels) */ ++ e_FM_PCD_MANIP_HDR_RMV_PPPOE /**< Remove the PPPoE header and PPP protocol field. */ + } e_FmPcdManipHdrRmvSpecificL2; + + /**************************************************************************//** +@@ -1146,7 +1147,8 @@ typedef enum e_FmPcdManipHdrFieldUpdateVlan { + @Description Enumeration type for selecting specific L2 header insertion + *//***************************************************************************/ + typedef enum e_FmPcdManipHdrInsrtSpecificL2 { +- e_FM_PCD_MANIP_HDR_INSRT_MPLS /**< Insert MPLS header (Unlimited MPLS labels) */ ++ e_FM_PCD_MANIP_HDR_INSRT_MPLS, /**< Insert MPLS header (Unlimited MPLS labels) */ ++ e_FM_PCD_MANIP_HDR_INSRT_PPPOE /**< Insert PPPOE */ + } e_FmPcdManipHdrInsrtSpecificL2; + + #if (DPAA_VERSION >= 11) +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/core_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/core_ext.h +index 42174cf..ec89a6d 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/inc/core_ext.h ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/core_ext.h +@@ -43,7 +43,10 @@ + #ifndef __CORE_EXT_H + #define __CORE_EXT_H + +- ++#ifdef CONFIG_FMAN_ARM ++#include "arm_ext.h" ++#include ++#else + #ifdef NCSW_PPC_CORE + #include "ppc_ext.h" + #elif defined(NCSW_VXWORKS) +@@ -60,6 +63,8 @@ + #error "Must define the core cache-line size!" + #endif /* !CORE_CACHELINE_SIZE */ + ++#endif /* CONFIG_FMAN_ARM */ ++ + + /**************************************************************************//** + @Function CORE_GetId +@@ -83,4 +88,3 @@ void CORE_MemoryBarrier(void); + #define fsl_mem_core_barrier() CORE_MemoryBarrier() + + #endif /* __CORE_EXT_H */ +- +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/cores/arm_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/cores/arm_ext.h +new file mode 100644 +index 0000000..e63444a +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/cores/arm_ext.h +@@ -0,0 +1,55 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++ ++/**************************************************************************//** ++ @File arm_ext.h ++ ++ @Description Core API for ARM cores ++ ++ These routines must be implemented by each specific PowerPC ++ core driver. ++*//***************************************************************************/ ++#ifndef __ARM_EXT_H ++#define __ARM_EXT_H ++ ++#include "part_ext.h" ++ ++ ++#define CORE_IS_LITTLE_ENDIAN ++ ++static __inline__ void CORE_MemoryBarrier(void) ++{ ++ mb(); ++} ++ ++#endif /* __PPC_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/error_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/error_ext.h +index 71f9398..2a5ad67 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/inc/error_ext.h ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/error_ext.h +@@ -327,7 +327,7 @@ int ERROR_DYNAMIC_LEVEL = ERROR_GLOBAL_LEVEL; + #endif /* !ERROR_DYNAMIC_LEVEL */ + + #define PRINT_FORMAT "[CPU%02d, %s:%d %s]" +-#define PRINT_FMT_PARAMS CORE_GetId(), __FILE__, __LINE__, __FUNCTION__ ++#define PRINT_FMT_PARAMS raw_smp_processor_id(), __FILE__, __LINE__, __FUNCTION__ + + #if (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) + /* No debug/error/event messages at all */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/etc/memcpy_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/etc/memcpy_ext.h +index cc5bb72..1b3a2fa 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/inc/etc/memcpy_ext.h ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/etc/memcpy_ext.h +@@ -167,6 +167,40 @@ void * MemSet64(void* pDst, uint8_t val, uint32_t size); + *//***************************************************************************/ + void MemDisp(uint8_t *addr, int size); + ++/**************************************************************************//** ++ @Function MemCpy8 ++ ++ @Description Trivial copy one memory buffer into another byte by byte ++ ++ @Param[in] pDst - The address of the destination buffer. ++ @Param[in] pSrc - The address of the source buffer. ++ @Param[in] size - The number of bytes that will be copied from pSrc to pDst. ++ ++ @Return pDst (the address of the destination buffer). ++ ++ @Cautions There is no parameter or boundary checking! It is up to the user ++ to supply non-null parameters as source & destination and size ++ that actually fits into the destination buffer. ++*//***************************************************************************/ ++void * MemCpy8(void* pDst,void* pSrc, uint32_t size); ++ ++/**************************************************************************//** ++ @Function MemSet8 ++ ++ @Description Sets all bytes of a memory buffer to a specific value byte by byte. ++ ++ @Param[in] pDst - The address of the destination buffer. ++ @Param[in] c - Value to set destination bytes to. ++ @Param[in] size - The number of bytes that will be set to val. ++ ++ @Return pDst (the address of the destination buffer). ++ ++ @Cautions There is no parameter or boundary checking! It is up to the user ++ to supply non null parameter as destination and size ++ that actually fits into the destination buffer. ++*//***************************************************************************/ ++void * MemSet8(void* pDst, int c, uint32_t size); ++ + /** @} */ /* end of mem_cpy group */ + /** @} */ /* end of etc_id group */ + +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/common/general.h b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/common/general.h +index 8150e01..b3f516f 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/inc/flib/common/general.h ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/flib/common/general.h +@@ -41,9 +41,10 @@ + + extern uint32_t get_mac_addr_crc(uint64_t _addr); + +- ++#ifndef CONFIG_FMAN_ARM + #define iowrite32be(val, addr) WRITE_UINT32(*addr, val) + #define ioread32be(addr) GET_UINT32(*addr) ++#endif + + #define ether_crc(len, addr) get_mac_addr_crc(*(uint64_t *)(addr)>>16) + +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/LS1043/dpaa_integration_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/LS1043/dpaa_integration_ext.h +new file mode 100644 +index 0000000..5a8f358 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/LS1043/dpaa_integration_ext.h +@@ -0,0 +1,291 @@ ++/* ++ * Copyright 2012 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. ++ */ ++ ++/** ++ ++ @File dpaa_integration_ext.h ++ ++ @Description T4240 FM external definitions and structures. ++*//***************************************************************************/ ++#ifndef __DPAA_INTEGRATION_EXT_H ++#define __DPAA_INTEGRATION_EXT_H ++ ++#include "std_ext.h" ++ ++ ++#define DPAA_VERSION 11 ++ ++/**************************************************************************//** ++ @Description DPAA SW Portals Enumeration. ++*//***************************************************************************/ ++typedef enum ++{ ++ e_DPAA_SWPORTAL0 = 0, ++ e_DPAA_SWPORTAL1, ++ e_DPAA_SWPORTAL2, ++ e_DPAA_SWPORTAL3, ++ e_DPAA_SWPORTAL4, ++ e_DPAA_SWPORTAL5, ++ e_DPAA_SWPORTAL6, ++ e_DPAA_SWPORTAL7, ++ e_DPAA_SWPORTAL8, ++ e_DPAA_SWPORTAL9, ++ e_DPAA_SWPORTAL10, ++ e_DPAA_SWPORTAL11, ++ e_DPAA_SWPORTAL12, ++ e_DPAA_SWPORTAL13, ++ e_DPAA_SWPORTAL14, ++ e_DPAA_SWPORTAL15, ++ e_DPAA_SWPORTAL16, ++ e_DPAA_SWPORTAL17, ++ e_DPAA_SWPORTAL18, ++ e_DPAA_SWPORTAL19, ++ e_DPAA_SWPORTAL20, ++ e_DPAA_SWPORTAL21, ++ e_DPAA_SWPORTAL22, ++ e_DPAA_SWPORTAL23, ++ e_DPAA_SWPORTAL24, ++ e_DPAA_SWPORTAL_DUMMY_LAST ++} e_DpaaSwPortal; ++ ++/**************************************************************************//** ++ @Description DPAA Direct Connect Portals Enumeration. ++*//***************************************************************************/ ++typedef enum ++{ ++ e_DPAA_DCPORTAL0 = 0, ++ e_DPAA_DCPORTAL1, ++ e_DPAA_DCPORTAL2, ++ e_DPAA_DCPORTAL_DUMMY_LAST ++} e_DpaaDcPortal; ++ ++#define DPAA_MAX_NUM_OF_SW_PORTALS e_DPAA_SWPORTAL_DUMMY_LAST ++#define DPAA_MAX_NUM_OF_DC_PORTALS e_DPAA_DCPORTAL_DUMMY_LAST ++ ++/***************************************************************************** ++ QMan INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define QM_MAX_NUM_OF_POOL_CHANNELS 15 /**< Total number of channels, dedicated and pool */ ++#define QM_MAX_NUM_OF_WQ 8 /**< Number of work queues per channel */ ++#define QM_MAX_NUM_OF_CGS 256 /**< Congestion groups number */ ++#define QM_MAX_NUM_OF_FQIDS (16 * MEGABYTE) ++ /**< FQIDs range - 24 bits */ ++ ++/**************************************************************************//** ++ @Description Work Queue Channel assignments in QMan. ++*//***************************************************************************/ ++typedef enum ++{ ++ e_QM_FQ_CHANNEL_SWPORTAL0 = 0x0, /**< Dedicated channels serviced by software portals 0 to 24 */ ++ e_QM_FQ_CHANNEL_SWPORTAL1, ++ e_QM_FQ_CHANNEL_SWPORTAL2, ++ e_QM_FQ_CHANNEL_SWPORTAL3, ++ e_QM_FQ_CHANNEL_SWPORTAL4, ++ e_QM_FQ_CHANNEL_SWPORTAL5, ++ e_QM_FQ_CHANNEL_SWPORTAL6, ++ e_QM_FQ_CHANNEL_SWPORTAL7, ++ e_QM_FQ_CHANNEL_SWPORTAL8, ++ e_QM_FQ_CHANNEL_SWPORTAL9, ++ e_QM_FQ_CHANNEL_SWPORTAL10, ++ e_QM_FQ_CHANNEL_SWPORTAL11, ++ e_QM_FQ_CHANNEL_SWPORTAL12, ++ e_QM_FQ_CHANNEL_SWPORTAL13, ++ e_QM_FQ_CHANNEL_SWPORTAL14, ++ e_QM_FQ_CHANNEL_SWPORTAL15, ++ e_QM_FQ_CHANNEL_SWPORTAL16, ++ e_QM_FQ_CHANNEL_SWPORTAL17, ++ e_QM_FQ_CHANNEL_SWPORTAL18, ++ e_QM_FQ_CHANNEL_SWPORTAL19, ++ e_QM_FQ_CHANNEL_SWPORTAL20, ++ e_QM_FQ_CHANNEL_SWPORTAL21, ++ e_QM_FQ_CHANNEL_SWPORTAL22, ++ e_QM_FQ_CHANNEL_SWPORTAL23, ++ e_QM_FQ_CHANNEL_SWPORTAL24, ++ ++ e_QM_FQ_CHANNEL_POOL1 = 0x401, /**< Pool channels that can be serviced by any of the software portals */ ++ e_QM_FQ_CHANNEL_POOL2, ++ e_QM_FQ_CHANNEL_POOL3, ++ e_QM_FQ_CHANNEL_POOL4, ++ e_QM_FQ_CHANNEL_POOL5, ++ e_QM_FQ_CHANNEL_POOL6, ++ e_QM_FQ_CHANNEL_POOL7, ++ e_QM_FQ_CHANNEL_POOL8, ++ e_QM_FQ_CHANNEL_POOL9, ++ e_QM_FQ_CHANNEL_POOL10, ++ e_QM_FQ_CHANNEL_POOL11, ++ e_QM_FQ_CHANNEL_POOL12, ++ e_QM_FQ_CHANNEL_POOL13, ++ e_QM_FQ_CHANNEL_POOL14, ++ e_QM_FQ_CHANNEL_POOL15, ++ ++ e_QM_FQ_CHANNEL_FMAN0_SP0 = 0x800, /**< Dedicated channels serviced by Direct Connect Portal 0: ++ connected to FMan 0; assigned in incrementing order to ++ each sub-portal (SP) in the portal */ ++ e_QM_FQ_CHANNEL_FMAN0_SP1, ++ e_QM_FQ_CHANNEL_FMAN0_SP2, ++ e_QM_FQ_CHANNEL_FMAN0_SP3, ++ e_QM_FQ_CHANNEL_FMAN0_SP4, ++ e_QM_FQ_CHANNEL_FMAN0_SP5, ++ e_QM_FQ_CHANNEL_FMAN0_SP6, ++ e_QM_FQ_CHANNEL_FMAN0_SP7, ++ e_QM_FQ_CHANNEL_FMAN0_SP8, ++ e_QM_FQ_CHANNEL_FMAN0_SP9, ++ e_QM_FQ_CHANNEL_FMAN0_SP10, ++ e_QM_FQ_CHANNEL_FMAN0_SP11, ++ e_QM_FQ_CHANNEL_FMAN0_SP12, ++ e_QM_FQ_CHANNEL_FMAN0_SP13, ++ e_QM_FQ_CHANNEL_FMAN0_SP14, ++ e_QM_FQ_CHANNEL_FMAN0_SP15, ++ ++ e_QM_FQ_CHANNEL_RMAN_SP0 = 0x820, /**< Dedicated channels serviced by Direct Connect Portal 1: connected to RMan */ ++ e_QM_FQ_CHANNEL_RMAN_SP1, ++ ++ e_QM_FQ_CHANNEL_CAAM = 0x840 /**< Dedicated channel serviced by Direct Connect Portal 2: ++ connected to SEC */ ++} e_QmFQChannel; ++ ++/***************************************************************************** ++ BMan INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define BM_MAX_NUM_OF_POOLS 64 /**< Number of buffers pools */ ++ ++/***************************************************************************** ++ SEC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define SEC_NUM_OF_DECOS 3 ++#define SEC_ALL_DECOS_MASK 0x00000003 ++ ++ ++/***************************************************************************** ++ FM INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define INTG_MAX_NUM_OF_FM 2 ++ ++/* Ports defines */ ++#define FM_MAX_NUM_OF_1G_MACS 6 ++#define FM_MAX_NUM_OF_10G_MACS 2 ++#define FM_MAX_NUM_OF_MACS (FM_MAX_NUM_OF_1G_MACS + FM_MAX_NUM_OF_10G_MACS) ++#define FM_MAX_NUM_OF_OH_PORTS 6 ++ ++#define FM_MAX_NUM_OF_1G_RX_PORTS FM_MAX_NUM_OF_1G_MACS ++#define FM_MAX_NUM_OF_10G_RX_PORTS FM_MAX_NUM_OF_10G_MACS ++#define FM_MAX_NUM_OF_RX_PORTS (FM_MAX_NUM_OF_10G_RX_PORTS + FM_MAX_NUM_OF_1G_RX_PORTS) ++ ++#define FM_MAX_NUM_OF_1G_TX_PORTS FM_MAX_NUM_OF_1G_MACS ++#define FM_MAX_NUM_OF_10G_TX_PORTS FM_MAX_NUM_OF_10G_MACS ++#define FM_MAX_NUM_OF_TX_PORTS (FM_MAX_NUM_OF_10G_TX_PORTS + FM_MAX_NUM_OF_1G_TX_PORTS) ++ ++#define FM_PORT_MAX_NUM_OF_EXT_POOLS 4 /**< Number of external BM pools per Rx port */ ++#define FM_PORT_NUM_OF_CONGESTION_GRPS 256 /**< Total number of congestion groups in QM */ ++#define FM_MAX_NUM_OF_SUB_PORTALS 16 ++#define FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS 0 ++ ++#define FM_VSP_MAX_NUM_OF_ENTRIES 64 ++#define FM_MAX_NUM_OF_PFC_PRIORITIES 8 ++ ++/* RAMs defines */ ++#define FM_MURAM_SIZE (384 * KILOBYTE) ++#define FM_IRAM_SIZE(major, minor) (64 * KILOBYTE) ++#define FM_NUM_OF_CTRL 4 ++ ++/* PCD defines */ ++#define FM_PCD_PLCR_NUM_ENTRIES 256 /**< Total number of policer profiles */ ++#define FM_PCD_KG_NUM_OF_SCHEMES 32 /**< Total number of KG schemes */ ++#define FM_PCD_MAX_NUM_OF_CLS_PLANS 256 /**< Number of classification plan entries. */ ++#define FM_PCD_PRS_SW_PATCHES_SIZE 0x00000600 /**< Number of bytes saved for patches */ ++#define FM_PCD_SW_PRS_SIZE 0x00000800 /**< Total size of SW parser area */ ++ ++/* RTC defines */ ++#define FM_RTC_NUM_OF_ALARMS 2 /**< RTC number of alarms */ ++#define FM_RTC_NUM_OF_PERIODIC_PULSES 3 /**< RTC number of periodic pulses */ ++#define FM_RTC_NUM_OF_EXT_TRIGGERS 2 /**< RTC number of external triggers */ ++ ++/* QMI defines */ ++#define QMI_MAX_NUM_OF_TNUMS 64 ++#define QMI_DEF_TNUMS_THRESH 32 ++/* FPM defines */ ++#define FM_NUM_OF_FMAN_CTRL_EVENT_REGS 4 ++ ++/* DMA defines */ ++#define DMA_THRESH_MAX_COMMQ 83 ++#define DMA_THRESH_MAX_BUF 127 ++ ++/* BMI defines */ ++#define BMI_MAX_NUM_OF_TASKS 128 ++#define BMI_MAX_NUM_OF_DMAS 84 ++ ++#define BMI_MAX_FIFO_SIZE (FM_MURAM_SIZE) ++#define PORT_MAX_WEIGHT 16 ++ ++#define FM_CHECK_PORT_RESTRICTIONS(__validPorts, __newPortIndx) TRUE ++ ++/* Unique T4240 */ ++#define FM_OP_OPEN_DMA_MIN_LIMIT ++#define FM_NO_RESTRICT_ON_ACCESS_RSRC ++#define FM_NO_OP_OBSERVED_POOLS ++#define FM_FRAME_END_PARAMS_FOR_OP ++#define FM_DEQ_PIPELINE_PARAMS_FOR_OP ++#define FM_QMI_NO_SINGLE_ECC_EXCEPTION ++ ++#define FM_NO_GUARANTEED_RESET_VALUES ++ ++/* FM errata */ ++#define FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 ++#define FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 ++#define FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 ++#define FM_OP_NO_VSP_NO_RELEASE_ERRATA_FMAN_A006675 ++#define FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981 ++ ++#define FM_BCB_ERRATA_BMI_SW001 ++#define FM_LEN_CHECK_ERRATA_FMAN_SW002 ++#define FM_AID_MODE_NO_TNUM_SW005 /* refer to pdm TKT068794 - only support of port_id on aid */ ++#define FM_ERROR_VSP_NO_MATCH_SW006 /* refer to pdm TKT174304 - no match between errorQ and VSP */ ++ ++/***************************************************************************** ++ RMan INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define RM_MAX_NUM_OF_IB 4 /**< Number of inbound blocks */ ++#define RM_NUM_OF_IBCU 8 /**< NUmber of classification units in an inbound block */ ++ ++/* RMan erratas */ ++#define RM_ERRONEOUS_ACK_ERRATA_RMAN_A006756 ++ ++/***************************************************************************** ++ FM MACSEC INTEGRATION-SPECIFIC DEFINITIONS ++******************************************************************************/ ++#define NUM_OF_RX_SC 16 ++#define NUM_OF_TX_SC 16 ++ ++#define NUM_OF_SA_PER_RX_SC 2 ++#define NUM_OF_SA_PER_TX_SC 2 ++ ++#endif /* __DPAA_INTEGRATION_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/LS1043/part_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/LS1043/part_ext.h +new file mode 100644 +index 0000000..4787e19 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/LS1043/part_ext.h +@@ -0,0 +1,64 @@ ++/* ++ * Copyright 2012 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. ++ */ ++ ++/**************************************************************************//** ++ ++ @File part_ext.h ++ ++ @Description Definitions for the part (integration) module. ++*//***************************************************************************/ ++ ++#ifndef __PART_EXT_H ++#define __PART_EXT_H ++ ++#include "std_ext.h" ++#include "part_integration_ext.h" ++ ++#if !(defined(LS1043)) ++#error "unable to proceed without chip-definition" ++#endif ++ ++ ++/**************************************************************************//* ++ @Description Part data structure - must be contained in any integration ++ data structure. ++*//***************************************************************************/ ++typedef struct t_Part ++{ ++ uintptr_t (* f_GetModuleBase)(t_Handle h_Part, e_ModuleId moduleId); ++ /**< Returns the address of the module's memory map base. */ ++ e_ModuleId (* f_GetModuleIdByBase)(t_Handle h_Part, uintptr_t baseAddress); ++ /**< Returns the module's ID according to its memory map base. */ ++} t_Part; ++ ++ ++#endif /* __PART_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/LS1043/part_integration_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/LS1043/part_integration_ext.h +new file mode 100644 +index 0000000..85ba2a4 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/integrations/LS1043/part_integration_ext.h +@@ -0,0 +1,185 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/** ++ ++ @File part_integration_ext.h ++ ++ @Description T4240 external definitions and structures. ++*//***************************************************************************/ ++#ifndef __PART_INTEGRATION_EXT_H ++#define __PART_INTEGRATION_EXT_H ++ ++#include "std_ext.h" ++#include "ddr_std_ext.h" ++#include "enet_ext.h" ++#include "dpaa_integration_ext.h" ++ ++ ++/**************************************************************************//** ++ @Group T4240_chip_id T4240 Application Programming Interface ++ ++ @Description T4240 Chip functions,definitions and enums. ++ ++ @{ ++*//***************************************************************************/ ++ ++#define INTG_MAX_NUM_OF_CORES 4 ++ ++/**************************************************************************//** ++ @Description Module types. ++*//***************************************************************************/ ++typedef enum e_ModuleId ++{ ++ e_MODULE_ID_DUART_1 = 0, ++ e_MODULE_ID_DUART_2, ++ e_MODULE_ID_DUART_3, ++ e_MODULE_ID_DUART_4, ++ e_MODULE_ID_LAW, ++ e_MODULE_ID_IFC, ++ e_MODULE_ID_PAMU, ++ e_MODULE_ID_QM, /**< Queue manager module */ ++ e_MODULE_ID_BM, /**< Buffer manager module */ ++ e_MODULE_ID_QM_CE_PORTAL_0, ++ e_MODULE_ID_QM_CI_PORTAL_0, ++ e_MODULE_ID_QM_CE_PORTAL_1, ++ e_MODULE_ID_QM_CI_PORTAL_1, ++ e_MODULE_ID_QM_CE_PORTAL_2, ++ e_MODULE_ID_QM_CI_PORTAL_2, ++ e_MODULE_ID_QM_CE_PORTAL_3, ++ e_MODULE_ID_QM_CI_PORTAL_3, ++ e_MODULE_ID_QM_CE_PORTAL_4, ++ e_MODULE_ID_QM_CI_PORTAL_4, ++ e_MODULE_ID_QM_CE_PORTAL_5, ++ e_MODULE_ID_QM_CI_PORTAL_5, ++ e_MODULE_ID_QM_CE_PORTAL_6, ++ e_MODULE_ID_QM_CI_PORTAL_6, ++ e_MODULE_ID_QM_CE_PORTAL_7, ++ e_MODULE_ID_QM_CI_PORTAL_7, ++ e_MODULE_ID_QM_CE_PORTAL_8, ++ e_MODULE_ID_QM_CI_PORTAL_8, ++ e_MODULE_ID_QM_CE_PORTAL_9, ++ e_MODULE_ID_QM_CI_PORTAL_9, ++ e_MODULE_ID_BM_CE_PORTAL_0, ++ e_MODULE_ID_BM_CI_PORTAL_0, ++ e_MODULE_ID_BM_CE_PORTAL_1, ++ e_MODULE_ID_BM_CI_PORTAL_1, ++ e_MODULE_ID_BM_CE_PORTAL_2, ++ e_MODULE_ID_BM_CI_PORTAL_2, ++ e_MODULE_ID_BM_CE_PORTAL_3, ++ e_MODULE_ID_BM_CI_PORTAL_3, ++ e_MODULE_ID_BM_CE_PORTAL_4, ++ e_MODULE_ID_BM_CI_PORTAL_4, ++ e_MODULE_ID_BM_CE_PORTAL_5, ++ e_MODULE_ID_BM_CI_PORTAL_5, ++ e_MODULE_ID_BM_CE_PORTAL_6, ++ e_MODULE_ID_BM_CI_PORTAL_6, ++ e_MODULE_ID_BM_CE_PORTAL_7, ++ e_MODULE_ID_BM_CI_PORTAL_7, ++ e_MODULE_ID_BM_CE_PORTAL_8, ++ e_MODULE_ID_BM_CI_PORTAL_8, ++ e_MODULE_ID_BM_CE_PORTAL_9, ++ e_MODULE_ID_BM_CI_PORTAL_9, ++ e_MODULE_ID_FM, /**< Frame manager module */ ++ e_MODULE_ID_FM_RTC, /**< FM Real-Time-Clock */ ++ e_MODULE_ID_FM_MURAM, /**< FM Multi-User-RAM */ ++ e_MODULE_ID_FM_BMI, /**< FM BMI block */ ++ e_MODULE_ID_FM_QMI, /**< FM QMI block */ ++ e_MODULE_ID_FM_PARSER, /**< FM parser block */ ++ e_MODULE_ID_FM_PORT_HO1, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO2, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO3, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO4, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO5, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO6, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_HO7, /**< FM Host-command/offline-parsing port block */ ++ e_MODULE_ID_FM_PORT_1GRx1, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx2, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx3, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx4, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx5, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GRx6, /**< FM Rx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_10GRx1, /**< FM Rx 10G MAC port block */ ++ e_MODULE_ID_FM_PORT_10GRx2, /**< FM Rx 10G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx1, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx2, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx3, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx4, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx5, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_1GTx6, /**< FM Tx 1G MAC port block */ ++ e_MODULE_ID_FM_PORT_10GTx1, /**< FM Tx 10G MAC port block */ ++ e_MODULE_ID_FM_PORT_10GTx2, /**< FM Tx 10G MAC port block */ ++ e_MODULE_ID_FM_PLCR, /**< FM Policer */ ++ e_MODULE_ID_FM_KG, /**< FM Keygen */ ++ e_MODULE_ID_FM_DMA, /**< FM DMA */ ++ e_MODULE_ID_FM_FPM, /**< FM FPM */ ++ e_MODULE_ID_FM_IRAM, /**< FM Instruction-RAM */ ++ e_MODULE_ID_FM_1GMDIO, /**< FM 1G MDIO MAC */ ++ e_MODULE_ID_FM_10GMDIO, /**< FM 10G MDIO */ ++ e_MODULE_ID_FM_PRS_IRAM, /**< FM SW-parser Instruction-RAM */ ++ e_MODULE_ID_FM_1GMAC1, /**< FM 1G MAC #1 */ ++ e_MODULE_ID_FM_1GMAC2, /**< FM 1G MAC #2 */ ++ e_MODULE_ID_FM_1GMAC3, /**< FM 1G MAC #3 */ ++ e_MODULE_ID_FM_1GMAC4, /**< FM 1G MAC #4 */ ++ e_MODULE_ID_FM_1GMAC5, /**< FM 1G MAC #5 */ ++ e_MODULE_ID_FM_1GMAC6, /**< FM 1G MAC #6 */ ++ e_MODULE_ID_FM_10GMAC1, /**< FM 10G MAC */ ++ e_MODULE_ID_FM_10GMAC2, /**< FM 10G MAC */ ++ ++ e_MODULE_ID_SEC_GEN, /**< SEC 4.0 General registers */ ++ e_MODULE_ID_SEC_QI, /**< SEC 4.0 QI registers */ ++ e_MODULE_ID_SEC_JQ0, /**< SEC 4.0 JQ-0 registers */ ++ e_MODULE_ID_SEC_JQ1, /**< SEC 4.0 JQ-1 registers */ ++ e_MODULE_ID_SEC_JQ2, /**< SEC 4.0 JQ-2 registers */ ++ e_MODULE_ID_SEC_JQ3, /**< SEC 4.0 JQ-3 registers */ ++ e_MODULE_ID_SEC_RTIC, /**< SEC 4.0 RTIC registers */ ++ e_MODULE_ID_SEC_DECO0_CCB0, /**< SEC 4.0 DECO-0/CCB-0 registers */ ++ e_MODULE_ID_SEC_DECO1_CCB1, /**< SEC 4.0 DECO-1/CCB-1 registers */ ++ e_MODULE_ID_SEC_DECO2_CCB2, /**< SEC 4.0 DECO-2/CCB-2 registers */ ++ e_MODULE_ID_SEC_DECO3_CCB3, /**< SEC 4.0 DECO-3/CCB-3 registers */ ++ e_MODULE_ID_SEC_DECO4_CCB4, /**< SEC 4.0 DECO-4/CCB-4 registers */ ++ ++ e_MODULE_ID_PIC, /**< PIC */ ++ e_MODULE_ID_GPIO, /**< GPIO */ ++ e_MODULE_ID_SERDES, /**< SERDES */ ++ e_MODULE_ID_CPC_1, /**< CoreNet-Platform-Cache 1 */ ++ e_MODULE_ID_CPC_2, /**< CoreNet-Platform-Cache 2 */ ++ ++ e_MODULE_ID_SRIO_PORTS, /**< RapidIO controller */ ++ ++ e_MODULE_ID_DUMMY_LAST ++} e_ModuleId; ++ ++#define NUM_OF_MODULES e_MODULE_ID_DUMMY_LAST ++ ++ ++#endif /* __PART_INTEGRATION_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/inc/types_ext.h b/drivers/net/ethernet/freescale/sdk_fman/inc/types_ext.h +index fd900e2..8c87edb 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/inc/types_ext.h ++++ b/drivers/net/ethernet/freescale/sdk_fman/inc/types_ext.h +@@ -59,46 +59,4 @@ + #include "types_dflt.h" + #endif /* defined (__ROCOO__) */ + +-static __inline__ void TypesChecker(void) +-{ +-#if defined(__MWERKS__) && !defined(__GNUC__) +-#pragma pack(push,1) +-#endif /* defined(__MWERKS__) && ... */ +- _Packed struct strct { +- __volatile__ int vi; +- } _PackedType; +-#if defined(__MWERKS__) && !defined(__GNUC__) +-#pragma pack(pop) +-#endif /* defined(__MWERKS__) && ... */ +- size_t size = 0; +- bool tr = TRUE, fls = FALSE; +- struct strct *p_Struct = NULL; +- physAddress_t addr = 0x100; +- +- tr = fls; +- p_Struct = p_Struct; +- size++; +- if (tr) size++; +- +- WRITE_UINT8(*((uint8_t*)((size_t)(addr))), +- GET_UINT8(*((uint8_t*)((size_t)(addr))))); +- +- WRITE_UINT8(*((uint8_t*)((size_t)(UINT8_MAX))), +- GET_UINT8(*((uint8_t*)((size_t)(UINT8_MAX))))); +- WRITE_UINT16(*((uint16_t*)((size_t)(UINT16_MAX))), +- GET_UINT16(*((uint16_t*)((size_t)(UINT16_MAX))))); +- WRITE_UINT32(*((uint32_t*)((size_t)(UINT32_MAX))), +- GET_UINT32(*((uint32_t*)((size_t)(UINT32_MAX))))); +- WRITE_UINT64(*((uint64_t*)((size_t)(UINT64_MAX))), +- GET_UINT64(*((uint64_t*)((size_t)(UINT64_MAX))))); +- WRITE_UINT8(*((uint8_t*)((size_t)(INT8_MAX))), +- GET_UINT8(*((uint8_t*)((size_t)(INT8_MIN))))); +- WRITE_UINT16(*((uint16_t*)((size_t)(INT16_MAX))), +- GET_UINT16(*((uint16_t*)((size_t)(INT16_MIN))))); +- WRITE_UINT32(*((uint32_t*)((size_t)(INT32_MAX))), +- GET_UINT32(*((uint32_t*)((size_t)(INT32_MIN))))); +- WRITE_UINT64(*((uint64_t*)((size_t)(INT64_MAX))), +- GET_UINT64(*((uint64_t*)((size_t)(INT64_MIN))))); +-} +- + #endif /* __TYPES_EXT_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/ls1043_dflags.h b/drivers/net/ethernet/freescale/sdk_fman/ls1043_dflags.h +new file mode 100644 +index 0000000..c3a5a62 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/ls1043_dflags.h +@@ -0,0 +1,56 @@ ++/* ++ * Copyright 2012 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 __dflags_h ++#define __dflags_h ++ ++ ++#define NCSW_LINUX ++ ++#define LS1043 ++ ++#define DEBUG_ERRORS 1 ++ ++#if defined(DEBUG) ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_INFO ++ ++#define DEBUG_XX_MALLOC ++#define DEBUG_MEM_LEAKS ++ ++#else ++#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_WARNING ++#endif /* (DEBUG) */ ++ ++#define REPORT_EVENTS 1 ++#define EVENT_GLOBAL_LEVEL REPORT_LEVEL_MINOR ++ ++#endif /* __dflags_h */ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk b/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk +index b1fde53..586f9c7 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk ++++ b/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk +@@ -17,6 +17,9 @@ endif + ifdef CONFIG_FMAN_V3L + ccflags-y +=-include $(FMAN)/fmanv3l_dflags.h + endif ++ifdef CONFIG_FMAN_ARM ++ccflags-y +=-include $(FMAN)/ls1043_dflags.h ++endif + + ccflags-y += -I$(DRV_DPA)/ + ccflags-y += -I$(FMAN)/inc +@@ -37,6 +40,9 @@ endif + ifdef CONFIG_FMAN_V3L + ccflags-y += -I$(FMAN)/inc/integrations/FMANV3L + endif ++ifdef CONFIG_FMAN_ARM ++ccflags-y += -I$(FMAN)/inc/integrations/LS1043 ++endif + + ccflags-y += -I$(FMAN)/src/inc + ccflags-y += -I$(FMAN)/src/inc/system +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/inc/types_linux.h b/drivers/net/ethernet/freescale/sdk_fman/src/inc/types_linux.h +index ac15d66..201ad69 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/src/inc/types_linux.h ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/inc/types_linux.h +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) + #error "This kernel is probably not supported!!!" +@@ -91,6 +92,13 @@ typedef phys_addr_t physAddress_t; + /************************/ + /* memory access macros */ + /************************/ ++#ifdef CONFIG_FMAN_ARM ++#define in_be16(a) __be16_to_cpu(__raw_readw(a)) ++#define in_be32(a) __be32_to_cpu(__raw_readl(a)) ++#define out_be16(a, v) __raw_writew(__cpu_to_be16(v), a) ++#define out_be32(a, v) __raw_writel(__cpu_to_be32(v), a) ++#endif ++ + #define GET_UINT8(arg) *(volatile uint8_t *)(&(arg)) + #define GET_UINT16(arg) in_be16(&(arg))//*(volatile uint16_t*)(&(arg)) + #define GET_UINT32(arg) in_be32(&(arg))//*(volatile uint32_t*)(&(arg)) +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c +index 135e5bb..f21d2fd 100755 +--- a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c +@@ -59,8 +59,10 @@ + #include + #include + #include /* For struct qe_firmware */ ++#ifndef CONFIG_FMAN_ARM + #include + #include ++#endif + #include /* For file access mask */ + #include + #include +@@ -504,6 +506,7 @@ static t_LnxWrpFmDev * ReadFmDevTreeNode (struct platform_device *of_dev) + struct resource res; + const uint32_t *uint32_prop; + int _errno=0, lenp; ++ uint32_t tmp_prop; + + fm_node = of_node_get(of_dev->dev.of_node); + +@@ -512,19 +515,22 @@ static t_LnxWrpFmDev * ReadFmDevTreeNode (struct platform_device *of_dev) + REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_get_property(%s, cell-index) failed", fm_node->full_name)); + return NULL; + } ++ tmp_prop = be32_to_cpu(*uint32_prop); ++ + if (WARN_ON(lenp != sizeof(uint32_t))) + return NULL; +- if (*uint32_prop > INTG_MAX_NUM_OF_FM) { ++ ++ if (tmp_prop > INTG_MAX_NUM_OF_FM) { + REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("fm id!")); + return NULL; + } +- p_LnxWrpFmDev = CreateFmDev(*uint32_prop); ++ p_LnxWrpFmDev = CreateFmDev(tmp_prop); + if (!p_LnxWrpFmDev) { + REPORT_ERROR(MAJOR, E_NULL_POINTER, NO_MSG); + return NULL; + } + p_LnxWrpFmDev->dev = &of_dev->dev; +- p_LnxWrpFmDev->id = *uint32_prop; ++ p_LnxWrpFmDev->id = tmp_prop; + + /* Get the FM interrupt */ + p_LnxWrpFmDev->irq = of_irq_to_resource(fm_node, 0, NULL); +@@ -535,13 +541,11 @@ static t_LnxWrpFmDev * ReadFmDevTreeNode (struct platform_device *of_dev) + + /* Get the FM error interrupt */ + p_LnxWrpFmDev->err_irq = of_irq_to_resource(fm_node, 1, NULL); +- /* TODO - un-comment it once there will be err_irq in the DTS */ +-#if 0 ++ + if (unlikely(p_LnxWrpFmDev->err_irq == /*NO_IRQ*/0)) { + REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_irq_to_resource() = %d", NO_IRQ)); + return NULL; + } +-#endif /* 0 */ + + /* Get the FM address */ + _errno = of_address_to_resource(fm_node, 0, &res); +@@ -560,10 +564,11 @@ static t_LnxWrpFmDev * ReadFmDevTreeNode (struct platform_device *of_dev) + REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_get_property(%s, clock-frequency) failed", fm_node->full_name)); + return NULL; + } ++ tmp_prop = be32_to_cpu(*uint32_prop); ++ + if (WARN_ON(lenp != sizeof(uint32_t))) + return NULL; +- p_LnxWrpFmDev->fmDevSettings.param.fmClkFreq = (*uint32_prop + 500000)/1000000; /* In MHz, rounded */ +- ++ p_LnxWrpFmDev->fmDevSettings.param.fmClkFreq = (tmp_prop + 500000)/1000000; /* In MHz, rounded */ + /* Get the MURAM base address and size */ + memset(&name, 0, sizeof(struct of_device_id)); + if (WARN_ON(strlen("muram") >= sizeof(name.name))) +@@ -583,6 +588,8 @@ static t_LnxWrpFmDev * ReadFmDevTreeNode (struct platform_device *of_dev) + p_LnxWrpFmDev->fmMuramBaseAddr = 0; + p_LnxWrpFmDev->fmMuramPhysBaseAddr = res.start; + p_LnxWrpFmDev->fmMuramMemSize = res.end + 1 - res.start; ++ ++#ifndef CONFIG_FMAN_ARM + { + uint32_t svr; + svr = mfspr(SPRN_SVR); +@@ -590,6 +597,7 @@ static t_LnxWrpFmDev * ReadFmDevTreeNode (struct platform_device *of_dev) + if ((svr & ~SVR_VER_IGNORE_MASK) >= SVR_B4860_REV2_VALUE) + p_LnxWrpFmDev->fmMuramMemSize = 0x80000; + } ++#endif + } + } + +@@ -706,6 +714,7 @@ struct device_node *GetFmAdvArgsDevTreeNode (uint8_t fmIndx) + struct device_node *dev_node; + const uint32_t *uint32_prop; + int lenp; ++ uint32_t tmp_prop; + + for_each_compatible_node(dev_node, NULL, "fsl,fman-extended-args") { + uint32_prop = (uint32_t *)of_get_property(dev_node, "cell-index", &lenp); +@@ -715,13 +724,14 @@ struct device_node *GetFmAdvArgsDevTreeNode (uint8_t fmIndx) + dev_node->full_name)); + return NULL; + } ++ tmp_prop = be32_to_cpu(*uint32_prop); + if (WARN_ON(lenp != sizeof(uint32_t))) + return NULL; +- if (*uint32_prop > INTG_MAX_NUM_OF_FM) { ++ if (tmp_prop > INTG_MAX_NUM_OF_FM) { + REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("fm id!")); + return NULL; + } +- if (fmIndx == *uint32_prop) ++ if (fmIndx == tmp_prop) + return dev_node; + } + +@@ -735,6 +745,7 @@ static t_Error CheckNConfigFmAdvArgs (t_LnxWrpFmDev *p_LnxWrpFmDev) + const uint32_t *uint32_prop; + const char *str_prop; + int lenp; ++ uint32_t tmp_prop; + + dev_node = GetFmAdvArgsDevTreeNode(p_LnxWrpFmDev->id); + if (!dev_node) /* no advance parameters for FMan */ +@@ -754,22 +765,24 @@ static t_Error CheckNConfigFmAdvArgs (t_LnxWrpFmDev *p_LnxWrpFmDev) + uint32_prop = (uint32_t *)of_get_property(dev_node, + "total-fifo-size", &lenp); + if (uint32_prop) { ++ tmp_prop = be32_to_cpu(*uint32_prop); + if (WARN_ON(lenp != sizeof(uint32_t))) + RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); + + if (FM_ConfigTotalFifoSize(p_LnxWrpFmDev->h_Dev, +- *uint32_prop) != E_OK) ++ tmp_prop) != E_OK) + RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); + } + + uint32_prop = (uint32_t *)of_get_property(dev_node, "tnum-aging-period", + &lenp); +- if (uint32_prop) { +- if (WARN_ON(lenp != sizeof(uint32_t))) +- RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); ++ if (uint32_prop) { ++ tmp_prop = be32_to_cpu(*uint32_prop); ++ if (WARN_ON(lenp != sizeof(uint32_t))) ++ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); + + err = FM_ConfigTnumAgingPeriod(p_LnxWrpFmDev->h_Dev, +- (uint16_t)uint32_prop[0]/*tnumAgingPeriod*/); ++ (uint16_t)tmp_prop/*tnumAgingPeriod*/); + + if (err != E_OK) + RETURN_ERROR(MINOR, err, NO_MSG); +@@ -894,6 +907,7 @@ static t_Error ConfigureFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev) + return FillRestFmInfo(p_LnxWrpFmDev); + } + ++#ifndef CONFIG_FMAN_ARM + /* + * Table for matching compatible strings, for device tree + * guts node, for QorIQ SOCs. +@@ -926,6 +940,7 @@ static unsigned int get_rcwsr(int regnum) + + return ioread32be(&guts_regs->rcwsr[regnum]); + } ++#endif + + static t_Error InitFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev) + { +@@ -946,15 +961,26 @@ static t_Error InitFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev) + p_LnxWrpFmDev->fmDevSettings.param.firmware.p_Code = NULL; + } else { + p_LnxWrpFmDev->fmDevSettings.param.firmware.p_Code = +- (void *) fw + fw->microcode[0].code_offset; ++ (void *) fw + be32_to_cpu(fw->microcode[0].code_offset); + p_LnxWrpFmDev->fmDevSettings.param.firmware.size = +- sizeof(u32) * fw->microcode[0].count; ++ sizeof(u32) * be32_to_cpu(fw->microcode[0].count); + DBG(INFO, ("Loading fman-controller code version %d.%d.%d", + fw->microcode[0].major, + fw->microcode[0].minor, + fw->microcode[0].revision)); + } + ++#ifdef CONFIG_FMAN_ARM ++ { /* endianness adjustments: byteswap the ucode retrieved from the f/w blob */ ++ int i; ++ int usz = p_LnxWrpFmDev->fmDevSettings.param.firmware.size; ++ void * p_Code = p_LnxWrpFmDev->fmDevSettings.param.firmware.p_Code; ++ ++ for(i=0; i < usz / 4; ++i) ++ ((u32 *)p_Code)[i] = be32_to_cpu(((u32 *)p_Code)[i]); ++ } ++#endif ++ + p_LnxWrpFmDev->fmDevSettings.param.h_FmMuram = p_LnxWrpFmDev->h_MuramDev; + + #if (DPAA_VERSION >= 11) +@@ -965,6 +991,9 @@ static t_Error InitFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev) + } + #endif + ++#ifdef CONFIG_FMAN_ARM ++ p_LnxWrpFmDev->fmDevSettings.param.fmMacClkRatio = 1; ++#else + if(p_LnxWrpFmDev->fmDevSettings.param.fmId == 0) + p_LnxWrpFmDev->fmDevSettings.param.fmMacClkRatio = + !!(get_rcwsr(4) & 0x2); /* RCW[FM_MAC_RAT0] */ +@@ -980,6 +1009,7 @@ static t_Error InitFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev) + if ((svr & SVR_DEVICE_ID_MASK) == SVR_T4_DEVICE_ID) + p_LnxWrpFmDev->fmDevSettings.param.fmMacClkRatio = 1; + } ++#endif /* CONFIG_FMAN_ARM */ + + if ((p_LnxWrpFmDev->h_Dev = FM_Config(&p_LnxWrpFmDev->fmDevSettings.param)) == NULL) + RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM")); +@@ -1197,7 +1227,6 @@ static int fm_soc_suspend(struct device *dev) + { + #ifdef CONFIG_FSL_QORIQ_PM + device_set_wakeup_enable(p_LnxWrpFmDev->dev, 1); +-// TODO: fsl_set_power_except(dev->of_node?); + #endif + err = FM_PORT_EnterDsarFinal(p_LnxWrpFmDev->h_DsarRxPort, + p_LnxWrpFmDev->h_DsarTxPort); +@@ -1214,7 +1243,6 @@ static int fm_soc_resume(struct device *dev) + if (p_LnxWrpFmDev->h_DsarRxPort) + { + #ifdef CONFIG_FSL_QORIQ_PM +-// TODO fsl_set_power_except(dev->of_node?); + device_set_wakeup_enable(p_LnxWrpFmDev->dev, 0); + #endif + FM_PORT_ExitDsar(p_LnxWrpFmDev->h_DsarRxPort, +@@ -1380,8 +1408,8 @@ void fm_port_get_buff_layout_ext_params(struct fm_port *port, struct fm_port_par + if (WARN_ON(lenp != sizeof(uint32_t)*2)) + return; + +- params->manip_extra_space = (uint8_t)uint32_prop[0]; +- params->data_align = (uint16_t)uint32_prop[1]; ++ params->manip_extra_space = (uint8_t)be32_to_cpu(uint32_prop[0]); ++ params->data_align = (uint16_t)be32_to_cpu(uint32_prop[1]); + } + + of_node_put(port_node); +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm_port.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm_port.c +index 2cba7a5..56b0b40 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm_port.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm_port.c +@@ -51,7 +51,10 @@ + #include + #include + #include ++#ifndef CONFIG_FMAN_ARM + #include ++#endif ++#include + + #include "sprint_ext.h" + #include "fm_common.h" +@@ -82,8 +85,10 @@ do {\ + } \ + } while (0) + ++#ifndef CONFIG_FMAN_ARM + #define IS_T1023_T1024 (SVR_SOC_VER(mfspr(SPRN_SVR)) == SVR_T1024 || \ + SVR_SOC_VER(mfspr(SPRN_SVR)) == SVR_T1023) ++#endif + + static volatile int hcFrmRcv/* = 0 */; + static spinlock_t lock; +@@ -96,6 +101,31 @@ static enum qman_cb_dqrr_result qm_tx_conf_dqrr_cb(struct qman_portal *portal, + t_LnxWrpFmDev *p_LnxWrpFmDev = ((t_FmTestFq *) fq)->h_Arg; + unsigned long flags; + ++#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ++{ ++ /* extract the HC frame address */ ++ uint64_t hcf_va = XX_PhysToVirt(((struct qm_fd *)&dq->fd)->addr); ++ int hcf_l = ((struct qm_fd *)&dq->fd)->length20; ++ int i; ++ ++ /* 32b byteswap of all data in the HC Frame */ ++ for(i = 0; i < hcf_l / 4; ++i) ++ ((uint32_t *)(hcf_va))[i] = ++ ___constant_swab32(((uint32_t *)(hcf_va))[i]); ++} ++{ ++ /* byteswap FD's 40bit address field LE to BE*/ ++ uint8_t t; ++ ++ t = ((uint8_t*)&dq->fd)[6]; ++ ((uint8_t*)&dq->fd)[6] = ((uint8_t*)&dq->fd)[5]; ++ ((uint8_t*)&dq->fd)[5] = ((uint8_t*)&dq->fd)[4]; ++ ((uint8_t*)&dq->fd)[4] = ((uint8_t*)&dq->fd)[3]; ++ ((uint8_t*)&dq->fd)[3] = ((uint8_t*)&dq->fd)[7]; ++ ((uint8_t*)&dq->fd)[7] = t; ++} ++ ++#endif + FM_PCD_HcTxConf(p_LnxWrpFmDev->h_PcdDev, (t_DpaaFD *)&dq->fd); + spin_lock_irqsave(&lock, flags); + hcFrmRcv--; +@@ -207,6 +237,31 @@ static t_Error QmEnqueueCB(t_Handle h_Arg, void *p_Fd) + hcFrmRcv++; + spin_unlock_irqrestore(&lock, flags); + ++#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ++{ ++ /* byteswap FD's 40bit address field */ ++ uint8_t t; ++ ++ t = ((uint8_t*)p_Fd)[7]; ++ ((uint8_t*)p_Fd)[7] = ((uint8_t*)p_Fd)[3]; ++ ((uint8_t*)p_Fd)[3] = ((uint8_t*)p_Fd)[4]; ++ ((uint8_t*)p_Fd)[4] = ((uint8_t*)p_Fd)[5]; ++ ((uint8_t*)p_Fd)[5] = ((uint8_t*)p_Fd)[6]; ++ ((uint8_t*)p_Fd)[6] = t; ++} ++{ ++ /* extract the HC frame address */ ++ uint64_t hcf_va = XX_PhysToVirt(((struct qm_fd *) p_Fd)->addr); ++ int hcf_l = ((struct qm_fd *)p_Fd)->length20; ++ int i; ++ ++ /* 32b byteswap of all data in the HC Frame */ ++ for(i = 0; i < hcf_l / 4; ++i) ++ ((uint32_t *)(hcf_va))[i] = ++ ___constant_swab32(((uint32_t *)(hcf_va))[i]); ++} ++#endif ++ + _errno = qman_enqueue(p_LnxWrpFmDev->hc_tx_fq, (struct qm_fd *) p_Fd, + 0); + if (_errno) +@@ -236,6 +291,8 @@ static t_LnxWrpFmPortDev *ReadFmPortDevTreeNode(struct platform_device + struct resource res; + const uint32_t *uint32_prop; + int _errno = 0, lenp; ++ uint32_t tmp_prop; ++ + #ifdef CONFIG_FMAN_P1023 + static unsigned char have_oh_port/* = 0 */; + #endif +@@ -266,10 +323,11 @@ static t_LnxWrpFmPortDev *ReadFmPortDevTreeNode(struct platform_device + port_node->full_name)); + return NULL; + } ++ tmp_prop = be32_to_cpu(*uint32_prop); + if (WARN_ON(lenp != sizeof(uint32_t))) + return NULL; + if (of_device_is_compatible(port_node, "fsl,fman-port-oh")) { +- if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_OH_PORTS)) { ++ if (unlikely(tmp_prop >= FM_MAX_NUM_OF_OH_PORTS)) { + REPORT_ERROR(MAJOR, E_INVALID_VALUE, + ("of_get_property(%s, cell-index) failed", + port_node->full_name)); +@@ -285,7 +343,7 @@ static t_LnxWrpFmPortDev *ReadFmPortDevTreeNode(struct platform_device + #else + /* Here it is hardcoded the use of the OH port 1 + (with cell-index 0) */ +- if (*uint32_prop == 0) { ++ if (tmp_prop == 0) { + #endif + p_LnxWrpFmPortDev = &p_LnxWrpFmDev->hcPort; + p_LnxWrpFmPortDev->id = 0; +@@ -297,12 +355,12 @@ static t_LnxWrpFmPortDev *ReadFmPortDevTreeNode(struct platform_device + e_FM_PORT_TYPE_OH_HOST_COMMAND; + } else { + p_LnxWrpFmPortDev = +- &p_LnxWrpFmDev->opPorts[*uint32_prop - 1]; +- p_LnxWrpFmPortDev->id = *uint32_prop - 1; ++ &p_LnxWrpFmDev->opPorts[tmp_prop - 1]; ++ p_LnxWrpFmPortDev->id = tmp_prop- 1; + p_LnxWrpFmPortDev->settings.param.portType = + e_FM_PORT_TYPE_OH_OFFLINE_PARSING; + } +- p_LnxWrpFmPortDev->settings.param.portId = *uint32_prop; ++ p_LnxWrpFmPortDev->settings.param.portId = tmp_prop; + + uint32_prop = + (uint32_t *) of_get_property(port_node, +@@ -316,22 +374,23 @@ static t_LnxWrpFmPortDev *ReadFmPortDevTreeNode(struct platform_device + " for OH port.\n"); + return NULL; + } ++ tmp_prop = be32_to_cpu(*uint32_prop); + if (WARN_ON(lenp != sizeof(uint32_t))) + return NULL; +- p_LnxWrpFmPortDev->txCh = *uint32_prop; ++ p_LnxWrpFmPortDev->txCh = tmp_prop; + + p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams. + qmChannel = p_LnxWrpFmPortDev->txCh; + } else if (of_device_is_compatible(port_node, "fsl,fman-port-1g-tx")) { +- if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_1G_TX_PORTS)) { ++ if (unlikely(tmp_prop >= FM_MAX_NUM_OF_1G_TX_PORTS)) { + REPORT_ERROR(MAJOR, E_INVALID_VALUE, + ("of_get_property(%s, cell-index) failed", + port_node->full_name)); + return NULL; + } +- p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[*uint32_prop]; ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[tmp_prop]; + +- p_LnxWrpFmPortDev->id = *uint32_prop; ++ p_LnxWrpFmPortDev->id = tmp_prop; + p_LnxWrpFmPortDev->settings.param.portId = + p_LnxWrpFmPortDev->id; + p_LnxWrpFmPortDev->settings.param.portType = e_FM_PORT_TYPE_TX; +@@ -343,25 +402,28 @@ static t_LnxWrpFmPortDev *ReadFmPortDevTreeNode(struct platform_device + ("missing fsl,qman-channel-id")); + return NULL; + } ++ tmp_prop = be32_to_cpu(*uint32_prop); + if (WARN_ON(lenp != sizeof(uint32_t))) + return NULL; +- p_LnxWrpFmPortDev->txCh = *uint32_prop; ++ p_LnxWrpFmPortDev->txCh = tmp_prop; + p_LnxWrpFmPortDev-> + settings.param.specificParams.nonRxParams.qmChannel = + p_LnxWrpFmPortDev->txCh; + } else if (of_device_is_compatible(port_node, "fsl,fman-port-10g-tx")) { +- if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_10G_TX_PORTS)) { ++ if (unlikely(tmp_prop>= FM_MAX_NUM_OF_10G_TX_PORTS)) { + REPORT_ERROR(MAJOR, E_INVALID_VALUE, + ("of_get_property(%s, cell-index) failed", + port_node->full_name)); + return NULL; + } +- p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[*uint32_prop + ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[tmp_prop + + FM_MAX_NUM_OF_1G_TX_PORTS]; ++#ifndef CONFIG_FMAN_ARM + if (IS_T1023_T1024) + p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[*uint32_prop]; ++#endif + +- p_LnxWrpFmPortDev->id = *uint32_prop; ++ p_LnxWrpFmPortDev->id = tmp_prop; + p_LnxWrpFmPortDev->settings.param.portId = + p_LnxWrpFmPortDev->id; + p_LnxWrpFmPortDev->settings.param.portType = +@@ -373,40 +435,43 @@ static t_LnxWrpFmPortDev *ReadFmPortDevTreeNode(struct platform_device + ("missing fsl,qman-channel-id")); + return NULL; + } ++ tmp_prop = be32_to_cpu(*uint32_prop); + if (WARN_ON(lenp != sizeof(uint32_t))) + return NULL; +- p_LnxWrpFmPortDev->txCh = *uint32_prop; ++ p_LnxWrpFmPortDev->txCh = tmp_prop; + p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams. + qmChannel = p_LnxWrpFmPortDev->txCh; + } else if (of_device_is_compatible(port_node, "fsl,fman-port-1g-rx")) { +- if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_1G_RX_PORTS)) { ++ if (unlikely(tmp_prop >= FM_MAX_NUM_OF_1G_RX_PORTS)) { + REPORT_ERROR(MAJOR, E_INVALID_VALUE, + ("of_get_property(%s, cell-index) failed", + port_node->full_name)); + return NULL; + } +- p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[*uint32_prop]; ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[tmp_prop]; + +- p_LnxWrpFmPortDev->id = *uint32_prop; ++ p_LnxWrpFmPortDev->id = tmp_prop; + p_LnxWrpFmPortDev->settings.param.portId = + p_LnxWrpFmPortDev->id; + p_LnxWrpFmPortDev->settings.param.portType = e_FM_PORT_TYPE_RX; + if (p_LnxWrpFmDev->pcdActive) + p_LnxWrpFmPortDev->defPcd = p_LnxWrpFmDev->defPcd; + } else if (of_device_is_compatible(port_node, "fsl,fman-port-10g-rx")) { +- if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_10G_RX_PORTS)) { ++ if (unlikely(tmp_prop >= FM_MAX_NUM_OF_10G_RX_PORTS)) { + REPORT_ERROR(MAJOR, E_INVALID_VALUE, + ("of_get_property(%s, cell-index) failed", + port_node->full_name)); + return NULL; + } +- p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[*uint32_prop + ++ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[tmp_prop + + FM_MAX_NUM_OF_1G_RX_PORTS]; + ++#ifndef CONFIG_FMAN_ARM + if (IS_T1023_T1024) + p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[*uint32_prop]; ++#endif + +- p_LnxWrpFmPortDev->id = *uint32_prop; ++ p_LnxWrpFmPortDev->id = tmp_prop; + p_LnxWrpFmPortDev->settings.param.portId = + p_LnxWrpFmPortDev->id; + p_LnxWrpFmPortDev->settings.param.portType = +@@ -454,6 +519,7 @@ struct device_node * GetFmPortAdvArgsDevTreeNode (struct device_node *fm_node, + const uint32_t *uint32_prop; + int lenp; + char *portTypeString; ++ uint32_t tmp_prop; + + switch(portType) { + case e_FM_PORT_TYPE_OH_OFFLINE_PARSING: +@@ -483,9 +549,10 @@ struct device_node * GetFmPortAdvArgsDevTreeNode (struct device_node *fm_node, + port_node->full_name)); + return NULL; + } ++ tmp_prop = be32_to_cpu(*uint32_prop); + if (WARN_ON(lenp != sizeof(uint32_t))) + return NULL; +- if ((portId == *uint32_prop) && ++ if ((portId == tmp_prop) && + (of_device_is_compatible(port_node, portTypeString))) { + return port_node; + } +@@ -543,8 +610,8 @@ static t_Error CheckNConfigFmPortAdvArgs (t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) + if (WARN_ON(lenp != sizeof(uint32_t)*2)) + RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); + +- portRsrc.num = uint32_prop[0]; +- portRsrc.extra = uint32_prop[1]; ++ portRsrc.num = be32_to_cpu(uint32_prop[0]); ++ portRsrc.extra = be32_to_cpu(uint32_prop[1]); + + if ((err = FM_PORT_ConfigNumOfTasks(p_LnxWrpFmPortDev->h_Dev, + &portRsrc)) != E_OK) +@@ -556,8 +623,8 @@ static t_Error CheckNConfigFmPortAdvArgs (t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) + if (WARN_ON(lenp != sizeof(uint32_t)*2)) + RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); + +- portRsrc.num = uint32_prop[0]; +- portRsrc.extra = uint32_prop[1]; ++ portRsrc.num = be32_to_cpu(uint32_prop[0]); ++ portRsrc.extra = be32_to_cpu(uint32_prop[1]); + + if ((err = FM_PORT_ConfigNumOfOpenDmas(p_LnxWrpFmPortDev->h_Dev, + &portRsrc)) != E_OK) +@@ -569,8 +636,8 @@ static t_Error CheckNConfigFmPortAdvArgs (t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) + if (WARN_ON(lenp != sizeof(uint32_t)*2)) + RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); + +- portRsrc.num = uint32_prop[0]; +- portRsrc.extra = uint32_prop[1]; ++ portRsrc.num = be32_to_cpu(uint32_prop[0]); ++ portRsrc.extra = be32_to_cpu(uint32_prop[1]); + + if ((err = FM_PORT_ConfigSizeOfFifo(p_LnxWrpFmPortDev->h_Dev, + &portRsrc)) != E_OK) +@@ -582,7 +649,7 @@ static t_Error CheckNConfigFmPortAdvArgs (t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) + if (WARN_ON(lenp != sizeof(uint32_t))) + RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); + if ((err = FM_PORT_ConfigErrorsToDiscard(p_LnxWrpFmPortDev->h_Dev, +- uint32_prop[0])) != E_OK) ++ be32_to_cpu(uint32_prop[0]))) != E_OK) + RETURN_ERROR(MINOR, err, NO_MSG); + } + +@@ -602,33 +669,34 @@ static t_Error CheckNConfigFmPortAdvArgs (t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) + memset(&p_LnxWrpFmPortDev->dsar_table_sizes, 0, sizeof(struct auto_res_tables_sizes)); + + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_arp_entries = +- (uint16_t)uint32_prop[0]; ++ (uint16_t)be32_to_cpu(uint32_prop[0]); + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_echo_ipv4_entries = +- (uint16_t)uint32_prop[1]; ++ (uint16_t)be32_to_cpu(uint32_prop[1]); + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_ndp_entries = +- (uint16_t)uint32_prop[2]; ++ (uint16_t)be32_to_cpu(uint32_prop[2]); + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_echo_ipv6_entries = +- (uint16_t)uint32_prop[3]; ++ (uint16_t)be32_to_cpu(uint32_prop[3]); + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_snmp_ipv4_entries = +- (uint16_t)uint32_prop[4]; ++ (uint16_t)be32_to_cpu(uint32_prop[4]); + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_snmp_ipv6_entries = +- (uint16_t)uint32_prop[5]; ++ (uint16_t)be32_to_cpu(uint32_prop[5]); + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_snmp_oid_entries = +- (uint16_t)uint32_prop[6]; ++ (uint16_t)be32_to_cpu(uint32_prop[6]); + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_snmp_char = +- (uint16_t)uint32_prop[7]; +- uint32_prop = (uint32_t *)of_get_property(port_node, ++ (uint16_t)be32_to_cpu(uint32_prop[7]); ++ ++ uint32_prop = (uint32_t *)of_get_property(port_node, + "ar-filters-sizes", &lenp); + if (uint32_prop) { + if (WARN_ON(lenp != sizeof(uint32_t)*3)) + RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); + + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_ip_prot_filtering = +- (uint16_t)uint32_prop[0]; ++ (uint16_t)be32_to_cpu(uint32_prop[0]); + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_tcp_port_filtering = +- (uint16_t)uint32_prop[1]; ++ (uint16_t)be32_to_cpu(uint32_prop[1]); + p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_udp_port_filtering = +- (uint16_t)uint32_prop[2]; ++ (uint16_t)be32_to_cpu(uint32_prop[2]); + } + + if ((err = FM_PORT_ConfigDsarSupport(p_LnxWrpFmPortDev->h_Dev, +@@ -682,8 +750,8 @@ static t_Error CheckNSetFmPortAdvArgs (t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) + memset(&portVSPAllocParams, 0, sizeof(portVSPAllocParams)); + memset(&fmVspParams, 0, sizeof(fmVspParams)); + +- portVSPAllocParams.numOfProfiles = (uint8_t)uint32_prop[0]; +- portVSPAllocParams.dfltRelativeId = (uint8_t)uint32_prop[1]; ++ portVSPAllocParams.numOfProfiles = (uint8_t)be32_to_cpu(uint32_prop[0]); ++ portVSPAllocParams.dfltRelativeId = (uint8_t)be32_to_cpu(uint32_prop[1]); + fmVspParams.h_Fm = p_LnxWrpFmDev->h_Dev; + + fmVspParams.portParams.portType = p_LnxWrpFmPortDev->settings.param.portType; +@@ -694,7 +762,9 @@ static t_Error CheckNSetFmPortAdvArgs (t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) + { + portId = fmVspParams.portParams.portId; + if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX_10G){ ++#ifndef CONFIG_FMAN_ARM + if (!(IS_T1023_T1024)) ++#endif + portId += FM_MAX_NUM_OF_1G_RX_PORTS; + } + portVSPAllocParams.h_FmTxPort = +@@ -814,6 +884,7 @@ static t_Error InitFmPortDev(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) + } + #endif /* !FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ + ++#ifndef CONFIG_FMAN_ARM + #ifdef FM_BCB_ERRATA_BMI_SW001 + /* Configure BCB workaround on Rx ports, only for B4860 rev1 */ + #define SVR_SECURITY_MASK 0x00080000 +@@ -833,7 +904,7 @@ static t_Error InitFmPortDev(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev) + FM_PORT_ConfigBCBWorkaround(p_LnxWrpFmPortDev->h_Dev); + } + #endif /* FM_BCB_ERRATA_BMI_SW001 */ +- ++#endif /* CONFIG_FMAN_ARM */ + /* Call the driver's advanced configuration routines, if requested: + Compare the function pointer of each entry to the available routines, + and invoke the matching routine with proper casting of arguments. */ +@@ -1270,6 +1341,7 @@ static int /*__devinit*/ fm_port_probe(struct platform_device *of_dev) + p_LnxWrpFmPortDev->minor = + p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_RX_PORTS + + DEV_FM_RX_PORTS_MINOR_BASE; ++#ifndef CONFIG_FMAN_ARM + if (IS_T1023_T1024) { + Sprint(p_LnxWrpFmPortDev->name, "%s-port-rx%d", + p_LnxWrpFmDev->name, +@@ -1278,6 +1350,7 @@ static int /*__devinit*/ fm_port_probe(struct platform_device *of_dev) + p_LnxWrpFmPortDev->id + + DEV_FM_RX_PORTS_MINOR_BASE; + } ++#endif + } else if (p_LnxWrpFmPortDev->settings.param.portType == + e_FM_PORT_TYPE_TX) { + Sprint(p_LnxWrpFmPortDev->name, "%s-port-tx%d", +@@ -1292,6 +1365,7 @@ static int /*__devinit*/ fm_port_probe(struct platform_device *of_dev) + p_LnxWrpFmPortDev->minor = + p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_TX_PORTS + + DEV_FM_TX_PORTS_MINOR_BASE; ++#ifndef CONFIG_FMAN_ARM + if (IS_T1023_T1024) { + Sprint(p_LnxWrpFmPortDev->name, "%s-port-tx%d", + p_LnxWrpFmDev->name, +@@ -1300,6 +1374,7 @@ static int /*__devinit*/ fm_port_probe(struct platform_device *of_dev) + p_LnxWrpFmPortDev->id + + DEV_FM_TX_PORTS_MINOR_BASE; + } ++#endif + } else if (p_LnxWrpFmPortDev->settings.param.portType == + e_FM_PORT_TYPE_OH_HOST_COMMAND) { + Sprint(p_LnxWrpFmPortDev->name, "%s-port-oh%d", +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c +index 2476dfa..181ea19 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm.c +@@ -59,8 +59,10 @@ + #include + #include + #include ++#ifndef CONFIG_FMAN_ARM + #include + #include ++#endif + + #if defined(CONFIG_COMPAT) + #include +@@ -72,8 +74,10 @@ + #include "fm_port_ioctls.h" + #include "fm_vsp_ext.h" + ++#ifndef CONFIG_FMAN_ARM + #define IS_T1023_T1024 (SVR_SOC_VER(mfspr(SPRN_SVR)) == SVR_T1024 || \ + SVR_SOC_VER(mfspr(SPRN_SVR)) == SVR_T1023) ++#endif + + #define __ERR_MODULE__ MODULE_FM + +@@ -345,10 +349,16 @@ void LnxWrpPCDIOCTLTypeChecking(void) + ASSERT_COND(sizeof(ioc_fm_pcd_from_hdr_t) == sizeof(t_FmPcdFromHdr)); + ASSERT_COND(sizeof(ioc_fm_pcd_from_field_t) == sizeof(t_FmPcdFromField)); + ASSERT_COND(sizeof(ioc_fm_pcd_distinction_unit_t) == sizeof(t_FmPcdDistinctionUnit)); ++ ++#if defined(CONFIG_FMAN_ARM) ++ /* different alignment */ ++ ASSERT_COND(sizeof(ioc_fm_pcd_net_env_params_t) == sizeof(t_FmPcdNetEnvParams) + sizeof(void *) + 4); ++#else + #if !defined(CONFIG_COMPAT) + /* different alignment */ + ASSERT_COND(sizeof(ioc_fm_pcd_net_env_params_t) == sizeof(t_FmPcdNetEnvParams) + sizeof(void *)); + #endif ++#endif + ASSERT_COND(sizeof(ioc_fm_pcd_extract_entry_t) == sizeof(t_FmPcdExtractEntry)); + ASSERT_COND(sizeof(ioc_fm_pcd_kg_extract_mask_t) == sizeof(t_FmPcdKgExtractMask)); + ASSERT_COND(sizeof(ioc_fm_pcd_kg_extract_dflt_t) == sizeof(t_FmPcdKgExtractDflt)); +@@ -403,6 +413,9 @@ void LnxWrpPCDIOCTLTypeChecking(void) + /*ioc_fm_pcd_cc_node_modify_key_params_t : private */ + /*ioc_fm_manip_hdr_info_t : private */ + /*ioc_fm_pcd_hash_table_set_t : private */ ++#ifdef CONFIG_FMAN_ARM ++#warning "ls1043 temporary remove size validation" ++#else + ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_ip_params_t) == sizeof(t_FmPcdManipFragIpParams)); + ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_ip_params_t) == sizeof(t_FmPcdManipReassemIpParams)); + ASSERT_COND(sizeof(ioc_fm_pcd_manip_special_offload_ipsec_params_t) == sizeof(t_FmPcdManipSpecialOffloadIPSecParams)); +@@ -433,7 +446,7 @@ void LnxWrpPCDIOCTLTypeChecking(void) + ASSERT_COND(sizeof(ioc_fm_pcd_kg_scheme_select_t) == sizeof(t_FmPcdKgSchemeSelect)); + ASSERT_COND(sizeof(ioc_fm_pcd_port_schemes_params_t) == sizeof(t_FmPcdPortSchemesParams)); + ASSERT_COND(sizeof(ioc_fm_pcd_prs_start_t) == sizeof(t_FmPcdPrsStart)); +- ++#endif + return; + } + +@@ -1531,9 +1544,13 @@ Status: feature not supported + + case (e_IOC_FM_PORT_TYPE_RX_10G): + if (port_params->port_id < FM_MAX_NUM_OF_10G_RX_PORTS) { ++#ifndef CONFIG_FMAN_ARM + if (IS_T1023_T1024) { + h_Port = p_LnxWrpFmDev->rxPorts[port_params->port_id].h_Dev; + } else { ++#else ++ { ++#endif + h_Port = p_LnxWrpFmDev->rxPorts[port_params->port_id + FM_MAX_NUM_OF_1G_RX_PORTS].h_Dev; + } + break; +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.c +index 1de4886..659676b 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.c +@@ -53,7 +53,9 @@ + #include + #include + #include ++#ifndef CONFIG_FMAN_ARM + #include ++#endif + + #include "part_ext.h" + #include "fm_ioctls.h" +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/xx/Makefile b/drivers/net/ethernet/freescale/sdk_fman/src/xx/Makefile +index 1545c8b..90aa941 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/src/xx/Makefile ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/xx/Makefile +@@ -7,5 +7,12 @@ ccflags-y += -DVERSION=\"\" + include $(srctree)/drivers/net/ethernet/freescale/sdk_fman/ncsw_config.mk + + obj-y += fsl-ncsw-xx.o +-fsl-ncsw-xx-objs := xx_linux.o udivdi3.o \ ++ ++ifneq ($(CONFIG_FMAN_ARM),y) ++fsl-ncsw-xx-objs := xx_linux.o udivdi3.o \ ++ module_strings.o ++else ++fsl-ncsw-xx-objs := xx_arm_linux.o udivdi3.o \ + module_strings.o ++endif ++ +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/xx/xx_arm_linux.c b/drivers/net/ethernet/freescale/sdk_fman/src/xx/xx_arm_linux.c +new file mode 100644 +index 0000000..dd3e376 +--- /dev/null ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/xx/xx_arm_linux.c +@@ -0,0 +1,905 @@ ++/* ++ * Copyright 2008-2012 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. ++ */ ++ ++/**************************************************************************//** ++ @File xx_arm_linux.c ++ ++ @Description XX routines implementation for Linux. ++*//***************************************************************************/ ++#include ++ ++#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) ++#define MODVERSIONS ++#endif ++#ifdef MODVERSIONS ++#include ++#endif /* MODVERSIONS */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#ifdef BIGPHYSAREA_ENABLE ++#include ++#endif /* BIGPHYSAREA_ENABLE */ ++ ++//#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "error_ext.h" ++#include "std_ext.h" ++#include "list_ext.h" ++#include "mm_ext.h" ++#include "sys_io_ext.h" ++#include "xx.h" ++ ++ ++#define __ERR_MODULE__ MODULE_UNKNOWN ++ ++#ifdef BIGPHYSAREA_ENABLE ++#define MAX_ALLOCATION_SIZE 128 * 1024 /* Maximum size allocated with kmalloc is 128K */ ++ ++ ++/* TODO: large allocations => use big phys area */ ++/****************************************************************************** ++ * routine: get_nr_pages ++ * ++ * description: ++ * calculates the number of memory pages for a given size (in bytes) ++ * ++ * arguments: ++ * size - the number of bytes ++ * ++ * return code: ++ * The number of pages ++ * ++ *****************************************************************************/ ++static __inline__ uint32_t get_nr_pages (uint32_t size) ++{ ++ return (uint32_t)((size >> PAGE_SHIFT) + (size & PAGE_SHIFT ? 1 : 0)); ++} ++ ++static bool in_big_phys_area (uint32_t addr) ++{ ++ uint32_t base, size; ++ ++ bigphysarea_get_details (&base, &size); ++ return ((addr >= base) && (addr < base + size)); ++} ++#endif /* BIGPHYSAREA_ENABLE */ ++ ++void * xx_Malloc(uint32_t n) ++{ ++ void *a; ++ uint32_t flags; ++ ++ flags = XX_DisableAllIntr(); ++#ifdef BIGPHYSAREA_ENABLE ++ if (n >= MAX_ALLOCATION_SIZE) ++ a = (void*)bigphysarea_alloc_pages(get_nr_pages(n), 0, GFP_ATOMIC); ++ else ++#endif /* BIGPHYSAREA_ENABLE */ ++ a = (void *)kmalloc((uint32_t)n, GFP_ATOMIC); ++ if (!a) ++ XX_Print("No memory for XX_Malloc\n"); ++ XX_RestoreAllIntr(flags); ++ ++ return a; ++} ++ ++void xx_Free(void *p) ++{ ++#ifdef BIGPHYSAREA_ENABLE ++ if (in_big_phys_area ((uint32_t)p)) ++ bigphysarea_free_pages(p); ++ else ++#endif /* BIGPHYSAREA_ENABLE */ ++ kfree(p); ++} ++ ++void XX_Exit(int status) ++{ ++ WARN(1, "\n\nFMD: fatal error, driver can't go on!!!\n\n"); ++} ++ ++#define BUF_SIZE 512 ++void XX_Print(char *str, ...) ++{ ++ va_list args; ++#ifdef CONFIG_SMP ++ char buf[BUF_SIZE]; ++#endif /* CONFIG_SMP */ ++ ++ va_start(args, str); ++#ifdef CONFIG_SMP ++ if (vsnprintf (buf, BUF_SIZE, str, args) >= BUF_SIZE) ++ printk(KERN_WARNING "Illegal string to print!\n more than %d characters.\n\tString was not printed completelly.\n", BUF_SIZE); ++ printk(KERN_CRIT "cpu %d: %s", raw_smp_processor_id(), buf); ++#else ++ vprintk(str, args); ++#endif /* CONFIG_SMP */ ++ va_end(args); ++} ++ ++void XX_Fprint(void *file, char *str, ...) ++{ ++ va_list args; ++#ifdef CONFIG_SMP ++ char buf[BUF_SIZE]; ++#endif /* CONFIG_SMP */ ++ ++ va_start(args, str); ++#ifdef CONFIG_SMP ++ if (vsnprintf (buf, BUF_SIZE, str, args) >= BUF_SIZE) ++ printk(KERN_WARNING "Illegal string to print!\n more than %d characters.\n\tString was not printed completelly.\n", BUF_SIZE); ++ printk (KERN_CRIT "cpu %d: %s", smp_processor_id(), buf); ++ ++#else ++ vprintk(str, args); ++#endif /* CONFIG_SMP */ ++ va_end(args); ++} ++ ++#ifdef DEBUG_XX_MALLOC ++typedef void (*t_ffn)(void *); ++typedef struct { ++ t_ffn f_free; ++ void *mem; ++ char *fname; ++ int fline; ++ uint32_t size; ++ t_List node; ++} t_MemDebug; ++#define MEMDBG_OBJECT(p_List) LIST_OBJECT(p_List, t_MemDebug, node) ++ ++LIST(memDbgLst); ++ ++ ++void * XX_MallocDebug(uint32_t size, char *fname, int line) ++{ ++ void *mem; ++ t_MemDebug *p_MemDbg; ++ ++ p_MemDbg = (t_MemDebug *)xx_Malloc(sizeof(t_MemDebug)); ++ if (p_MemDbg == NULL) ++ return NULL; ++ ++ mem = xx_Malloc(size); ++ if (mem == NULL) ++ { ++ XX_Free(p_MemDbg); ++ return NULL; ++ } ++ ++ INIT_LIST(&p_MemDbg->node); ++ p_MemDbg->f_free = xx_Free; ++ p_MemDbg->mem = mem; ++ p_MemDbg->fname = fname; ++ p_MemDbg->fline = line; ++ p_MemDbg->size = size+sizeof(t_MemDebug); ++ LIST_AddToTail(&p_MemDbg->node, &memDbgLst); ++ ++ return mem; ++} ++ ++void * XX_MallocSmartDebug(uint32_t size, ++ int memPartitionId, ++ uint32_t align, ++ char *fname, ++ int line) ++{ ++ void *mem; ++ t_MemDebug *p_MemDbg; ++ ++ p_MemDbg = (t_MemDebug *)XX_Malloc(sizeof(t_MemDebug)); ++ if (p_MemDbg == NULL) ++ return NULL; ++ ++ mem = xx_MallocSmart((uint32_t)size, memPartitionId, align); ++ if (mem == NULL) ++ { ++ XX_Free(p_MemDbg); ++ return NULL; ++ } ++ ++ INIT_LIST(&p_MemDbg->node); ++ p_MemDbg->f_free = xx_FreeSmart; ++ p_MemDbg->mem = mem; ++ p_MemDbg->fname = fname; ++ p_MemDbg->fline = line; ++ p_MemDbg->size = size+sizeof(t_MemDebug); ++ LIST_AddToTail(&p_MemDbg->node, &memDbgLst); ++ ++ return mem; ++} ++ ++static void debug_free(void *mem) ++{ ++ t_List *p_MemDbgLh = NULL; ++ t_MemDebug *p_MemDbg; ++ bool found = FALSE; ++ ++ if (LIST_IsEmpty(&memDbgLst)) ++ { ++ REPORT_ERROR(MAJOR, E_ALREADY_FREE, ("Unbalanced free (0x%08x)", mem)); ++ return; ++ } ++ ++ LIST_FOR_EACH(p_MemDbgLh, &memDbgLst) ++ { ++ p_MemDbg = MEMDBG_OBJECT(p_MemDbgLh); ++ if (p_MemDbg->mem == mem) ++ { ++ found = TRUE; ++ break; ++ } ++ } ++ ++ if (!found) ++ { ++ REPORT_ERROR(MAJOR, E_NOT_FOUND, ++ ("Attempt to free unallocated address (0x%08x)",mem)); ++ dump_stack(); ++ return; ++ } ++ ++ LIST_Del(p_MemDbgLh); ++ p_MemDbg->f_free(mem); ++ p_MemDbg->f_free(p_MemDbg); ++} ++ ++void XX_FreeSmart(void *p) ++{ ++ debug_free(p); ++} ++ ++ ++void XX_Free(void *p) ++{ ++ debug_free(p); ++} ++ ++#else /* not DEBUG_XX_MALLOC */ ++void * XX_Malloc(uint32_t size) ++{ ++ return xx_Malloc(size); ++} ++ ++void * XX_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment) ++{ ++ return xx_MallocSmart(size,memPartitionId, alignment); ++} ++ ++void XX_FreeSmart(void *p) ++{ ++ xx_FreeSmart(p); ++} ++ ++ ++void XX_Free(void *p) ++{ ++ xx_Free(p); ++} ++#endif /* not DEBUG_XX_MALLOC */ ++ ++ ++#if (defined(REPORT_EVENTS) && (REPORT_EVENTS > 0)) ++void XX_EventById(uint32_t event, t_Handle appId, uint16_t flags, char *msg) ++{ ++ e_Event eventCode = (e_Event)event; ++ ++ UNUSED(eventCode); ++ UNUSED(appId); ++ UNUSED(flags); ++ UNUSED(msg); ++} ++#endif /* (defined(REPORT_EVENTS) && ... */ ++ ++ ++uint32_t XX_DisableAllIntr(void) ++{ ++ unsigned long flags; ++ ++#ifdef local_irq_save_nort ++ local_irq_save_nort(flags); ++#else ++ local_irq_save(flags); ++#endif ++ ++ return (uint32_t)flags; ++} ++ ++void XX_RestoreAllIntr(uint32_t flags) ++{ ++#ifdef local_irq_restore_nort ++ local_irq_restore_nort((unsigned long)flags); ++#else ++ local_irq_restore((unsigned long)flags); ++#endif ++} ++ ++t_Error XX_Call( uint32_t qid, t_Error (* f)(t_Handle), t_Handle id, t_Handle appId, uint16_t flags ) ++{ ++ UNUSED(qid); ++ UNUSED(appId); ++ UNUSED(flags); ++ ++ return f(id); ++} ++ ++int XX_IsICacheEnable(void) ++{ ++ return TRUE; ++} ++ ++int XX_IsDCacheEnable(void) ++{ ++ return TRUE; ++} ++ ++ ++typedef struct { ++ t_Isr *f_Isr; ++ t_Handle handle; ++} t_InterruptHandler; ++ ++ ++t_Handle interruptHandlers[0x00010000]; ++ ++static irqreturn_t LinuxInterruptHandler (int irq, void *dev_id) ++{ ++ t_InterruptHandler *p_IntrHndl = (t_InterruptHandler *)dev_id; ++ p_IntrHndl->f_Isr(p_IntrHndl->handle); ++ return IRQ_HANDLED; ++} ++ ++t_Error XX_SetIntr(int irq, t_Isr *f_Isr, t_Handle handle) ++{ ++ const char *device; ++ t_InterruptHandler *p_IntrHndl; ++ ++ device = GetDeviceName(irq); ++ if (device == NULL) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Interrupt source - %d", irq)); ++ ++ p_IntrHndl = (t_InterruptHandler *)XX_Malloc(sizeof(t_InterruptHandler)); ++ if (p_IntrHndl == NULL) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ p_IntrHndl->f_Isr = f_Isr; ++ p_IntrHndl->handle = handle; ++ interruptHandlers[irq] = p_IntrHndl; ++ ++ if (request_irq(GetDeviceIrqNum(irq), LinuxInterruptHandler, 0, device, p_IntrHndl) < 0) ++ RETURN_ERROR(MAJOR, E_BUSY, ("Can't get IRQ %s\n", device)); ++ disable_irq(GetDeviceIrqNum(irq)); ++ ++ return E_OK; ++} ++ ++t_Error XX_FreeIntr(int irq) ++{ ++ t_InterruptHandler *p_IntrHndl = interruptHandlers[irq]; ++ free_irq(GetDeviceIrqNum(irq), p_IntrHndl); ++ XX_Free(p_IntrHndl); ++ interruptHandlers[irq] = 0; ++ return E_OK; ++} ++ ++t_Error XX_EnableIntr(int irq) ++{ ++ enable_irq(GetDeviceIrqNum(irq)); ++ return E_OK; ++} ++ ++t_Error XX_DisableIntr(int irq) ++{ ++ disable_irq(GetDeviceIrqNum(irq)); ++ return E_OK; ++} ++ ++ ++/*****************************************************************************/ ++/* Tasklet Service Routines */ ++/*****************************************************************************/ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++typedef struct ++{ ++ t_Handle h_Data; ++ void (*f_Callback) (void *); ++ struct delayed_work dwork; ++} t_Tasklet; ++ ++static void GenericTaskletCallback(struct work_struct *p_Work) ++{ ++ t_Tasklet *p_Task = container_of(p_Work, t_Tasklet, dwork.work); ++ ++ p_Task->f_Callback(p_Task->h_Data); ++} ++#endif /* LINUX_VERSION_CODE */ ++ ++ ++t_TaskletHandle XX_InitTasklet (void (*routine)(void *), void *data) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ struct work_struct *p_Task; ++ p_Task = (struct work_struct *)XX_Malloc(sizeof(struct work_struct)); ++ INIT_WORK(p_Task, routine, data); ++#else ++ t_Tasklet *p_Task = (t_Tasklet *)XX_Malloc(sizeof(t_Tasklet)); ++ p_Task->h_Data = data; ++ p_Task->f_Callback = routine; ++ INIT_DELAYED_WORK(&p_Task->dwork, GenericTaskletCallback); ++#endif /* LINUX_VERSION_CODE */ ++ ++ return (t_TaskletHandle)p_Task; ++} ++ ++ ++void XX_FreeTasklet (t_TaskletHandle h_Tasklet) ++{ ++ if (h_Tasklet) ++ XX_Free(h_Tasklet); ++} ++ ++int XX_ScheduleTask(t_TaskletHandle h_Tasklet, int immediate) ++{ ++ int ans; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ if (immediate) ++ ans = schedule_work(h_Tasklet); ++ else ++ ans = schedule_delayed_work(h_Tasklet, 1); ++#else ++ if (immediate) ++ ans = schedule_delayed_work(&((t_Tasklet *)h_Tasklet)->dwork, 0); ++ else ++ ans = schedule_delayed_work(&((t_Tasklet *)h_Tasklet)->dwork, HZ); ++#endif /* LINUX_VERSION_CODE */ ++ ++ return ans; ++} ++ ++void XX_FlushScheduledTasks(void) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ++ flush_scheduled_tasks(); ++#else ++ flush_scheduled_work(); ++#endif /* LINUX_VERSION_CODE */ ++} ++ ++int XX_TaskletIsQueued(t_TaskletHandle h_Tasklet) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ return (int)(((struct work_struct *)h_Tasklet)->pending); ++#else ++ return (int)delayed_work_pending(&((t_Tasklet *)h_Tasklet)->dwork); ++#endif /* LINUX_VERSION_CODE */ ++} ++ ++void XX_SetTaskletData(t_TaskletHandle h_Tasklet, t_Handle data) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ++ ((struct tq_struct *)h_Tasklet)->data = data; ++#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ ((struct work_struct *)h_Tasklet)->data = data; ++#else ++ ((t_Tasklet *)h_Tasklet)->h_Data = data; ++#endif /* LINUX_VERSION_CODE */ ++} ++ ++t_Handle XX_GetTaskletData(t_TaskletHandle h_Tasklet) ++{ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++ return (t_Handle)(((struct work_struct *)h_Tasklet)->data); ++#else ++ return ((t_Tasklet *)h_Tasklet)->h_Data; ++#endif /* LINUX_VERSION_CODE */ ++} ++ ++ ++/*****************************************************************************/ ++/* Spinlock Service Routines */ ++/*****************************************************************************/ ++ ++t_Handle XX_InitSpinlock(void) ++{ ++ spinlock_t *p_Spinlock = (spinlock_t *)XX_Malloc(sizeof(spinlock_t)); ++ if (!p_Spinlock) ++ return NULL; ++ ++ spin_lock_init(p_Spinlock); ++ ++ return (t_Handle)p_Spinlock; ++} ++ ++void XX_FreeSpinlock(t_Handle h_Spinlock) ++{ ++ if (h_Spinlock) ++ XX_Free(h_Spinlock); ++} ++ ++void XX_LockSpinlock(t_Handle h_Spinlock) ++{ ++ spin_lock((spinlock_t *)h_Spinlock); ++} ++ ++void XX_UnlockSpinlock(t_Handle h_Spinlock) ++{ ++ spin_unlock((spinlock_t *)h_Spinlock); ++} ++ ++uint32_t XX_LockIntrSpinlock(t_Handle h_Spinlock) ++{ ++ unsigned long intrFlags; ++ spin_lock_irqsave((spinlock_t *)h_Spinlock, intrFlags); ++ return intrFlags; ++} ++ ++void XX_UnlockIntrSpinlock(t_Handle h_Spinlock, uint32_t intrFlags) ++{ ++ spin_unlock_irqrestore((spinlock_t *)h_Spinlock, (unsigned long)intrFlags); ++} ++ ++ ++/*****************************************************************************/ ++/* Timers Service Routines */ ++/*****************************************************************************/ ++/* The time now is in mili sec. resolution */ ++uint32_t XX_CurrentTime(void) ++{ ++ return (jiffies*1000)/HZ; ++} ++ ++ ++t_Handle XX_CreateTimer(void) ++{ ++ struct timer_list *p_Timer = (struct timer_list *)XX_Malloc(sizeof(struct timer_list)); ++ if (p_Timer) ++ { ++ memset(p_Timer, 0, sizeof(struct timer_list)); ++ init_timer(p_Timer); ++ } ++ return (t_Handle)p_Timer; ++} ++ ++void XX_FreeTimer(t_Handle h_Timer) ++{ ++ if (h_Timer) ++ XX_Free(h_Timer); ++} ++ ++void XX_StartTimer(t_Handle h_Timer, ++ uint32_t msecs, ++ bool periodic, ++ void (*f_TimerExpired)(t_Handle), ++ t_Handle h_Arg) ++{ ++ int tmp_jiffies = (msecs*HZ)/1000; ++ struct timer_list *p_Timer = (struct timer_list *)h_Timer; ++ ++ SANITY_CHECK_RETURN((periodic == FALSE), E_NOT_SUPPORTED); ++ ++ p_Timer->function = (void (*)(unsigned long))f_TimerExpired; ++ p_Timer->data = (unsigned long)h_Arg; ++ if ((msecs*HZ)%1000) ++ tmp_jiffies++; ++ p_Timer->expires = (jiffies + tmp_jiffies); ++ ++ add_timer((struct timer_list *)h_Timer); ++} ++ ++void XX_SetTimerData(t_Handle h_Timer, t_Handle data) ++{ ++ struct timer_list *p_Timer = (struct timer_list *)h_Timer; ++ ++ p_Timer->data = (unsigned long)data; ++} ++ ++t_Handle XX_GetTimerData(t_Handle h_Timer) ++{ ++ struct timer_list *p_Timer = (struct timer_list *)h_Timer; ++ ++ return (t_Handle)p_Timer->data; ++} ++ ++uint32_t XX_GetExpirationTime(t_Handle h_Timer) ++{ ++ struct timer_list *p_Timer = (struct timer_list *)h_Timer; ++ ++ return (uint32_t)p_Timer->expires; ++} ++ ++void XX_StopTimer(t_Handle h_Timer) ++{ ++ del_timer((struct timer_list *)h_Timer); ++} ++ ++void XX_ModTimer(t_Handle h_Timer, uint32_t msecs) ++{ ++ int tmp_jiffies = (msecs*HZ)/1000; ++ ++ if ((msecs*HZ)%1000) ++ tmp_jiffies++; ++ mod_timer((struct timer_list *)h_Timer, jiffies + tmp_jiffies); ++} ++ ++int XX_TimerIsActive(t_Handle h_Timer) ++{ ++ return timer_pending((struct timer_list *)h_Timer); ++} ++ ++uint32_t XX_Sleep(uint32_t msecs) ++{ ++ int tmp_jiffies = (msecs*HZ)/1000; ++ ++ if ((msecs*HZ)%1000) ++ tmp_jiffies++; ++ return schedule_timeout(tmp_jiffies); ++} ++ ++/*BEWARE!!!!! UDelay routine is BUSY WAITTING!!!!!*/ ++void XX_UDelay(uint32_t usecs) ++{ ++ udelay(usecs); ++} ++ ++/* TODO: verify that these are correct */ ++#define MSG_BODY_SIZE 512 ++typedef t_Error (t_MsgHandler) (t_Handle h_Mod, uint32_t msgId, uint8_t msgBody[MSG_BODY_SIZE]); ++typedef void (t_MsgCompletionCB) (t_Handle h_Arg, uint8_t msgBody[MSG_BODY_SIZE]); ++t_Error XX_SendMessage(char *p_DestAddr, ++ uint32_t msgId, ++ uint8_t msgBody[MSG_BODY_SIZE], ++ t_MsgCompletionCB *f_CompletionCB, ++ t_Handle h_CBArg); ++ ++typedef struct { ++ char *p_Addr; ++ t_MsgHandler *f_MsgHandlerCB; ++ t_Handle h_Mod; ++ t_List node; ++} t_MsgHndlr; ++#define MSG_HNDLR_OBJECT(ptr) LIST_OBJECT(ptr, t_MsgHndlr, node) ++ ++LIST(msgHndlrList); ++ ++static void EnqueueMsgHndlr(t_MsgHndlr *p_MsgHndlr) ++{ ++ uint32_t intFlags; ++ ++ intFlags = XX_DisableAllIntr(); ++ LIST_AddToTail(&p_MsgHndlr->node, &msgHndlrList); ++ XX_RestoreAllIntr(intFlags); ++} ++/* TODO: add this for multi-platform support ++static t_MsgHndlr * DequeueMsgHndlr(void) ++{ ++ t_MsgHndlr *p_MsgHndlr = NULL; ++ uint32_t intFlags; ++ ++ intFlags = XX_DisableAllIntr(); ++ if (!LIST_IsEmpty(&msgHndlrList)) ++ { ++ p_MsgHndlr = MSG_HNDLR_OBJECT(msgHndlrList.p_Next); ++ LIST_DelAndInit(&p_MsgHndlr->node); ++ } ++ XX_RestoreAllIntr(intFlags); ++ ++ return p_MsgHndlr; ++} ++*/ ++static t_MsgHndlr * FindMsgHndlr(char *p_Addr) ++{ ++ t_MsgHndlr *p_MsgHndlr; ++ t_List *p_Pos; ++ ++ LIST_FOR_EACH(p_Pos, &msgHndlrList) ++ { ++ p_MsgHndlr = MSG_HNDLR_OBJECT(p_Pos); ++ if (strstr(p_MsgHndlr->p_Addr, p_Addr)) ++ return p_MsgHndlr; ++ } ++ ++ return NULL; ++} ++ ++t_Error XX_RegisterMessageHandler (char *p_Addr, t_MsgHandler *f_MsgHandlerCB, t_Handle h_Mod) ++{ ++ t_MsgHndlr *p_MsgHndlr; ++ uint32_t len; ++ ++ p_MsgHndlr = (t_MsgHndlr*)XX_Malloc(sizeof(t_MsgHndlr)); ++ if (!p_MsgHndlr) ++ RETURN_ERROR(MINOR, E_NO_MEMORY, ("message handler object!!!")); ++ memset(p_MsgHndlr, 0, sizeof(t_MsgHndlr)); ++ ++ len = strlen(p_Addr); ++ p_MsgHndlr->p_Addr = (char*)XX_Malloc(len+1); ++ strncpy(p_MsgHndlr->p_Addr,p_Addr, (uint32_t)(len+1)); ++ ++ p_MsgHndlr->f_MsgHandlerCB = f_MsgHandlerCB; ++ p_MsgHndlr->h_Mod = h_Mod; ++ INIT_LIST(&p_MsgHndlr->node); ++ EnqueueMsgHndlr(p_MsgHndlr); ++ ++ return E_OK; ++} ++ ++t_Error XX_UnregisterMessageHandler (char *p_Addr) ++{ ++ t_MsgHndlr *p_MsgHndlr = FindMsgHndlr(p_Addr); ++ if (!p_MsgHndlr) ++ RETURN_ERROR(MINOR, E_NO_DEVICE, ("message handler not found in list!!!")); ++ ++ LIST_Del(&p_MsgHndlr->node); ++ XX_Free(p_MsgHndlr->p_Addr); ++ XX_Free(p_MsgHndlr); ++ ++ return E_OK; ++} ++ ++t_Error XX_SendMessage(char *p_DestAddr, ++ uint32_t msgId, ++ uint8_t msgBody[MSG_BODY_SIZE], ++ t_MsgCompletionCB *f_CompletionCB, ++ t_Handle h_CBArg) ++{ ++ t_Error ans; ++ t_MsgHndlr *p_MsgHndlr = FindMsgHndlr(p_DestAddr); ++ if (!p_MsgHndlr) ++ RETURN_ERROR(MINOR, E_NO_DEVICE, ("message handler not found in list!!!")); ++ ++ ans = p_MsgHndlr->f_MsgHandlerCB(p_MsgHndlr->h_Mod, msgId, msgBody); ++ ++ if (f_CompletionCB) ++ f_CompletionCB(h_CBArg, msgBody); ++ ++ return ans; ++} ++ ++t_Error XX_IpcRegisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH], ++ t_IpcMsgHandler *f_MsgHandler, ++ t_Handle h_Module, ++ uint32_t replyLength) ++{ ++ UNUSED(addr);UNUSED(f_MsgHandler);UNUSED(h_Module);UNUSED(replyLength); ++ return E_OK; ++} ++ ++t_Error XX_IpcUnregisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH]) ++{ ++ UNUSED(addr); ++ return E_OK; ++} ++ ++ ++t_Error XX_IpcSendMessage(t_Handle h_Session, ++ uint8_t *p_Msg, ++ uint32_t msgLength, ++ uint8_t *p_Reply, ++ uint32_t *p_ReplyLength, ++ t_IpcMsgCompletion *f_Completion, ++ t_Handle h_Arg) ++{ ++ UNUSED(h_Session); UNUSED(p_Msg); UNUSED(msgLength); UNUSED(p_Reply); ++ UNUSED(p_ReplyLength); UNUSED(f_Completion); UNUSED(h_Arg); ++ return E_OK; ++} ++ ++t_Handle XX_IpcInitSession(char destAddr[XX_IPC_MAX_ADDR_NAME_LENGTH], ++ char srcAddr[XX_IPC_MAX_ADDR_NAME_LENGTH]) ++{ ++ UNUSED(destAddr); UNUSED(srcAddr); ++ return E_OK; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) ++int GetDeviceIrqNum(int irq) ++{ ++ struct device_node *iPar; ++ struct irq_domain *irqHost; ++ uint32_t hwIrq; ++ ++ /* Get the interrupt controller */ ++ iPar = of_find_node_by_name(NULL, "mpic"); ++ hwIrq = 0; ++ ++ ASSERT_COND(iPar != NULL); ++ /* Get the irq host */ ++ irqHost = irq_find_host(iPar); ++ of_node_put(iPar); ++ ++ /* Create irq mapping */ ++ return irq_create_mapping(irqHost, hwIrq); ++} ++#else ++#error "kernel not supported!!!" ++#endif /* LINUX_VERSION_CODE */ ++ ++void * XX_PhysToVirt(physAddress_t addr) ++{ ++ return UINT_TO_PTR(SYS_PhysToVirt((uint64_t)addr)); ++} ++ ++physAddress_t XX_VirtToPhys(void * addr) ++{ ++ return (physAddress_t)SYS_VirtToPhys(PTR_TO_UINT(addr)); ++} ++ ++void * xx_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment) ++{ ++ uintptr_t *returnCode, tmp; ++ ++ if (alignment < sizeof(uintptr_t)) ++ alignment = sizeof(uintptr_t); ++ size += alignment + sizeof(returnCode); ++ tmp = (uintptr_t)xx_Malloc(size); ++ if (tmp == 0) ++ return NULL; ++ returnCode = (uintptr_t*)((tmp + alignment + sizeof(returnCode)) & ~((uintptr_t)alignment - 1)); ++ *(returnCode - 1) = tmp; ++ ++ return (void*)returnCode; ++} ++ ++void xx_FreeSmart(void *p) ++{ ++ xx_Free((void*)(*((uintptr_t *)(p) - 1))); ++} +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/xx/xx_linux.c b/drivers/net/ethernet/freescale/sdk_fman/src/xx/xx_linux.c +index d5c639a..992757d 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/src/xx/xx_linux.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/xx/xx_linux.c +@@ -62,6 +62,9 @@ + #include + #include + #include ++#ifdef CONFIG_FMAN_ARM ++#include ++#endif + + #include + +@@ -69,7 +72,9 @@ + #include + #endif /* BIGPHYSAREA_ENABLE */ + ++#ifndef CONFIG_FMAN_ARM + #include ++#endif + #include + #include + #include +@@ -168,7 +173,7 @@ void XX_Print(char *str, ...) + #ifdef CONFIG_SMP + if (vsnprintf (buf, BUF_SIZE, str, args) >= BUF_SIZE) + printk(KERN_WARNING "Illegal string to print!\n more than %d characters.\n\tString was not printed completelly.\n", BUF_SIZE); +- printk(KERN_CRIT "cpu%d/%d: %s", get_hard_smp_processor_id(raw_smp_processor_id()), raw_smp_processor_id(), buf); ++ printk(KERN_CRIT "cpu%d/%d: %s", raw_smp_processor_id(), NR_CPUS, buf); + #else + vprintk(str, args); + #endif /* CONFIG_SMP */ +@@ -186,7 +191,7 @@ void XX_Fprint(void *file, char *str, ...) + #ifdef CONFIG_SMP + if (vsnprintf (buf, BUF_SIZE, str, args) >= BUF_SIZE) + printk(KERN_WARNING "Illegal string to print!\n more than %d characters.\n\tString was not printed completelly.\n", BUF_SIZE); +- printk (KERN_CRIT "cpu%d/%d: %s",hard_smp_processor_id(), smp_processor_id(), buf); ++ printk (KERN_CRIT "cpu%d/%d: %s", raw_smp_processor_id(), NR_CPUS, buf); + + #else + vprintk(str, args); +@@ -400,10 +405,36 @@ typedef struct { + + t_Handle interruptHandlers[0x00010000]; + ++#ifdef CONFIG_FMAN_ARM ++static irqreturn_t LinuxInterruptHandler (int irq, void *dev_id) ++{ ++ t_InterruptHandler *p_IntrHndl = (t_InterruptHandler *)dev_id; ++ p_IntrHndl->f_Isr(p_IntrHndl->handle); ++ return IRQ_HANDLED; ++} ++#endif + + t_Error XX_SetIntr(int irq, t_Isr *f_Isr, t_Handle handle) + { +-/* not used */ ++#ifdef CONFIG_FMAN_ARM ++ const char *device; ++ t_InterruptHandler *p_IntrHndl; ++ ++ device = GetDeviceName(irq); ++ if (device == NULL) ++ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Interrupt source - %d", irq)); ++ ++ p_IntrHndl = (t_InterruptHandler *)XX_Malloc(sizeof(t_InterruptHandler)); ++ if (p_IntrHndl == NULL) ++ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG); ++ p_IntrHndl->f_Isr = f_Isr; ++ p_IntrHndl->handle = handle; ++ interruptHandlers[irq] = p_IntrHndl; ++ ++ if (request_irq(GetDeviceIrqNum(irq), LinuxInterruptHandler, 0, device, p_IntrHndl) < 0) ++ RETURN_ERROR(MAJOR, E_BUSY, ("Can't get IRQ %s\n", device)); ++ disable_irq(GetDeviceIrqNum(irq)); ++#endif + return E_OK; + } + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0067-dpaa_eth-Use-S-G-accessors-in-the-Shared-Mac-driver.patch b/target/linux/layerscape-64b/patches-4.1/0067-dpaa_eth-Use-S-G-accessors-in-the-Shared-Mac-driver.patch new file mode 100644 index 0000000..9418ab6 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0067-dpaa_eth-Use-S-G-accessors-in-the-Shared-Mac-driver.patch @@ -0,0 +1,78 @@ +From fe56fa16a32e5d429e0e3e19c3999de8bc078d3b Mon Sep 17 00:00:00 2001 +From: Cristian Sovaiala +Date: Tue, 14 Jul 2015 15:25:04 +0300 +Subject: [PATCH 067/151] dpaa_eth: Use S/G accessors in the Shared-Mac driver + +Signed-off-by: Cristian Sovaiala +--- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_shared.c | 30 ++++++++++++---------- + 1 file changed, 17 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_shared.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_shared.c +index 6564758..da50dc4 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_shared.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_shared.c +@@ -235,6 +235,9 @@ shared_rx_dqrr(struct qman_portal *portal, struct qman_fq *fq, + struct sk_buff *skb; + struct qm_sg_entry *sgt; + int i; ++ void *frag_addr; ++ u32 frag_length; ++ u32 offset; + + net_dev = ((struct dpa_fq *)fq)->net_dev; + priv = netdev_priv(net_dev); +@@ -270,20 +273,21 @@ shared_rx_dqrr(struct qman_portal *portal, struct qman_fq *fq, + + if (fd->format == qm_fd_sg) { + if (dpa_bp->vaddr) { +- sgt = dpa_phys2virt(dpa_bp, qm_fd_addr(fd)) + +- dpa_fd_offset(fd); ++ sgt = dpa_phys2virt(dpa_bp, ++ qm_fd_addr(fd)) + dpa_fd_offset(fd); + + for (i = 0; i < DPA_SGT_MAX_ENTRIES; i++) { +- void *frag_addr = dpa_phys2virt(dpa_bp, +- qm_sg_addr(&sgt[i]) + +- be16_to_cpu(sgt[i].offset)); +- u32 frag_length = be32_to_cpu(sgt[i].length); +- BUG_ON(sgt[i].extension); ++ offset = qm_sg_entry_get_offset(&sgt[i]); ++ frag_addr = dpa_phys2virt(dpa_bp, ++ qm_sg_addr(&sgt[i]) + ++ offset); ++ DPA_BUG_ON(qm_sg_entry_get_ext(&sgt[i])); ++ frag_length = qm_sg_entry_get_len(&sgt[i]); + + /* copy from sgt[i] */ + memcpy(skb_put(skb, frag_length), frag_addr, +- frag_length); +- if (sgt[i].final) ++ frag_length); ++ if (qm_sg_entry_get_final(&sgt[i])) + break; + } + } else { +@@ -302,15 +306,15 @@ shared_rx_dqrr(struct qman_portal *portal, struct qman_fq *fq, + dpa_bp->size)); + + for (i = 0; i < DPA_SGT_MAX_ENTRIES; i++) { +- u32 frag_length = be32_to_cpu(sgt[i].length); +- BUG_ON(sgt[i].extension); ++ DPA_BUG_ON(qm_sg_entry_get_ext(&sgt[i])); ++ frag_length = qm_sg_entry_get_len(&sgt[i]); + copy_from_unmapped_area( + skb_put(skb, frag_length), + qm_sg_addr(&sgt[i]) + +- be16_to_cpu(sgt[i].offset), ++ qm_sg_entry_get_offset(&sgt[i]), + frag_length); + +- if (sgt[i].final) ++ if (qm_sg_entry_get_final(&sgt[i])) + break; + } + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0068-dpaa_eth-fix-S-G-for-ARM.patch b/target/linux/layerscape-64b/patches-4.1/0068-dpaa_eth-fix-S-G-for-ARM.patch new file mode 100644 index 0000000..c6a171b --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0068-dpaa_eth-fix-S-G-for-ARM.patch @@ -0,0 +1,212 @@ +From d9a877f36103da57d12eae3587811454b7d1d8f2 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Mon, 11 May 2015 17:45:48 +0300 +Subject: [PATCH 068/151] dpaa_eth: fix S/G for ARM + +This patch makes the endianness conversion needed for ARM's LE data processing +of the S/G tables. + +A new union was created in the S/G Table structure for easy reference to the +32bit concatenated field. + +Change-Id: I7d21da325596530528805845acad92d7f9a707df +Signed-off-by: Marian-Cristian Rotariu +Reviewed-on: http://git.am.freescale.net:8181/39539 +Reviewed-by: Madalin-Cristian Bucur +--- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_common.c | 1 + + .../net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 72 ++++++++++++++-------- + 2 files changed, 48 insertions(+), 25 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +index cc3968b..dcef8dd 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +@@ -1545,6 +1545,7 @@ void dpa_release_sgt(struct qm_sg_entry *sgt) + + j = 0; + do { ++ be32_to_cpus(&sgt[i].sgt_efl); + DPA_BUG_ON(sgt[i].extension); + + bmb[j].hi = sgt[i].addr_hi; +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +index 92d0f06..8a95d06 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +@@ -219,6 +219,7 @@ struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv, + struct sk_buff *skb = NULL; + const enum dma_data_direction dma_dir = DMA_TO_DEVICE; + int nr_frags; ++ int sg_len; + + dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, dma_dir); + +@@ -246,19 +247,22 @@ struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv, + } + #endif /* CONFIG_FSL_DPAA_TS */ + ++ be32_to_cpus(&sgt[0].sgt_efl); ++ + /* sgt[0] is from lowmem, was dma_map_single()-ed */ +- /* TODO: sg_addr should be in CPU endianess */ +- sg_addr = qm_sg_addr(&sgt[0]); +- dma_unmap_single(dpa_bp->dev, sg_addr, +- be32_to_cpu(sgt[0].length), dma_dir); ++ sg_addr = sgt[0].addr_hi << 32; ++ sg_addr += be32_to_cpu(sgt[0].addr_lo); ++ sg_len = sgt[0].length; ++ dma_unmap_single(dpa_bp->dev, sg_addr, sg_len, dma_dir); + + /* remaining pages were mapped with dma_map_page() */ +- for (i = 1; i < nr_frags; i++) { ++ for (i = 1; i <= nr_frags; i++) { ++ be32_to_cpus(&sgt[i].sgt_efl); + DPA_BUG_ON(sgt[i].extension); +- /* TODO: sg_addr should be in CPU endianess */ +- sg_addr = qm_sg_addr(&sgt[i]); +- dma_unmap_page(dpa_bp->dev, sg_addr, +- be32_to_cpu(sgt[i].length), dma_dir); ++ sg_addr = sgt[i].addr_hi << 32; ++ sg_addr += be32_to_cpu(sgt[i].addr_lo); ++ sg_len = sgt[i].length; ++ dma_unmap_page(dpa_bp->dev, sg_addr, sg_len, dma_dir); + } + + /* Free the page frag that we allocated on Tx */ +@@ -421,13 +425,14 @@ static struct sk_buff *__hot sg_fd_to_skb(const struct dpa_priv_s *priv, + /* Iterate through the SGT entries and add data buffers to the skb */ + sgt = vaddr + fd_off; + for (i = 0; i < DPA_SGT_MAX_ENTRIES; i++) { ++ be32_to_cpus(&sgt[i].sgt_efl); + /* Extension bit is not supported */ + DPA_BUG_ON(sgt[i].extension); + + /* We use a single global Rx pool */ + DPA_BUG_ON(dpa_bp != dpa_bpid2pool(sgt[i].bpid)); + +- /* TODO: sg_addr should be in CPU endianess */ ++ be64_to_cpus(sgt + i); + sg_addr = qm_sg_addr(&sgt[i]); + sg_vaddr = phys_to_virt(sg_addr); + DPA_BUG_ON(!IS_ALIGNED((unsigned long)sg_vaddr, +@@ -462,7 +467,7 @@ static struct sk_buff *__hot sg_fd_to_skb(const struct dpa_priv_s *priv, + */ + DPA_BUG_ON(fd_off != priv->rx_headroom); + skb_reserve(skb, fd_off); +- skb_put(skb, be32_to_cpu(sgt[i].length)); ++ skb_put(skb, sgt[i].length); + } else { + /* Not the first S/G entry; all data from buffer will + * be added in an skb fragment; fragment index is offset +@@ -488,8 +493,8 @@ static struct sk_buff *__hot sg_fd_to_skb(const struct dpa_priv_s *priv, + /* page_offset only refers to the beginning of sgt[i]; + * but the buffer itself may have an internal offset. + */ +- frag_offset = be16_to_cpu(sgt[i].offset) + page_offset; +- frag_len = be32_to_cpu(sgt[i].length); ++ frag_offset = sgt[i].offset + page_offset; ++ frag_len = sgt[i].length; + /* skb_add_rx_frag() does no checking on the page; if + * we pass it a tail page, we'll end up with + * bad page accounting and eventually with segafults. +@@ -722,8 +727,10 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + { + struct dpa_bp *dpa_bp = priv->dpa_bp; + dma_addr_t addr; ++ dma_addr_t sg_addr; + struct sk_buff **skbh; + struct net_device *net_dev = priv->net_dev; ++ int sg_len; + int err; + + struct qm_sg_entry *sgt; +@@ -763,16 +770,21 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + sgt = (struct qm_sg_entry *)(sgt_buf + priv->tx_headroom); + sgt[0].bpid = 0xff; + sgt[0].offset = 0; +- sgt[0].length = cpu_to_be32(skb_headlen(skb)); ++ sgt[0].length = skb_headlen(skb); + sgt[0].extension = 0; + sgt[0].final = 0; +- addr = dma_map_single(dpa_bp->dev, skb->data, sgt[0].length, dma_dir); ++ sg_len = sgt[0].length; ++ ++ cpu_to_be32s(&sgt[0].sgt_efl); ++ ++ addr = dma_map_single(dpa_bp->dev, skb->data, sg_len, dma_dir); + if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { + dev_err(dpa_bp->dev, "DMA mapping failed"); + err = -EINVAL; + goto sg0_map_failed; + + } ++ + sgt[0].addr_hi = (uint8_t)upper_32_bits(addr); + sgt[0].addr_lo = cpu_to_be32(lower_32_bits(addr)); + +@@ -781,24 +793,31 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + frag = &skb_shinfo(skb)->frags[i - 1]; + sgt[i].bpid = 0xff; + sgt[i].offset = 0; +- sgt[i].length = cpu_to_be32(frag->size); ++ sgt[i].length = frag->size; + sgt[i].extension = 0; +- sgt[i].final = 0; ++ sg_len = sgt[i].length; ++ if (i == nr_frags) ++ sgt[i].final = 1; ++ else ++ sgt[i].final = 0; ++ + + DPA_BUG_ON(!skb_frag_page(frag)); +- addr = skb_frag_dma_map(dpa_bp->dev, frag, 0, sgt[i].length, +- dma_dir); ++ ++ cpu_to_be32s(&sgt[i].sgt_efl); ++ ++ addr = skb_frag_dma_map(dpa_bp->dev, frag, 0, sg_len, dma_dir); + if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { + dev_err(dpa_bp->dev, "DMA mapping failed"); + err = -EINVAL; + goto sg_map_failed; + } + ++ + /* keep the offset in the address */ + sgt[i].addr_hi = (uint8_t)upper_32_bits(addr); + sgt[i].addr_lo = cpu_to_be32(lower_32_bits(addr)); + } +- sgt[i - 1].final = 1; + + fd->length20 = skb->len; + fd->offset = priv->tx_headroom; +@@ -820,16 +839,19 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + + fd->bpid = 0xff; + fd->cmd |= FM_FD_CMD_FCO; +- fd->addr_hi = (uint8_t)upper_32_bits(addr); +- fd->addr_lo = lower_32_bits(addr); ++ fd->addr = addr; + + return 0; + + sgt_map_failed: + sg_map_failed: +- for (j = 0; j < i; j++) +- dma_unmap_page(dpa_bp->dev, qm_sg_addr(&sgt[j]), +- be32_to_cpu(sgt[j].length), dma_dir); ++ for (j = 0; j < i; j++) { ++ be32_to_cpus(&sgt[j].sgt_efl); ++ sg_addr = sgt[j].addr_hi << 32; ++ sg_addr += be32_to_cpu(sgt[j].addr_lo); ++ dma_unmap_page(dpa_bp->dev, sg_addr, sgt[j].length, ++ dma_dir); ++ } + sg0_map_failed: + csum_failed: + put_page(virt_to_head_page(sgt_buf)); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0069-dpaa_eth-memset-bm_buffer-and-qm_sg_entry-structures.patch b/target/linux/layerscape-64b/patches-4.1/0069-dpaa_eth-memset-bm_buffer-and-qm_sg_entry-structures.patch new file mode 100644 index 0000000..b9a6ffb --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0069-dpaa_eth-memset-bm_buffer-and-qm_sg_entry-structures.patch @@ -0,0 +1,26 @@ +From 60bb39fd0e6230a63149d50ef5a9e93b0fd7c5f3 Mon Sep 17 00:00:00 2001 +From: Cristian Sovaiala +Date: Mon, 15 Jun 2015 17:30:24 +0300 +Subject: [PATCH 069/151] dpaa_eth: memset bm_buffer and qm_sg_entry structures + +Signed-off-by: Cristian Sovaiala +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +index 8a95d06..bab3bfc 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +@@ -59,6 +59,8 @@ static void dpa_bp_recycle_frag(struct dpa_bp *dpa_bp, unsigned long vaddr, + struct bm_buffer bmb; + dma_addr_t addr; + ++ memset(&bmb, 0, sizeof(struct bm_buffer)); ++ + addr = dma_map_single(dpa_bp->dev, (void *)vaddr, dpa_bp->size, + DMA_BIDIRECTIONAL); + if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0070-dpaa_eth-Fix-dma_map-unmap-for-the-Tx-S-G-path.patch b/target/linux/layerscape-64b/patches-4.1/0070-dpaa_eth-Fix-dma_map-unmap-for-the-Tx-S-G-path.patch new file mode 100644 index 0000000..d358cb7 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0070-dpaa_eth-Fix-dma_map-unmap-for-the-Tx-S-G-path.patch @@ -0,0 +1,87 @@ +From 7328eb3e0b768326c2fc48b4ac2194a4a075df64 Mon Sep 17 00:00:00 2001 +From: Cristian Sovaiala +Date: Thu, 18 Jun 2015 16:03:28 +0300 +Subject: [PATCH 070/151] dpaa_eth: Fix dma_map/unmap for the Tx S/G path + +Signed-off-by: Madalin Bucur +--- + .../net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 28 +++++++++++----------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +index bab3bfc..64a270e 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +@@ -223,13 +223,14 @@ struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv, + int nr_frags; + int sg_len; + +- dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, dma_dir); +- + /* retrieve skb back pointer */ + DPA_READ_SKB_PTR(skb, skbh, phys_to_virt(addr), 0); +- nr_frags = skb_shinfo(skb)->nr_frags; + +- if (fd->format == qm_fd_sg) { ++ if (unlikely(fd->format == qm_fd_sg)) { ++ nr_frags = skb_shinfo(skb)->nr_frags; ++ dma_unmap_single(dpa_bp->dev, addr, dpa_fd_offset(fd) + ++ sizeof(struct qm_sg_entry) * (1 + nr_frags), ++ dma_dir); + /* The sgt buffer has been allocated with netdev_alloc_frag(), + * it's from lowmem. + */ +@@ -269,9 +270,10 @@ struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv, + + /* Free the page frag that we allocated on Tx */ + put_page(virt_to_head_page(sgt)); +- } ++ } else { ++ dma_unmap_single(dpa_bp->dev, addr, ++ skb_tail_pointer(skb) - (u8 *)skbh, dma_dir); + #ifdef CONFIG_FSL_DPAA_TS +- else { + /* get the timestamp for non-SG frames */ + #ifdef CONFIG_FSL_DPAA_1588 + if (priv->tsu && priv->tsu->valid && +@@ -285,8 +287,8 @@ struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv, + dpa_get_ts(priv, TX, &shhwtstamps, (void *)skbh); + skb_tstamp_tx(skb, &shhwtstamps); + } +- } + #endif ++ } + + return skb; + } +@@ -711,7 +713,7 @@ int __hot skb_to_contig_fd(struct dpa_priv_s *priv, + + /* Map the entire buffer size that may be seen by FMan, but no more */ + addr = dma_map_single(dpa_bp->dev, skbh, +- skb_end_pointer(skb) - buffer_start, dma_dir); ++ skb_tail_pointer(skb) - buffer_start, dma_dir); + if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { + if (netif_msg_tx_err(priv) && net_ratelimit()) + netdev_err(net_dev, "dma_map_single() failed\n"); +@@ -825,14 +827,12 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + fd->offset = priv->tx_headroom; + + /* DMA map the SGT page */ +- buffer_start = (void *)sgt - dpa_fd_offset(fd); +- /* Can't write at "negative" offset in buffer_start, because this skb +- * may not have been allocated by us. +- */ ++ buffer_start = (void *)sgt - priv->tx_headroom; + DPA_WRITE_SKB_PTR(skb, skbh, buffer_start, 0); + +- addr = dma_map_single(dpa_bp->dev, buffer_start, +- skb_end_pointer(skb) - (unsigned char *)buffer_start, dma_dir); ++ addr = dma_map_single(dpa_bp->dev, buffer_start, priv->tx_headroom + ++ sizeof(struct qm_sg_entry) * (1 + nr_frags), ++ dma_dir); + if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { + dev_err(dpa_bp->dev, "DMA mapping failed"); + err = -EINVAL; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0071-dpaa_eth-Use-raw_smp_processor_id-to-get-queue-mappi.patch b/target/linux/layerscape-64b/patches-4.1/0071-dpaa_eth-Use-raw_smp_processor_id-to-get-queue-mappi.patch new file mode 100644 index 0000000..62b995b --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0071-dpaa_eth-Use-raw_smp_processor_id-to-get-queue-mappi.patch @@ -0,0 +1,32 @@ +From 6ed162716da6c1d05210aef7894dbccb42e0a71f Mon Sep 17 00:00:00 2001 +From: Cristian Sovaiala +Date: Thu, 18 Jun 2015 15:16:28 +0300 +Subject: [PATCH 071/151] dpaa_eth: Use raw_smp_processor_id() to get queue + mapping + +Use raw_smp_processor_id() instead of smp_processor_id() to get +frame queue mapping. This is especially required on preemptible +kernels where preemption can change the CPU where the code is +executing on. + +Signed-off-by: Cristian Sovaiala +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +index db52ede..40d956b 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +@@ -639,7 +639,7 @@ static inline void _dpa_assign_wq(struct dpa_fq *fq) + + #else + #define dpa_get_queue_mapping(skb) \ +- smp_processor_id() ++ raw_smp_processor_id() + #endif + #else + /* Use the queue selected by XPS */ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0072-dpaa_eth-added-qsgmii-support.patch b/target/linux/layerscape-64b/patches-4.1/0072-dpaa_eth-added-qsgmii-support.patch new file mode 100644 index 0000000..22e4e20 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0072-dpaa_eth-added-qsgmii-support.patch @@ -0,0 +1,56 @@ +From de8a249150dbc599b588fdd095b2514b56b7b99f Mon Sep 17 00:00:00 2001 +From: Shaohui Xie +Date: Wed, 8 Jul 2015 17:24:17 +0800 +Subject: [PATCH 072/151] dpaa_eth: added qsgmii support + +Signed-off-by: Shaohui Xie +Signed-off-by: Mingkai Hu +--- + drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c | 1 + + drivers/net/ethernet/freescale/sdk_dpaa/mac.c | 4 +++- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c b/drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c +index ad764af..af78576 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c +@@ -83,6 +83,7 @@ static const enet_mode_t _100[] = { + static const enet_mode_t _1000[] = { + [PHY_INTERFACE_MODE_GMII] = e_ENET_MODE_GMII_1000, + [PHY_INTERFACE_MODE_SGMII] = e_ENET_MODE_SGMII_1000, ++ [PHY_INTERFACE_MODE_QSGMII] = e_ENET_MODE_QSGMII_1000, + [PHY_INTERFACE_MODE_TBI] = e_ENET_MODE_TBI_1000, + [PHY_INTERFACE_MODE_RGMII] = e_ENET_MODE_RGMII_1000, + [PHY_INTERFACE_MODE_RGMII_ID] = e_ENET_MODE_RGMII_1000, +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/mac.c b/drivers/net/ethernet/freescale/sdk_dpaa/mac.c +index d004038..367b625 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/mac.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/mac.c +@@ -65,6 +65,7 @@ static const char phy_str[][11] = { + [PHY_INTERFACE_MODE_MII] = "mii", + [PHY_INTERFACE_MODE_GMII] = "gmii", + [PHY_INTERFACE_MODE_SGMII] = "sgmii", ++ [PHY_INTERFACE_MODE_QSGMII] = "qsgmii", + [PHY_INTERFACE_MODE_TBI] = "tbi", + [PHY_INTERFACE_MODE_RMII] = "rmii", + [PHY_INTERFACE_MODE_RGMII] = "rgmii", +@@ -91,6 +92,7 @@ static const uint16_t phy2speed[] = { + [PHY_INTERFACE_MODE_MII] = SPEED_100, + [PHY_INTERFACE_MODE_GMII] = SPEED_1000, + [PHY_INTERFACE_MODE_SGMII] = SPEED_1000, ++ [PHY_INTERFACE_MODE_QSGMII] = SPEED_1000, + [PHY_INTERFACE_MODE_TBI] = SPEED_1000, + [PHY_INTERFACE_MODE_RMII] = SPEED_100, + [PHY_INTERFACE_MODE_RGMII] = SPEED_1000, +@@ -335,7 +337,7 @@ static int __cold mac_probe(struct platform_device *_of_dev) + mac_dev->max_speed = mac_dev->speed; + mac_dev->if_support = DTSEC_SUPPORTED; + /* We don't support half-duplex in SGMII mode */ +- if (strstr(char_prop, "sgmii")) ++ if (strstr(char_prop, "sgmii") || strstr(char_prop, "qsgmii")) + mac_dev->if_support &= ~(SUPPORTED_10baseT_Half | + SUPPORTED_100baseT_Half); + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0073-dpaa_eth-Use-accessors-to-update-and-query-the-qm_sg.patch b/target/linux/layerscape-64b/patches-4.1/0073-dpaa_eth-Use-accessors-to-update-and-query-the-qm_sg.patch new file mode 100644 index 0000000..ef2c359 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0073-dpaa_eth-Use-accessors-to-update-and-query-the-qm_sg.patch @@ -0,0 +1,227 @@ +From 01eda39503976c5939978a74af1c364300b60174 Mon Sep 17 00:00:00 2001 +From: Cristian Sovaiala +Date: Fri, 17 Jul 2015 09:50:16 +0300 +Subject: [PATCH 073/151] dpaa_eth: Use accessors to update and query the + qm_sg_entry structure + +Signed-off-by: Cristian Sovaiala +Change-Id: Ie8546ed04a7e23eda4c5fa8a4cea041ddc40fccb +--- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_common.c | 17 ++--- + .../net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 82 +++++++++------------- + 2 files changed, 40 insertions(+), 59 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +index dcef8dd..c1fdca5 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +@@ -1540,26 +1540,23 @@ void dpa_release_sgt(struct qm_sg_entry *sgt) + memset(bmb, 0, DPA_BUFF_RELEASE_MAX * sizeof(struct bm_buffer)); + + do { +- dpa_bp = dpa_bpid2pool(sgt[i].bpid); ++ dpa_bp = dpa_bpid2pool(qm_sg_entry_get_bpid(&sgt[i])); + DPA_BUG_ON(!dpa_bp); + + j = 0; + do { +- be32_to_cpus(&sgt[i].sgt_efl); +- DPA_BUG_ON(sgt[i].extension); +- +- bmb[j].hi = sgt[i].addr_hi; +- bmb[j].lo = be32_to_cpu(sgt[i].addr_lo); +- ++ DPA_BUG_ON(qm_sg_entry_get_ext(&sgt[i])); ++ bm_buffer_set64(&bmb[j], qm_sg_addr(&sgt[i])); + + j++; i++; + } while (j < ARRAY_SIZE(bmb) && +- !sgt[i-1].final && +- sgt[i-1].bpid == sgt[i].bpid); ++ !qm_sg_entry_get_final(&sgt[i-1]) && ++ qm_sg_entry_get_bpid(&sgt[i-1]) == ++ qm_sg_entry_get_bpid(&sgt[i])); + + while (bman_release(dpa_bp->pool, bmb, j, 0)) + cpu_relax(); +- } while (!sgt[i-1].final); ++ } while (!qm_sg_entry_get_final(&sgt[i-1])); + } + EXPORT_SYMBOL(dpa_release_sgt); + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +index 64a270e..743fe42 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +@@ -250,21 +250,16 @@ struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv, + } + #endif /* CONFIG_FSL_DPAA_TS */ + +- be32_to_cpus(&sgt[0].sgt_efl); +- + /* sgt[0] is from lowmem, was dma_map_single()-ed */ +- sg_addr = sgt[0].addr_hi << 32; +- sg_addr += be32_to_cpu(sgt[0].addr_lo); +- sg_len = sgt[0].length; ++ sg_addr = qm_sg_addr(&sgt[0]); ++ sg_len = qm_sg_entry_get_len(&sgt[0]); + dma_unmap_single(dpa_bp->dev, sg_addr, sg_len, dma_dir); + + /* remaining pages were mapped with dma_map_page() */ + for (i = 1; i <= nr_frags; i++) { +- be32_to_cpus(&sgt[i].sgt_efl); +- DPA_BUG_ON(sgt[i].extension); +- sg_addr = sgt[i].addr_hi << 32; +- sg_addr += be32_to_cpu(sgt[i].addr_lo); +- sg_len = sgt[i].length; ++ DPA_BUG_ON(qm_sg_entry_get_ext(&sgt[i])); ++ sg_addr = qm_sg_addr(&sgt[i]); ++ sg_len = qm_sg_entry_get_len(&sgt[i]); + dma_unmap_page(dpa_bp->dev, sg_addr, sg_len, dma_dir); + } + +@@ -429,14 +424,13 @@ static struct sk_buff *__hot sg_fd_to_skb(const struct dpa_priv_s *priv, + /* Iterate through the SGT entries and add data buffers to the skb */ + sgt = vaddr + fd_off; + for (i = 0; i < DPA_SGT_MAX_ENTRIES; i++) { +- be32_to_cpus(&sgt[i].sgt_efl); + /* Extension bit is not supported */ +- DPA_BUG_ON(sgt[i].extension); ++ DPA_BUG_ON(qm_sg_entry_get_ext(&sgt[i])); + + /* We use a single global Rx pool */ +- DPA_BUG_ON(dpa_bp != dpa_bpid2pool(sgt[i].bpid)); ++ DPA_BUG_ON(dpa_bp != ++ dpa_bpid2pool(qm_sg_entry_get_bpid(&sgt[i]))); + +- be64_to_cpus(sgt + i); + sg_addr = qm_sg_addr(&sgt[i]); + sg_vaddr = phys_to_virt(sg_addr); + DPA_BUG_ON(!IS_ALIGNED((unsigned long)sg_vaddr, +@@ -471,7 +465,7 @@ static struct sk_buff *__hot sg_fd_to_skb(const struct dpa_priv_s *priv, + */ + DPA_BUG_ON(fd_off != priv->rx_headroom); + skb_reserve(skb, fd_off); +- skb_put(skb, sgt[i].length); ++ skb_put(skb, qm_sg_entry_get_len(&sgt[i])); + } else { + /* Not the first S/G entry; all data from buffer will + * be added in an skb fragment; fragment index is offset +@@ -497,8 +491,9 @@ static struct sk_buff *__hot sg_fd_to_skb(const struct dpa_priv_s *priv, + /* page_offset only refers to the beginning of sgt[i]; + * but the buffer itself may have an internal offset. + */ +- frag_offset = sgt[i].offset + page_offset; +- frag_len = sgt[i].length; ++ frag_offset = qm_sg_entry_get_offset(&sgt[i]) + ++ page_offset; ++ frag_len = qm_sg_entry_get_len(&sgt[i]); + /* skb_add_rx_frag() does no checking on the page; if + * we pass it a tail page, we'll end up with + * bad page accounting and eventually with segafults. +@@ -509,7 +504,7 @@ static struct sk_buff *__hot sg_fd_to_skb(const struct dpa_priv_s *priv, + /* Update the pool count for the current {cpu x bpool} */ + (*count_ptr)--; + +- if (sgt[i].final) ++ if (qm_sg_entry_get_final(&sgt[i])) + break; + } + WARN_ONCE(i == DPA_SGT_MAX_ENTRIES, "No final bit on SGT\n"); +@@ -772,14 +767,12 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + } + + sgt = (struct qm_sg_entry *)(sgt_buf + priv->tx_headroom); +- sgt[0].bpid = 0xff; +- sgt[0].offset = 0; +- sgt[0].length = skb_headlen(skb); +- sgt[0].extension = 0; +- sgt[0].final = 0; +- sg_len = sgt[0].length; +- +- cpu_to_be32s(&sgt[0].sgt_efl); ++ sg_len = skb_headlen(skb); ++ qm_sg_entry_set_bpid(&sgt[0], 0xff); ++ qm_sg_entry_set_offset(&sgt[0], 0); ++ qm_sg_entry_set_len(&sgt[0], sg_len); ++ qm_sg_entry_set_ext(&sgt[0], 0); ++ qm_sg_entry_set_final(&sgt[0], 0); + + addr = dma_map_single(dpa_bp->dev, skb->data, sg_len, dma_dir); + if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { +@@ -789,38 +782,32 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + + } + +- sgt[0].addr_hi = (uint8_t)upper_32_bits(addr); +- sgt[0].addr_lo = cpu_to_be32(lower_32_bits(addr)); ++ qm_sg_entry_set64(&sgt[0], addr); + + /* populate the rest of SGT entries */ + for (i = 1; i <= nr_frags; i++) { + frag = &skb_shinfo(skb)->frags[i - 1]; +- sgt[i].bpid = 0xff; +- sgt[i].offset = 0; +- sgt[i].length = frag->size; +- sgt[i].extension = 0; +- sg_len = sgt[i].length; ++ qm_sg_entry_set_bpid(&sgt[i], 0xff); ++ qm_sg_entry_set_offset(&sgt[i], 0); ++ qm_sg_entry_set_len(&sgt[i], frag->size); ++ qm_sg_entry_set_ext(&sgt[i], 0); ++ + if (i == nr_frags) +- sgt[i].final = 1; ++ qm_sg_entry_set_final(&sgt[i], 1); + else +- sgt[i].final = 0; +- ++ qm_sg_entry_set_final(&sgt[i], 0); + + DPA_BUG_ON(!skb_frag_page(frag)); +- +- cpu_to_be32s(&sgt[i].sgt_efl); +- +- addr = skb_frag_dma_map(dpa_bp->dev, frag, 0, sg_len, dma_dir); ++ addr = skb_frag_dma_map(dpa_bp->dev, frag, 0, frag->size, ++ dma_dir); + if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { + dev_err(dpa_bp->dev, "DMA mapping failed"); + err = -EINVAL; + goto sg_map_failed; + } + +- + /* keep the offset in the address */ +- sgt[i].addr_hi = (uint8_t)upper_32_bits(addr); +- sgt[i].addr_lo = cpu_to_be32(lower_32_bits(addr)); ++ qm_sg_entry_set64(&sgt[i], addr); + } + + fd->length20 = skb->len; +@@ -829,7 +816,6 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + /* DMA map the SGT page */ + buffer_start = (void *)sgt - priv->tx_headroom; + DPA_WRITE_SKB_PTR(skb, skbh, buffer_start, 0); +- + addr = dma_map_single(dpa_bp->dev, buffer_start, priv->tx_headroom + + sizeof(struct qm_sg_entry) * (1 + nr_frags), + dma_dir); +@@ -848,11 +834,9 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + sgt_map_failed: + sg_map_failed: + for (j = 0; j < i; j++) { +- be32_to_cpus(&sgt[j].sgt_efl); +- sg_addr = sgt[j].addr_hi << 32; +- sg_addr += be32_to_cpu(sgt[j].addr_lo); +- dma_unmap_page(dpa_bp->dev, sg_addr, sgt[j].length, +- dma_dir); ++ sg_addr = qm_sg_addr(&sgt[j]); ++ dma_unmap_page(dpa_bp->dev, sg_addr, ++ qm_sg_entry_get_len(&sgt[j]), dma_dir); + } + sg0_map_failed: + csum_failed: +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0074-dpaa_eth-support-PTPd-1588-stack-for-ARM.patch b/target/linux/layerscape-64b/patches-4.1/0074-dpaa_eth-support-PTPd-1588-stack-for-ARM.patch new file mode 100644 index 0000000..0ac9ed9 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0074-dpaa_eth-support-PTPd-1588-stack-for-ARM.patch @@ -0,0 +1,48 @@ +From e5ad06a641c967f11529326bf10a90c7b602f2d7 Mon Sep 17 00:00:00 2001 +From: Yangbo Lu +Date: Fri, 10 Jul 2015 20:02:01 +0800 +Subject: [PATCH 074/151] dpaa_eth: support PTPd 1588 stack for ARM + +This patch does some fix to support PTPd 1588 stack for both +PowerPC and ARM. + +Signed-off-by: Yangbo Lu +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c | 14 ++++---------- + 1 file changed, 4 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +index c1fdca5..6192d49 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +@@ -558,11 +558,6 @@ dpa_mac_probe(struct platform_device *_of_dev) + struct dpa_priv_s *priv = NULL; + struct device_node *timer_node; + #endif +-#ifdef CONFIG_PTP_1588_CLOCK_DPAA +- int lenp_ptp; +- const phandle *phandle_ptp; +-#endif +- + dpa_dev = &_of_dev->dev; + + mac_node = of_parse_phandle(_of_dev->dev.of_node, "fsl,fman-mac", 0); +@@ -607,11 +602,10 @@ dpa_mac_probe(struct platform_device *_of_dev) + #endif + + #ifdef CONFIG_PTP_1588_CLOCK_DPAA +- phandle_ptp = of_get_property(mac_node, "ptimer-handle", &lenp_ptp); +- if (phandle_ptp && ((mac_dev->phy_if != PHY_INTERFACE_MODE_SGMII) || +- ((mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII) && +- (mac_dev->speed == SPEED_1000)))) { +- ptp_priv.node = of_find_node_by_phandle(*phandle_ptp); ++ if ((mac_dev->phy_if != PHY_INTERFACE_MODE_SGMII) || ++ ((mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII) && ++ (mac_dev->speed == SPEED_1000))) { ++ ptp_priv.node = of_parse_phandle(mac_node, "ptimer-handle", 0); + if (ptp_priv.node) { + ptp_priv.of_dev = of_find_device_by_node(ptp_priv.node); + if (unlikely(ptp_priv.of_dev == NULL)) { +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0075-dpaa_eth-read-ts-value-according-to-its-endianness-t.patch b/target/linux/layerscape-64b/patches-4.1/0075-dpaa_eth-read-ts-value-according-to-its-endianness-t.patch new file mode 100644 index 0000000..0005a96 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0075-dpaa_eth-read-ts-value-according-to-its-endianness-t.patch @@ -0,0 +1,28 @@ +From 9177960d32b760d0029c5548bb065771e411e02f Mon Sep 17 00:00:00 2001 +From: Mandy Lavi +Date: Tue, 21 Jul 2015 14:14:14 +0300 +Subject: [PATCH 075/151] dpaa_eth: read ts value according to its endianness + type + +Signed-off-by: Mandy Lavi +Change-Id: I01f885821e508268b430ec9728026182abc92c4a +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +index 6192d49..66e7b11 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +@@ -346,6 +346,8 @@ u64 dpa_get_timestamp_ns(const struct dpa_priv_s *priv, enum port_type rx_tx, + if (!ts || *ts == 0) + return 0; + ++ be64_to_cpus(ts); ++ + /* multiple DPA_PTP_NOMINAL_FREQ_PERIOD_NS for case of non power of 2 */ + ns = *ts << DPA_PTP_NOMINAL_FREQ_PERIOD_SHIFT; + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0076-dpaa_eth-fix-fq-dts-parser-for-macless.patch b/target/linux/layerscape-64b/patches-4.1/0076-dpaa_eth-fix-fq-dts-parser-for-macless.patch new file mode 100644 index 0000000..0c65873 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0076-dpaa_eth-fix-fq-dts-parser-for-macless.patch @@ -0,0 +1,39 @@ +From f8f03c6547cb2d23536c66257bcfd3017b654ed6 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Wed, 9 Sep 2015 18:55:11 +0300 +Subject: [PATCH 076/151] dpaa_eth: fix fq dts parser for macless + +This patch converts the BE fq dts entries to the CPU endianness. + +Signed-off-by: Marian-Cristian Rotariu +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c +index 68b6e5b..21a3b84 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c +@@ -239,7 +239,7 @@ static int dpa_fq_probe_macless(struct device *dev, struct list_head *list, + enum port_type ptype) + { + struct device_node *np = dev->of_node; +- const struct fqid_cell *fqids; ++ struct fqid_cell *fqids; + int num_ranges; + int i, lenp; + +@@ -253,6 +253,10 @@ static int dpa_fq_probe_macless(struct device *dev, struct list_head *list, + + /* All ranges defined in the device tree are used as Rx/Tx queues */ + for (i = 0; i < num_ranges; i++) { ++ /* convert to CPU endianess */ ++ fqids[i].start = be32_to_cpup(&fqids[i].start); ++ fqids[i].count = be32_to_cpup(&fqids[i].count); ++ + if (!dpa_fq_alloc(dev, &fqids[i], list, ptype == RX ? + FQ_TYPE_RX_PCD : FQ_TYPE_TX)) { + dev_err(dev, "_dpa_fq_alloc() failed\n"); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0077-dpaa_eth-fix-modification-of-const-data.patch b/target/linux/layerscape-64b/patches-4.1/0077-dpaa_eth-fix-modification-of-const-data.patch new file mode 100644 index 0000000..daf73dd --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0077-dpaa_eth-fix-modification-of-const-data.patch @@ -0,0 +1,226 @@ +From 50123ee5c09979384e27b9ee3340fdd0998f024e Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Wed, 21 Oct 2015 17:36:53 +0300 +Subject: [PATCH 077/151] dpaa_eth: fix modification of const data + +Address issue introduced in a previous commit: + + commit 85d2d3926aedfa06e510f24c2589d6323d6e3a09 + Author: Marian-Cristian Rotariu + Date: Wed Sep 9 18:55:11 2015 +0300 + + dpaa_eth: fix fq dts parser for macless + + This patch converts the BE fq dts entries to the CPU endianness. + +Signed-off-by: Madalin Bucur +--- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_common.c | 29 +++++++++++++--------- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_common.h | 7 +++--- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c | 13 ++++++---- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c | 11 +++----- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.c | 13 +++++----- + 5 files changed, 40 insertions(+), 33 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +index 66e7b11..d072623 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +@@ -886,30 +886,31 @@ EXPORT_SYMBOL(dpa_select_queue); + #endif + + struct dpa_fq *dpa_fq_alloc(struct device *dev, +- const struct fqid_cell *fqids, +- struct list_head *list, +- enum dpa_fq_type fq_type) ++ u32 fq_start, ++ u32 fq_count, ++ struct list_head *list, ++ enum dpa_fq_type fq_type) + { + int i; + struct dpa_fq *dpa_fq; + +- dpa_fq = devm_kzalloc(dev, sizeof(*dpa_fq) * fqids->count, GFP_KERNEL); ++ dpa_fq = devm_kzalloc(dev, sizeof(*dpa_fq) * fq_count, GFP_KERNEL); + if (dpa_fq == NULL) + return NULL; + +- for (i = 0; i < fqids->count; i++) { ++ for (i = 0; i < fq_count; i++) { + dpa_fq[i].fq_type = fq_type; +- dpa_fq[i].fqid = fqids->start ? fqids->start + i : 0; ++ dpa_fq[i].fqid = fq_start ? fq_start + i : 0; + list_add_tail(&dpa_fq[i].list, list); + } + + #ifdef CONFIG_FMAN_PFC + if (fq_type == FQ_TYPE_TX) +- for (i = 0; i < fqids->count; i++) ++ for (i = 0; i < fq_count; i++) + dpa_fq[i].wq = i / dpa_num_cpus; + else + #endif +- for (i = 0; i < fqids->count; i++) ++ for (i = 0; i < fq_count; i++) + _dpa_assign_wq(dpa_fq + i); + + return dpa_fq; +@@ -930,7 +931,8 @@ int dpa_fq_probe_mac(struct device *dev, struct list_head *list, + int i, lenp; + + if (ptype == TX && alloc_tx_conf_fqs) { +- if (!dpa_fq_alloc(dev, tx_confirm_fqids, list, ++ if (!dpa_fq_alloc(dev, tx_confirm_fqids->start, ++ tx_confirm_fqids->count, list, + FQ_TYPE_TX_CONF_MQ)) + goto fq_alloc_failed; + } +@@ -964,7 +966,8 @@ int dpa_fq_probe_mac(struct device *dev, struct list_head *list, + if (fqids[i].count != 1) + goto invalid_error_queue; + +- dpa_fq = dpa_fq_alloc(dev, &fqids[i], list, ++ dpa_fq = dpa_fq_alloc(dev, fqids[i].start, ++ fqids[i].count, list, + ptype == RX ? + FQ_TYPE_RX_ERROR : + FQ_TYPE_TX_ERROR); +@@ -981,7 +984,8 @@ int dpa_fq_probe_mac(struct device *dev, struct list_head *list, + if (fqids[i].count != 1) + goto invalid_default_queue; + +- dpa_fq = dpa_fq_alloc(dev, &fqids[i], list, ++ dpa_fq = dpa_fq_alloc(dev, fqids[i].start, ++ fqids[i].count, list, + ptype == RX ? + FQ_TYPE_RX_DEFAULT : + FQ_TYPE_TX_CONFIRM); +@@ -995,7 +999,8 @@ int dpa_fq_probe_mac(struct device *dev, struct list_head *list, + break; + default: + /* all subsequent queues are either RX PCD or Tx */ +- if (!dpa_fq_alloc(dev, &fqids[i], list, ptype == RX ? ++ if (!dpa_fq_alloc(dev, fqids[i].start, ++ fqids[i].count, list, ptype == RX ? + FQ_TYPE_RX_PCD : FQ_TYPE_TX)) + goto fq_alloc_failed; + break; +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h +index 6ffae91..08fddf9 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h +@@ -170,9 +170,10 @@ u16 dpa_select_queue(struct net_device *net_dev, struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback); + #endif + struct dpa_fq *dpa_fq_alloc(struct device *dev, +- const struct fqid_cell *fqids, +- struct list_head *list, +- enum dpa_fq_type fq_type); ++ u32 fq_start, ++ u32 fq_count, ++ struct list_head *list, ++ enum dpa_fq_type fq_type); + int dpa_fq_probe_mac(struct device *dev, struct list_head *list, + struct fm_port_fqs *port_fqs, + bool tx_conf_fqs_per_core, +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +index 2ea3bac..e8d5c15 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +@@ -983,9 +983,10 @@ static struct list_head *dpa_generic_fq_probe(struct platform_device *_of_dev, + } + + fqids = __fq_alloc(dev, num_ranges, fqids_off); +- if (!dpa_fq_alloc(dev, &fqids[0], list, FQ_TYPE_RX_ERROR) || +- !dpa_fq_alloc(dev, &fqids[1], list, +- FQ_TYPE_RX_DEFAULT)) { ++ if (!dpa_fq_alloc(dev, fqids[0].start, fqids[0].count, list, ++ FQ_TYPE_RX_ERROR) || ++ !dpa_fq_alloc(dev, fqids[1].start, fqids[1].count, ++ list, FQ_TYPE_RX_DEFAULT)) { + dev_err(dev, "Cannot allocate space for default frame queues\n"); + return ERR_PTR(-ENOMEM); + } +@@ -1002,7 +1003,8 @@ static struct list_head *dpa_generic_fq_probe(struct platform_device *_of_dev, + num_ranges = lenp / sizeof(*fqids); + fqids = __fq_alloc(dev, num_ranges, fqids_off); + for (i = 0; i < num_ranges; i++) { +- if (!dpa_fq_alloc(dev, &fqids[i], list, FQ_TYPE_TX)) { ++ if (!dpa_fq_alloc(dev, fqids[i].start, fqids[i].count, list, ++ FQ_TYPE_TX)) { + dev_err(dev, "_dpa_fq_alloc() failed\n"); + return ERR_PTR(-ENOMEM); + } +@@ -1016,7 +1018,8 @@ static struct list_head *dpa_generic_fq_probe(struct platform_device *_of_dev, + num_ranges = lenp / sizeof(*fqids); + fqids = __fq_alloc(dev, num_ranges, fqids_off); + for (i = 0; i < num_ranges; i++) { +- if (!dpa_fq_alloc(dev, &fqids[i], list, FQ_TYPE_RX_PCD)) { ++ if (!dpa_fq_alloc(dev, fqids[i].start, fqids[i].count, list, ++ FQ_TYPE_RX_PCD)) { + dev_err(dev, "_dpa_fq_alloc() failed\n"); + return ERR_PTR(-ENOMEM); + } +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c +index 21a3b84..393de9b 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macless.c +@@ -239,7 +239,7 @@ static int dpa_fq_probe_macless(struct device *dev, struct list_head *list, + enum port_type ptype) + { + struct device_node *np = dev->of_node; +- struct fqid_cell *fqids; ++ const struct fqid_cell *fqids; + int num_ranges; + int i, lenp; + +@@ -253,12 +253,9 @@ static int dpa_fq_probe_macless(struct device *dev, struct list_head *list, + + /* All ranges defined in the device tree are used as Rx/Tx queues */ + for (i = 0; i < num_ranges; i++) { +- /* convert to CPU endianess */ +- fqids[i].start = be32_to_cpup(&fqids[i].start); +- fqids[i].count = be32_to_cpup(&fqids[i].count); +- +- if (!dpa_fq_alloc(dev, &fqids[i], list, ptype == RX ? +- FQ_TYPE_RX_PCD : FQ_TYPE_TX)) { ++ if (!dpa_fq_alloc(dev, be32_to_cpu(fqids[i].start), ++ be32_to_cpu(fqids[i].count), list, ++ ptype == RX ? FQ_TYPE_RX_PCD : FQ_TYPE_TX)) { + dev_err(dev, "_dpa_fq_alloc() failed\n"); + return -ENOMEM; + } +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.c +index 0a9da8f..e3ecf29 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_macsec.c +@@ -1471,18 +1471,19 @@ static int macsec_setup(void) + INIT_LIST_HEAD(&macsec_priv[macsec_id]->dpa_fq_list); + + dpa_fq = dpa_fq_alloc(dev, +- tx_fqids, +- &macsec_priv[macsec_id]->dpa_fq_list, +- FQ_TYPE_TX); ++ tx_fqids->start, tx_fqids->count, ++ &macsec_priv[macsec_id]->dpa_fq_list, ++ FQ_TYPE_TX); + if (unlikely(dpa_fq == NULL)) { + dev_err(dev, "dpa_fq_alloc() failed\n"); + return -ENOMEM; + } + + dpa_fq = dpa_fq_alloc(dev, +- tx_confirm_fqids, +- &macsec_priv[macsec_id]->dpa_fq_list, +- FQ_TYPE_TX_CONF_MQ); ++ tx_confirm_fqids->start, ++ tx_confirm_fqids->count, ++ &macsec_priv[macsec_id]->dpa_fq_list, ++ FQ_TYPE_TX_CONF_MQ); + if (unlikely(dpa_fq == NULL)) { + dev_err(dev, "dpa_fq_alloc() failed\n"); + return -ENOMEM; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0078-dpaa_eth-add-primitives-for-buffer-alignment.patch b/target/linux/layerscape-64b/patches-4.1/0078-dpaa_eth-add-primitives-for-buffer-alignment.patch new file mode 100644 index 0000000..0557a8b --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0078-dpaa_eth-add-primitives-for-buffer-alignment.patch @@ -0,0 +1,32 @@ +From 2d68127594b89e1f599a6d99c30acffca6d1aa7c Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Thu, 22 Oct 2015 12:47:11 +0300 +Subject: [PATCH 078/151] dpaa_eth: add primitives for buffer alignment + +These primitives are used on ARM architectures that have the 4K boundary +limitation. + +Signed-off-by: Marian-Cristian Rotariu +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +index 40d956b..056ac82 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +@@ -661,4 +661,11 @@ static inline void _dpa_bp_free_pf(void *addr) + put_page(virt_to_head_page(addr)); + } + ++#ifdef CONFIG_ARM64 ++#define HAS_DMA_ISSUE(start, size) \ ++ (((u64)(start) ^ ((u64)(start) + (u64)(size))) & ~0xFFF) ++ ++#define BOUNDARY_4K(start, size) (((u64)(start) + (u64)(size)) & ~0xFFF) ++#endif ++ + #endif /* __DPA_H */ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0079-dpaa_eth-remove-jumbo-frame-optimization.patch b/target/linux/layerscape-64b/patches-4.1/0079-dpaa_eth-remove-jumbo-frame-optimization.patch new file mode 100644 index 0000000..058d630 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0079-dpaa_eth-remove-jumbo-frame-optimization.patch @@ -0,0 +1,37 @@ +From 34f75e2aee9798323ad2ab561de24d76a367e2b4 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Thu, 22 Oct 2015 18:20:43 +0300 +Subject: [PATCH 079/151] dpaa_eth: remove jumbo frame optimization + +This optimization cannot be used on ARM platforms with the 4K hardware +limitation since it determines the creation of more that 4K sized buffers. + +Signed-off-by: Marian-Cristian Rotariu +Signed-off-by: Madalin Bucur +--- + drivers/net/ethernet/freescale/sdk_dpaa/Kconfig | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig b/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig +index 9af50cc..8857662 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig +@@ -56,6 +56,7 @@ config FSL_DPAA_GENERIC_DRIVER + + config FSL_DPAA_ETH_JUMBO_FRAME + bool "Optimize for jumbo frames" ++ depends on !ARM64 + default n + ---help--- + Optimize the DPAA Ethernet driver throughput for large frames +@@ -65,6 +66,7 @@ config FSL_DPAA_ETH_JUMBO_FRAME + Using this option in combination with small frames increases + significantly the driver's memory footprint and may even deplete + the system memory. ++ This option is not available on LS1043. + + config FSL_DPAA_TS + bool "Linux compliant timestamping" +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0080-dpaa_eth-allocate-one-full-page-for-buffers.patch b/target/linux/layerscape-64b/patches-4.1/0080-dpaa_eth-allocate-one-full-page-for-buffers.patch new file mode 100644 index 0000000..917f561 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0080-dpaa_eth-allocate-one-full-page-for-buffers.patch @@ -0,0 +1,33 @@ +From c3cf5c852cc5a3f8cd84fe79fb98827c8ea00b27 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Thu, 22 Oct 2015 17:58:00 +0300 +Subject: [PATCH 080/151] dpaa_eth: allocate one full page for buffers + +By allocating one 4K page, the buffers are constructed inside 4K memory space. +This is required in order to fix the 4K hardware limitation in which all the +frames must reside inside a 4K memory space. + +Signed-off-by: Marian-Cristian Rotariu +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +index 743fe42..4ea0001 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +@@ -96,7 +96,11 @@ static int _dpa_bp_add_8_bufs(const struct dpa_bp *dpa_bp) + * We only need enough space to store a pointer, but allocate + * an entire cacheline for performance reasons. + */ ++#ifdef CONFIG_ARM64 ++ new_buf = page_address(alloc_page(GFP_ATOMIC)); ++#else + new_buf = netdev_alloc_frag(SMP_CACHE_BYTES + DPA_BP_RAW_SIZE); ++#endif + if (unlikely(!new_buf)) + goto netdev_alloc_failed; + new_buf = PTR_ALIGN(new_buf + SMP_CACHE_BYTES, SMP_CACHE_BYTES); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0081-dpaa_eth-create-particular-define-for-4K-issue.patch b/target/linux/layerscape-64b/patches-4.1/0081-dpaa_eth-create-particular-define-for-4K-issue.patch new file mode 100644 index 0000000..e542073 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0081-dpaa_eth-create-particular-define-for-4K-issue.patch @@ -0,0 +1,54 @@ +From 2e181e469422aa9508afc215d10de2c2e3926c94 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Tue, 27 Oct 2015 17:02:40 +0200 +Subject: [PATCH 081/151] dpaa_eth: create particular define for 4K issue + +Signed-off-by: Marian-Cristian Rotariu +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h | 13 +++++++++++-- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 2 +- + 2 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +index 056ac82..1d9a292 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +@@ -661,11 +661,20 @@ static inline void _dpa_bp_free_pf(void *addr) + put_page(virt_to_head_page(addr)); + } + +-#ifdef CONFIG_ARM64 ++/* TODO: LS1043A SoC has a HW issue regarding FMan DMA transactions; The issue ++ * manifests itself at high traffic rates when frames exceed 4K memory ++ * boundaries; For the moment, we use a SW workaround to avoid frames larger ++ * than 4K or that exceed 4K alignements. ++ */ ++#ifdef CONFIG_ARCH_FSL_LS1043A ++#define DPAA_LS1043A_DMA_4K_ISSUE 1 ++#endif ++ ++#ifdef DPAA_LS1043A_DMA_4K_ISSUE + #define HAS_DMA_ISSUE(start, size) \ + (((u64)(start) ^ ((u64)(start) + (u64)(size))) & ~0xFFF) + + #define BOUNDARY_4K(start, size) (((u64)(start) + (u64)(size)) & ~0xFFF) +-#endif ++#endif /* DPAA_LS1043A_DMA_4K_ISSUE */ + + #endif /* __DPA_H */ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +index 4ea0001..4c92424 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +@@ -96,7 +96,7 @@ static int _dpa_bp_add_8_bufs(const struct dpa_bp *dpa_bp) + * We only need enough space to store a pointer, but allocate + * an entire cacheline for performance reasons. + */ +-#ifdef CONFIG_ARM64 ++#ifdef DPAA_LS1043A_DMA_4K_ISSUE + new_buf = page_address(alloc_page(GFP_ATOMIC)); + #else + new_buf = netdev_alloc_frag(SMP_CACHE_BYTES + DPA_BP_RAW_SIZE); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0082-dpaa_eth-fix-S-G-for-TX-on-ARM-platforms.patch b/target/linux/layerscape-64b/patches-4.1/0082-dpaa_eth-fix-S-G-for-TX-on-ARM-platforms.patch new file mode 100644 index 0000000..efe88fd --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0082-dpaa_eth-fix-S-G-for-TX-on-ARM-platforms.patch @@ -0,0 +1,216 @@ +From 520f440ddf664ade7d6311f1c71e76f32d380075 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Wed, 28 Oct 2015 13:20:37 +0200 +Subject: [PATCH 082/151] dpaa_eth: fix S/G for TX on ARM platforms + +This patch adds a workaround for the 4K memory boundary limitation on ARM. If a +S/G entry exceeds the 4K boundary it is devided into two S/G entries. + +Signed-off-by: Marian-Cristian Rotariu +--- + .../net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 114 ++++++++++++++++++++- + 1 file changed, 113 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +index 4c92424..e35130b 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +@@ -232,9 +232,18 @@ struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv, + + if (unlikely(fd->format == qm_fd_sg)) { + nr_frags = skb_shinfo(skb)->nr_frags; ++#ifdef DPAA_LS1043A_DMA_4K_ISSUE ++/* addressing the 4k DMA issue can yield a larger number of fragments than ++ * the skb had ++ */ ++ dma_unmap_single(dpa_bp->dev, addr, dpa_fd_offset(fd) + ++ sizeof(struct qm_sg_entry) * DPA_SGT_MAX_ENTRIES, ++ dma_dir); ++#else + dma_unmap_single(dpa_bp->dev, addr, dpa_fd_offset(fd) + + sizeof(struct qm_sg_entry) * (1 + nr_frags), + dma_dir); ++#endif + /* The sgt buffer has been allocated with netdev_alloc_frag(), + * it's from lowmem. + */ +@@ -258,7 +267,15 @@ struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv, + sg_addr = qm_sg_addr(&sgt[0]); + sg_len = qm_sg_entry_get_len(&sgt[0]); + dma_unmap_single(dpa_bp->dev, sg_addr, sg_len, dma_dir); +- ++#ifdef DPAA_LS1043A_DMA_4K_ISSUE ++ i = 1; ++ do { ++ DPA_BUG_ON(qm_sg_entry_get_ext(&sgt[i])); ++ sg_addr = qm_sg_addr(&sgt[i]); ++ sg_len = qm_sg_entry_get_len(&sgt[i]); ++ dma_unmap_page(dpa_bp->dev, sg_addr, sg_len, dma_dir); ++ } while (!qm_sg_entry_get_final(&sgt[i++])); ++#else + /* remaining pages were mapped with dma_map_page() */ + for (i = 1; i <= nr_frags; i++) { + DPA_BUG_ON(qm_sg_entry_get_ext(&sgt[i])); +@@ -266,6 +283,7 @@ struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv, + sg_len = qm_sg_entry_get_len(&sgt[i]); + dma_unmap_page(dpa_bp->dev, sg_addr, sg_len, dma_dir); + } ++#endif + + /* Free the page frag that we allocated on Tx */ + put_page(virt_to_head_page(sgt)); +@@ -735,6 +753,10 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + struct net_device *net_dev = priv->net_dev; + int sg_len; + int err; ++#ifdef DPAA_LS1043A_DMA_4K_ISSUE ++ dma_addr_t boundary; ++ int k; ++#endif + + struct qm_sg_entry *sgt; + void *sgt_buf; +@@ -745,7 +767,19 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + const int nr_frags = skb_shinfo(skb)->nr_frags; + + fd->format = qm_fd_sg; ++#ifdef DPAA_LS1043A_DMA_4K_ISSUE ++ /* get a page frag to store the SGTable */ ++ sgt_buf = netdev_alloc_frag(priv->tx_headroom + ++ sizeof(struct qm_sg_entry) * DPA_SGT_MAX_ENTRIES); ++ if (unlikely(!sgt_buf)) { ++ dev_err(dpa_bp->dev, "netdev_alloc_frag() failed\n"); ++ return -ENOMEM; ++ } + ++ /* it seems that the memory allocator does not zero the allocated mem */ ++ memset(sgt_buf, 0, priv->tx_headroom + ++ sizeof(struct qm_sg_entry) * DPA_SGT_MAX_ENTRIES); ++#else + /* get a page frag to store the SGTable */ + sgt_buf = netdev_alloc_frag(priv->tx_headroom + + sizeof(struct qm_sg_entry) * (1 + nr_frags)); +@@ -756,6 +790,7 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + + memset(sgt_buf, 0, priv->tx_headroom + + sizeof(struct qm_sg_entry) * (1 + nr_frags)); ++#endif + + /* Enable L3/L4 hardware checksum computation. + * +@@ -788,6 +823,68 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + + qm_sg_entry_set64(&sgt[0], addr); + ++#ifdef DPAA_LS1043A_DMA_4K_ISSUE ++ j = 0; ++ if (unlikely(HAS_DMA_ISSUE(skb->data, sg_len))) { ++ boundary = (void *)BOUNDARY_4K(skb->data, sg_len); ++ qm_sg_entry_set_len(&sgt[j], (u64)boundary - (u64)addr); ++ ++ j++; ++ qm_sg_entry_set_bpid(&sgt[j], 0xff); ++ qm_sg_entry_set_offset(&sgt[j], 0); ++ qm_sg_entry_set_len(&sgt[j], ++ ((u64)skb->data + (u64)sg_len) - (u64)boundary); ++ qm_sg_entry_set_ext(&sgt[j], 0); ++ qm_sg_entry_set_final(&sgt[j], 0); ++ ++ /* keep the offset in the address */ ++ qm_sg_entry_set64(&sgt[j], addr + ++ ((u64)boundary - (u64)skb->data)); ++ } ++ j++; ++ ++ /* populate the rest of SGT entries */ ++ for (i = 1; i <= nr_frags; i++, j++) { ++ frag = &skb_shinfo(skb)->frags[i - 1]; ++ qm_sg_entry_set_bpid(&sgt[j], 0xff); ++ qm_sg_entry_set_offset(&sgt[j], 0); ++ qm_sg_entry_set_len(&sgt[j], frag->size); ++ qm_sg_entry_set_ext(&sgt[j], 0); ++ ++ DPA_BUG_ON(!skb_frag_page(frag)); ++ addr = skb_frag_dma_map(dpa_bp->dev, frag, 0, frag->size, ++ dma_dir); ++ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { ++ dev_err(dpa_bp->dev, "DMA mapping failed"); ++ err = -EINVAL; ++ goto sg_map_failed; ++ } ++ ++ /* keep the offset in the address */ ++ qm_sg_entry_set64(&sgt[j], addr); ++ ++ if (unlikely(HAS_DMA_ISSUE(frag, frag->size))) { ++ boundary = (void *)BOUNDARY_4K(frag, frag->size); ++ qm_sg_entry_set_len(&sgt[j], (u64)boundary - (u64)frag); ++ ++ j++; ++ qm_sg_entry_set_bpid(&sgt[j], 0xff); ++ qm_sg_entry_set_offset(&sgt[j], 0); ++ qm_sg_entry_set_len(&sgt[j], ((u64)frag->size - ++ ((u64)boundary - (u64)frag))); ++ qm_sg_entry_set_ext(&sgt[j], 0); ++ ++ /* keep the offset in the address */ ++ qm_sg_entry_set64(&sgt[j], addr + ++ ((u64)boundary - (u64)frag)); ++ } ++ ++ if (i == nr_frags) ++ qm_sg_entry_set_final(&sgt[j], 1); ++ else ++ qm_sg_entry_set_final(&sgt[j], 0); ++#else ++ + /* populate the rest of SGT entries */ + for (i = 1; i <= nr_frags; i++) { + frag = &skb_shinfo(skb)->frags[i - 1]; +@@ -812,6 +909,7 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + + /* keep the offset in the address */ + qm_sg_entry_set64(&sgt[i], addr); ++#endif + } + + fd->length20 = skb->len; +@@ -820,9 +918,15 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + /* DMA map the SGT page */ + buffer_start = (void *)sgt - priv->tx_headroom; + DPA_WRITE_SKB_PTR(skb, skbh, buffer_start, 0); ++#ifdef DPAA_LS1043A_DMA_4K_ISSUE ++ addr = dma_map_single(dpa_bp->dev, buffer_start, priv->tx_headroom + ++ sizeof(struct qm_sg_entry) * DPA_SGT_MAX_ENTRIES, ++ dma_dir); ++#else + addr = dma_map_single(dpa_bp->dev, buffer_start, priv->tx_headroom + + sizeof(struct qm_sg_entry) * (1 + nr_frags), + dma_dir); ++#endif + if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) { + dev_err(dpa_bp->dev, "DMA mapping failed"); + err = -EINVAL; +@@ -837,11 +941,19 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + + sgt_map_failed: + sg_map_failed: ++#ifdef DPAA_LS1043A_DMA_4K_ISSUE ++ for (k = 0; k < j; k++) { ++ sg_addr = qm_sg_addr(&sgt[k]); ++ dma_unmap_page(dpa_bp->dev, sg_addr, ++ qm_sg_entry_get_len(&sgt[k]), dma_dir); ++ } ++#else + for (j = 0; j < i; j++) { + sg_addr = qm_sg_addr(&sgt[j]); + dma_unmap_page(dpa_bp->dev, sg_addr, + qm_sg_entry_get_len(&sgt[j]), dma_dir); + } ++#endif + sg0_map_failed: + csum_failed: + put_page(virt_to_head_page(sgt_buf)); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0083-dpaa_eth-create-a-S-G-frame-for-4K-contig-frames.patch b/target/linux/layerscape-64b/patches-4.1/0083-dpaa_eth-create-a-S-G-frame-for-4K-contig-frames.patch new file mode 100644 index 0000000..45c580c --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0083-dpaa_eth-create-a-S-G-frame-for-4K-contig-frames.patch @@ -0,0 +1,39 @@ +From 5ae5009b09207f9fc1a86a1e733f54d116922715 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Wed, 28 Oct 2015 16:08:33 +0200 +Subject: [PATCH 083/151] dpaa_eth: create a S/G frame for >4K contig frames + +This patch creates a S/G frame when the stack creates a frame that exceeds the +4K boundary. This is necessary because of ARM platform limitation that cannot +receive >4K frames at high traffic rates. + +Signed-off-by: Marian-Cristian Rotariu +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +index e35130b..65c3605 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +@@ -1062,8 +1062,17 @@ int __hot dpa_tx_extended(struct sk_buff *skb, struct net_device *net_dev, + /* Common out-of-memory error path */ + goto enomem; + ++#ifdef DPAA_LS1043A_DMA_4K_ISSUE ++ if (unlikely(HAS_DMA_ISSUE(skb->data, skb->len))) { ++ err = skb_to_sg_fd(priv, skb, &fd); ++ percpu_priv->tx_frag_skbuffs++; ++ } else { ++ err = skb_to_contig_fd(priv, skb, &fd, countptr, &offset); ++ } ++#else + /* Finally, create a contig FD from this skb */ + err = skb_to_contig_fd(priv, skb, &fd, countptr, &offset); ++#endif + } + if (unlikely(err < 0)) + goto skb_to_fd_failed; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0084-dpaa_eth-fix-max-number-of-S-G-entries-for-ARM.patch b/target/linux/layerscape-64b/patches-4.1/0084-dpaa_eth-fix-max-number-of-S-G-entries-for-ARM.patch new file mode 100644 index 0000000..f52b068 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0084-dpaa_eth-fix-max-number-of-S-G-entries-for-ARM.patch @@ -0,0 +1,47 @@ +From 865ecd2c5c089e723efa5b72a0256836f38656e0 Mon Sep 17 00:00:00 2001 +From: Marian-Cristian Rotariu +Date: Wed, 28 Oct 2015 20:00:40 +0200 +Subject: [PATCH 084/151] dpaa_eth: fix max number of S/G entries for ARM + +Signed-off-by: Marian-Cristian Rotariu +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h | 9 +++++++++ + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 2 +- + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h +index 08fddf9..557a800 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.h +@@ -56,6 +56,15 @@ + } + + #define DPA_SGT_MAX_ENTRIES 16 /* maximum number of entries in SG Table */ ++ ++#ifdef DPAA_LS1043A_DMA_4K_ISSUE ++/* each S/G entry can be divided into two S/G entries */ ++#define DPA_SGT_ENTRIES_THRESHOLD 7 ++#else ++#define DPA_SGT_ENTRIES_THRESHOLD DPA_SGT_MAX_ENTRIES ++#endif /* DPAA_LS1043A_DMA_4K_ISSUE */ ++ ++ + #define DPA_BUFF_RELEASE_MAX 8 /* maximum number of buffers released at once */ + + /* return codes for the dpaa-eth hooks */ +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +index 65c3605..104bf1e 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +@@ -1019,7 +1019,7 @@ int __hot dpa_tx_extended(struct sk_buff *skb, struct net_device *net_dev, + * the skb, so we're one extra frag short. + */ + if (nonlinear && +- likely(skb_shinfo(skb)->nr_frags < DPA_SGT_MAX_ENTRIES)) { ++ likely(skb_shinfo(skb)->nr_frags < DPA_SGT_ENTRIES_THRESHOLD)) { + /* Just create a S/G fd based on the skb */ + err = skb_to_sg_fd(priv, skb, &fd); + percpu_priv->tx_frag_skbuffs++; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0085-dpaa_eth-set-dma-coherent-mask-when-setting-dma-mask.patch b/target/linux/layerscape-64b/patches-4.1/0085-dpaa_eth-set-dma-coherent-mask-when-setting-dma-mask.patch new file mode 100644 index 0000000..a1aff12 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0085-dpaa_eth-set-dma-coherent-mask-when-setting-dma-mask.patch @@ -0,0 +1,26 @@ +From 024c42fd360dc813a0a8a2647f7e35437e978feb Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Tue, 13 Oct 2015 17:26:59 +0300 +Subject: [PATCH 085/151] dpaa_eth: set dma coherent mask when setting dma mask + +Signed-off-by: Madalin Bucur +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +index d072623..1ae6396 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +@@ -758,7 +758,7 @@ dpa_bp_alloc(struct dpa_bp *dpa_bp) + goto pdev_register_failed; + } + +- err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)); ++ err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40)); + if (err) + goto pdev_mask_failed; + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0086-dpaa_eth-force-DMA-coherency.patch b/target/linux/layerscape-64b/patches-4.1/0086-dpaa_eth-force-DMA-coherency.patch new file mode 100644 index 0000000..d26b3be --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0086-dpaa_eth-force-DMA-coherency.patch @@ -0,0 +1,26 @@ +From 4859eedbb73c3f0290244383a832baae510ca6f8 Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Wed, 14 Oct 2015 18:35:31 +0300 +Subject: [PATCH 086/151] dpaa_eth: force DMA coherency + +Signed-off-by: Madalin Bucur +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +index 1ae6396..d2596c3 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +@@ -761,6 +761,8 @@ dpa_bp_alloc(struct dpa_bp *dpa_bp) + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40)); + if (err) + goto pdev_mask_failed; ++ /* force coherency */ ++ pdev->dev.archdata.dma_coherent = true; + + dpa_bp->dev = &pdev->dev; + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0087-dpaa_eth-force-DMA-coherency-ops.patch b/target/linux/layerscape-64b/patches-4.1/0087-dpaa_eth-force-DMA-coherency-ops.patch new file mode 100644 index 0000000..210c802 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0087-dpaa_eth-force-DMA-coherency-ops.patch @@ -0,0 +1,30 @@ +From 9e39c02e40aae6325c3e4a8bcdee630fef0b2873 Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Mon, 26 Oct 2015 18:10:49 +0200 +Subject: [PATCH 087/151] dpaa_eth: force DMA coherency ops + +Signed-off-by: Madalin Bucur +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +index d2596c3..f2e44ee 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +@@ -761,8 +761,12 @@ dpa_bp_alloc(struct dpa_bp *dpa_bp) + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40)); + if (err) + goto pdev_mask_failed; ++ ++#ifdef CONFIG_FMAN_ARM + /* force coherency */ + pdev->dev.archdata.dma_coherent = true; ++ arch_setup_dma_ops(&pdev->dev, 0, 0, NULL, true); ++#endif + + dpa_bp->dev = &pdev->dev; + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0088-dpaa_eth-devm_ioremap_prot-was-removed.patch b/target/linux/layerscape-64b/patches-4.1/0088-dpaa_eth-devm_ioremap_prot-was-removed.patch new file mode 100644 index 0000000..c719806 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0088-dpaa_eth-devm_ioremap_prot-was-removed.patch @@ -0,0 +1,59 @@ +From 2b64fdbb9c43a088ee24ef43b8ee289bbf3401b6 Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Tue, 23 Feb 2016 12:08:01 +0200 +Subject: [PATCH 088/151] dpaa_eth: devm_ioremap_prot() was removed + +Signed-off-by: Madalin Bucur +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c +index 459823e..629c7b5 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_base.c +@@ -40,6 +40,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -166,6 +167,8 @@ EXPORT_SYMBOL(dpa_bp_probe); + + int dpa_bp_shared_port_seed(struct dpa_bp *bp) + { ++ void __iomem **ptr; ++ + /* In MAC-less and Shared-MAC scenarios the physical + * address of the buffer pool in device tree is set + * to 0 to specify that another entity (USDPAA) will +@@ -177,12 +180,22 @@ int dpa_bp_shared_port_seed(struct dpa_bp *bp) + /* allocate memory region for buffers */ + devm_request_mem_region(bp->dev, bp->paddr, + bp->size * bp->config_count, KBUILD_MODNAME); +- bp->vaddr = devm_ioremap_prot(bp->dev, bp->paddr, +- bp->size * bp->config_count, 0); ++ /* managed ioremap unmapping */ ++ ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL); ++ if (!ptr) ++ return -EIO; ++#ifdef CONFIG_ARM64 ++ bp->vaddr = ioremap_cache_ns(bp->paddr, bp->size * bp->config_count); ++#else ++ bp->vaddr = ioremap_prot(bp->paddr, bp->size * bp->config_count, 0); ++#endif + if (bp->vaddr == NULL) { + pr_err("Could not map memory for pool %d\n", bp->bpid); ++ devres_free(ptr); + return -EIO; + } ++ *ptr = bp->vaddr; ++ devres_add(bp->dev, ptr); + + /* seed pool with buffers from that memory region */ + if (bp->seed_pool) { +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0089-dpaa_eth-include-needed-header.patch b/target/linux/layerscape-64b/patches-4.1/0089-dpaa_eth-include-needed-header.patch new file mode 100644 index 0000000..7c068f7 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0089-dpaa_eth-include-needed-header.patch @@ -0,0 +1,25 @@ +From 748ec7b3ad485c7b666128c05a40167778f87bd7 Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Tue, 23 Feb 2016 17:03:17 +0200 +Subject: [PATCH 089/151] dpaa_eth: include needed header + +Signed-off-by: Madalin Bucur +--- + drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c b/drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c +index af78576..7737a45 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/mac-api.c +@@ -40,6 +40,7 @@ + + #include + #include ++#include + #include + #include + #include +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0090-dpaa_eth-small-fixes.patch b/target/linux/layerscape-64b/patches-4.1/0090-dpaa_eth-small-fixes.patch new file mode 100644 index 0000000..cfa78bf --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0090-dpaa_eth-small-fixes.patch @@ -0,0 +1,129 @@ +From bfbe51394747b7833ac894b23b1e50e86d6231cd Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Tue, 23 Feb 2016 12:08:01 +0200 +Subject: [PATCH 090/151] dpaa_eth: small fixes + +Signed-off-by: Madalin Bucur +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h | 2 +- + .../ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c | 22 +++++++++++++--------- + .../net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 4 ++-- + 3 files changed, 16 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +index 1d9a292..bc500be 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +@@ -670,7 +670,7 @@ static inline void _dpa_bp_free_pf(void *addr) + #define DPAA_LS1043A_DMA_4K_ISSUE 1 + #endif + +-#ifdef DPAA_LS1043A_DMA_4K_ISSUE ++#ifdef DPAA_LS1043A_DMA_4K_ISSUE + #define HAS_DMA_ISSUE(start, size) \ + (((u64)(start) ^ ((u64)(start) + (u64)(size))) & ~0xFFF) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +index e8d5c15..3464313 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_generic.c +@@ -1,4 +1,4 @@ +-/* Copyright 2013 Freescale Semiconductor Inc. ++/* 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: +@@ -7,6 +7,10 @@ + * * 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 +@@ -161,7 +165,7 @@ static int get_port_ref(struct device_node *dev_node, + struct fm_port **port) + { + struct platform_device *port_of_dev = NULL; +- struct device *oh_dev = NULL; ++ struct device *op_dev = NULL; + struct device_node *port_node = NULL; + + port_node = of_parse_phandle(dev_node, "fsl,fman-oh-port", 0); +@@ -175,8 +179,8 @@ static int get_port_ref(struct device_node *dev_node, + return -EINVAL; + + /* get the reference to oh port from FMD */ +- oh_dev = &port_of_dev->dev; +- *port = fm_port_bind(oh_dev); ++ op_dev = &port_of_dev->dev; ++ *port = fm_port_bind(op_dev); + + if (*port == NULL) + return -EINVAL; +@@ -210,7 +214,7 @@ static void dpaa_generic_napi_disable(struct dpa_generic_priv_s *priv) + } + } + +-static struct device_node *get_rx_oh_port_node(struct platform_device *_of_dev) ++static struct device_node *get_rx_op_port_node(struct platform_device *_of_dev) + { + struct device *dev = &_of_dev->dev; + struct device_node *port_node = NULL; +@@ -480,7 +484,7 @@ static void dpa_generic_drain_bp(struct dpa_bp *bp, u8 nbuf) + ret = bman_acquire(bp->pool, bmb, nbuf, 0); + if (ret > 0) { + for (i = 0; i < nbuf; i++) { +- addr = bm_buffer_get64(&bmb[i]); ++ addr = bm_buf_addr(&bmb[i]); + skbh = (struct sk_buff **)phys_to_virt(addr); + dma_unmap_single(bp->dev, addr, bp->size, + DMA_TO_DEVICE); +@@ -968,7 +972,7 @@ static struct list_head *dpa_generic_fq_probe(struct platform_device *_of_dev, + INIT_LIST_HEAD(list); + + /* RX queues (RX error, RX default) are specified in Rx O/H port node */ +- oh_node = get_rx_oh_port_node(_of_dev); ++ oh_node = get_rx_op_port_node(_of_dev); + fqids_off = of_get_property(oh_node, "fsl,qman-frame-queues-oh", &lenp); + if (fqids_off == NULL) { + dev_err(dev, "Need Rx FQ definition in dts for generic devices\n"); +@@ -1074,7 +1078,7 @@ static int dpa_generic_rx_bp_probe(struct platform_device *_of_dev, + int na = 0, ns = 0; + int err = 0, i = 0; + +- oh_node = get_rx_oh_port_node(_of_dev); ++ oh_node = get_rx_op_port_node(_of_dev); + + bp_count = of_count_phandle_with_args(oh_node, + "fsl,bman-buffer-pools", NULL); +@@ -1134,7 +1138,7 @@ static int dpa_generic_rx_bp_probe(struct platform_device *_of_dev, + } + + bp[i].percpu_count = devm_alloc_percpu(dev, +- *bp[i].percpu_count); ++ *bp[i].percpu_count); + } + + of_node_put(oh_node); +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +index 104bf1e..a1946f0 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c +@@ -866,8 +866,8 @@ int __hot skb_to_sg_fd(struct dpa_priv_s *priv, + if (unlikely(HAS_DMA_ISSUE(frag, frag->size))) { + boundary = (void *)BOUNDARY_4K(frag, frag->size); + qm_sg_entry_set_len(&sgt[j], (u64)boundary - (u64)frag); +- +- j++; ++ ++ j++; + qm_sg_entry_set_bpid(&sgt[j], 0xff); + qm_sg_entry_set_offset(&sgt[j], 0); + qm_sg_entry_set_len(&sgt[j], ((u64)frag->size - +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0091-dpaa_eth-use-proper-identifier-for-ARM64.patch b/target/linux/layerscape-64b/patches-4.1/0091-dpaa_eth-use-proper-identifier-for-ARM64.patch new file mode 100644 index 0000000..d57810f --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0091-dpaa_eth-use-proper-identifier-for-ARM64.patch @@ -0,0 +1,27 @@ +From 186da1212bc93e095bb074604a4b8a83aeb59e21 Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Thu, 25 Feb 2016 15:50:44 +0200 +Subject: [PATCH 091/151] dpaa_eth: use proper identifier for ARM64 + +Signed-off-by: Madalin Bucur +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +index bc500be..c4b3162 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h +@@ -666,7 +666,8 @@ static inline void _dpa_bp_free_pf(void *addr) + * boundaries; For the moment, we use a SW workaround to avoid frames larger + * than 4K or that exceed 4K alignements. + */ +-#ifdef CONFIG_ARCH_FSL_LS1043A ++ ++#ifdef ARM64 + #define DPAA_LS1043A_DMA_4K_ISSUE 1 + #endif + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0092-dpaa_eth-enable-on-both-ARM64-or-FSL_SOC.patch b/target/linux/layerscape-64b/patches-4.1/0092-dpaa_eth-enable-on-both-ARM64-or-FSL_SOC.patch new file mode 100644 index 0000000..b5c0366 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0092-dpaa_eth-enable-on-both-ARM64-or-FSL_SOC.patch @@ -0,0 +1,25 @@ +From 4524d26d72ed4c2681b7cec17eb8f4864767c42d Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Tue, 23 Feb 2016 17:07:53 +0200 +Subject: [PATCH 092/151] dpaa_eth: enable on both ARM64 or FSL_SOC + +Signed-off-by: Madalin Bucur +--- + drivers/net/ethernet/freescale/sdk_dpaa/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig b/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig +index 8857662..973d739 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/Kconfig +@@ -1,6 +1,6 @@ + menuconfig FSL_SDK_DPAA_ETH + tristate "DPAA Ethernet" +- depends on FSL_SOC && FSL_BMAN && FSL_QMAN && FSL_SDK_FMAN ++ depends on (FSL_SOC || ARM64) && FSL_BMAN && FSL_QMAN && FSL_SDK_FMAN + select PHYLIB + ---help--- + Data Path Acceleration Architecture Ethernet driver, +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0093-dpaa_eth-remove-ASF-related-code.patch b/target/linux/layerscape-64b/patches-4.1/0093-dpaa_eth-remove-ASF-related-code.patch new file mode 100644 index 0000000..b9df3d9 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0093-dpaa_eth-remove-ASF-related-code.patch @@ -0,0 +1,29 @@ +From 32b5182e5d102b898a7bb3c118b001c20ca59592 Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Fri, 4 Mar 2016 16:28:10 +0200 +Subject: [PATCH 093/151] dpaa_eth: remove ASF related code + +Signed-off-by: Madalin Bucur +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +index f2e44ee..52134e4 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_common.c +@@ -53,11 +53,7 @@ + #include "mac.h" + + /* DPAA platforms benefit from hardware-assisted queue management */ +-#ifdef CONFIG_AS_FASTPATH +-#define DPA_NETIF_FEATURES (NETIF_F_HW_QDISC | NETIF_F_HW_ACCEL_MQ) +-#else + #define DPA_NETIF_FEATURES NETIF_F_HW_ACCEL_MQ +-#endif + + /* Size in bytes of the FQ taildrop threshold */ + #define DPA_FQ_TD 0x200000 +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0094-fmd-fix-issue-with-HM-in-CC-in-compat-mode.patch b/target/linux/layerscape-64b/patches-4.1/0094-fmd-fix-issue-with-HM-in-CC-in-compat-mode.patch new file mode 100644 index 0000000..8d57301 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0094-fmd-fix-issue-with-HM-in-CC-in-compat-mode.patch @@ -0,0 +1,33 @@ +From b6c1cb28f5ad1b5f2c9046ab13c583f3479e574e Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Wed, 9 Mar 2016 19:50:46 +0200 +Subject: [PATCH 094/151] fmd: fix issue with HM in CC in compat mode + +Signed-off-by: Madalin Bucur +--- + .../ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.c +index 659676b..5e5243c 100644 +--- a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_ioctls_fm_compat.c +@@ -366,6 +366,7 @@ static inline void compat_copy_fm_pcd_cc_next_engine( + break; + #endif /* DPAA_VERSION >= 11 */ + case e_IOC_FM_PCD_CC: ++ param->manip_id = compat_pcd_id2ptr(compat_param->manip_id); + compat_copy_fm_pcd_cc_next_cc(&compat_param->params.cc_params, ¶m->params.cc_params, compat); + break; + case e_IOC_FM_PCD_KG: +@@ -392,6 +393,7 @@ static inline void compat_copy_fm_pcd_cc_next_engine( + break; + #endif /* DPAA_VERSION >= 11 */ + case e_IOC_FM_PCD_CC: ++ compat_param->manip_id = compat_pcd_ptr2id(param->manip_id); + compat_copy_fm_pcd_cc_next_cc(&compat_param->params.cc_params, ¶m->params.cc_params, compat); + break; + case e_IOC_FM_PCD_KG: +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0095-dpaa_eth-do-not-print-debug-message-as-error.patch b/target/linux/layerscape-64b/patches-4.1/0095-dpaa_eth-do-not-print-debug-message-as-error.patch new file mode 100644 index 0000000..f295411 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0095-dpaa_eth-do-not-print-debug-message-as-error.patch @@ -0,0 +1,26 @@ +From 6113ef331463faa2cb595cf10f1caceb09533df1 Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Thu, 17 Mar 2016 09:33:01 +0200 +Subject: [PATCH 095/151] dpaa_eth: do not print debug message as error + +Signed-off-by: Madalin Bucur +--- + drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c +index 6ec6e7a..5e859c9 100644 +--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c ++++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.c +@@ -254,7 +254,7 @@ static void _dpa_rx_error(struct net_device *net_dev, + pr_warn_once("fsl-dpa: non-zero error counters in fman statistics (sysfs)\n"); + else + if (netif_msg_hw(priv) && net_ratelimit()) +- netdev_err(net_dev, "Err FD status = 0x%08x\n", ++ netdev_dbg(net_dev, "Err FD status = 0x%08x\n", + fd->status & FM_FD_STAT_RX_ERRORS); + #ifdef CONFIG_FSL_DPAA_HOOKS + if (dpaa_eth_hooks.rx_error && +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0096-fmd-adapt-to-the-new-clocking-model.patch b/target/linux/layerscape-64b/patches-4.1/0096-fmd-adapt-to-the-new-clocking-model.patch new file mode 100644 index 0000000..90c0f5b --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0096-fmd-adapt-to-the-new-clocking-model.patch @@ -0,0 +1,65 @@ +From 833e748dd595f4e6ba6ac9d9da5b502c1fcf1702 Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Tue, 22 Mar 2016 16:41:23 +0200 +Subject: [PATCH 096/151] fmd: adapt to the new clocking model + +Signed-off-by: Madalin Bucur +--- + .../freescale/sdk_fman/src/wrapper/lnxwrp_fm.c | 24 +++++++++++++++------- + 1 file changed, 17 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c +index f21d2fd..caf8659 100755 +--- a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c +@@ -56,6 +56,7 @@ + #include + #include + #include ++#include + #include + #include + #include /* For struct qe_firmware */ +@@ -504,6 +505,8 @@ static t_LnxWrpFmDev * ReadFmDevTreeNode (struct platform_device *of_dev) + struct device_node *fm_node, *dev_node; + struct of_device_id name; + struct resource res; ++ struct clk *clk; ++ u32 clk_rate; + const uint32_t *uint32_prop; + int _errno=0, lenp; + uint32_t tmp_prop; +@@ -559,16 +562,23 @@ static t_LnxWrpFmDev * ReadFmDevTreeNode (struct platform_device *of_dev) + p_LnxWrpFmDev->fmPhysBaseAddr = res.start; + p_LnxWrpFmDev->fmMemSize = res.end + 1 - res.start; + +- uint32_prop = (uint32_t *)of_get_property(fm_node, "clock-frequency", &lenp); +- if (unlikely(uint32_prop == NULL)) { +- REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_get_property(%s, clock-frequency) failed", fm_node->full_name)); +- return NULL; ++ clk = of_clk_get(fm_node, 0); ++ if (IS_ERR(clk)) { ++ dev_err(&of_dev->dev, "%s: Failed to get FM clock structure\n", ++ __func__); ++ of_node_put(fm_node); ++ return NULL; + } +- tmp_prop = be32_to_cpu(*uint32_prop); + +- if (WARN_ON(lenp != sizeof(uint32_t))) ++ clk_rate = clk_get_rate(clk); ++ if (!clk_rate) { ++ dev_err(&of_dev->dev, "%s: Failed to determine FM clock rate\n", ++ __func__); ++ of_node_put(fm_node); + return NULL; +- p_LnxWrpFmDev->fmDevSettings.param.fmClkFreq = (tmp_prop + 500000)/1000000; /* In MHz, rounded */ ++ } ++ ++ p_LnxWrpFmDev->fmDevSettings.param.fmClkFreq = DIV_ROUND_UP(clk_rate, 1000000); /* In MHz, rounded */ + /* Get the MURAM base address and size */ + memset(&name, 0, sizeof(struct of_device_id)); + if (WARN_ON(strlen("muram") >= sizeof(name.name))) +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0097-arm64-dts-align-to-the-new-clocking-model.patch b/target/linux/layerscape-64b/patches-4.1/0097-arm64-dts-align-to-the-new-clocking-model.patch new file mode 100644 index 0000000..65fc147 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0097-arm64-dts-align-to-the-new-clocking-model.patch @@ -0,0 +1,30 @@ +From f4607f2fff4d11404a365ff6f8d01cc4d00534d8 Mon Sep 17 00:00:00 2001 +From: Madalin Bucur +Date: Wed, 23 Mar 2016 21:25:30 +0200 +Subject: [PATCH 097/151] arm64/dts: align to the new clocking model + +Signed-off-by: Madalin Bucur +--- + arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +index 5c6fb76..446483e 100644 +--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +@@ -203,9 +203,9 @@ + compatible = "fsl,fman", "simple-bus"; + ranges = <0x0 0x00 0x1a00000 0x100000>; + reg = <0x00 0x1a00000 0x0 0x100000>; +- clock-frequency = <0>; +- interrupts = <0 44 0x4>, +- <0 45 0x4>; ++ interrupts = <0 44 0x4>, <0 45 0x4>; ++ clocks = <&clockgen 3 0>; ++ clock-names = "fmanclk"; + + cc { + compatible = "fsl,fman-cc"; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0098-cpufreq-qoriq-optimize-the-CPU-frequency-switching-t.patch b/target/linux/layerscape-64b/patches-4.1/0098-cpufreq-qoriq-optimize-the-CPU-frequency-switching-t.patch new file mode 100644 index 0000000..52a8da9 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0098-cpufreq-qoriq-optimize-the-CPU-frequency-switching-t.patch @@ -0,0 +1,130 @@ +From e30db5a12db9469bf3d43e33b24a30c0f58908c1 Mon Sep 17 00:00:00 2001 +From: Tang Yuantian +Date: Fri, 15 Jan 2016 07:34:32 +0000 +Subject: [PATCH 098/151] cpufreq: qoriq: optimize the CPU frequency switching + time + +Each time the CPU switches its frequency, the clock nodes in +DTS are walked through to find proper clock source. This is +very time-consuming, for example, it is up to 500+ us on T4240. +Besides, switching time varies from clock to clock. +To optimize this, each input clock of CPU is buffered, so that +it can be picked up instantly when needed. + +Since for each CPU each input clock is stored in a pointer +which takes 4 or 8 bytes memory and normally there are several +input clocks per CPU, that will not take much memory as well. + +Signed-off-by: Tang Yuantian +Acked-by: Viresh Kumar +Signed-off-by: Rafael J. Wysocki +(cherry picked from commit 8a95c1441c799bb0f0d31cdb11523d91923d51a7) +Signed-off-by: Scott Wood +--- + drivers/cpufreq/qoriq-cpufreq.c | 32 +++++++++++++++++++++----------- + 1 file changed, 21 insertions(+), 11 deletions(-) + +diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c +index 88b21ae..358f075 100644 +--- a/drivers/cpufreq/qoriq-cpufreq.c ++++ b/drivers/cpufreq/qoriq-cpufreq.c +@@ -27,11 +27,11 @@ + + /** + * struct cpu_data +- * @parent: the parent node of cpu clock ++ * @pclk: the parent clock of cpu + * @table: frequency table + */ + struct cpu_data { +- struct device_node *parent; ++ struct clk **pclk; + struct cpufreq_frequency_table *table; + }; + +@@ -196,7 +196,7 @@ static void freq_table_sort(struct cpufreq_frequency_table *freq_table, + + static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) + { +- struct device_node *np; ++ struct device_node *np, *pnode; + int i, count, ret; + u32 freq, mask; + struct clk *clk; +@@ -219,17 +219,23 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) + goto err_nomem2; + } + +- data->parent = of_parse_phandle(np, "clocks", 0); +- if (!data->parent) { ++ pnode = of_parse_phandle(np, "clocks", 0); ++ if (!pnode) { + pr_err("%s: could not get clock information\n", __func__); + goto err_nomem2; + } + +- count = of_property_count_strings(data->parent, "clock-names"); ++ count = of_property_count_strings(pnode, "clock-names"); ++ data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL); ++ if (!data->pclk) { ++ pr_err("%s: no memory\n", __func__); ++ goto err_node; ++ } ++ + table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL); + if (!table) { + pr_err("%s: no memory\n", __func__); +- goto err_node; ++ goto err_pclk; + } + + if (fmask) +@@ -238,7 +244,8 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) + mask = 0x0; + + for (i = 0; i < count; i++) { +- clk = of_clk_get(data->parent, i); ++ clk = of_clk_get(pnode, i); ++ data->pclk[i] = clk; + freq = clk_get_rate(clk); + /* + * the clock is valid if its frequency is not masked +@@ -273,13 +280,16 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) + policy->cpuinfo.transition_latency = u64temp + 1; + + of_node_put(np); ++ of_node_put(pnode); + + return 0; + + err_nomem1: + kfree(table); ++err_pclk: ++ kfree(data->pclk); + err_node: +- of_node_put(data->parent); ++ of_node_put(pnode); + err_nomem2: + policy->driver_data = NULL; + kfree(data); +@@ -293,7 +303,7 @@ static int __exit qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy) + { + struct cpu_data *data = policy->driver_data; + +- of_node_put(data->parent); ++ kfree(data->pclk); + kfree(data->table); + kfree(data); + policy->driver_data = NULL; +@@ -307,7 +317,7 @@ static int qoriq_cpufreq_target(struct cpufreq_policy *policy, + struct clk *parent; + struct cpu_data *data = policy->driver_data; + +- parent = of_clk_get(data->parent, data->table[index].driver_data); ++ parent = data->pclk[data->table[index].driver_data]; + return clk_set_parent(policy->clk, parent); + } + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0099-cpufreq-qoriq-Don-t-look-at-clock-implementation-det.patch b/target/linux/layerscape-64b/patches-4.1/0099-cpufreq-qoriq-Don-t-look-at-clock-implementation-det.patch new file mode 100644 index 0000000..a8ecf3f --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0099-cpufreq-qoriq-Don-t-look-at-clock-implementation-det.patch @@ -0,0 +1,279 @@ +From 17e6a564d3432a3c5e29e2e3bbb65888dbcb590b Mon Sep 17 00:00:00 2001 +From: Scott Wood +Date: Fri, 15 Jan 2016 07:34:33 +0000 +Subject: [PATCH 099/151] cpufreq: qoriq: Don't look at clock implementation + details + +Get the CPU clock's potential parent clocks from the clock interface +itself, rather than manually parsing the clocks property to find a +phandle, looking at the clock-names property of that, and assuming that +those are valid parent clocks for the cpu clock. + +This is necessary now that the clocks are generated based on the clock +driver's knowledge of the chip rather than a fragile device-tree +description of the mux options. + +We can now rely on the clock driver to ensure that the mux only exposes +options that are valid. The cpufreq driver was currently being overly +conservative in some cases -- for example, the "min_cpufreq = +get_bus_freq()" restriction only applies to chips with erratum +A-004510, and whether the freq_mask used on p5020 is needed depends on +the actual frequencies of the PLLs (FWIW, p5040 has a similar +limitation but its .freq_mask was zero) -- and the frequency mask +mechanism made assumptions about particular parent clock indices that +are no longer valid. + +Signed-off-by: Scott Wood +Acked-by: Viresh Kumar +--- + drivers/cpufreq/qoriq-cpufreq.c | 138 ++++++++++++---------------------------- + 1 file changed, 41 insertions(+), 97 deletions(-) + +diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c +index 358f075..039ed85 100644 +--- a/drivers/cpufreq/qoriq-cpufreq.c ++++ b/drivers/cpufreq/qoriq-cpufreq.c +@@ -11,6 +11,7 @@ + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + + #include ++#include + #include + #include + #include +@@ -35,53 +36,20 @@ struct cpu_data { + struct cpufreq_frequency_table *table; + }; + ++/* ++ * Don't use cpufreq on this SoC -- used when the SoC would have otherwise ++ * matched a more generic compatible. ++ */ ++#define SOC_BLACKLIST 1 ++ + /** + * struct soc_data - SoC specific data +- * @freq_mask: mask the disallowed frequencies +- * @flag: unique flags ++ * @flags: SOC_xxx + */ + struct soc_data { +- u32 freq_mask[4]; +- u32 flag; +-}; +- +-#define FREQ_MASK 1 +-/* see hardware specification for the allowed frqeuencies */ +-static const struct soc_data sdata[] = { +- { /* used by p2041 and p3041 */ +- .freq_mask = {0x8, 0x8, 0x2, 0x2}, +- .flag = FREQ_MASK, +- }, +- { /* used by p5020 */ +- .freq_mask = {0x8, 0x2}, +- .flag = FREQ_MASK, +- }, +- { /* used by p4080, p5040 */ +- .freq_mask = {0}, +- .flag = 0, +- }, ++ u32 flags; + }; + +-/* +- * the minimum allowed core frequency, in Hz +- * for chassis v1.0, >= platform frequency +- * for chassis v2.0, >= platform frequency / 2 +- */ +-static u32 min_cpufreq; +-static const u32 *fmask; +- +-#if defined(CONFIG_ARM) +-static int get_cpu_physical_id(int cpu) +-{ +- return topology_core_id(cpu); +-} +-#else +-static int get_cpu_physical_id(int cpu) +-{ +- return get_hard_smp_processor_id(cpu); +-} +-#endif +- + static u32 get_bus_freq(void) + { + struct device_node *soc; +@@ -99,9 +67,10 @@ static u32 get_bus_freq(void) + return sysfreq; + } + +-static struct device_node *cpu_to_clk_node(int cpu) ++static struct clk *cpu_to_clk(int cpu) + { +- struct device_node *np, *clk_np; ++ struct device_node *np; ++ struct clk *clk; + + if (!cpu_present(cpu)) + return NULL; +@@ -110,37 +79,28 @@ static struct device_node *cpu_to_clk_node(int cpu) + if (!np) + return NULL; + +- clk_np = of_parse_phandle(np, "clocks", 0); +- if (!clk_np) +- return NULL; +- ++ clk = of_clk_get(np, 0); + of_node_put(np); +- +- return clk_np; ++ return clk; + } + + /* traverse cpu nodes to get cpu mask of sharing clock wire */ + static void set_affected_cpus(struct cpufreq_policy *policy) + { +- struct device_node *np, *clk_np; + struct cpumask *dstp = policy->cpus; ++ struct clk *clk; + int i; + +- np = cpu_to_clk_node(policy->cpu); +- if (!np) +- return; +- + for_each_present_cpu(i) { +- clk_np = cpu_to_clk_node(i); +- if (!clk_np) ++ clk = cpu_to_clk(i); ++ if (IS_ERR(clk)) { ++ pr_err("%s: no clock for cpu %d\n", __func__, i); + continue; ++ } + +- if (clk_np == np) ++ if (clk_is_match(policy->clk, clk)) + cpumask_set_cpu(i, dstp); +- +- of_node_put(clk_np); + } +- of_node_put(np); + } + + /* reduce the duplicated frequencies in frequency table */ +@@ -198,7 +158,7 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) + { + struct device_node *np, *pnode; + int i, count, ret; +- u32 freq, mask; ++ u32 freq; + struct clk *clk; + struct cpufreq_frequency_table *table; + struct cpu_data *data; +@@ -219,17 +179,12 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) + goto err_nomem2; + } + +- pnode = of_parse_phandle(np, "clocks", 0); +- if (!pnode) { +- pr_err("%s: could not get clock information\n", __func__); +- goto err_nomem2; +- } ++ count = clk_get_num_parents(policy->clk); + +- count = of_property_count_strings(pnode, "clock-names"); + data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL); + if (!data->pclk) { + pr_err("%s: no memory\n", __func__); +- goto err_node; ++ goto err_nomem2; + } + + table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL); +@@ -238,23 +193,11 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) + goto err_pclk; + } + +- if (fmask) +- mask = fmask[get_cpu_physical_id(cpu)]; +- else +- mask = 0x0; +- + for (i = 0; i < count; i++) { +- clk = of_clk_get(pnode, i); ++ clk = clk_get_parent_by_index(policy->clk, i); + data->pclk[i] = clk; + freq = clk_get_rate(clk); +- /* +- * the clock is valid if its frequency is not masked +- * and large than minimum allowed frequency. +- */ +- if (freq < min_cpufreq || (mask & (1 << i))) +- table[i].frequency = CPUFREQ_ENTRY_INVALID; +- else +- table[i].frequency = freq / 1000; ++ table[i].frequency = freq / 1000; + table[i].driver_data = i; + } + freq_table_redup(table, count); +@@ -288,10 +231,7 @@ err_nomem1: + kfree(table); + err_pclk: + kfree(data->pclk); +-err_node: +- of_node_put(pnode); + err_nomem2: +- policy->driver_data = NULL; + kfree(data); + err_np: + of_node_put(np); +@@ -332,12 +272,20 @@ static struct cpufreq_driver qoriq_cpufreq_driver = { + .attr = cpufreq_generic_attr, + }; + ++static const struct soc_data blacklist = { ++ .flags = SOC_BLACKLIST, ++}; ++ + static const struct of_device_id node_matches[] __initconst = { +- { .compatible = "fsl,p2041-clockgen", .data = &sdata[0], }, +- { .compatible = "fsl,p3041-clockgen", .data = &sdata[0], }, +- { .compatible = "fsl,p5020-clockgen", .data = &sdata[1], }, +- { .compatible = "fsl,p4080-clockgen", .data = &sdata[2], }, +- { .compatible = "fsl,p5040-clockgen", .data = &sdata[2], }, ++ /* e6500 cannot use cpufreq due to erratum A-008083 */ ++ { .compatible = "fsl,b4420-clockgen", &blacklist }, ++ { .compatible = "fsl,b4860-clockgen", &blacklist }, ++ { .compatible = "fsl,t2080-clockgen", &blacklist }, ++ { .compatible = "fsl,t4240-clockgen", &blacklist }, ++ ++ { .compatible = "fsl,ls1021a-clockgen", }, ++ { .compatible = "fsl,p4080-clockgen", }, ++ { .compatible = "fsl,qoriq-clockgen-1.0", }, + { .compatible = "fsl,qoriq-clockgen-2.0", }, + {} + }; +@@ -355,16 +303,12 @@ static int __init qoriq_cpufreq_init(void) + + match = of_match_node(node_matches, np); + data = match->data; +- if (data) { +- if (data->flag) +- fmask = data->freq_mask; +- min_cpufreq = get_bus_freq(); +- } else { +- min_cpufreq = get_bus_freq() / 2; +- } + + of_node_put(np); + ++ if (data && data->flags & SOC_BLACKLIST) ++ return -ENODEV; ++ + ret = cpufreq_register_driver(&qoriq_cpufreq_driver); + if (!ret) + pr_info("Freescale QorIQ CPU frequency scaling driver\n"); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0100-net-phy-Add-support-for-Realtek-RTL8211F.patch b/target/linux/layerscape-64b/patches-4.1/0100-net-phy-Add-support-for-Realtek-RTL8211F.patch new file mode 100644 index 0000000..a91e262 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0100-net-phy-Add-support-for-Realtek-RTL8211F.patch @@ -0,0 +1,126 @@ +From 2075d0319982ac079d1618da92cfd8f39fced17e Mon Sep 17 00:00:00 2001 +From: Shengzhou Liu +Date: Thu, 18 Jun 2015 16:42:47 +0800 +Subject: [PATCH 100/151] net/phy: Add support for Realtek RTL8211F + +RTL8211F has different register definitions from RTL8211E. +Specially it needs to enable TXDLY in case of RGMII. + +Signed-off-by: Shengzhou Liu +Signed-off-by: David S. Miller +Signed-off-by: Shaohui Xie +--- + drivers/net/phy/realtek.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 67 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 96a0f0f..4535361 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -22,8 +22,12 @@ + #define RTL821x_INER 0x12 + #define RTL821x_INER_INIT 0x6400 + #define RTL821x_INSR 0x13 ++#define RTL8211E_INER_LINK_STATUS 0x400 + +-#define RTL8211E_INER_LINK_STATUS 0x400 ++#define RTL8211F_INER_LINK_STATUS 0x0010 ++#define RTL8211F_INSR 0x1d ++#define RTL8211F_PAGE_SELECT 0x1f ++#define RTL8211F_TX_DELAY 0x100 + + MODULE_DESCRIPTION("Realtek PHY driver"); + MODULE_AUTHOR("Johnson Leung"); +@@ -38,6 +42,18 @@ static int rtl821x_ack_interrupt(struct phy_device *phydev) + return (err < 0) ? err : 0; + } + ++static int rtl8211f_ack_interrupt(struct phy_device *phydev) ++{ ++ int err; ++ ++ phy_write(phydev, RTL8211F_PAGE_SELECT, 0xa43); ++ err = phy_read(phydev, RTL8211F_INSR); ++ /* restore to default page 0 */ ++ phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0); ++ ++ return (err < 0) ? err : 0; ++} ++ + static int rtl8211b_config_intr(struct phy_device *phydev) + { + int err; +@@ -64,6 +80,41 @@ static int rtl8211e_config_intr(struct phy_device *phydev) + return err; + } + ++static int rtl8211f_config_intr(struct phy_device *phydev) ++{ ++ int err; ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) ++ err = phy_write(phydev, RTL821x_INER, ++ RTL8211F_INER_LINK_STATUS); ++ else ++ err = phy_write(phydev, RTL821x_INER, 0); ++ ++ return err; ++} ++ ++static int rtl8211f_config_init(struct phy_device *phydev) ++{ ++ int ret; ++ u16 reg; ++ ++ ret = genphy_config_init(phydev); ++ if (ret < 0) ++ return ret; ++ ++ if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { ++ /* enable TXDLY */ ++ phy_write(phydev, RTL8211F_PAGE_SELECT, 0xd08); ++ reg = phy_read(phydev, 0x11); ++ reg |= RTL8211F_TX_DELAY; ++ phy_write(phydev, 0x11, reg); ++ /* restore to default page 0 */ ++ phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0); ++ } ++ ++ return 0; ++} ++ + static struct phy_driver realtek_drvs[] = { + { + .phy_id = 0x00008201, +@@ -98,6 +149,20 @@ static struct phy_driver realtek_drvs[] = { + .suspend = genphy_suspend, + .resume = genphy_resume, + .driver = { .owner = THIS_MODULE,}, ++ }, { ++ .phy_id = 0x001cc916, ++ .name = "RTL8211F Gigabit Ethernet", ++ .phy_id_mask = 0x001fffff, ++ .features = PHY_GBIT_FEATURES, ++ .flags = PHY_HAS_INTERRUPT, ++ .config_aneg = &genphy_config_aneg, ++ .config_init = &rtl8211f_config_init, ++ .read_status = &genphy_read_status, ++ .ack_interrupt = &rtl8211f_ack_interrupt, ++ .config_intr = &rtl8211f_config_intr, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .driver = { .owner = THIS_MODULE }, + }, + }; + +@@ -106,6 +171,7 @@ module_phy_driver(realtek_drvs); + static struct mdio_device_id __maybe_unused realtek_tbl[] = { + { 0x001cc912, 0x001fffff }, + { 0x001cc915, 0x001fffff }, ++ { 0x001cc916, 0x001fffff }, + { } + }; + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0101-net-phy-add-RealTek-RTL8211DN-phy-id.patch b/target/linux/layerscape-64b/patches-4.1/0101-net-phy-add-RealTek-RTL8211DN-phy-id.patch new file mode 100644 index 0000000..f136605 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0101-net-phy-add-RealTek-RTL8211DN-phy-id.patch @@ -0,0 +1,48 @@ +From 2072fc478aeb5cdfbc033982834a5595225da9fb Mon Sep 17 00:00:00 2001 +From: Shaohui Xie +Date: Thu, 6 Aug 2015 19:03:35 +0800 +Subject: [PATCH 101/151] net: phy: add RealTek RTL8211DN phy id + +RTL8211DN is compatible with RTL8211E. + +Signed-off-by: Shaohui Xie +Signed-off-by: David S. Miller +--- + drivers/net/phy/realtek.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c +index 4535361..43ab691 100644 +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -137,6 +137,19 @@ static struct phy_driver realtek_drvs[] = { + .config_intr = &rtl8211b_config_intr, + .driver = { .owner = THIS_MODULE,}, + }, { ++ .phy_id = 0x001cc914, ++ .name = "RTL8211DN Gigabit Ethernet", ++ .phy_id_mask = 0x001fffff, ++ .features = PHY_GBIT_FEATURES, ++ .flags = PHY_HAS_INTERRUPT, ++ .config_aneg = genphy_config_aneg, ++ .read_status = genphy_read_status, ++ .ack_interrupt = rtl821x_ack_interrupt, ++ .config_intr = rtl8211e_config_intr, ++ .suspend = genphy_suspend, ++ .resume = genphy_resume, ++ .driver = { .owner = THIS_MODULE,}, ++ }, { + .phy_id = 0x001cc915, + .name = "RTL8211E Gigabit Ethernet", + .phy_id_mask = 0x001fffff, +@@ -170,6 +183,7 @@ module_phy_driver(realtek_drvs); + + static struct mdio_device_id __maybe_unused realtek_tbl[] = { + { 0x001cc912, 0x001fffff }, ++ { 0x001cc914, 0x001fffff }, + { 0x001cc915, 0x001fffff }, + { 0x001cc916, 0x001fffff }, + { } +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0102-net-phy-tune-get_phy_c45_ids-to-support-more-c45-phy.patch b/target/linux/layerscape-64b/patches-4.1/0102-net-phy-tune-get_phy_c45_ids-to-support-more-c45-phy.patch new file mode 100644 index 0000000..6283584 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0102-net-phy-tune-get_phy_c45_ids-to-support-more-c45-phy.patch @@ -0,0 +1,60 @@ +From c16306e69a9b4af7e1c0344346c1918cd836c390 Mon Sep 17 00:00:00 2001 +From: Shengzhou Liu +Date: Fri, 26 Jun 2015 17:58:52 +0800 +Subject: [PATCH 102/151] net/phy: tune get_phy_c45_ids to support more c45 phy + +As some C45 10G PHYs(e.g. Cortina CS4315/CS4340 PHY) have +zero Devices In package, current driver can't get correct +devices_in_package value by non-zero Devices In package. +so let's probe more with zero Devices In package to support +more C45 PHYs. + +Signed-off-by: Shengzhou Liu +Reviewed-by: Florian Fainelli +Signed-off-by: David S. Miller +--- + drivers/net/phy/phy_device.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index 7ad653f..d849140 100644 +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -230,7 +230,7 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr, u32 *phy_id, + for (i = 1; + i < num_ids && c45_ids->devices_in_package == 0; + i++) { +- reg_addr = MII_ADDR_C45 | i << 16 | MDIO_DEVS2; ++retry: reg_addr = MII_ADDR_C45 | i << 16 | MDIO_DEVS2; + phy_reg = mdiobus_read(bus, addr, reg_addr); + if (phy_reg < 0) + return -EIO; +@@ -242,12 +242,20 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr, u32 *phy_id, + return -EIO; + c45_ids->devices_in_package |= (phy_reg & 0xffff); + +- /* If mostly Fs, there is no device there, +- * let's get out of here. +- */ + if ((c45_ids->devices_in_package & 0x1fffffff) == 0x1fffffff) { +- *phy_id = 0xffffffff; +- return 0; ++ if (i) { ++ /* If mostly Fs, there is no device there, ++ * then let's continue to probe more, as some ++ * 10G PHYs have zero Devices In package, ++ * e.g. Cortina CS4315/CS4340 PHY. ++ */ ++ i = 0; ++ goto retry; ++ } else { ++ /* no device there, let's get out of here */ ++ *phy_id = 0xffffffff; ++ return 0; ++ } + } + } + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0103-net-phy-fix-a-bug-in-get_phy_c45_ids.patch b/target/linux/layerscape-64b/patches-4.1/0103-net-phy-fix-a-bug-in-get_phy_c45_ids.patch new file mode 100644 index 0000000..02f2464 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0103-net-phy-fix-a-bug-in-get_phy_c45_ids.patch @@ -0,0 +1,126 @@ +From 45dbbfef9c3cd6717c49471ca3c2447f0eee6340 Mon Sep 17 00:00:00 2001 +From: Shaohui Xie +Date: Tue, 3 Nov 2015 12:27:33 +0800 +Subject: [PATCH 103/151] net: phy: fix a bug in get_phy_c45_ids + +When probing devices-in-package for a c45 phy, device zero is the last +device to probe, however, if driver reads 0 from device zero, +c45_ids->devices_in_package is set to '0', the loop condition of probing +will be matched again, see codes below: + +for (i = 1;i < num_ids && c45_ids->devices_in_package == 0;i++) + +driver will run in a dead loop. + +This patch restructures the bug and confusing loop, it provides a helper +function get_phy_c45_devs_in_pkg which to read devices-in-package registers +of a MMD, and rewrites the loop with using the helper function. + +Signed-off-by: Shaohui Xie +Signed-off-by: David S. Miller +--- + drivers/net/phy/phy_device.c | 74 +++++++++++++++++++++++++++++--------------- + 1 file changed, 49 insertions(+), 25 deletions(-) + +diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c +index d849140..620931d 100644 +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -205,6 +205,37 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id, + } + EXPORT_SYMBOL(phy_device_create); + ++/* get_phy_c45_devs_in_pkg - reads a MMD's devices in package registers. ++ * @bus: the target MII bus ++ * @addr: PHY address on the MII bus ++ * @dev_addr: MMD address in the PHY. ++ * @devices_in_package: where to store the devices in package information. ++ * ++ * Description: reads devices in package registers of a MMD at @dev_addr ++ * from PHY at @addr on @bus. ++ * ++ * Returns: 0 on success, -EIO on failure. ++ */ ++static int get_phy_c45_devs_in_pkg(struct mii_bus *bus, int addr, int dev_addr, ++ u32 *devices_in_package) ++{ ++ int phy_reg, reg_addr; ++ ++ reg_addr = MII_ADDR_C45 | dev_addr << 16 | MDIO_DEVS2; ++ phy_reg = mdiobus_read(bus, addr, reg_addr); ++ if (phy_reg < 0) ++ return -EIO; ++ *devices_in_package = (phy_reg & 0xffff) << 16; ++ ++ reg_addr = MII_ADDR_C45 | dev_addr << 16 | MDIO_DEVS1; ++ phy_reg = mdiobus_read(bus, addr, reg_addr); ++ if (phy_reg < 0) ++ return -EIO; ++ *devices_in_package |= (phy_reg & 0xffff); ++ ++ return 0; ++} ++ + /** + * get_phy_c45_ids - reads the specified addr for its 802.3-c45 IDs. + * @bus: the target MII bus +@@ -223,38 +254,31 @@ static int get_phy_c45_ids(struct mii_bus *bus, int addr, u32 *phy_id, + int phy_reg; + int i, reg_addr; + const int num_ids = ARRAY_SIZE(c45_ids->device_ids); ++ u32 *devs = &c45_ids->devices_in_package; + +- /* Find first non-zero Devices In package. Device +- * zero is reserved, so don't probe it. ++ /* Find first non-zero Devices In package. Device zero is reserved ++ * for 802.3 c45 complied PHYs, so don't probe it at first. + */ +- for (i = 1; +- i < num_ids && c45_ids->devices_in_package == 0; +- i++) { +-retry: reg_addr = MII_ADDR_C45 | i << 16 | MDIO_DEVS2; +- phy_reg = mdiobus_read(bus, addr, reg_addr); ++ for (i = 1; i < num_ids && *devs == 0; i++) { ++ phy_reg = get_phy_c45_devs_in_pkg(bus, addr, i, devs); + if (phy_reg < 0) + return -EIO; +- c45_ids->devices_in_package = (phy_reg & 0xffff) << 16; + +- reg_addr = MII_ADDR_C45 | i << 16 | MDIO_DEVS1; +- phy_reg = mdiobus_read(bus, addr, reg_addr); +- if (phy_reg < 0) +- return -EIO; +- c45_ids->devices_in_package |= (phy_reg & 0xffff); +- +- if ((c45_ids->devices_in_package & 0x1fffffff) == 0x1fffffff) { +- if (i) { +- /* If mostly Fs, there is no device there, +- * then let's continue to probe more, as some +- * 10G PHYs have zero Devices In package, +- * e.g. Cortina CS4315/CS4340 PHY. +- */ +- i = 0; +- goto retry; +- } else { +- /* no device there, let's get out of here */ ++ if ((*devs & 0x1fffffff) == 0x1fffffff) { ++ /* If mostly Fs, there is no device there, ++ * then let's continue to probe more, as some ++ * 10G PHYs have zero Devices In package, ++ * e.g. Cortina CS4315/CS4340 PHY. ++ */ ++ phy_reg = get_phy_c45_devs_in_pkg(bus, addr, 0, devs); ++ if (phy_reg < 0) ++ return -EIO; ++ /* no device there, let's get out of here */ ++ if ((*devs & 0x1fffffff) == 0x1fffffff) { + *phy_id = 0xffffffff; + return 0; ++ } else { ++ break; + } + } + } +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0104-net-mdio-fix-mdio_bus_match-for-c45-PHY.patch b/target/linux/layerscape-64b/patches-4.1/0104-net-mdio-fix-mdio_bus_match-for-c45-PHY.patch new file mode 100644 index 0000000..caff4e9 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0104-net-mdio-fix-mdio_bus_match-for-c45-PHY.patch @@ -0,0 +1,54 @@ +From b482c8bc3646b2a071e2d9daf16b10def3328c18 Mon Sep 17 00:00:00 2001 +From: Shaohui Xie +Date: Fri, 17 Jul 2015 18:07:19 +0800 +Subject: [PATCH 104/151] net/mdio: fix mdio_bus_match for c45 PHY + +We store c45 PHY's id information in c45_ids, so it should be used to +check the matching between PHY driver and PHY device for c45 PHY. + +Signed-off-by: Shaohui Xie +Signed-off-by: David S. Miller +--- + drivers/net/phy/mdio_bus.c | 19 +++++++++++++++++-- + 1 file changed, 17 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c +index 3537c30..4bbb5f7 100644 +--- a/drivers/net/phy/mdio_bus.c ++++ b/drivers/net/phy/mdio_bus.c +@@ -441,6 +441,8 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv) + { + struct phy_device *phydev = to_phy_device(dev); + struct phy_driver *phydrv = to_phy_driver(drv); ++ const int num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids); ++ int i; + + if (of_driver_match_device(dev, drv)) + return 1; +@@ -448,8 +450,21 @@ static int mdio_bus_match(struct device *dev, struct device_driver *drv) + if (phydrv->match_phy_device) + return phydrv->match_phy_device(phydev); + +- return (phydrv->phy_id & phydrv->phy_id_mask) == +- (phydev->phy_id & phydrv->phy_id_mask); ++ if (phydev->is_c45) { ++ for (i = 1; i < num_ids; i++) { ++ if (!(phydev->c45_ids.devices_in_package & (1 << i))) ++ continue; ++ ++ if ((phydrv->phy_id & phydrv->phy_id_mask) == ++ (phydev->c45_ids.device_ids[i] & ++ phydrv->phy_id_mask)) ++ return 1; ++ } ++ return 0; ++ } else { ++ return (phydrv->phy_id & phydrv->phy_id_mask) == ++ (phydev->phy_id & phydrv->phy_id_mask); ++ } + } + + #ifdef CONFIG_PM +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0105-net-phy-add-driver-for-aquantia-phy.patch b/target/linux/layerscape-64b/patches-4.1/0105-net-phy-add-driver-for-aquantia-phy.patch new file mode 100644 index 0000000..a8821d6 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0105-net-phy-add-driver-for-aquantia-phy.patch @@ -0,0 +1,210 @@ +From 721014769a073a6cbfe2924206ccd9d469be5668 Mon Sep 17 00:00:00 2001 +From: Shaohui Xie +Date: Wed, 22 Jun 2016 17:36:32 +0800 +Subject: [PATCH 105/151] net: phy: add driver for aquantia phy + +commit d3656cecaadf29d150cba13d59c63d64a5b60f34 +[context adjustment] + +This patch added driver to support Aquantia PHYs AQ1202, AQ2104, AQR105, +AQR405, which accessed through clause 45. + +Signed-off-by: Shaohui Xie +Signed-off-by: David S. Miller +Integrated-by: Li Jingyu +--- + drivers/net/phy/Kconfig | 5 ++ + drivers/net/phy/Makefile | 1 + + drivers/net/phy/aquantia.c | 152 +++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 158 insertions(+) + create mode 100644 drivers/net/phy/aquantia.c + +diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig +index 6fecc2f..da6f9df 100644 +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -28,6 +28,11 @@ config SWCONFIG_LEDS + + comment "MII PHY device drivers" + ++config AQUANTIA_PHY ++ tristate "Drivers for the Aquantia PHYs" ++ ---help--- ++ Currently supports the Aquantia AQ1202, AQ2104, AQR105, AQR405 ++ + config AT803X_PHY + tristate "Drivers for Atheros AT803X PHYs" + ---help--- +diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile +index eac058a..118090f 100644 +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -6,6 +6,7 @@ obj-$(CONFIG_MDIO_BOARDINFO) += mdio-boardinfo.o + + obj-$(CONFIG_PHYLIB) += libphy.o + obj-$(CONFIG_SWCONFIG) += swconfig.o ++obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o + obj-$(CONFIG_MARVELL_PHY) += marvell.o + obj-$(CONFIG_DAVICOM_PHY) += davicom.o + obj-$(CONFIG_CICADA_PHY) += cicada.o +diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c +new file mode 100644 +index 0000000..73d347d +--- /dev/null ++++ b/drivers/net/phy/aquantia.c +@@ -0,0 +1,152 @@ ++/* ++ * Driver for Aquantia PHY ++ * ++ * Author: Shaohui Xie ++ * ++ * Copyright 2015 Freescale Semiconductor, Inc. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PHY_ID_AQ1202 0x03a1b445 ++#define PHY_ID_AQ2104 0x03a1b460 ++#define PHY_ID_AQR105 0x03a1b4a2 ++#define PHY_ID_AQR405 0x03a1b4b0 ++ ++#define PHY_AQUANTIA_FEATURES (SUPPORTED_10000baseT_Full | \ ++ SUPPORTED_1000baseT_Full | \ ++ SUPPORTED_100baseT_Full | \ ++ PHY_DEFAULT_FEATURES) ++ ++static int aquantia_config_aneg(struct phy_device *phydev) ++{ ++ phydev->supported = PHY_AQUANTIA_FEATURES; ++ phydev->advertising = phydev->supported; ++ ++ return 0; ++} ++ ++static int aquantia_aneg_done(struct phy_device *phydev) ++{ ++ int reg; ++ ++ reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); ++ return (reg < 0) ? reg : (reg & BMSR_ANEGCOMPLETE); ++} ++ ++static int aquantia_read_status(struct phy_device *phydev) ++{ ++ int reg; ++ ++ reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); ++ reg = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); ++ if (reg & MDIO_STAT1_LSTATUS) ++ phydev->link = 1; ++ else ++ phydev->link = 0; ++ ++ reg = phy_read_mmd(phydev, MDIO_MMD_AN, 0xc800); ++ mdelay(10); ++ reg = phy_read_mmd(phydev, MDIO_MMD_AN, 0xc800); ++ ++ switch (reg) { ++ case 0x9: ++ phydev->speed = SPEED_2500; ++ break; ++ case 0x5: ++ phydev->speed = SPEED_1000; ++ break; ++ case 0x3: ++ phydev->speed = SPEED_100; ++ break; ++ case 0x7: ++ default: ++ phydev->speed = SPEED_10000; ++ break; ++ } ++ phydev->duplex = DUPLEX_FULL; ++ ++ return 0; ++} ++ ++static struct phy_driver aquantia_driver[] = { ++{ ++ .phy_id = PHY_ID_AQ1202, ++ .phy_id_mask = 0xfffffff0, ++ .name = "Aquantia AQ1202", ++ .features = PHY_AQUANTIA_FEATURES, ++ .aneg_done = aquantia_aneg_done, ++ .config_aneg = aquantia_config_aneg, ++ .read_status = aquantia_read_status, ++ .driver = { .owner = THIS_MODULE,}, ++}, ++{ ++ .phy_id = PHY_ID_AQ2104, ++ .phy_id_mask = 0xfffffff0, ++ .name = "Aquantia AQ2104", ++ .features = PHY_AQUANTIA_FEATURES, ++ .aneg_done = aquantia_aneg_done, ++ .config_aneg = aquantia_config_aneg, ++ .read_status = aquantia_read_status, ++ .driver = { .owner = THIS_MODULE,}, ++}, ++{ ++ .phy_id = PHY_ID_AQR105, ++ .phy_id_mask = 0xfffffff0, ++ .name = "Aquantia AQR105", ++ .features = PHY_AQUANTIA_FEATURES, ++ .aneg_done = aquantia_aneg_done, ++ .config_aneg = aquantia_config_aneg, ++ .read_status = aquantia_read_status, ++ .driver = { .owner = THIS_MODULE,}, ++}, ++{ ++ .phy_id = PHY_ID_AQR405, ++ .phy_id_mask = 0xfffffff0, ++ .name = "Aquantia AQR405", ++ .features = PHY_AQUANTIA_FEATURES, ++ .aneg_done = aquantia_aneg_done, ++ .config_aneg = aquantia_config_aneg, ++ .read_status = aquantia_read_status, ++ .driver = { .owner = THIS_MODULE,}, ++}, ++}; ++ ++static int __init aquantia_init(void) ++{ ++ return phy_drivers_register(aquantia_driver, ++ ARRAY_SIZE(aquantia_driver)); ++} ++ ++static void __exit aquantia_exit(void) ++{ ++ return phy_drivers_unregister(aquantia_driver, ++ ARRAY_SIZE(aquantia_driver)); ++} ++ ++module_init(aquantia_init); ++module_exit(aquantia_exit); ++ ++static struct mdio_device_id __maybe_unused aquantia_tbl[] = { ++ { PHY_ID_AQ1202, 0xfffffff0 }, ++ { PHY_ID_AQ2104, 0xfffffff0 }, ++ { PHY_ID_AQR105, 0xfffffff0 }, ++ { PHY_ID_AQR405, 0xfffffff0 }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(mdio, aquantia_tbl); ++ ++MODULE_DESCRIPTION("Aquantia PHY driver"); ++MODULE_AUTHOR("Shaohui Xie "); ++MODULE_LICENSE("GPL v2"); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0106-net-fsl-Enable-XGMAC_MDIO-on-LS2085A-SoC.patch b/target/linux/layerscape-64b/patches-4.1/0106-net-fsl-Enable-XGMAC_MDIO-on-LS2085A-SoC.patch new file mode 100644 index 0000000..6b217cd --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0106-net-fsl-Enable-XGMAC_MDIO-on-LS2085A-SoC.patch @@ -0,0 +1,42 @@ +From c0961d3dde62d3cdae2fe459179491783f75a811 Mon Sep 17 00:00:00 2001 +From: Bogdan Hamciuc +Date: Tue, 6 Oct 2015 17:18:18 +0300 +Subject: [PATCH 106/151] net/fsl: Enable XGMAC_MDIO on LS2085A SoC + +XGMAC_MDIO is defined under NET_VENDOR_FREESCALE, which historically +was enabled on some Power platforms produced by Freescale. But some +newer, ARM-based, SoCs also have it, LS2085A being an example. + +Signed-off-by: Bogdan Hamciuc +--- + drivers/net/ethernet/freescale/Kconfig | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig +index d0c0ad7..bd739db 100644 +--- a/drivers/net/ethernet/freescale/Kconfig ++++ b/drivers/net/ethernet/freescale/Kconfig +@@ -7,7 +7,8 @@ config NET_VENDOR_FREESCALE + default y + depends on FSL_SOC || QUICC_ENGINE || CPM1 || CPM2 || PPC_MPC512x || \ + M523x || M527x || M5272 || M528x || M520x || M532x || \ +- ARCH_MXC || ARCH_MXS || (PPC_MPC52xx && PPC_BESTCOMM) ++ ARCH_MXC || ARCH_MXS || (PPC_MPC52xx && PPC_BESTCOMM) || \ ++ ARCH_FSL_LS2085A + ---help--- + If you have a network (Ethernet) card belonging to this class, say Y + and read the Ethernet-HOWTO, available from +@@ -67,8 +68,8 @@ config FSL_XGMAC_MDIO + select PHYLIB + select OF_MDIO + ---help--- +- This driver supports the MDIO bus on the Fman 10G Ethernet MACs, and +- on the FMan mEMAC (which supports both Clauses 22 and 45) ++ This driver supports the MDIO bus on the Fman 10G Ethernet MACs and ++ on mEMAC (which supports both Clauses 22 and 45) + + config UCC_GETH + tristate "Freescale QE Gigabit Ethernet" +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0107-net-fsl-change-ls2-arch-define-to-ARCH_LAYERSCAPE.patch b/target/linux/layerscape-64b/patches-4.1/0107-net-fsl-change-ls2-arch-define-to-ARCH_LAYERSCAPE.patch new file mode 100644 index 0000000..0a9e4a1 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0107-net-fsl-change-ls2-arch-define-to-ARCH_LAYERSCAPE.patch @@ -0,0 +1,29 @@ +From e42e4bf2b628bee24994e3fc13d9473e83580c23 Mon Sep 17 00:00:00 2001 +From: Stuart Yoder +Date: Thu, 29 Oct 2015 09:15:51 -0500 +Subject: [PATCH 107/151] net/fsl: change ls2 arch define to ARCH_LAYERSCAPE + +the arch define for the ls2 platform is changed from +ARCH_LS2085A to ARCH_LAYERSCAPE + +Signed-off-by: Stuart Yoder +--- + drivers/net/ethernet/freescale/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig +index bd739db..38eb6af 100644 +--- a/drivers/net/ethernet/freescale/Kconfig ++++ b/drivers/net/ethernet/freescale/Kconfig +@@ -8,7 +8,7 @@ config NET_VENDOR_FREESCALE + depends on FSL_SOC || QUICC_ENGINE || CPM1 || CPM2 || PPC_MPC512x || \ + M523x || M527x || M5272 || M528x || M520x || M532x || \ + ARCH_MXC || ARCH_MXS || (PPC_MPC52xx && PPC_BESTCOMM) || \ +- ARCH_FSL_LS2085A ++ ARCH_LAYERSCAPE + ---help--- + If you have a network (Ethernet) card belonging to this class, say Y + and read the Ethernet-HOWTO, available from +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0108-net-phy-fix-PHY_RUNNING-in-phy_state_machine.patch b/target/linux/layerscape-64b/patches-4.1/0108-net-phy-fix-PHY_RUNNING-in-phy_state_machine.patch new file mode 100644 index 0000000..b96a171 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0108-net-phy-fix-PHY_RUNNING-in-phy_state_machine.patch @@ -0,0 +1,56 @@ +From 76e21b99746a33a4b6f01c691669e3bdae5044f8 Mon Sep 17 00:00:00 2001 +From: Shaohui Xie +Date: Fri, 14 Aug 2015 12:23:40 +0800 +Subject: [PATCH 108/151] net: phy: fix PHY_RUNNING in phy_state_machine + +Currently, if phy state is PHY_RUNNING, we always register a CHANGE +when phy works in polling or interrupt ignored, this will make the +adjust_link being called even the phy link did Not changed. + +checking the phy link to make sure the link did changed before we +register a CHANGE, if link did not changed, we do nothing. + +Signed-off-by: Shaohui Xie +Signed-off-by: David S. Miller +--- + drivers/net/phy/phy.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c +index bdd17c8..bd77e38 100644 +--- a/drivers/net/phy/phy.c ++++ b/drivers/net/phy/phy.c +@@ -829,6 +829,7 @@ void phy_state_machine(struct work_struct *work) + container_of(dwork, struct phy_device, state_queue); + bool needs_aneg = false, do_suspend = false; + int err = 0; ++ int old_link; + + mutex_lock(&phydev->lock); + +@@ -912,11 +913,18 @@ void phy_state_machine(struct work_struct *work) + phydev->adjust_link(phydev->attached_dev); + break; + case PHY_RUNNING: +- /* Only register a CHANGE if we are +- * polling or ignoring interrupts ++ /* Only register a CHANGE if we are polling or ignoring ++ * interrupts and link changed since latest checking. + */ +- if (!phy_interrupt_is_valid(phydev)) +- phydev->state = PHY_CHANGELINK; ++ if (!phy_interrupt_is_valid(phydev)) { ++ old_link = phydev->link; ++ err = phy_read_status(phydev); ++ if (err) ++ break; ++ ++ if (old_link != phydev->link) ++ phydev->state = PHY_CHANGELINK; ++ } + break; + case PHY_CHANGELINK: + err = phy_read_status(phydev); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0109-net-phy-add-interrupt-support-for-aquantia-phy.patch b/target/linux/layerscape-64b/patches-4.1/0109-net-phy-add-interrupt-support-for-aquantia-phy.patch new file mode 100644 index 0000000..c4a3000 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0109-net-phy-add-interrupt-support-for-aquantia-phy.patch @@ -0,0 +1,113 @@ +From f065b9000f96809bb397f0d6d92b3ddf3832f8f2 Mon Sep 17 00:00:00 2001 +From: Shaohui Xie +Date: Fri, 21 Aug 2015 15:29:29 +0800 +Subject: [PATCH 109/151] net: phy: add interrupt support for aquantia phy + +By implementing config_intr & ack_interrupt, now the phy can support +link connect/disconnect interrupt. + +Signed-off-by: Shaohui Xie +Signed-off-by: David S. Miller +--- + drivers/net/phy/aquantia.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) + +diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c +index 73d347d..d6111af 100644 +--- a/drivers/net/phy/aquantia.c ++++ b/drivers/net/phy/aquantia.c +@@ -44,6 +44,43 @@ static int aquantia_aneg_done(struct phy_device *phydev) + return (reg < 0) ? reg : (reg & BMSR_ANEGCOMPLETE); + } + ++static int aquantia_config_intr(struct phy_device *phydev) ++{ ++ int err; ++ ++ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { ++ err = phy_write_mmd(phydev, MDIO_MMD_AN, 0xd401, 1); ++ if (err < 0) ++ return err; ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xff00, 1); ++ if (err < 0) ++ return err; ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xff01, 0x1001); ++ } else { ++ err = phy_write_mmd(phydev, MDIO_MMD_AN, 0xd401, 0); ++ if (err < 0) ++ return err; ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xff00, 0); ++ if (err < 0) ++ return err; ++ ++ err = phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xff01, 0); ++ } ++ ++ return err; ++} ++ ++static int aquantia_ack_interrupt(struct phy_device *phydev) ++{ ++ int reg; ++ ++ reg = phy_read_mmd(phydev, MDIO_MMD_AN, 0xcc01); ++ return (reg < 0) ? reg : 0; ++} ++ + static int aquantia_read_status(struct phy_device *phydev) + { + int reg; +@@ -85,8 +122,11 @@ static struct phy_driver aquantia_driver[] = { + .phy_id_mask = 0xfffffff0, + .name = "Aquantia AQ1202", + .features = PHY_AQUANTIA_FEATURES, ++ .flags = PHY_HAS_INTERRUPT, + .aneg_done = aquantia_aneg_done, + .config_aneg = aquantia_config_aneg, ++ .config_intr = aquantia_config_intr, ++ .ack_interrupt = aquantia_ack_interrupt, + .read_status = aquantia_read_status, + .driver = { .owner = THIS_MODULE,}, + }, +@@ -95,8 +135,11 @@ static struct phy_driver aquantia_driver[] = { + .phy_id_mask = 0xfffffff0, + .name = "Aquantia AQ2104", + .features = PHY_AQUANTIA_FEATURES, ++ .flags = PHY_HAS_INTERRUPT, + .aneg_done = aquantia_aneg_done, + .config_aneg = aquantia_config_aneg, ++ .config_intr = aquantia_config_intr, ++ .ack_interrupt = aquantia_ack_interrupt, + .read_status = aquantia_read_status, + .driver = { .owner = THIS_MODULE,}, + }, +@@ -105,8 +148,11 @@ static struct phy_driver aquantia_driver[] = { + .phy_id_mask = 0xfffffff0, + .name = "Aquantia AQR105", + .features = PHY_AQUANTIA_FEATURES, ++ .flags = PHY_HAS_INTERRUPT, + .aneg_done = aquantia_aneg_done, + .config_aneg = aquantia_config_aneg, ++ .config_intr = aquantia_config_intr, ++ .ack_interrupt = aquantia_ack_interrupt, + .read_status = aquantia_read_status, + .driver = { .owner = THIS_MODULE,}, + }, +@@ -115,8 +161,11 @@ static struct phy_driver aquantia_driver[] = { + .phy_id_mask = 0xfffffff0, + .name = "Aquantia AQR405", + .features = PHY_AQUANTIA_FEATURES, ++ .flags = PHY_HAS_INTERRUPT, + .aneg_done = aquantia_aneg_done, + .config_aneg = aquantia_config_aneg, ++ .config_intr = aquantia_config_intr, ++ .ack_interrupt = aquantia_ack_interrupt, + .read_status = aquantia_read_status, + .driver = { .owner = THIS_MODULE,}, + }, +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0110-arm64-add-ioremap-for-normal-cacheable-non-shareable.patch b/target/linux/layerscape-64b/patches-4.1/0110-arm64-add-ioremap-for-normal-cacheable-non-shareable.patch new file mode 100644 index 0000000..9ad2cac --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0110-arm64-add-ioremap-for-normal-cacheable-non-shareable.patch @@ -0,0 +1,46 @@ +From 6db848eaca7291d7d62664db5added771dd656f0 Mon Sep 17 00:00:00 2001 +From: Haiying Wang +Date: Wed, 22 Apr 2015 13:07:25 -0400 +Subject: [PATCH 110/151] arm64: add ioremap for normal cacheable non-shareable + memory + +Signed-off-by: Haiying Wang +Change-Id: Iab7413f182a64bd6ad4707dd1d6254d04f51a3b1 +Reviewed-on: http://git.am.freescale.net:8181/35486 +Tested-by: Review Code-CDREVIEW +Reviewed-by: Roy Pledge +Reviewed-by: Stuart Yoder +--- + arch/arm64/include/asm/io.h | 2 ++ + arch/arm64/include/asm/pgtable.h | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h +index 540f7c0..2640b8d 100644 +--- a/arch/arm64/include/asm/io.h ++++ b/arch/arm64/include/asm/io.h +@@ -170,6 +170,8 @@ extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size); + #define ioremap(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE)) + #define ioremap_nocache(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE)) + #define ioremap_wc(addr, size) __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC)) ++#define ioremap_cache_ns(addr, size) __ioremap((addr), (size), \ ++ __pgprot(PROT_NORMAL_NS)) + #define iounmap __iounmap + + /* +diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h +index 526a9cb..51df64f 100644 +--- a/arch/arm64/include/asm/pgtable.h ++++ b/arch/arm64/include/asm/pgtable.h +@@ -66,6 +66,8 @@ extern void __pgd_error(const char *file, int line, unsigned long val); + #define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE)) + #define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL_NC)) + #define PROT_NORMAL (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL)) ++#define PROT_NORMAL_NS (PTE_TYPE_PAGE | PTE_AF | PTE_PXN | PTE_UXN | \ ++ PTE_ATTRINDX(MT_NORMAL)) + + #define PROT_SECT_DEVICE_nGnRE (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE)) + #define PROT_SECT_NORMAL (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL)) +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0111-arm64-add-support-to-remap-kernel-cacheable-memory-t.patch b/target/linux/layerscape-64b/patches-4.1/0111-arm64-add-support-to-remap-kernel-cacheable-memory-t.patch new file mode 100644 index 0000000..39feeda --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0111-arm64-add-support-to-remap-kernel-cacheable-memory-t.patch @@ -0,0 +1,33 @@ +From 3eeccff5e792907a361d32a7a6f4a93363e014e8 Mon Sep 17 00:00:00 2001 +From: Haiying Wang +Date: Wed, 22 Apr 2015 13:09:47 -0400 +Subject: [PATCH 111/151] arm64: add support to remap kernel cacheable memory + to userspace + +Signed-off-by: Haiying Wang +Change-Id: I50ee4798a2929932fa9ff7c9cdb42cd1a215f77a +Reviewed-on: http://git.am.freescale.net:8181/35488 +Tested-by: Review Code-CDREVIEW +Reviewed-by: Roy Pledge +Reviewed-by: Stuart Yoder +--- + arch/arm64/include/asm/pgtable.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h +index 51df64f..93ae77d 100644 +--- a/arch/arm64/include/asm/pgtable.h ++++ b/arch/arm64/include/asm/pgtable.h +@@ -326,6 +326,9 @@ static inline int has_transparent_hugepage(void) + __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRnE) | PTE_PXN | PTE_UXN) + #define pgprot_writecombine(prot) \ + __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN) ++#define pgprot_cached(prot) \ ++ __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL) | \ ++ PTE_PXN | PTE_UXN) + #define pgprot_device(prot) \ + __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRE) | PTE_PXN | PTE_UXN) + #define __HAVE_PHYS_MEM_ACCESS_PROT +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0112-arm64-pgtable-add-support-to-map-cacheable-and-non-s.patch b/target/linux/layerscape-64b/patches-4.1/0112-arm64-pgtable-add-support-to-map-cacheable-and-non-s.patch new file mode 100644 index 0000000..9351c1c --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0112-arm64-pgtable-add-support-to-map-cacheable-and-non-s.patch @@ -0,0 +1,27 @@ +From ba8b364a5dd98138dec197aeabef830186bb72ba Mon Sep 17 00:00:00 2001 +From: Haiying Wang +Date: Sat, 8 Aug 2015 07:25:02 -0400 +Subject: [PATCH 112/151] arm64/pgtable: add support to map cacheable and non + shareable memory + +Signed-off-by: Haiying Wang +--- + arch/arm64/include/asm/pgtable.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h +index 93ae77d..11f514b 100644 +--- a/arch/arm64/include/asm/pgtable.h ++++ b/arch/arm64/include/asm/pgtable.h +@@ -329,6 +329,8 @@ static inline int has_transparent_hugepage(void) + #define pgprot_cached(prot) \ + __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_NORMAL) | \ + PTE_PXN | PTE_UXN) ++#define pgprot_cached_ns(prot) \ ++ __pgprot(pgprot_val(pgprot_cached(prot)) ^ PTE_SHARED) + #define pgprot_device(prot) \ + __pgprot_modify(prot, PTE_ATTRINDX_MASK, PTE_ATTRINDX(MT_DEVICE_nGnRE) | PTE_PXN | PTE_UXN) + #define __HAVE_PHYS_MEM_ACCESS_PROT +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0113-fmd-remove-misuse-of-IRQF_NO_SUSPEND-flag.patch b/target/linux/layerscape-64b/patches-4.1/0113-fmd-remove-misuse-of-IRQF_NO_SUSPEND-flag.patch new file mode 100644 index 0000000..ad2f5dc --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0113-fmd-remove-misuse-of-IRQF_NO_SUSPEND-flag.patch @@ -0,0 +1,77 @@ +From ac99880c34071a9855846d3e1ecbfb8995d2aef8 Mon Sep 17 00:00:00 2001 +From: Claudiu Manoil +Date: Thu, 25 Feb 2016 17:34:44 +0200 +Subject: [PATCH 113/151] fmd: remove misuse of IRQF_NO_SUSPEND flag + +Use proper wakeup API instead of IRQF_NO_SUSPEND to set +the interrupt as wakeup source. + +Fixes: +WARNING: CPU: 0 PID: 1 at kernel/irq/pm.c:51 +irq_pm_install_action+0xd4/0xfc() +Modules linked in: +CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.1.8-gc3db090 #1 +Hardware name: LS1043A RDB Board (DT) +Call trace: +[] dump_backtrace+0x0/0x11c +[] show_stack+0x10/0x1c +[] dump_stack+0x88/0xc8 +[] warn_slowpath_common+0x94/0xd0 +[] warn_slowpath_null+0x14/0x20 +[] irq_pm_install_action+0xd0/0xfc +[] __setup_irq+0x208/0x48c +[] request_threaded_irq+0xc4/0x178 +[] devm_request_threaded_irq+0x68/0xd0 +[] fm_probe+0x144/0x15c0 +[] platform_drv_probe+0x48/0xb8 +[] driver_probe_device+0x168/0x2a4 +[] __driver_attach+0x98/0xa0 +[] bus_for_each_dev+0x54/0x98 +[] driver_attach+0x1c/0x28 +[] bus_add_driver+0x14c/0x204 +[] driver_register+0x5c/0x11c +[] __platform_driver_register+0x5c/0x68 +[] LNXWRP_FM_Init+0x40/0x54 +[] fm_load+0x8/0x50 +[] do_one_initcall+0x88/0x1a0 +[] kernel_init_freeable+0x148/0x1ec +[] kernel_init+0xc/0xd8 + +Signed-off-by: Claudiu Manoil +--- + drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c +index caf8659..3b415d1 100755 +--- a/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c ++++ b/drivers/net/ethernet/freescale/sdk_fman/src/wrapper/lnxwrp_fm.c +@@ -843,19 +843,23 @@ static t_Error ConfigureFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev) + if (unlikely(_errno < 0)) + RETURN_ERROR(MAJOR, E_INVALID_STATE, ("can_request_irq() = %d", _errno)); + #endif +- _errno = devm_request_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->irq, fm_irq, IRQF_NO_SUSPEND, "fman", p_LnxWrpFmDev); ++ _errno = devm_request_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->irq, fm_irq, 0, "fman", p_LnxWrpFmDev); + if (unlikely(_errno < 0)) + RETURN_ERROR(MAJOR, E_INVALID_STATE, ("request_irq(%d) = %d", p_LnxWrpFmDev->irq, _errno)); + ++ enable_irq_wake(p_LnxWrpFmDev->irq); ++ + if (p_LnxWrpFmDev->err_irq != 0) { + #ifndef MODULE + _errno = can_request_irq(p_LnxWrpFmDev->err_irq, 0); + if (unlikely(_errno < 0)) + RETURN_ERROR(MAJOR, E_INVALID_STATE, ("can_request_irq() = %d", _errno)); + #endif +- _errno = devm_request_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->err_irq, fm_err_irq, IRQF_SHARED | IRQF_NO_SUSPEND, "fman-err", p_LnxWrpFmDev); ++ _errno = devm_request_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->err_irq, fm_err_irq, IRQF_SHARED, "fman-err", p_LnxWrpFmDev); + if (unlikely(_errno < 0)) + RETURN_ERROR(MAJOR, E_INVALID_STATE, ("request_irq(%d) = %d", p_LnxWrpFmDev->err_irq, _errno)); ++ ++ enable_irq_wake(p_LnxWrpFmDev->err_irq); + } + + p_LnxWrpFmDev->res = devm_request_mem_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize, "fman"); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0114-ls2085a-Add-support-for-reset.patch b/target/linux/layerscape-64b/patches-4.1/0114-ls2085a-Add-support-for-reset.patch new file mode 100644 index 0000000..2bf6946 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0114-ls2085a-Add-support-for-reset.patch @@ -0,0 +1,145 @@ +From b427f2d5dadfd8ef7fdca4a34afca132a5fbdd9c Mon Sep 17 00:00:00 2001 +From: pankaj chauhan +Date: Tue, 3 Feb 2015 13:08:52 +0530 +Subject: [PATCH 114/151] ls2085a: Add support for reset + +Add support for layerscape reset driver. +Reset is implemented by raising RESET_REQ_B. + +Signed-off-by: pankaj chauhan +Signed-off-by: Stuart Yoder +(cherry picked from commit f248be3aea58ca32b7d77413d742996249b293e9) +--- + drivers/power/reset/Kconfig | 7 +++- + drivers/power/reset/Makefile | 1 + + drivers/power/reset/ls-reboot.c | 93 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 100 insertions(+), 1 deletion(-) + create mode 100644 drivers/power/reset/ls-reboot.c + +diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig +index 17d93a7..b3df3c5 100644 +--- a/drivers/power/reset/Kconfig ++++ b/drivers/power/reset/Kconfig +@@ -166,5 +166,10 @@ config POWER_RESET_RMOBILE + help + Reboot support for Renesas R-Mobile and SH-Mobile SoCs. + +-endif ++config POWER_RESET_LAYERSCAPE ++ bool "Freescale LayerScape reset driver" ++ depends on ARCH_FSL_LS2085A ++ help ++ Reboot support for the Freescale LayerScape SoCs. + ++endif +diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile +index dbe06c3..81293d7 100644 +--- a/drivers/power/reset/Makefile ++++ b/drivers/power/reset/Makefile +@@ -19,3 +19,4 @@ obj-$(CONFIG_POWER_RESET_KEYSTONE) += keystone-reset.o + obj-$(CONFIG_POWER_RESET_SYSCON) += syscon-reboot.o + obj-$(CONFIG_POWER_RESET_SYSCON_POWEROFF) += syscon-poweroff.o + obj-$(CONFIG_POWER_RESET_RMOBILE) += rmobile-reset.o ++obj-$(CONFIG_POWER_RESET_LAYERSCAPE) += ls-reboot.o +diff --git a/drivers/power/reset/ls-reboot.c b/drivers/power/reset/ls-reboot.c +new file mode 100644 +index 0000000..fa1152c +--- /dev/null ++++ b/drivers/power/reset/ls-reboot.c +@@ -0,0 +1,93 @@ ++/* ++ * Freescale LayerScape reboot driver ++ * ++ * Copyright (c) 2015, Freescale Semiconductor. ++ * Author: Pankaj Chauhan ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct ls_reboot_priv { ++ struct device *dev; ++ u32 *rstcr; ++}; ++ ++static struct ls_reboot_priv *ls_reboot_priv; ++ ++static void ls_reboot(enum reboot_mode reboot_mode, const char *cmd) ++{ ++ struct ls_reboot_priv *priv = ls_reboot_priv; ++ u32 val; ++ unsigned long timeout; ++ ++ if (ls_reboot_priv) { ++ val = readl(priv->rstcr); ++ val |= 0x02; ++ writel(val, priv->rstcr); ++ } ++ ++ timeout = jiffies + HZ; ++ while (time_before(jiffies, timeout)) ++ cpu_relax(); ++ ++} ++ ++static int ls_reboot_probe(struct platform_device *pdev) ++{ ++ ls_reboot_priv = devm_kzalloc(&pdev->dev, ++ sizeof(*ls_reboot_priv), GFP_KERNEL); ++ if (!ls_reboot_priv) { ++ dev_err(&pdev->dev, "out of memory for context\n"); ++ return -ENODEV; ++ } ++ ++ ls_reboot_priv->rstcr = of_iomap(pdev->dev.of_node, 0); ++ if (!ls_reboot_priv->rstcr) { ++ devm_kfree(&pdev->dev, ls_reboot_priv); ++ dev_err(&pdev->dev, "can not map resource\n"); ++ return -ENODEV; ++ } ++ ++ ls_reboot_priv->dev = &pdev->dev; ++ ++ arm_pm_restart = ls_reboot; ++ ++ return 0; ++} ++ ++static struct of_device_id ls_reboot_of_match[] = { ++ { .compatible = "fsl,ls-reset" }, ++ {} ++}; ++ ++static struct platform_driver ls_reboot_driver = { ++ .probe = ls_reboot_probe, ++ .driver = { ++ .name = "ls-reset", ++ .of_match_table = ls_reboot_of_match, ++ }, ++}; ++ ++static int __init ls_reboot_init(void) ++{ ++ return platform_driver_register(&ls_reboot_driver); ++} ++device_initcall(ls_reboot_init); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0115-dts-ls1043a-add-reset-node.patch b/target/linux/layerscape-64b/patches-4.1/0115-dts-ls1043a-add-reset-node.patch new file mode 100644 index 0000000..891caa7 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0115-dts-ls1043a-add-reset-node.patch @@ -0,0 +1,33 @@ +From 5b8519ffa98c8aac8e4f724fbc19008260111619 Mon Sep 17 00:00:00 2001 +From: Shaohui Xie +Date: Fri, 22 Jan 2016 11:57:10 +0800 +Subject: [PATCH 115/151] dts: ls1043a: add reset node + +The reset component in ls1043a is big endian, so property 'big-endian' +is added in the node. + +Signed-off-by: Shaohui Xie +--- + arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +index 446483e..d7d2fa6 100644 +--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +@@ -167,6 +167,12 @@ + reg = <0x0 0x1ee0000 0x0 0x10000>; + }; + ++ reset: reset at 1EE00B0 { ++ compatible = "fsl,ls-reset"; ++ reg = <0x0 0x1EE00B0 0x0 0x4>; ++ big-endian; ++ }; ++ + ifc: ifc at 1530000 { + compatible = "fsl,ifc", "simple-bus"; + reg = <0x0 0x1530000 0x0 0x10000>; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0116-ls1043a-Add-support-for-reset.patch b/target/linux/layerscape-64b/patches-4.1/0116-ls1043a-Add-support-for-reset.patch new file mode 100644 index 0000000..0f069bc --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0116-ls1043a-Add-support-for-reset.patch @@ -0,0 +1,61 @@ +From 24e7b4a3b6a6e0c10921d98a6187404bdfbdb0c2 Mon Sep 17 00:00:00 2001 +From: Shaohui Xie +Date: Fri, 22 Jan 2016 12:01:28 +0800 +Subject: [PATCH 116/151] ls1043a: Add support for reset + +The reset in ls1043a is similar to ls2085a, but accessed in big endian, +so we modify the existing driver to handle endianness, if driver probes +property 'big-endian' in DTS, driver works in big endian mode, +otherwise, driver works in little endian by default. + +Signed-off-by: Shaohui Xie +--- + drivers/power/reset/ls-reboot.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/drivers/power/reset/ls-reboot.c b/drivers/power/reset/ls-reboot.c +index fa1152c..7358150 100644 +--- a/drivers/power/reset/ls-reboot.c ++++ b/drivers/power/reset/ls-reboot.c +@@ -28,6 +28,7 @@ + struct ls_reboot_priv { + struct device *dev; + u32 *rstcr; ++ bool is_big_endian; + }; + + static struct ls_reboot_priv *ls_reboot_priv; +@@ -39,9 +40,15 @@ static void ls_reboot(enum reboot_mode reboot_mode, const char *cmd) + unsigned long timeout; + + if (ls_reboot_priv) { +- val = readl(priv->rstcr); +- val |= 0x02; +- writel(val, priv->rstcr); ++ if (priv->is_big_endian) { ++ val = ioread32be(priv->rstcr); ++ val |= 0x02; ++ iowrite32be(val, priv->rstcr); ++ } else { ++ val = readl(priv->rstcr); ++ val |= 0x02; ++ writel(val, priv->rstcr); ++ } + } + + timeout = jiffies + HZ; +@@ -66,6 +73,11 @@ static int ls_reboot_probe(struct platform_device *pdev) + return -ENODEV; + } + ++ if (of_get_property(pdev->dev.of_node, "big-endian", NULL)) ++ ls_reboot_priv->is_big_endian = true; ++ else ++ ls_reboot_priv->is_big_endian = false; ++ + ls_reboot_priv->dev = &pdev->dev; + + arm_pm_restart = ls_reboot; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0117-reset-driver-Kconfig-Change-define-to-ARCH_LAYERSCAP.patch b/target/linux/layerscape-64b/patches-4.1/0117-reset-driver-Kconfig-Change-define-to-ARCH_LAYERSCAP.patch new file mode 100644 index 0000000..91e21c2 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0117-reset-driver-Kconfig-Change-define-to-ARCH_LAYERSCAP.patch @@ -0,0 +1,27 @@ +From d37c3d30d4b2a9ee695c327095747f3bd744f350 Mon Sep 17 00:00:00 2001 +From: Rai Harninder-B01044 +Date: Wed, 28 Oct 2015 13:24:44 +0530 +Subject: [PATCH 117/151] reset driver: Kconfig: Change define to + ARCH_LAYERSCAPE + +Signed-off-by: Rai Harninder-B01044 +--- + drivers/power/reset/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig +index b3df3c5..08bfb2e 100644 +--- a/drivers/power/reset/Kconfig ++++ b/drivers/power/reset/Kconfig +@@ -168,7 +168,7 @@ config POWER_RESET_RMOBILE + + config POWER_RESET_LAYERSCAPE + bool "Freescale LayerScape reset driver" +- depends on ARCH_FSL_LS2085A ++ depends on ARCH_LAYERSCAPE + help + Reboot support for the Freescale LayerScape SoCs. + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0118-pci-designware-Add-base-driver-for-Designware-PCIe.patch b/target/linux/layerscape-64b/patches-4.1/0118-pci-designware-Add-base-driver-for-Designware-PCIe.patch new file mode 100644 index 0000000..323c46b --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0118-pci-designware-Add-base-driver-for-Designware-PCIe.patch @@ -0,0 +1,407 @@ +From 7f432a80471be678f472410e17b7c0d2f783ee48 Mon Sep 17 00:00:00 2001 +From: Minghuan Lian +Date: Mon, 23 Mar 2015 15:55:52 +0800 +Subject: [PATCH 118/151] pci/designware: Add base driver for Designware PCIe + +The Synopsys Designware IP is shared with couples of platforms +under multiple architectures. The patch is to provide basic +architecture-independent Designware PCIe host driver including +ATU initialization and PCI OPS. Currently, which supports arm +and arm64 simultaneously. + +Signed-off-by: Minghuan Lian +Change-Id: I6daa7853c6acf0d14264d9f14cf2bb40e0e5c928 +Reviewed-on: http://git.am.freescale.net:8181/33248 +Reviewed-by: Stuart Yoder +Tested-by: Stuart Yoder +--- + drivers/pci/host/Kconfig | 3 + + drivers/pci/host/Makefile | 1 + + drivers/pci/host/pcie-designware-base.c | 282 ++++++++++++++++++++++++++++++++ + drivers/pci/host/pcie-designware-base.h | 62 +++++++ + 4 files changed, 348 insertions(+) + create mode 100644 drivers/pci/host/pcie-designware-base.c + create mode 100644 drivers/pci/host/pcie-designware-base.h + +diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig +index 1dfb567..2a697c0 100644 +--- a/drivers/pci/host/Kconfig ++++ b/drivers/pci/host/Kconfig +@@ -18,6 +18,9 @@ config PCI_MVEBU + config PCIE_DW + bool + ++config PCIE_DW_BASE ++ bool ++ + config PCI_EXYNOS + bool "Samsung Exynos PCIe controller" + depends on SOC_EXYNOS5440 +diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile +index f733b4e..da985e1 100644 +--- a/drivers/pci/host/Makefile ++++ b/drivers/pci/host/Makefile +@@ -1,3 +1,4 @@ ++obj-$(CONFIG_PCIE_DW_BASE) += pcie-designware-base.o + obj-$(CONFIG_PCIE_DW) += pcie-designware.o + obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o + obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o +diff --git a/drivers/pci/host/pcie-designware-base.c b/drivers/pci/host/pcie-designware-base.c +new file mode 100644 +index 0000000..f661151 +--- /dev/null ++++ b/drivers/pci/host/pcie-designware-base.c +@@ -0,0 +1,282 @@ ++/* ++ * Synopsys Designware PCIe host controller base driver ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "pcie-designware-base.h" ++ ++void dw_pcie_dbi_write(struct dw_pcie_port *pp, u32 value, u32 offset) ++{ ++ iowrite32(value, pp->dbi + offset); ++} ++ ++u32 dw_pcie_dbi_read(struct dw_pcie_port *pp, u32 offset) ++{ ++ return ioread32(pp->dbi + offset); ++} ++ ++int dw_pcie_host_link_up(struct dw_pcie_port *pp) ++{ ++ if (pp->dw_ops->link_up) ++ return pp->dw_ops->link_up(pp); ++ else ++ return 0; ++} ++ ++void dw_pcie_atu_outbound_set(struct dw_pcie_port *pp, int idx, int type, ++ u64 cpu_addr, u64 pci_addr, u32 size) ++{ ++ if (idx >= pp->atu_num) ++ return; ++ ++ dw_pcie_dbi_write(pp, PCIE_ATU_REGION_OUTBOUND | idx, ++ PCIE_ATU_VIEWPORT); ++ dw_pcie_dbi_write(pp, lower_32_bits(cpu_addr), ++ PCIE_ATU_LOWER_BASE); ++ dw_pcie_dbi_write(pp, upper_32_bits(cpu_addr), ++ PCIE_ATU_UPPER_BASE); ++ dw_pcie_dbi_write(pp, lower_32_bits(cpu_addr + size - 1), ++ PCIE_ATU_LIMIT); ++ dw_pcie_dbi_write(pp, lower_32_bits(pci_addr), ++ PCIE_ATU_LOWER_TARGET); ++ dw_pcie_dbi_write(pp, upper_32_bits(pci_addr), ++ PCIE_ATU_UPPER_TARGET); ++ dw_pcie_dbi_write(pp, type, PCIE_ATU_CR1); ++ dw_pcie_dbi_write(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); ++} ++ ++static void __iomem * ++dw_pcie_map_bus(struct pci_bus *bus, unsigned int devfn, int offset) ++{ ++ struct dw_pcie_port *pp = bus->sysdata; ++ u32 type, busdev; ++ ++ /* If there is no link, then there is no device */ ++ if (!pci_is_root_bus(bus) && !dw_pcie_host_link_up(pp)) ++ return NULL; ++ ++ /* access only one slot on each root port */ ++ if (pci_is_root_bus(bus) && devfn > 0) ++ return NULL; ++ ++ if (pci_is_root_bus(bus)) ++ return pp->dbi + offset; ++ ++ busdev = PCIE_ATU_BUS(bus->number) | ++ PCIE_ATU_DEV(PCI_SLOT(devfn)) | ++ PCIE_ATU_FUNC(PCI_FUNC(devfn)); ++ ++ if (pci_is_root_bus(bus->parent)) ++ type = PCIE_ATU_TYPE_CFG0; ++ else ++ type = PCIE_ATU_TYPE_CFG1; ++ ++ dw_pcie_atu_outbound_set(pp, ++ PCIE_ATU_REGION_INDEX0, ++ type, ++ pp->cfg_addr, ++ busdev, ++ pp->cfg_size); ++ ++ return pp->cfg + offset; ++} ++ ++static int dw_pcie_config_read(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 *val) ++{ ++ struct dw_pcie_port *pp = bus->sysdata; ++ int ret; ++ ++ ret = pci_generic_config_read32(bus, devfn, where, size, val); ++ ++ if (pp->atu_num == 2 && !pci_is_root_bus(bus)) ++ /* reassign ATU0 to map IO space */ ++ dw_pcie_atu_outbound_set(pp, ++ PCIE_ATU_REGION_INDEX0, ++ PCIE_ATU_TYPE_IO, ++ pp->io_cpu_addr, ++ pp->io_pci_addr, ++ pp->io_size); ++ ++ return ret; ++} ++ ++static int dw_pcie_config_write(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 val) ++{ ++ struct dw_pcie_port *pp = bus->sysdata; ++ int ret; ++ ++ ret = pci_generic_config_write32(bus, devfn, where, size, val); ++ ++ if (pp->atu_num == 2 && !pci_is_root_bus(bus)) ++ /* reassign ATU0 to map IO space */ ++ dw_pcie_atu_outbound_set(pp, ++ PCIE_ATU_REGION_INDEX0, ++ PCIE_ATU_TYPE_IO, ++ pp->io_cpu_addr, ++ pp->io_pci_addr, ++ pp->io_size); ++ ++ return ret; ++} ++ ++static struct pci_ops dw_pcie_ops = { ++ .map_bus = dw_pcie_map_bus, ++ .read = dw_pcie_config_read, ++ .write = dw_pcie_config_write, ++}; ++ ++static int dw_pcie_map_reg(struct dw_pcie_port *pp) ++{ ++ struct platform_device *pdev = to_platform_device(pp->dev); ++ struct resource *res; ++ ++ if (!pp->dbi) { ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, ++ "dbi"); ++ if (!res) { ++ dev_err(pp->dev, "missing *dbi* reg space\n"); ++ return -ENODEV; ++ } ++ ++ pp->dbi = devm_ioremap_resource(pp->dev, res); ++ if (IS_ERR(pp->dbi)) ++ return PTR_ERR(pp->dbi); ++ } ++ ++ if (!pp->cfg) { ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, ++ "config"); ++ if (!res) { ++ dev_err(pp->dev, "missing *config* reg space\n"); ++ return -ENODEV; ++ } ++ ++ pp->cfg = devm_ioremap_resource(pp->dev, res); ++ if (IS_ERR(pp->cfg)) ++ return PTR_ERR(pp->cfg); ++ ++ pp->cfg_addr = res->start; ++ pp->cfg_size = resource_size(res); ++ } ++ ++ return 0; ++} ++ ++/* ++ * If ATU number = 2, ATU0 is shared by transaction CFG and IO, ++ * ATU1 is used for transaction MEM ++ * If ATU number > 2, ATU0 is used for transaction CFG ++ * the other ATUs are used for MEM and IO separately. ++ */ ++static int dw_pcie_atu_init(struct dw_pcie_port *pp, ++ struct list_head *res, ++ resource_size_t io_base) ++{ ++ struct resource_entry *window; ++ struct device *dev = pp->dev; ++ int idx = 1, ret; ++ ++ if (pp->atu_num < 2) ++ pp->atu_num = 2; ++ ++ resource_list_for_each_entry(window, res) { ++ struct resource *res = window->res; ++ unsigned long restype = resource_type(res); ++ ++ switch (restype) { ++ case IORESOURCE_IO: ++ if (pp->atu_num == 2) ++ idx = 0; ++ ++ pp->io_cpu_addr = io_base; ++ pp->io_pci_addr = res->start - window->offset; ++ pp->io_size = resource_size(res); ++ dw_pcie_atu_outbound_set(pp, ++ idx, ++ PCIE_ATU_TYPE_IO, ++ pp->io_cpu_addr, ++ pp->io_pci_addr, ++ pp->io_size); ++ ret = pci_remap_iospace(res, io_base); ++ if (ret < 0) ++ return ret; ++ idx++; ++ break; ++ case IORESOURCE_MEM: ++ if (pp->atu_num == 2) ++ idx = 1; ++ ++ dw_pcie_atu_outbound_set(pp, ++ idx, ++ PCIE_ATU_TYPE_MEM, ++ res->start, ++ res->start - window->offset, ++ resource_size(res)); ++ idx++; ++ break; ++ case IORESOURCE_BUS: ++ break; ++ default: ++ dev_err(dev, "invalid resource %pR\n", res); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++int dw_pcie_port_init(struct dw_pcie_port *pp) ++{ ++ struct device_node *dn = pp->dev->of_node; ++ resource_size_t iobase = 0; ++ struct pci_bus *bus; ++ int ret; ++ LIST_HEAD(res); ++ ++ ret = dw_pcie_map_reg(pp); ++ if (ret) ++ return ret; ++ ++ ret = of_pci_get_host_bridge_resources(dn, 0, 0xff, &res, &iobase); ++ if (ret) ++ return ret; ++ ++ ret = dw_pcie_atu_init(pp, &res, iobase); ++ if (ret) ++ return ret; ++ ++ if (!pp->pci_ops) ++ pp->pci_ops = &dw_pcie_ops; ++ ++ if (pp->dw_ops->host_init) { ++ if (pp->dw_ops->host_init(pp)) ++ return ret; ++ } ++ ++ bus = pci_create_root_bus(pp->dev, 0, pp->pci_ops, ++ pp, &res); ++ if (!bus) ++ return -ENOMEM; ++ ++ pci_scan_child_bus(bus); ++ pci_assign_unassigned_bus_resources(bus); ++ pci_bus_add_devices(bus); ++ ++ return 0; ++} ++ ++MODULE_AUTHOR("Minghuan Lian "); ++MODULE_DESCRIPTION("Designware PCIe controller driver with Multiarch support"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/pci/host/pcie-designware-base.h b/drivers/pci/host/pcie-designware-base.h +new file mode 100644 +index 0000000..dd7a3b3 +--- /dev/null ++++ b/drivers/pci/host/pcie-designware-base.h +@@ -0,0 +1,62 @@ ++/* ++ * Synopsys Designware PCIe host controller base driver ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef _PCIE_DESIGNWARE_BASE_H ++#define _PCIE_DESIGNWARE_BASE_H ++ ++/* Synopsis specific PCIE configuration registers */ ++#define PCIE_ATU_VIEWPORT 0x900 ++#define PCIE_ATU_REGION_INBOUND (0x1 << 31) ++#define PCIE_ATU_REGION_OUTBOUND (0x0 << 31) ++#define PCIE_ATU_REGION_INDEX0 (0x0 << 0) ++#define PCIE_ATU_CR1 0x904 ++#define PCIE_ATU_TYPE_MEM (0x0 << 0) ++#define PCIE_ATU_TYPE_IO (0x2 << 0) ++#define PCIE_ATU_TYPE_CFG0 (0x4 << 0) ++#define PCIE_ATU_TYPE_CFG1 (0x5 << 0) ++#define PCIE_ATU_CR2 0x908 ++#define PCIE_ATU_ENABLE (0x1 << 31) ++#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30) ++#define PCIE_ATU_LOWER_BASE 0x90C ++#define PCIE_ATU_UPPER_BASE 0x910 ++#define PCIE_ATU_LIMIT 0x914 ++#define PCIE_ATU_LOWER_TARGET 0x918 ++#define PCIE_ATU_BUS(x) (((x) & 0xff) << 24) ++#define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19) ++#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) ++#define PCIE_ATU_UPPER_TARGET 0x91C ++ ++struct dw_pcie_port; ++ ++struct dw_host_ops { ++ int (*link_up)(struct dw_pcie_port *pp); ++ int (*host_init)(struct dw_pcie_port *pp); ++}; ++ ++struct dw_pcie_port { ++ struct device *dev; ++ void __iomem *dbi; ++ void __iomem *cfg; ++ u64 cfg_addr; ++ u32 cfg_size; ++ u64 io_cpu_addr; ++ u64 io_pci_addr; ++ u32 io_size; ++ u32 atu_num; ++ struct dw_host_ops *dw_ops; ++ struct pci_ops *pci_ops; ++}; ++ ++void dw_pcie_dbi_write(struct dw_pcie_port *pp, u32 value, u32 offset); ++u32 dw_pcie_dbi_read(struct dw_pcie_port *pp, u32 offset); ++int dw_pcie_host_link_up(struct dw_pcie_port *pp); ++void dw_pcie_atu_outbound_set(struct dw_pcie_port *pp, int idx, int type, ++ u64 cpu_addr, u64 pci_addr, u32 size); ++int dw_pcie_port_init(struct dw_pcie_port *pp); ++ ++#endif /* _PCIE_DESIGNWARE_BASE_H */ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0119-pci-designware-find-msi-controller-via-msi-parent-ha.patch b/target/linux/layerscape-64b/patches-4.1/0119-pci-designware-find-msi-controller-via-msi-parent-ha.patch new file mode 100644 index 0000000..23dc603 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0119-pci-designware-find-msi-controller-via-msi-parent-ha.patch @@ -0,0 +1,79 @@ +From a8db2f6d9b388a4f6ae1027f7045bf7c0b768f39 Mon Sep 17 00:00:00 2001 +From: Minghuan Lian +Date: Fri, 3 Jul 2015 14:57:08 +0800 +Subject: [PATCH 119/151] pci/designware: find msi controller via msi-parent + handler + +If pci dts node contains "msi-parent" handler, the driver will find +corresponding msi controller and register it to pci bus. + +Signed-off-by: Minghuan Lian +--- + drivers/pci/host/pcie-designware-base.c | 17 +++++++++++++++++ + drivers/pci/host/pcie-designware-base.h | 1 + + 2 files changed, 18 insertions(+) + +diff --git a/drivers/pci/host/pcie-designware-base.c b/drivers/pci/host/pcie-designware-base.c +index f661151..923d732 100644 +--- a/drivers/pci/host/pcie-designware-base.c ++++ b/drivers/pci/host/pcie-designware-base.c +@@ -8,6 +8,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -237,6 +238,18 @@ static int dw_pcie_atu_init(struct dw_pcie_port *pp, + return 0; + } + ++static void dw_pcie_msi_init(struct dw_pcie_port *pp) ++{ ++ struct device_node *msi_node; ++ ++ if (pp->msi_chip) ++ return; ++ ++ msi_node = of_parse_phandle(pp->dev->of_node, "msi-parent", 0); ++ if (msi_node) ++ pp->msi_chip = of_pci_find_msi_chip_by_node(msi_node); ++} ++ + int dw_pcie_port_init(struct dw_pcie_port *pp) + { + struct device_node *dn = pp->dev->of_node; +@@ -257,6 +270,8 @@ int dw_pcie_port_init(struct dw_pcie_port *pp) + if (ret) + return ret; + ++ dw_pcie_msi_init(pp); ++ + if (!pp->pci_ops) + pp->pci_ops = &dw_pcie_ops; + +@@ -270,6 +285,8 @@ int dw_pcie_port_init(struct dw_pcie_port *pp) + if (!bus) + return -ENOMEM; + ++ bus->msi = pp->msi_chip; ++ + pci_scan_child_bus(bus); + pci_assign_unassigned_bus_resources(bus); + pci_bus_add_devices(bus); +diff --git a/drivers/pci/host/pcie-designware-base.h b/drivers/pci/host/pcie-designware-base.h +index dd7a3b3..60c82de 100644 +--- a/drivers/pci/host/pcie-designware-base.h ++++ b/drivers/pci/host/pcie-designware-base.h +@@ -50,6 +50,7 @@ struct dw_pcie_port { + u32 atu_num; + struct dw_host_ops *dw_ops; + struct pci_ops *pci_ops; ++ struct msi_controller *msi_chip; + }; + + void dw_pcie_dbi_write(struct dw_pcie_port *pp, u32 value, u32 offset); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0120-pci-layerscape-Add-LS2085A-PCIe-support.patch b/target/linux/layerscape-64b/patches-4.1/0120-pci-layerscape-Add-LS2085A-PCIe-support.patch new file mode 100644 index 0000000..27913de --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0120-pci-layerscape-Add-LS2085A-PCIe-support.patch @@ -0,0 +1,326 @@ +From 5609183df85f18ad1de2fe9acf4cea2e075cfad4 Mon Sep 17 00:00:00 2001 +From: Minghuan Lian +Date: Mon, 23 Mar 2015 15:55:52 +0800 +Subject: [PATCH 120/151] pci/layerscape: Add LS2085A PCIe support + +LS2085a is based on arm64 architecture, however, currently, +layerscape PCIe driver based on pci-desginware.c is not +compatible with arm64 architecture. The patch changes code +to reuse PCIe Designware Base driver and provides LS2085a +PCIe support. + +Signed-off-by: Minghuan Lian +[Stuart: resolved minor merge conflict in probe] +Signed-off-by: Stuart Yoder +--- + drivers/pci/host/Kconfig | 4 +- + drivers/pci/host/pci-layerscape.c | 186 +++++++++++++++++++------------- + drivers/pci/host/pcie-designware-base.h | 3 + + 3 files changed, 114 insertions(+), 79 deletions(-) + +diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig +index 2a697c0..e59783a 100644 +--- a/drivers/pci/host/Kconfig ++++ b/drivers/pci/host/Kconfig +@@ -99,8 +99,8 @@ config PCI_XGENE + + config PCI_LAYERSCAPE + bool "Freescale Layerscape PCIe controller" +- depends on OF && ARM +- select PCIE_DW ++ depends on OF && (ARM || ARM64) ++ select PCIE_DW_BASE + select MFD_SYSCON + help + Say Y here if you want PCIe controller support on Layerscape SoCs. +diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c +index 4a6e62f..e866563 100644 +--- a/drivers/pci/host/pci-layerscape.c ++++ b/drivers/pci/host/pci-layerscape.c +@@ -1,7 +1,7 @@ + /* + * PCIe host controller driver for Freescale Layerscape SoCs + * +- * Copyright (C) 2014 Freescale Semiconductor. ++ * Copyright (C) 2014 - 2015 Freescale Semiconductor. + * + * Author: Minghuan Lian + * +@@ -11,20 +11,16 @@ + */ + + #include +-#include +-#include ++#include + #include + #include + #include +-#include +-#include + #include + #include +-#include +-#include + #include ++#include + +-#include "pcie-designware.h" ++#include "pcie-designware-base.h" + + /* PEX1/2 Misc Ports Status Register */ + #define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4) +@@ -32,26 +28,29 @@ + #define LTSSM_STATE_MASK 0x3f + #define LTSSM_PCIE_L0 0x11 /* L0 state */ + +-/* Symbol Timer Register and Filter Mask Register 1 */ +-#define PCIE_STRFMR1 0x71c ++/* PEX LUT registers */ ++#define PCIE_LUT_BASE 0x80000 ++#define PCIE_LUT_DBG 0x7FC /* PEX LUT Debug register */ ++ ++#define PCIE_ATU_NUM 6 + + struct ls_pcie { +- struct list_head node; +- struct device *dev; +- struct pci_bus *bus; +- void __iomem *dbi; +- struct regmap *scfg; +- struct pcie_port pp; +- int index; +- int msi_irq; ++ struct dw_pcie_port pp; ++ void __iomem *regs; ++ void __iomem *lut; ++ struct regmap *scfg; ++ int index; + }; + + #define to_ls_pcie(x) container_of(x, struct ls_pcie, pp) + +-static int ls_pcie_link_up(struct pcie_port *pp) ++static int ls1_pcie_link_up(struct dw_pcie_port *pp) + { +- u32 state; + struct ls_pcie *pcie = to_ls_pcie(pp); ++ u32 state; ++ ++ if (!pcie->scfg) ++ return 0; + + regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), &state); + state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK; +@@ -62,91 +61,130 @@ static int ls_pcie_link_up(struct pcie_port *pp) + return 1; + } + +-static void ls_pcie_host_init(struct pcie_port *pp) ++static int ls1_pcie_host_init(struct dw_pcie_port *pp) + { + struct ls_pcie *pcie = to_ls_pcie(pp); +- int count = 0; +- u32 val; +- +- dw_pcie_setup_rc(pp); ++ u32 val, index[2]; ++ int ret; + +- while (!ls_pcie_link_up(pp)) { +- usleep_range(100, 1000); +- count++; +- if (count >= 200) { +- dev_err(pp->dev, "phy link never came up\n"); +- return; +- } ++ pcie->scfg = syscon_regmap_lookup_by_phandle(pp->dev->of_node, ++ "fsl,pcie-scfg"); ++ if (IS_ERR(pcie->scfg)) { ++ dev_err(pp->dev, "No syscfg phandle specified\n"); ++ return PTR_ERR(pcie->scfg); + } + ++ ret = of_property_read_u32_array(pp->dev->of_node, ++ "fsl,pcie-scfg", index, 2); ++ if (ret) ++ return ret; ++ ++ pcie->index = index[1]; ++ + /* + * LS1021A Workaround for internal TKT228622 + * to fix the INTx hang issue + */ +- val = ioread32(pcie->dbi + PCIE_STRFMR1); ++ val = dw_pcie_dbi_read(pp, PCIE_SYMBOL_TIMER_1); + val &= 0xffff; +- iowrite32(val, pcie->dbi + PCIE_STRFMR1); ++ dw_pcie_dbi_write(pp, val, PCIE_SYMBOL_TIMER_1); ++ ++ /* Fix class value */ ++ val = dw_pcie_dbi_read(pp, PCI_CLASS_REVISION); ++ val = (val & 0x0000ffff) | (PCI_CLASS_BRIDGE_PCI << 16); ++ dw_pcie_dbi_write(pp, val, PCI_CLASS_REVISION); ++ ++ if (!ls1_pcie_link_up(pp)) ++ dev_err(pp->dev, "phy link never came up\n"); ++ ++ return 0; + } + +-static struct pcie_host_ops ls_pcie_host_ops = { +- .link_up = ls_pcie_link_up, +- .host_init = ls_pcie_host_init, ++static struct dw_host_ops ls1_dw_host_ops = { ++ .link_up = ls1_pcie_link_up, ++ .host_init = ls1_pcie_host_init, + }; + +-static int ls_add_pcie_port(struct ls_pcie *pcie) ++static int ls2_pcie_link_up(struct dw_pcie_port *pp) + { +- struct pcie_port *pp; +- int ret; ++ struct ls_pcie *pcie = to_ls_pcie(pp); ++ u32 state; + +- pp = &pcie->pp; +- pp->dev = pcie->dev; +- pp->dbi_base = pcie->dbi; +- pp->root_bus_nr = -1; +- pp->ops = &ls_pcie_host_ops; ++ if (!pcie->lut) ++ return 0; + +- ret = dw_pcie_host_init(pp); +- if (ret) { +- dev_err(pp->dev, "failed to initialize host\n"); +- return ret; +- } ++ state = ioread32(pcie->lut + PCIE_LUT_DBG) & LTSSM_STATE_MASK; ++ if (state < LTSSM_PCIE_L0) ++ return 0; ++ ++ return 1; ++} ++ ++static int ls2_pcie_host_init(struct dw_pcie_port *pp) ++{ ++ struct ls_pcie *pcie = to_ls_pcie(pp); ++ u32 val; ++ ++ pcie->lut = pp->dbi + PCIE_LUT_BASE; ++ ++ dw_pcie_dbi_write(pp, 1, PCIE_DBI_RO_WR_EN); ++ /* Fix class value */ ++ val = dw_pcie_dbi_read(pp, PCI_CLASS_REVISION); ++ val = (val & 0x0000ffff) | (PCI_CLASS_BRIDGE_PCI << 16); ++ dw_pcie_dbi_write(pp, val, PCI_CLASS_REVISION); ++ /* clean multi-func bit */ ++ val = dw_pcie_dbi_read(pp, PCI_HEADER_TYPE & ~0x3); ++ val &= ~(1 << 23); ++ dw_pcie_dbi_write(pp, val, PCI_HEADER_TYPE & ~0x3); ++ dw_pcie_dbi_write(pp, 0, PCIE_DBI_RO_WR_EN); ++ ++ if (!ls2_pcie_link_up(pp)) ++ dev_err(pp->dev, "phy link never came up\n"); + + return 0; + } + ++static struct dw_host_ops ls2_dw_host_ops = { ++ .link_up = ls2_pcie_link_up, ++ .host_init = ls2_pcie_host_init, ++}; ++ ++static const struct of_device_id ls_pcie_of_match[] = { ++ { .compatible = "fsl,ls1021a-pcie", .data = &ls1_dw_host_ops }, ++ { .compatible = "fsl,ls2085a-pcie", .data = &ls2_dw_host_ops }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, ls_pcie_of_match); ++ + static int __init ls_pcie_probe(struct platform_device *pdev) + { ++ const struct of_device_id *match; + struct ls_pcie *pcie; +- struct resource *dbi_base; +- u32 index[2]; ++ struct resource *res; + int ret; + ++ match = of_match_device(ls_pcie_of_match, &pdev->dev); ++ if (!match) ++ return -ENODEV; ++ + pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); + if (!pcie) + return -ENOMEM; + +- pcie->dev = &pdev->dev; +- +- dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); +- pcie->dbi = devm_ioremap_resource(&pdev->dev, dbi_base); +- if (IS_ERR(pcie->dbi)) { ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); ++ pcie->regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(pcie->regs)) { + dev_err(&pdev->dev, "missing *regs* space\n"); +- return PTR_ERR(pcie->dbi); +- } +- +- pcie->scfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, +- "fsl,pcie-scfg"); +- if (IS_ERR(pcie->scfg)) { +- dev_err(&pdev->dev, "No syscfg phandle specified\n"); +- return PTR_ERR(pcie->scfg); ++ return PTR_ERR(pcie->regs); + } + +- ret = of_property_read_u32_array(pdev->dev.of_node, +- "fsl,pcie-scfg", index, 2); +- if (ret) +- return ret; +- pcie->index = index[1]; ++ pcie->lut = pcie->regs + PCIE_LUT_BASE; ++ pcie->pp.dev = &pdev->dev; ++ pcie->pp.dbi = pcie->regs; ++ pcie->pp.dw_ops = (struct dw_host_ops *)match->data; ++ pcie->pp.atu_num = PCIE_ATU_NUM; + +- ret = ls_add_pcie_port(pcie); ++ ret = dw_pcie_port_init(&pcie->pp); + if (ret < 0) + return ret; + +@@ -155,12 +193,6 @@ static int __init ls_pcie_probe(struct platform_device *pdev) + return 0; + } + +-static const struct of_device_id ls_pcie_of_match[] = { +- { .compatible = "fsl,ls1021a-pcie" }, +- { }, +-}; +-MODULE_DEVICE_TABLE(of, ls_pcie_of_match); +- + static struct platform_driver ls_pcie_driver = { + .driver = { + .name = "layerscape-pcie", +diff --git a/drivers/pci/host/pcie-designware-base.h b/drivers/pci/host/pcie-designware-base.h +index 60c82de..98b62d6 100644 +--- a/drivers/pci/host/pcie-designware-base.h ++++ b/drivers/pci/host/pcie-designware-base.h +@@ -10,6 +10,9 @@ + #define _PCIE_DESIGNWARE_BASE_H + + /* Synopsis specific PCIE configuration registers */ ++#define PCIE_SYMBOL_TIMER_1 0x71c ++#define PCIE_DBI_RO_WR_EN 0x8bc ++ + #define PCIE_ATU_VIEWPORT 0x900 + #define PCIE_ATU_REGION_INBOUND (0x1 << 31) + #define PCIE_ATU_REGION_OUTBOUND (0x0 << 31) +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0121-pci-layerscape-PCIe-controller-stream-ID-partitionin.patch b/target/linux/layerscape-64b/patches-4.1/0121-pci-layerscape-PCIe-controller-stream-ID-partitionin.patch new file mode 100644 index 0000000..53e9391 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0121-pci-layerscape-PCIe-controller-stream-ID-partitionin.patch @@ -0,0 +1,155 @@ +From f70aab6da8ebf01a3a35f7dbcbf242897fc58fda Mon Sep 17 00:00:00 2001 +From: Varun Sethi +Date: Thu, 18 Jun 2015 17:20:43 +0530 +Subject: [PATCH 121/151] pci/layerscape: PCIe controller stream ID + partitioning patch. + +U-boot sets up the device Id to stream ID translation table. The SMMU +driver while creating the IOMMU group programs the hardware table with +these values. + +Signed-off-by: Varun Sethi +[Stuart: split the pci part from the smmu driver part] +Signed-off-by: Stuart Yoder + +Signed-off-by: Stuart Yoder +--- + drivers/pci/host/pci-layerscape.c | 52 ++++++++++++++++++++++++++++++--------- + drivers/pci/host/pci-layerscape.h | 32 ++++++++++++++++++++++++ + 2 files changed, 72 insertions(+), 12 deletions(-) + create mode 100644 drivers/pci/host/pci-layerscape.h + +diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c +index e866563..ece1337 100644 +--- a/drivers/pci/host/pci-layerscape.c ++++ b/drivers/pci/host/pci-layerscape.c +@@ -21,18 +21,7 @@ + #include + + #include "pcie-designware-base.h" +- +-/* PEX1/2 Misc Ports Status Register */ +-#define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4) +-#define LTSSM_STATE_SHIFT 20 +-#define LTSSM_STATE_MASK 0x3f +-#define LTSSM_PCIE_L0 0x11 /* L0 state */ +- +-/* PEX LUT registers */ +-#define PCIE_LUT_BASE 0x80000 +-#define PCIE_LUT_DBG 0x7FC /* PEX LUT Debug register */ +- +-#define PCIE_ATU_NUM 6 ++#include "pci-layerscape.h" + + struct ls_pcie { + struct dw_pcie_port pp; +@@ -40,10 +29,31 @@ struct ls_pcie { + void __iomem *lut; + struct regmap *scfg; + int index; ++ const u32 *avail_streamids; ++ int streamid_index; + }; + ++ + #define to_ls_pcie(x) container_of(x, struct ls_pcie, pp) + ++u32 set_pcie_streamid_translation(struct pci_dev *pdev, u32 devid) ++{ ++ u32 index, streamid; ++ struct dw_pcie_port *pp = pdev->bus->sysdata; ++ struct ls_pcie *pcie = to_ls_pcie(pp); ++ ++ if (!pcie->avail_streamids || !pcie->streamid_index) ++ return ~(u32)0; ++ ++ index = --pcie->streamid_index; ++ /* mask is set as all zeroes, want to match all bits */ ++ iowrite32((devid << 16), pcie->lut + PCIE_LUT_UDR(index)); ++ streamid = be32_to_cpup(&pcie->avail_streamids[index]); ++ iowrite32(streamid | PCIE_LUT_ENABLE, pcie->lut + PCIE_LUT_LDR(index)); ++ ++ return streamid; ++} ++ + static int ls1_pcie_link_up(struct dw_pcie_port *pp) + { + struct ls_pcie *pcie = to_ls_pcie(pp); +@@ -126,6 +136,8 @@ static int ls2_pcie_host_init(struct dw_pcie_port *pp) + u32 val; + + pcie->lut = pp->dbi + PCIE_LUT_BASE; ++ /* Disable LDR zero */ ++ iowrite32(0, pcie->lut + PCIE_LUT_LDR(0)); + + dw_pcie_dbi_write(pp, 1, PCIE_DBI_RO_WR_EN); + /* Fix class value */ +@@ -179,11 +191,27 @@ static int __init ls_pcie_probe(struct platform_device *pdev) + } + + pcie->lut = pcie->regs + PCIE_LUT_BASE; ++ /* Disable LDR zero */ ++ iowrite32(0, pcie->lut + PCIE_LUT_LDR(0)); + pcie->pp.dev = &pdev->dev; + pcie->pp.dbi = pcie->regs; + pcie->pp.dw_ops = (struct dw_host_ops *)match->data; + pcie->pp.atu_num = PCIE_ATU_NUM; + ++ if (of_device_is_compatible(pdev->dev.of_node, "fsl,ls2085a-pcie")) { ++ int len; ++ const u32 *prop; ++ struct device_node *np; ++ ++ np = pdev->dev.of_node; ++ prop = (u32 *)of_get_property(np, "available-stream-ids", &len); ++ if (prop) { ++ pcie->avail_streamids = prop; ++ pcie->streamid_index = len/sizeof(u32); ++ } else ++ dev_err(&pdev->dev, "PCIe endpoint partitioning not possible\n"); ++ } ++ + ret = dw_pcie_port_init(&pcie->pp); + if (ret < 0) + return ret; +diff --git a/drivers/pci/host/pci-layerscape.h b/drivers/pci/host/pci-layerscape.h +new file mode 100644 +index 0000000..8c0642a +--- /dev/null ++++ b/drivers/pci/host/pci-layerscape.h +@@ -0,0 +1,32 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef _PCI_LAYERSCAPE_H ++#define _PCI_LAYERSCAPE_H ++ ++/* PEX1/2 Misc Ports Status Register */ ++#define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4) ++#define LTSSM_STATE_SHIFT 20 ++#define LTSSM_STATE_MASK 0x3f ++#define LTSSM_PCIE_L0 0x11 /* L0 state */ ++ ++/* PEX LUT registers */ ++#define PCIE_LUT_BASE 0x80000 ++#define PCIE_LUT_PEXLSR 0x020 /* PEX LUT Status Register */ ++#define PCIE_LUT_PEXLCR 0x024 /* PEX LUT Control Register */ ++#define PCIE_LUT_DBG 0x7FC /* PEX LUT Debug register */ ++#define PCIE_LUT_UDR(n) (0x800 + (n) * 8) ++#define PCIE_LUT_LDR(n) (0x804 + (n) * 8) ++#define PCIE_LUT_MASK_ALL 0xffff ++#define PCIE_LUT_DR_NUM 32 ++#define PCIE_LUT_ENABLE (1 << 31) ++ ++/* function for setting up stream id to device id translation */ ++u32 set_pcie_streamid_translation(struct pci_dev *pdev, u32 devid); ++ ++#define PCIE_ATU_NUM 6 ++ ++#endif /* _PCI_LAYERSCAPE_H */ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0122-pci-layerscape-Add-compatible-string-for-LS2080.patch b/target/linux/layerscape-64b/patches-4.1/0122-pci-layerscape-Add-compatible-string-for-LS2080.patch new file mode 100644 index 0000000..2c0d7bf --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0122-pci-layerscape-Add-compatible-string-for-LS2080.patch @@ -0,0 +1,25 @@ +From 46139be0c7465a7c3eec053a0a0dc761d0d9c1a6 Mon Sep 17 00:00:00 2001 +From: Rai Harninder-B01044 +Date: Tue, 27 Oct 2015 17:19:11 +0530 +Subject: [PATCH 122/151] pci/layerscape: Add compatible string for LS2080 + +Signed-off-by: Rai Harninder-B01044 +--- + drivers/pci/host/pci-layerscape.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c +index ece1337..262b32e 100644 +--- a/drivers/pci/host/pci-layerscape.c ++++ b/drivers/pci/host/pci-layerscape.c +@@ -164,6 +164,7 @@ static struct dw_host_ops ls2_dw_host_ops = { + static const struct of_device_id ls_pcie_of_match[] = { + { .compatible = "fsl,ls1021a-pcie", .data = &ls1_dw_host_ops }, + { .compatible = "fsl,ls2085a-pcie", .data = &ls2_dw_host_ops }, ++ { .compatible = "fsl,ls2080a-pcie", .data = &ls2_dw_host_ops }, + { }, + }; + MODULE_DEVICE_TABLE(of, ls_pcie_of_match); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0123-pci-layerscape-Add-compatible-in-probe-function-for-.patch b/target/linux/layerscape-64b/patches-4.1/0123-pci-layerscape-Add-compatible-in-probe-function-for-.patch new file mode 100644 index 0000000..5952ce5 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0123-pci-layerscape-Add-compatible-in-probe-function-for-.patch @@ -0,0 +1,28 @@ +From 5718affa661fb0d1431a0119d684118e8d91d2d4 Mon Sep 17 00:00:00 2001 +From: Rai Harninder-B01044 +Date: Tue, 3 Nov 2015 12:44:21 +0530 +Subject: [PATCH 123/151] pci/layerscape: Add compatible in probe function for + LS2080A + +Signed-off-by: Rai Harninder-B01044 +--- + drivers/pci/host/pci-layerscape.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c +index 262b32e..f25c25b 100644 +--- a/drivers/pci/host/pci-layerscape.c ++++ b/drivers/pci/host/pci-layerscape.c +@@ -199,7 +199,8 @@ static int __init ls_pcie_probe(struct platform_device *pdev) + pcie->pp.dw_ops = (struct dw_host_ops *)match->data; + pcie->pp.atu_num = PCIE_ATU_NUM; + +- if (of_device_is_compatible(pdev->dev.of_node, "fsl,ls2085a-pcie")) { ++ if (of_device_is_compatible(pdev->dev.of_node, "fsl,ls2085a-pcie") || ++ of_device_is_compatible(pdev->dev.of_node, "fsl,ls2080a-pcie")) { + int len; + const u32 *prop; + struct device_node *np; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0124-pci-layerscape-Add-PCIe-RC-EP-mode-checking.patch b/target/linux/layerscape-64b/patches-4.1/0124-pci-layerscape-Add-PCIe-RC-EP-mode-checking.patch new file mode 100644 index 0000000..f583a0c --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0124-pci-layerscape-Add-PCIe-RC-EP-mode-checking.patch @@ -0,0 +1,48 @@ +From 5c99bd17df9d49a7ac92b3a47a1a97eb28b9ef60 Mon Sep 17 00:00:00 2001 +From: Minghuan Lian +Date: Tue, 17 Nov 2015 17:07:50 +0800 +Subject: [PATCH 124/151] pci/layerscape: Add PCIe RC/EP mode checking + +The patch will check PCIe controller work mode, if it is in +EP mode, directly return "-ENODEV". This allows the EP driver +to probe it again. + +Signed-off-by: Minghuan Lian +--- + drivers/pci/host/pci-layerscape.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c +index f25c25b..87997a1 100644 +--- a/drivers/pci/host/pci-layerscape.c ++++ b/drivers/pci/host/pci-layerscape.c +@@ -54,6 +54,16 @@ u32 set_pcie_streamid_translation(struct pci_dev *pdev, u32 devid) + return streamid; + } + ++static bool ls_pcie_is_bridge(struct ls_pcie *pcie) ++{ ++ u32 header_type; ++ ++ header_type = ioread32(pcie->regs + (PCI_HEADER_TYPE & ~0x3)); ++ header_type = (header_type >> (8 * (PCI_HEADER_TYPE & 0x3))) & 0x7f; ++ ++ return header_type == PCI_HEADER_TYPE_BRIDGE; ++} ++ + static int ls1_pcie_link_up(struct dw_pcie_port *pp) + { + struct ls_pcie *pcie = to_ls_pcie(pp); +@@ -214,6 +224,9 @@ static int __init ls_pcie_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "PCIe endpoint partitioning not possible\n"); + } + ++ if (!ls_pcie_is_bridge(pcie)) ++ return -ENODEV; ++ + ret = dw_pcie_port_init(&pcie->pp); + if (ret < 0) + return ret; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0125-PCI-layerscape-backport-from-4.4-rc1.patch b/target/linux/layerscape-64b/patches-4.1/0125-PCI-layerscape-backport-from-4.4-rc1.patch new file mode 100644 index 0000000..38e3f03 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0125-PCI-layerscape-backport-from-4.4-rc1.patch @@ -0,0 +1,387 @@ +From 84e8400c97219b44b82eae9b18efca227d15f48a Mon Sep 17 00:00:00 2001 +From: Mingkai Hu +Date: Fri, 22 Jan 2016 13:44:48 +0800 +Subject: [PATCH 125/151] PCI: layerscape: backport from 4.4-rc1 + +Signed-off-by: Mingkai Hu +--- + drivers/pci/host/pci-layerscape.c | 263 +++++++++++++++++++++----------------- + 1 file changed, 145 insertions(+), 118 deletions(-) + +diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c +index 87997a1..3923bed 100644 +--- a/drivers/pci/host/pci-layerscape.c ++++ b/drivers/pci/host/pci-layerscape.c +@@ -1,9 +1,9 @@ + /* + * PCIe host controller driver for Freescale Layerscape SoCs + * +- * Copyright (C) 2014 - 2015 Freescale Semiconductor. ++ * Copyright (C) 2014 Freescale Semiconductor. + * +- * Author: Minghuan Lian ++ * Author: Minghuan Lian + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as +@@ -11,63 +11,76 @@ + */ + + #include +-#include ++#include + #include + #include + #include ++#include ++#include + #include + #include +-#include + #include ++#include ++#include + +-#include "pcie-designware-base.h" +-#include "pci-layerscape.h" +- +-struct ls_pcie { +- struct dw_pcie_port pp; +- void __iomem *regs; +- void __iomem *lut; +- struct regmap *scfg; +- int index; +- const u32 *avail_streamids; +- int streamid_index; +-}; ++#include "pcie-designware.h" + ++/* PEX1/2 Misc Ports Status Register */ ++#define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4) ++#define LTSSM_STATE_SHIFT 20 ++#define LTSSM_STATE_MASK 0x3f ++#define LTSSM_PCIE_L0 0x11 /* L0 state */ + +-#define to_ls_pcie(x) container_of(x, struct ls_pcie, pp) ++/* PEX Internal Configuration Registers */ ++#define PCIE_STRFMR1 0x71c /* Symbol Timer & Filter Mask Register1 */ ++#define PCIE_DBI_RO_WR_EN 0x8bc /* DBI Read-Only Write Enable Register */ + +-u32 set_pcie_streamid_translation(struct pci_dev *pdev, u32 devid) +-{ +- u32 index, streamid; +- struct dw_pcie_port *pp = pdev->bus->sysdata; +- struct ls_pcie *pcie = to_ls_pcie(pp); ++/* PEX LUT registers */ ++#define PCIE_LUT_DBG 0x7FC /* PEX LUT Debug Register */ + +- if (!pcie->avail_streamids || !pcie->streamid_index) +- return ~(u32)0; ++struct ls_pcie_drvdata { ++ u32 lut_offset; ++ u32 ltssm_shift; ++ struct pcie_host_ops *ops; ++}; + +- index = --pcie->streamid_index; +- /* mask is set as all zeroes, want to match all bits */ +- iowrite32((devid << 16), pcie->lut + PCIE_LUT_UDR(index)); +- streamid = be32_to_cpup(&pcie->avail_streamids[index]); +- iowrite32(streamid | PCIE_LUT_ENABLE, pcie->lut + PCIE_LUT_LDR(index)); ++struct ls_pcie { ++ void __iomem *dbi; ++ void __iomem *lut; ++ struct regmap *scfg; ++ struct pcie_port pp; ++ const struct ls_pcie_drvdata *drvdata; ++ int index; ++}; + +- return streamid; +-} ++#define to_ls_pcie(x) container_of(x, struct ls_pcie, pp) + + static bool ls_pcie_is_bridge(struct ls_pcie *pcie) + { + u32 header_type; + +- header_type = ioread32(pcie->regs + (PCI_HEADER_TYPE & ~0x3)); +- header_type = (header_type >> (8 * (PCI_HEADER_TYPE & 0x3))) & 0x7f; ++ header_type = ioread8(pcie->dbi + PCI_HEADER_TYPE); ++ header_type &= 0x7f; + + return header_type == PCI_HEADER_TYPE_BRIDGE; + } + +-static int ls1_pcie_link_up(struct dw_pcie_port *pp) ++/* Clear multi-function bit */ ++static void ls_pcie_clear_multifunction(struct ls_pcie *pcie) ++{ ++ iowrite8(PCI_HEADER_TYPE_BRIDGE, pcie->dbi + PCI_HEADER_TYPE); ++} ++ ++/* Fix class value */ ++static void ls_pcie_fix_class(struct ls_pcie *pcie) ++{ ++ iowrite16(PCI_CLASS_BRIDGE_PCI, pcie->dbi + PCI_CLASS_DEVICE); ++} ++ ++static int ls1021_pcie_link_up(struct pcie_port *pp) + { +- struct ls_pcie *pcie = to_ls_pcie(pp); + u32 state; ++ struct ls_pcie *pcie = to_ls_pcie(pp); + + if (!pcie->scfg) + return 0; +@@ -81,109 +94,143 @@ static int ls1_pcie_link_up(struct dw_pcie_port *pp) + return 1; + } + +-static int ls1_pcie_host_init(struct dw_pcie_port *pp) ++static void ls1021_pcie_host_init(struct pcie_port *pp) + { + struct ls_pcie *pcie = to_ls_pcie(pp); + u32 val, index[2]; +- int ret; + + pcie->scfg = syscon_regmap_lookup_by_phandle(pp->dev->of_node, + "fsl,pcie-scfg"); + if (IS_ERR(pcie->scfg)) { + dev_err(pp->dev, "No syscfg phandle specified\n"); +- return PTR_ERR(pcie->scfg); ++ pcie->scfg = NULL; ++ return; + } + +- ret = of_property_read_u32_array(pp->dev->of_node, +- "fsl,pcie-scfg", index, 2); +- if (ret) +- return ret; +- ++ if (of_property_read_u32_array(pp->dev->of_node, ++ "fsl,pcie-scfg", index, 2)) { ++ pcie->scfg = NULL; ++ return; ++ } + pcie->index = index[1]; + ++ dw_pcie_setup_rc(pp); ++ + /* + * LS1021A Workaround for internal TKT228622 + * to fix the INTx hang issue + */ +- val = dw_pcie_dbi_read(pp, PCIE_SYMBOL_TIMER_1); ++ val = ioread32(pcie->dbi + PCIE_STRFMR1); + val &= 0xffff; +- dw_pcie_dbi_write(pp, val, PCIE_SYMBOL_TIMER_1); +- +- /* Fix class value */ +- val = dw_pcie_dbi_read(pp, PCI_CLASS_REVISION); +- val = (val & 0x0000ffff) | (PCI_CLASS_BRIDGE_PCI << 16); +- dw_pcie_dbi_write(pp, val, PCI_CLASS_REVISION); +- +- if (!ls1_pcie_link_up(pp)) +- dev_err(pp->dev, "phy link never came up\n"); +- +- return 0; ++ iowrite32(val, pcie->dbi + PCIE_STRFMR1); + } + +-static struct dw_host_ops ls1_dw_host_ops = { +- .link_up = ls1_pcie_link_up, +- .host_init = ls1_pcie_host_init, +-}; +- +-static int ls2_pcie_link_up(struct dw_pcie_port *pp) ++static int ls_pcie_link_up(struct pcie_port *pp) + { + struct ls_pcie *pcie = to_ls_pcie(pp); + u32 state; + +- if (!pcie->lut) +- return 0; ++ state = (ioread32(pcie->lut + PCIE_LUT_DBG) >> ++ pcie->drvdata->ltssm_shift) & ++ LTSSM_STATE_MASK; + +- state = ioread32(pcie->lut + PCIE_LUT_DBG) & LTSSM_STATE_MASK; + if (state < LTSSM_PCIE_L0) + return 0; + + return 1; + } + +-static int ls2_pcie_host_init(struct dw_pcie_port *pp) ++static void ls_pcie_host_init(struct pcie_port *pp) + { + struct ls_pcie *pcie = to_ls_pcie(pp); +- u32 val; +- +- pcie->lut = pp->dbi + PCIE_LUT_BASE; +- /* Disable LDR zero */ +- iowrite32(0, pcie->lut + PCIE_LUT_LDR(0)); +- +- dw_pcie_dbi_write(pp, 1, PCIE_DBI_RO_WR_EN); +- /* Fix class value */ +- val = dw_pcie_dbi_read(pp, PCI_CLASS_REVISION); +- val = (val & 0x0000ffff) | (PCI_CLASS_BRIDGE_PCI << 16); +- dw_pcie_dbi_write(pp, val, PCI_CLASS_REVISION); +- /* clean multi-func bit */ +- val = dw_pcie_dbi_read(pp, PCI_HEADER_TYPE & ~0x3); +- val &= ~(1 << 23); +- dw_pcie_dbi_write(pp, val, PCI_HEADER_TYPE & ~0x3); +- dw_pcie_dbi_write(pp, 0, PCIE_DBI_RO_WR_EN); +- +- if (!ls2_pcie_link_up(pp)) +- dev_err(pp->dev, "phy link never came up\n"); ++ ++ iowrite32(1, pcie->dbi + PCIE_DBI_RO_WR_EN); ++ ls_pcie_fix_class(pcie); ++ ls_pcie_clear_multifunction(pcie); ++ iowrite32(0, pcie->dbi + PCIE_DBI_RO_WR_EN); ++} ++ ++static int ls_pcie_msi_host_init(struct pcie_port *pp, ++ struct msi_controller *chip) ++{ ++ struct device_node *msi_node; ++ struct device_node *np = pp->dev->of_node; ++ ++ /* ++ * The MSI domain is set by the generic of_msi_configure(). This ++ * .msi_host_init() function keeps us from doing the default MSI ++ * domain setup in dw_pcie_host_init() and also enforces the ++ * requirement that "msi-parent" exists. ++ */ ++ msi_node = of_parse_phandle(np, "msi-parent", 0); ++ if (!msi_node) { ++ dev_err(pp->dev, "failed to find msi-parent\n"); ++ return -EINVAL; ++ } + + return 0; + } + +-static struct dw_host_ops ls2_dw_host_ops = { +- .link_up = ls2_pcie_link_up, +- .host_init = ls2_pcie_host_init, ++static struct pcie_host_ops ls1021_pcie_host_ops = { ++ .link_up = ls1021_pcie_link_up, ++ .host_init = ls1021_pcie_host_init, ++ .msi_host_init = ls_pcie_msi_host_init, ++}; ++ ++static struct pcie_host_ops ls_pcie_host_ops = { ++ .link_up = ls_pcie_link_up, ++ .host_init = ls_pcie_host_init, ++ .msi_host_init = ls_pcie_msi_host_init, ++}; ++ ++static struct ls_pcie_drvdata ls1021_drvdata = { ++ .ops = &ls1021_pcie_host_ops, ++}; ++ ++static struct ls_pcie_drvdata ls1043_drvdata = { ++ .lut_offset = 0x10000, ++ .ltssm_shift = 24, ++ .ops = &ls_pcie_host_ops, ++}; ++ ++static struct ls_pcie_drvdata ls2080_drvdata = { ++ .lut_offset = 0x80000, ++ .ltssm_shift = 0, ++ .ops = &ls_pcie_host_ops, + }; + + static const struct of_device_id ls_pcie_of_match[] = { +- { .compatible = "fsl,ls1021a-pcie", .data = &ls1_dw_host_ops }, +- { .compatible = "fsl,ls2085a-pcie", .data = &ls2_dw_host_ops }, +- { .compatible = "fsl,ls2080a-pcie", .data = &ls2_dw_host_ops }, ++ { .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata }, ++ { .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata }, ++ { .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata }, + { }, + }; + MODULE_DEVICE_TABLE(of, ls_pcie_of_match); + ++static int __init ls_add_pcie_port(struct pcie_port *pp, ++ struct platform_device *pdev) ++{ ++ int ret; ++ struct ls_pcie *pcie = to_ls_pcie(pp); ++ ++ pp->dev = &pdev->dev; ++ pp->dbi_base = pcie->dbi; ++ pp->ops = pcie->drvdata->ops; ++ ++ ret = dw_pcie_host_init(pp); ++ if (ret) { ++ dev_err(pp->dev, "failed to initialize host\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ + static int __init ls_pcie_probe(struct platform_device *pdev) + { + const struct of_device_id *match; + struct ls_pcie *pcie; +- struct resource *res; ++ struct resource *dbi_base; + int ret; + + match = of_match_device(ls_pcie_of_match, &pdev->dev); +@@ -194,40 +241,20 @@ static int __init ls_pcie_probe(struct platform_device *pdev) + if (!pcie) + return -ENOMEM; + +- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); +- pcie->regs = devm_ioremap_resource(&pdev->dev, res); +- if (IS_ERR(pcie->regs)) { ++ dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); ++ pcie->dbi = devm_ioremap_resource(&pdev->dev, dbi_base); ++ if (IS_ERR(pcie->dbi)) { + dev_err(&pdev->dev, "missing *regs* space\n"); +- return PTR_ERR(pcie->regs); ++ return PTR_ERR(pcie->dbi); + } + +- pcie->lut = pcie->regs + PCIE_LUT_BASE; +- /* Disable LDR zero */ +- iowrite32(0, pcie->lut + PCIE_LUT_LDR(0)); +- pcie->pp.dev = &pdev->dev; +- pcie->pp.dbi = pcie->regs; +- pcie->pp.dw_ops = (struct dw_host_ops *)match->data; +- pcie->pp.atu_num = PCIE_ATU_NUM; +- +- if (of_device_is_compatible(pdev->dev.of_node, "fsl,ls2085a-pcie") || +- of_device_is_compatible(pdev->dev.of_node, "fsl,ls2080a-pcie")) { +- int len; +- const u32 *prop; +- struct device_node *np; +- +- np = pdev->dev.of_node; +- prop = (u32 *)of_get_property(np, "available-stream-ids", &len); +- if (prop) { +- pcie->avail_streamids = prop; +- pcie->streamid_index = len/sizeof(u32); +- } else +- dev_err(&pdev->dev, "PCIe endpoint partitioning not possible\n"); +- } ++ pcie->drvdata = match->data; ++ pcie->lut = pcie->dbi + pcie->drvdata->lut_offset; + + if (!ls_pcie_is_bridge(pcie)) + return -ENODEV; + +- ret = dw_pcie_port_init(&pcie->pp); ++ ret = ls_add_pcie_port(&pcie->pp, pdev); + if (ret < 0) + return ret; + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0126-pci-layerscape-PCIe-controller-stream-ID-partitionin.patch b/target/linux/layerscape-64b/patches-4.1/0126-pci-layerscape-PCIe-controller-stream-ID-partitionin.patch new file mode 100644 index 0000000..3a635a8 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0126-pci-layerscape-PCIe-controller-stream-ID-partitionin.patch @@ -0,0 +1,127 @@ +From 19960f6ed0995025dd970c77a8ec8c63838e97e0 Mon Sep 17 00:00:00 2001 +From: Varun Sethi +Date: Fri, 22 Jan 2016 16:03:51 +0800 +Subject: [PATCH 126/151] pci/layerscape: PCIe controller stream ID + partitioning patch + +U-boot sets up the device Id to stream ID translation table. The SMMU +driver while creating the IOMMU group programs the hardware table with +these values. + +Signed-off-by: Varun Sethi +Signed-off-by: Stuart Yoder +Signed-off-by: Mingkai Hu +--- + drivers/pci/host/pci-layerscape.c | 42 +++++++++++++++++++++++++++++++++++++++ + drivers/pci/host/pci-layerscape.h | 19 ------------------ + 2 files changed, 42 insertions(+), 19 deletions(-) + +diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c +index 3923bed..122e224 100644 +--- a/drivers/pci/host/pci-layerscape.c ++++ b/drivers/pci/host/pci-layerscape.c +@@ -37,6 +37,11 @@ + + /* PEX LUT registers */ + #define PCIE_LUT_DBG 0x7FC /* PEX LUT Debug Register */ ++#define PCIE_LUT_UDR(n) (0x800 + (n) * 8) ++#define PCIE_LUT_LDR(n) (0x804 + (n) * 8) ++#define PCIE_LUT_MASK_ALL 0xffff ++#define PCIE_LUT_DR_NUM 32 ++#define PCIE_LUT_ENABLE (1 << 31) + + struct ls_pcie_drvdata { + u32 lut_offset; +@@ -51,10 +56,30 @@ struct ls_pcie { + struct pcie_port pp; + const struct ls_pcie_drvdata *drvdata; + int index; ++ const u32 *avail_streamids; ++ int streamid_index; + }; + + #define to_ls_pcie(x) container_of(x, struct ls_pcie, pp) + ++u32 set_pcie_streamid_translation(struct pci_dev *pdev, u32 devid) ++{ ++ u32 index, streamid; ++ struct pcie_port *pp = pdev->bus->sysdata; ++ struct ls_pcie *pcie = to_ls_pcie(pp); ++ ++ if (!pcie->avail_streamids || !pcie->streamid_index) ++ return ~(u32)0; ++ ++ index = --pcie->streamid_index; ++ /* mask is set as all zeroes, want to match all bits */ ++ iowrite32((devid << 16), pcie->lut + PCIE_LUT_UDR(index)); ++ streamid = be32_to_cpup(&pcie->avail_streamids[index]); ++ iowrite32(streamid | PCIE_LUT_ENABLE, pcie->lut + PCIE_LUT_LDR(index)); ++ ++ return streamid; ++} ++ + static bool ls_pcie_is_bridge(struct ls_pcie *pcie) + { + u32 header_type; +@@ -250,10 +275,27 @@ static int __init ls_pcie_probe(struct platform_device *pdev) + + pcie->drvdata = match->data; + pcie->lut = pcie->dbi + pcie->drvdata->lut_offset; ++ /* Disable LDR zero */ ++ iowrite32(0, pcie->lut + PCIE_LUT_LDR(0)); + + if (!ls_pcie_is_bridge(pcie)) + return -ENODEV; + ++ if (of_device_is_compatible(pdev->dev.of_node, "fsl,ls2085a-pcie") || ++ of_device_is_compatible(pdev->dev.of_node, "fsl,ls2080a-pcie")) { ++ int len; ++ const u32 *prop; ++ struct device_node *np; ++ ++ np = pdev->dev.of_node; ++ prop = (u32 *)of_get_property(np, "available-stream-ids", &len); ++ if (prop) { ++ pcie->avail_streamids = prop; ++ pcie->streamid_index = len/sizeof(u32); ++ } else ++ dev_err(&pdev->dev, "PCIe endpoint partitioning not possible\n"); ++ } ++ + ret = ls_add_pcie_port(&pcie->pp, pdev); + if (ret < 0) + return ret; +diff --git a/drivers/pci/host/pci-layerscape.h b/drivers/pci/host/pci-layerscape.h +index 8c0642a..e90e114 100644 +--- a/drivers/pci/host/pci-layerscape.h ++++ b/drivers/pci/host/pci-layerscape.h +@@ -7,26 +7,7 @@ + #ifndef _PCI_LAYERSCAPE_H + #define _PCI_LAYERSCAPE_H + +-/* PEX1/2 Misc Ports Status Register */ +-#define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4) +-#define LTSSM_STATE_SHIFT 20 +-#define LTSSM_STATE_MASK 0x3f +-#define LTSSM_PCIE_L0 0x11 /* L0 state */ +- +-/* PEX LUT registers */ +-#define PCIE_LUT_BASE 0x80000 +-#define PCIE_LUT_PEXLSR 0x020 /* PEX LUT Status Register */ +-#define PCIE_LUT_PEXLCR 0x024 /* PEX LUT Control Register */ +-#define PCIE_LUT_DBG 0x7FC /* PEX LUT Debug register */ +-#define PCIE_LUT_UDR(n) (0x800 + (n) * 8) +-#define PCIE_LUT_LDR(n) (0x804 + (n) * 8) +-#define PCIE_LUT_MASK_ALL 0xffff +-#define PCIE_LUT_DR_NUM 32 +-#define PCIE_LUT_ENABLE (1 << 31) +- + /* function for setting up stream id to device id translation */ + u32 set_pcie_streamid_translation(struct pci_dev *pdev, u32 devid); + +-#define PCIE_ATU_NUM 6 +- + #endif /* _PCI_LAYERSCAPE_H */ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0127-pci-layerscape-fix-MSG-TLP-drop-setting.patch b/target/linux/layerscape-64b/patches-4.1/0127-pci-layerscape-fix-MSG-TLP-drop-setting.patch new file mode 100644 index 0000000..df2f776 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0127-pci-layerscape-fix-MSG-TLP-drop-setting.patch @@ -0,0 +1,71 @@ +From 9e68e8591058ac600b6bbaec5450c625c34d99f9 Mon Sep 17 00:00:00 2001 +From: Minghuan Lian +Date: Wed, 24 Feb 2016 11:14:24 +0800 +Subject: [PATCH 127/151] pci/layerscape: fix MSG TLP drop setting + +Some kinds of Layerscape PCIe controllers will forward the received +message TLPs to system application address space, which could corrupt +system memory or lead to a system hang. The patch enables the MSG_DROP +to fix this issue. + +Signed-off-by: Minghuan Lian +--- + drivers/pci/host/pci-layerscape.c | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c +index 122e224..20b0acb 100644 +--- a/drivers/pci/host/pci-layerscape.c ++++ b/drivers/pci/host/pci-layerscape.c +@@ -102,6 +102,16 @@ static void ls_pcie_fix_class(struct ls_pcie *pcie) + iowrite16(PCI_CLASS_BRIDGE_PCI, pcie->dbi + PCI_CLASS_DEVICE); + } + ++/* Drop MSG TLP except for Vendor MSG */ ++static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie) ++{ ++ u32 val; ++ ++ val = ioread32(pcie->dbi + PCIE_STRFMR1); ++ val &= 0xDFFFFFFF; ++ iowrite32(val, pcie->dbi + PCIE_STRFMR1); ++} ++ + static int ls1021_pcie_link_up(struct pcie_port *pp) + { + u32 state; +@@ -122,7 +132,7 @@ static int ls1021_pcie_link_up(struct pcie_port *pp) + static void ls1021_pcie_host_init(struct pcie_port *pp) + { + struct ls_pcie *pcie = to_ls_pcie(pp); +- u32 val, index[2]; ++ u32 index[2]; + + pcie->scfg = syscon_regmap_lookup_by_phandle(pp->dev->of_node, + "fsl,pcie-scfg"); +@@ -141,13 +151,7 @@ static void ls1021_pcie_host_init(struct pcie_port *pp) + + dw_pcie_setup_rc(pp); + +- /* +- * LS1021A Workaround for internal TKT228622 +- * to fix the INTx hang issue +- */ +- val = ioread32(pcie->dbi + PCIE_STRFMR1); +- val &= 0xffff; +- iowrite32(val, pcie->dbi + PCIE_STRFMR1); ++ ls_pcie_drop_msg_tlp(pcie); + } + + static int ls_pcie_link_up(struct pcie_port *pp) +@@ -172,6 +176,7 @@ static void ls_pcie_host_init(struct pcie_port *pp) + iowrite32(1, pcie->dbi + PCIE_DBI_RO_WR_EN); + ls_pcie_fix_class(pcie); + ls_pcie_clear_multifunction(pcie); ++ ls_pcie_drop_msg_tlp(pcie); + iowrite32(0, pcie->dbi + PCIE_DBI_RO_WR_EN); + } + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0128-pci-msi-fix-compile-issue-on-arm32.patch b/target/linux/layerscape-64b/patches-4.1/0128-pci-msi-fix-compile-issue-on-arm32.patch new file mode 100644 index 0000000..ae4063f --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0128-pci-msi-fix-compile-issue-on-arm32.patch @@ -0,0 +1,40 @@ +From cabfb82ca59539aa4eb0d2ceb120ad0375d3c16e Mon Sep 17 00:00:00 2001 +From: Stuart Yoder +Date: Fri, 22 Jan 2016 13:23:43 -0600 +Subject: [PATCH 128/151] pci/msi: fix compile issue on arm32 + +commit 52bcf2046acc5d7ea756654c57e8ae401397776a +moved msi_list from pdev to dev, which includes +a change the dev field in msi_desc. This patch +fixes a build break on arm32. + +Signed-off-by: Stuart Yoder +--- + drivers/pci/host/pcie-designware.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c +index 2e9f84f..ca72c21 100644 +--- a/drivers/pci/host/pcie-designware.c ++++ b/drivers/pci/host/pcie-designware.c +@@ -238,7 +238,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq) + static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) + { + int irq, pos0, i; +- struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata); ++ struct pcie_port *pp = sys_to_pcie(to_pci_dev(desc->dev)->bus->sysdata); + + pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS, + order_base_2(no_irqs)); +@@ -310,7 +310,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq) + { + struct irq_data *data = irq_get_irq_data(irq); + struct msi_desc *msi = irq_data_get_msi(data); +- struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata); ++ struct pcie_port *pp = sys_to_pcie(to_pci_dev(msi->dev)->bus->sysdata); + + clear_irq_range(pp, irq, 1, data->hwirq); + } +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0129-PCI-designware-add-modifications-from-4.4-rc1.patch b/target/linux/layerscape-64b/patches-4.1/0129-PCI-designware-add-modifications-from-4.4-rc1.patch new file mode 100644 index 0000000..689e062 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0129-PCI-designware-add-modifications-from-4.4-rc1.patch @@ -0,0 +1,836 @@ +From f743f7384e4c1c0924849e1ebe98026ff8095dd4 Mon Sep 17 00:00:00 2001 +From: Mingkai Hu +Date: Fri, 22 Jan 2016 13:48:18 +0800 +Subject: [PATCH 129/151] PCI: designware: add modifications from 4.4-rc1 + +Signed-off-by: Mingkai Hu +--- + drivers/pci/host/Kconfig | 7 +- + drivers/pci/host/pcie-designware.c | 504 +++++++++++++++++-------------------- + drivers/pci/host/pcie-designware.h | 20 +- + 3 files changed, 240 insertions(+), 291 deletions(-) + +diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig +index e59783a..3d9688b 100644 +--- a/drivers/pci/host/Kconfig ++++ b/drivers/pci/host/Kconfig +@@ -18,9 +18,6 @@ config PCI_MVEBU + config PCIE_DW + bool + +-config PCIE_DW_BASE +- bool +- + config PCI_EXYNOS + bool "Samsung Exynos PCIe controller" + depends on SOC_EXYNOS5440 +@@ -99,8 +96,8 @@ config PCI_XGENE + + config PCI_LAYERSCAPE + bool "Freescale Layerscape PCIe controller" +- depends on OF && (ARM || ARM64) +- select PCIE_DW_BASE ++ depends on OF && (ARM || ARCH_LAYERSCAPE) ++ select PCIE_DW + select MFD_SYSCON + help + Say Y here if you want PCIe controller support on Layerscape SoCs. +diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c +index ca72c21..540f077 100644 +--- a/drivers/pci/host/pcie-designware.c ++++ b/drivers/pci/host/pcie-designware.c +@@ -31,13 +31,15 @@ + #define PORT_LINK_MODE_1_LANES (0x1 << 16) + #define PORT_LINK_MODE_2_LANES (0x3 << 16) + #define PORT_LINK_MODE_4_LANES (0x7 << 16) ++#define PORT_LINK_MODE_8_LANES (0xf << 16) + + #define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C + #define PORT_LOGIC_SPEED_CHANGE (0x1 << 17) +-#define PORT_LOGIC_LINK_WIDTH_MASK (0x1ff << 8) ++#define PORT_LOGIC_LINK_WIDTH_MASK (0x1f << 8) + #define PORT_LOGIC_LINK_WIDTH_1_LANES (0x1 << 8) + #define PORT_LOGIC_LINK_WIDTH_2_LANES (0x2 << 8) + #define PORT_LOGIC_LINK_WIDTH_4_LANES (0x4 << 8) ++#define PORT_LOGIC_LINK_WIDTH_8_LANES (0x8 << 8) + + #define PCIE_MSI_ADDR_LO 0x820 + #define PCIE_MSI_ADDR_HI 0x824 +@@ -67,39 +69,40 @@ + #define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) + #define PCIE_ATU_UPPER_TARGET 0x91C + +-static struct hw_pci dw_pci; ++static struct pci_ops dw_pcie_ops; + +-static unsigned long global_io_offset; +- +-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys) +-{ +- BUG_ON(!sys->private_data); +- +- return sys->private_data; +-} +- +-int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val) ++int dw_pcie_cfg_read(void __iomem *addr, int size, u32 *val) + { +- *val = readl(addr); ++ if ((uintptr_t)addr & (size - 1)) { ++ *val = 0; ++ return PCIBIOS_BAD_REGISTER_NUMBER; ++ } + +- if (size == 1) +- *val = (*val >> (8 * (where & 3))) & 0xff; ++ if (size == 4) ++ *val = readl(addr); + else if (size == 2) +- *val = (*val >> (8 * (where & 3))) & 0xffff; +- else if (size != 4) ++ *val = readw(addr); ++ else if (size == 1) ++ *val = readb(addr); ++ else { ++ *val = 0; + return PCIBIOS_BAD_REGISTER_NUMBER; ++ } + + return PCIBIOS_SUCCESSFUL; + } + +-int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val) ++int dw_pcie_cfg_write(void __iomem *addr, int size, u32 val) + { ++ if ((uintptr_t)addr & (size - 1)) ++ return PCIBIOS_BAD_REGISTER_NUMBER; ++ + if (size == 4) + writel(val, addr); + else if (size == 2) +- writew(val, addr + (where & 2)); ++ writew(val, addr); + else if (size == 1) +- writeb(val, addr + (where & 3)); ++ writeb(val, addr); + else + return PCIBIOS_BAD_REGISTER_NUMBER; + +@@ -130,8 +133,7 @@ static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, + if (pp->ops->rd_own_conf) + ret = pp->ops->rd_own_conf(pp, where, size, val); + else +- ret = dw_pcie_cfg_read(pp->dbi_base + (where & ~0x3), where, +- size, val); ++ ret = dw_pcie_cfg_read(pp->dbi_base + where, size, val); + + return ret; + } +@@ -144,12 +146,26 @@ static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, + if (pp->ops->wr_own_conf) + ret = pp->ops->wr_own_conf(pp, where, size, val); + else +- ret = dw_pcie_cfg_write(pp->dbi_base + (where & ~0x3), where, +- size, val); ++ ret = dw_pcie_cfg_write(pp->dbi_base + where, size, val); + + return ret; + } + ++static void dw_pcie_prog_outbound_atu(struct pcie_port *pp, int index, ++ int type, u64 cpu_addr, u64 pci_addr, u32 size) ++{ ++ dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | index, ++ PCIE_ATU_VIEWPORT); ++ dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr), PCIE_ATU_LOWER_BASE); ++ dw_pcie_writel_rc(pp, upper_32_bits(cpu_addr), PCIE_ATU_UPPER_BASE); ++ dw_pcie_writel_rc(pp, lower_32_bits(cpu_addr + size - 1), ++ PCIE_ATU_LIMIT); ++ dw_pcie_writel_rc(pp, lower_32_bits(pci_addr), PCIE_ATU_LOWER_TARGET); ++ dw_pcie_writel_rc(pp, upper_32_bits(pci_addr), PCIE_ATU_UPPER_TARGET); ++ dw_pcie_writel_rc(pp, type, PCIE_ATU_CR1); ++ dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); ++} ++ + static struct irq_chip dw_msi_irq_chip = { + .name = "PCI-MSI", + .irq_enable = pci_msi_unmask_irq, +@@ -188,12 +204,16 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) + + void dw_pcie_msi_init(struct pcie_port *pp) + { ++ u64 msi_target; ++ + pp->msi_data = __get_free_pages(GFP_KERNEL, 0); ++ msi_target = virt_to_phys((void *)pp->msi_data); + + /* program the msi_data */ + dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4, +- virt_to_phys((void *)pp->msi_data)); +- dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, 0); ++ (u32)(msi_target & 0xffffffff)); ++ dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, ++ (u32)(msi_target >> 32 & 0xffffffff)); + } + + static void dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq) +@@ -238,7 +258,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq) + static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) + { + int irq, pos0, i; +- struct pcie_port *pp = sys_to_pcie(to_pci_dev(desc->dev)->bus->sysdata); ++ struct pcie_port *pp = (struct pcie_port *) msi_desc_to_pci_sysdata(desc); + + pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS, + order_base_2(no_irqs)); +@@ -269,6 +289,9 @@ static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) + } + + *pos = pos0; ++ desc->nvec_used = no_irqs; ++ desc->msi_attrib.multiple = order_base_2(no_irqs); ++ + return irq; + + no_valid_irq: +@@ -276,12 +299,32 @@ no_valid_irq: + return -ENOSPC; + } + ++static void dw_msi_setup_msg(struct pcie_port *pp, unsigned int irq, u32 pos) ++{ ++ struct msi_msg msg; ++ u64 msi_target; ++ ++ if (pp->ops->get_msi_addr) ++ msi_target = pp->ops->get_msi_addr(pp); ++ else ++ msi_target = virt_to_phys((void *)pp->msi_data); ++ ++ msg.address_lo = (u32)(msi_target & 0xffffffff); ++ msg.address_hi = (u32)(msi_target >> 32 & 0xffffffff); ++ ++ if (pp->ops->get_msi_data) ++ msg.data = pp->ops->get_msi_data(pp, pos); ++ else ++ msg.data = pos; ++ ++ pci_write_msi_msg(irq, &msg); ++} ++ + static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev, + struct msi_desc *desc) + { + int irq, pos; +- struct msi_msg msg; +- struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata); ++ struct pcie_port *pp = pdev->bus->sysdata; + + if (desc->msi_attrib.is_msix) + return -EINVAL; +@@ -290,33 +333,50 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev, + if (irq < 0) + return irq; + +- if (pp->ops->get_msi_addr) +- msg.address_lo = pp->ops->get_msi_addr(pp); +- else +- msg.address_lo = virt_to_phys((void *)pp->msi_data); +- msg.address_hi = 0x0; ++ dw_msi_setup_msg(pp, irq, pos); + +- if (pp->ops->get_msi_data) +- msg.data = pp->ops->get_msi_data(pp, pos); +- else +- msg.data = pos; ++ return 0; ++} + +- pci_write_msi_msg(irq, &msg); ++static int dw_msi_setup_irqs(struct msi_controller *chip, struct pci_dev *pdev, ++ int nvec, int type) ++{ ++#ifdef CONFIG_PCI_MSI ++ int irq, pos; ++ struct msi_desc *desc; ++ struct pcie_port *pp = pdev->bus->sysdata; ++ ++ /* MSI-X interrupts are not supported */ ++ if (type == PCI_CAP_ID_MSIX) ++ return -EINVAL; ++ ++ WARN_ON(!list_is_singular(&pdev->dev.msi_list)); ++ desc = list_entry(pdev->dev.msi_list.next, struct msi_desc, list); ++ ++ irq = assign_irq(nvec, desc, &pos); ++ if (irq < 0) ++ return irq; ++ ++ dw_msi_setup_msg(pp, irq, pos); + + return 0; ++#else ++ return -EINVAL; ++#endif + } + + static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq) + { + struct irq_data *data = irq_get_irq_data(irq); +- struct msi_desc *msi = irq_data_get_msi(data); +- struct pcie_port *pp = sys_to_pcie(to_pci_dev(msi->dev)->bus->sysdata); ++ struct msi_desc *msi = irq_data_get_msi_desc(data); ++ struct pcie_port *pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi); + + clear_irq_range(pp, irq, 1, data->hwirq); + } + + static struct msi_controller dw_pcie_msi_chip = { + .setup_irq = dw_msi_setup_irq, ++ .setup_irqs = dw_msi_setup_irqs, + .teardown_irq = dw_msi_teardown_irq, + }; + +@@ -333,7 +393,6 @@ static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq, + { + irq_set_chip_and_handler(irq, &dw_msi_irq_chip, handle_simple_irq); + irq_set_chip_data(irq, domain->host_data); +- set_irq_flags(irq, IRQF_VALID); + + return 0; + } +@@ -346,18 +405,12 @@ int dw_pcie_host_init(struct pcie_port *pp) + { + struct device_node *np = pp->dev->of_node; + struct platform_device *pdev = to_platform_device(pp->dev); +- struct of_pci_range range; +- struct of_pci_range_parser parser; ++ struct pci_bus *bus, *child; + struct resource *cfg_res; +- u32 val, na, ns; +- const __be32 *addrp; +- int i, index, ret; +- +- /* Find the address cell size and the number of cells in order to get +- * the untranslated address. +- */ +- of_property_read_u32(np, "#address-cells", &na); +- ns = of_n_size_cells(np); ++ u32 val; ++ int i, ret; ++ LIST_HEAD(res); ++ struct resource_entry *win; + + cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); + if (cfg_res) { +@@ -365,88 +418,61 @@ int dw_pcie_host_init(struct pcie_port *pp) + pp->cfg1_size = resource_size(cfg_res)/2; + pp->cfg0_base = cfg_res->start; + pp->cfg1_base = cfg_res->start + pp->cfg0_size; +- +- /* Find the untranslated configuration space address */ +- index = of_property_match_string(np, "reg-names", "config"); +- addrp = of_get_address(np, index, NULL, NULL); +- pp->cfg0_mod_base = of_read_number(addrp, ns); +- pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size; +- } else { ++ } else if (!pp->va_cfg0_base) { + dev_err(pp->dev, "missing *config* reg space\n"); + } + +- if (of_pci_range_parser_init(&parser, np)) { +- dev_err(pp->dev, "missing ranges property\n"); +- return -EINVAL; +- } ++ ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base); ++ if (ret) ++ return ret; + + /* Get the I/O and memory ranges from DT */ +- for_each_of_pci_range(&parser, &range) { +- unsigned long restype = range.flags & IORESOURCE_TYPE_BITS; +- +- if (restype == IORESOURCE_IO) { +- of_pci_range_to_resource(&range, np, &pp->io); +- pp->io.name = "I/O"; +- pp->io.start = max_t(resource_size_t, +- PCIBIOS_MIN_IO, +- range.pci_addr + global_io_offset); +- pp->io.end = min_t(resource_size_t, +- IO_SPACE_LIMIT, +- range.pci_addr + range.size +- + global_io_offset - 1); +- pp->io_size = resource_size(&pp->io); +- pp->io_bus_addr = range.pci_addr; +- pp->io_base = range.cpu_addr; +- +- /* Find the untranslated IO space address */ +- pp->io_mod_base = of_read_number(parser.range - +- parser.np + na, ns); +- } +- if (restype == IORESOURCE_MEM) { +- of_pci_range_to_resource(&range, np, &pp->mem); +- pp->mem.name = "MEM"; +- pp->mem_size = resource_size(&pp->mem); +- pp->mem_bus_addr = range.pci_addr; +- +- /* Find the untranslated MEM space address */ +- pp->mem_mod_base = of_read_number(parser.range - +- parser.np + na, ns); +- } +- if (restype == 0) { +- of_pci_range_to_resource(&range, np, &pp->cfg); +- pp->cfg0_size = resource_size(&pp->cfg)/2; +- pp->cfg1_size = resource_size(&pp->cfg)/2; +- pp->cfg0_base = pp->cfg.start; +- pp->cfg1_base = pp->cfg.start + pp->cfg0_size; +- +- /* Find the untranslated configuration space address */ +- pp->cfg0_mod_base = of_read_number(parser.range - +- parser.np + na, ns); +- pp->cfg1_mod_base = pp->cfg0_mod_base + +- pp->cfg0_size; ++ resource_list_for_each_entry(win, &res) { ++ switch (resource_type(win->res)) { ++ case IORESOURCE_IO: ++ pp->io = win->res; ++ pp->io->name = "I/O"; ++ pp->io_size = resource_size(pp->io); ++ pp->io_bus_addr = pp->io->start - win->offset; ++ ret = pci_remap_iospace(pp->io, pp->io_base); ++ if (ret) { ++ dev_warn(pp->dev, "error %d: failed to map resource %pR\n", ++ ret, pp->io); ++ continue; ++ } ++ pp->io_base = pp->io->start; ++ break; ++ case IORESOURCE_MEM: ++ pp->mem = win->res; ++ pp->mem->name = "MEM"; ++ pp->mem_size = resource_size(pp->mem); ++ pp->mem_bus_addr = pp->mem->start - win->offset; ++ break; ++ case 0: ++ pp->cfg = win->res; ++ pp->cfg0_size = resource_size(pp->cfg)/2; ++ pp->cfg1_size = resource_size(pp->cfg)/2; ++ pp->cfg0_base = pp->cfg->start; ++ pp->cfg1_base = pp->cfg->start + pp->cfg0_size; ++ break; ++ case IORESOURCE_BUS: ++ pp->busn = win->res; ++ break; ++ default: ++ continue; + } + } + +- ret = of_pci_parse_bus_range(np, &pp->busn); +- if (ret < 0) { +- pp->busn.name = np->name; +- pp->busn.start = 0; +- pp->busn.end = 0xff; +- pp->busn.flags = IORESOURCE_BUS; +- dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n", +- ret, &pp->busn); +- } +- + if (!pp->dbi_base) { +- pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start, +- resource_size(&pp->cfg)); ++ pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start, ++ resource_size(pp->cfg)); + if (!pp->dbi_base) { + dev_err(pp->dev, "error with ioremap\n"); + return -ENOMEM; + } + } + +- pp->mem_base = pp->mem.start; ++ pp->mem_base = pp->mem->start; + + if (!pp->va_cfg0_base) { + pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base, +@@ -466,10 +492,9 @@ int dw_pcie_host_init(struct pcie_port *pp) + } + } + +- if (of_property_read_u32(np, "num-lanes", &pp->lanes)) { +- dev_err(pp->dev, "Failed to parse the number of lanes\n"); +- return -EINVAL; +- } ++ ret = of_property_read_u32(np, "num-lanes", &pp->lanes); ++ if (ret) ++ pp->lanes = 0; + + if (IS_ENABLED(CONFIG_PCI_MSI)) { + if (!pp->ops->msi_host_init) { +@@ -493,6 +518,11 @@ int dw_pcie_host_init(struct pcie_port *pp) + if (pp->ops->host_init) + pp->ops->host_init(pp); + ++ if (!pp->ops->rd_other_conf) ++ dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1, ++ PCIE_ATU_TYPE_MEM, pp->mem_base, ++ pp->mem_bus_addr, pp->mem_size); ++ + dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0); + + /* program correct class for RC */ +@@ -502,128 +532,103 @@ int dw_pcie_host_init(struct pcie_port *pp) + val |= PORT_LOGIC_SPEED_CHANGE; + dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val); + +-#ifdef CONFIG_PCI_MSI +- dw_pcie_msi_chip.dev = pp->dev; +- dw_pci.msi_ctrl = &dw_pcie_msi_chip; +-#endif +- +- dw_pci.nr_controllers = 1; +- dw_pci.private_data = (void **)&pp; +- +- pci_common_init_dev(pp->dev, &dw_pci); ++ pp->root_bus_nr = pp->busn->start; ++ if (IS_ENABLED(CONFIG_PCI_MSI)) { ++ bus = pci_scan_root_bus_msi(pp->dev, pp->root_bus_nr, ++ &dw_pcie_ops, pp, &res, ++ &dw_pcie_msi_chip); ++ dw_pcie_msi_chip.dev = pp->dev; ++ } else ++ bus = pci_scan_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops, ++ pp, &res); ++ if (!bus) ++ return -ENOMEM; + +- return 0; +-} ++ if (pp->ops->scan_bus) ++ pp->ops->scan_bus(pp); + +-static void dw_pcie_prog_viewport_cfg0(struct pcie_port *pp, u32 busdev) +-{ +- /* Program viewport 0 : OUTBOUND : CFG0 */ +- dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0, +- PCIE_ATU_VIEWPORT); +- dw_pcie_writel_rc(pp, pp->cfg0_mod_base, PCIE_ATU_LOWER_BASE); +- dw_pcie_writel_rc(pp, (pp->cfg0_mod_base >> 32), PCIE_ATU_UPPER_BASE); +- dw_pcie_writel_rc(pp, pp->cfg0_mod_base + pp->cfg0_size - 1, +- PCIE_ATU_LIMIT); +- dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET); +- dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET); +- dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG0, PCIE_ATU_CR1); +- dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); +-} ++#ifdef CONFIG_ARM ++ /* support old dtbs that incorrectly describe IRQs */ ++ pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); ++#endif + +-static void dw_pcie_prog_viewport_cfg1(struct pcie_port *pp, u32 busdev) +-{ +- /* Program viewport 1 : OUTBOUND : CFG1 */ +- dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, +- PCIE_ATU_VIEWPORT); +- dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1); +- dw_pcie_writel_rc(pp, pp->cfg1_mod_base, PCIE_ATU_LOWER_BASE); +- dw_pcie_writel_rc(pp, (pp->cfg1_mod_base >> 32), PCIE_ATU_UPPER_BASE); +- dw_pcie_writel_rc(pp, pp->cfg1_mod_base + pp->cfg1_size - 1, +- PCIE_ATU_LIMIT); +- dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET); +- dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET); +- dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); +-} ++ if (!pci_has_flag(PCI_PROBE_ONLY)) { ++ pci_bus_size_bridges(bus); ++ pci_bus_assign_resources(bus); + +-static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp) +-{ +- /* Program viewport 0 : OUTBOUND : MEM */ +- dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0, +- PCIE_ATU_VIEWPORT); +- dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1); +- dw_pcie_writel_rc(pp, pp->mem_mod_base, PCIE_ATU_LOWER_BASE); +- dw_pcie_writel_rc(pp, (pp->mem_mod_base >> 32), PCIE_ATU_UPPER_BASE); +- dw_pcie_writel_rc(pp, pp->mem_mod_base + pp->mem_size - 1, +- PCIE_ATU_LIMIT); +- dw_pcie_writel_rc(pp, pp->mem_bus_addr, PCIE_ATU_LOWER_TARGET); +- dw_pcie_writel_rc(pp, upper_32_bits(pp->mem_bus_addr), +- PCIE_ATU_UPPER_TARGET); +- dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); +-} ++ list_for_each_entry(child, &bus->children, node) ++ pcie_bus_configure_settings(child); ++ } + +-static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp) +-{ +- /* Program viewport 1 : OUTBOUND : IO */ +- dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, +- PCIE_ATU_VIEWPORT); +- dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1); +- dw_pcie_writel_rc(pp, pp->io_mod_base, PCIE_ATU_LOWER_BASE); +- dw_pcie_writel_rc(pp, (pp->io_mod_base >> 32), PCIE_ATU_UPPER_BASE); +- dw_pcie_writel_rc(pp, pp->io_mod_base + pp->io_size - 1, +- PCIE_ATU_LIMIT); +- dw_pcie_writel_rc(pp, pp->io_bus_addr, PCIE_ATU_LOWER_TARGET); +- dw_pcie_writel_rc(pp, upper_32_bits(pp->io_bus_addr), +- PCIE_ATU_UPPER_TARGET); +- dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); ++ pci_bus_add_devices(bus); ++ return 0; + } + + static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, + u32 devfn, int where, int size, u32 *val) + { +- int ret = PCIBIOS_SUCCESSFUL; +- u32 address, busdev; ++ int ret, type; ++ u32 busdev, cfg_size; ++ u64 cpu_addr; ++ void __iomem *va_cfg_base; + + busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) | + PCIE_ATU_FUNC(PCI_FUNC(devfn)); +- address = where & ~0x3; + + if (bus->parent->number == pp->root_bus_nr) { +- dw_pcie_prog_viewport_cfg0(pp, busdev); +- ret = dw_pcie_cfg_read(pp->va_cfg0_base + address, where, size, +- val); +- dw_pcie_prog_viewport_mem_outbound(pp); ++ type = PCIE_ATU_TYPE_CFG0; ++ cpu_addr = pp->cfg0_base; ++ cfg_size = pp->cfg0_size; ++ va_cfg_base = pp->va_cfg0_base; + } else { +- dw_pcie_prog_viewport_cfg1(pp, busdev); +- ret = dw_pcie_cfg_read(pp->va_cfg1_base + address, where, size, +- val); +- dw_pcie_prog_viewport_io_outbound(pp); ++ type = PCIE_ATU_TYPE_CFG1; ++ cpu_addr = pp->cfg1_base; ++ cfg_size = pp->cfg1_size; ++ va_cfg_base = pp->va_cfg1_base; + } + ++ dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, ++ type, cpu_addr, ++ busdev, cfg_size); ++ ret = dw_pcie_cfg_read(va_cfg_base + where, size, val); ++ dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, ++ PCIE_ATU_TYPE_IO, pp->io_base, ++ pp->io_bus_addr, pp->io_size); ++ + return ret; + } + + static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, + u32 devfn, int where, int size, u32 val) + { +- int ret = PCIBIOS_SUCCESSFUL; +- u32 address, busdev; ++ int ret, type; ++ u32 busdev, cfg_size; ++ u64 cpu_addr; ++ void __iomem *va_cfg_base; + + busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) | + PCIE_ATU_FUNC(PCI_FUNC(devfn)); +- address = where & ~0x3; + + if (bus->parent->number == pp->root_bus_nr) { +- dw_pcie_prog_viewport_cfg0(pp, busdev); +- ret = dw_pcie_cfg_write(pp->va_cfg0_base + address, where, size, +- val); +- dw_pcie_prog_viewport_mem_outbound(pp); ++ type = PCIE_ATU_TYPE_CFG0; ++ cpu_addr = pp->cfg0_base; ++ cfg_size = pp->cfg0_size; ++ va_cfg_base = pp->va_cfg0_base; + } else { +- dw_pcie_prog_viewport_cfg1(pp, busdev); +- ret = dw_pcie_cfg_write(pp->va_cfg1_base + address, where, size, +- val); +- dw_pcie_prog_viewport_io_outbound(pp); ++ type = PCIE_ATU_TYPE_CFG1; ++ cpu_addr = pp->cfg1_base; ++ cfg_size = pp->cfg1_size; ++ va_cfg_base = pp->va_cfg1_base; + } + ++ dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, ++ type, cpu_addr, ++ busdev, cfg_size); ++ ret = dw_pcie_cfg_write(va_cfg_base + where, size, val); ++ dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, ++ PCIE_ATU_TYPE_IO, pp->io_base, ++ pp->io_bus_addr, pp->io_size); ++ + return ret; + } + +@@ -653,7 +658,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp, + static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, + int size, u32 *val) + { +- struct pcie_port *pp = sys_to_pcie(bus->sysdata); ++ struct pcie_port *pp = bus->sysdata; + int ret; + + if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) { +@@ -677,7 +682,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, + static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn, + int where, int size, u32 val) + { +- struct pcie_port *pp = sys_to_pcie(bus->sysdata); ++ struct pcie_port *pp = bus->sysdata; + int ret; + + if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) +@@ -701,64 +706,6 @@ static struct pci_ops dw_pcie_ops = { + .write = dw_pcie_wr_conf, + }; + +-static int dw_pcie_setup(int nr, struct pci_sys_data *sys) +-{ +- struct pcie_port *pp; +- +- pp = sys_to_pcie(sys); +- +- if (global_io_offset < SZ_1M && pp->io_size > 0) { +- sys->io_offset = global_io_offset - pp->io_bus_addr; +- pci_ioremap_io(global_io_offset, pp->io_base); +- global_io_offset += SZ_64K; +- pci_add_resource_offset(&sys->resources, &pp->io, +- sys->io_offset); +- } +- +- sys->mem_offset = pp->mem.start - pp->mem_bus_addr; +- pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset); +- pci_add_resource(&sys->resources, &pp->busn); +- +- return 1; +-} +- +-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys) +-{ +- struct pci_bus *bus; +- struct pcie_port *pp = sys_to_pcie(sys); +- +- pp->root_bus_nr = sys->busnr; +- bus = pci_create_root_bus(pp->dev, sys->busnr, +- &dw_pcie_ops, sys, &sys->resources); +- if (!bus) +- return NULL; +- +- pci_scan_child_bus(bus); +- +- if (bus && pp->ops->scan_bus) +- pp->ops->scan_bus(pp); +- +- return bus; +-} +- +-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +-{ +- struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata); +- int irq; +- +- irq = of_irq_parse_and_map_pci(dev, slot, pin); +- if (!irq) +- irq = pp->irq; +- +- return irq; +-} +- +-static struct hw_pci dw_pci = { +- .setup = dw_pcie_setup, +- .scan = dw_pcie_scan_bus, +- .map_irq = dw_pcie_map_irq, +-}; +- + void dw_pcie_setup_rc(struct pcie_port *pp) + { + u32 val; +@@ -778,6 +725,12 @@ void dw_pcie_setup_rc(struct pcie_port *pp) + case 4: + val |= PORT_LINK_MODE_4_LANES; + break; ++ case 8: ++ val |= PORT_LINK_MODE_8_LANES; ++ break; ++ default: ++ dev_err(pp->dev, "num-lanes %u: invalid value\n", pp->lanes); ++ return; + } + dw_pcie_writel_rc(pp, val, PCIE_PORT_LINK_CONTROL); + +@@ -794,6 +747,9 @@ void dw_pcie_setup_rc(struct pcie_port *pp) + case 4: + val |= PORT_LOGIC_LINK_WIDTH_4_LANES; + break; ++ case 8: ++ val |= PORT_LOGIC_LINK_WIDTH_8_LANES; ++ break; + } + dw_pcie_writel_rc(pp, val, PCIE_LINK_WIDTH_SPEED_CONTROL); + +diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h +index d0bbd27..2356d29 100644 +--- a/drivers/pci/host/pcie-designware.h ++++ b/drivers/pci/host/pcie-designware.h +@@ -27,25 +27,21 @@ struct pcie_port { + u8 root_bus_nr; + void __iomem *dbi_base; + u64 cfg0_base; +- u64 cfg0_mod_base; + void __iomem *va_cfg0_base; + u32 cfg0_size; + u64 cfg1_base; +- u64 cfg1_mod_base; + void __iomem *va_cfg1_base; + u32 cfg1_size; +- u64 io_base; +- u64 io_mod_base; ++ resource_size_t io_base; + phys_addr_t io_bus_addr; + u32 io_size; + u64 mem_base; +- u64 mem_mod_base; + phys_addr_t mem_bus_addr; + u32 mem_size; +- struct resource cfg; +- struct resource io; +- struct resource mem; +- struct resource busn; ++ struct resource *cfg; ++ struct resource *io; ++ struct resource *mem; ++ struct resource *busn; + int irq; + u32 lanes; + struct pcie_host_ops *ops; +@@ -70,14 +66,14 @@ struct pcie_host_ops { + void (*host_init)(struct pcie_port *pp); + void (*msi_set_irq)(struct pcie_port *pp, int irq); + void (*msi_clear_irq)(struct pcie_port *pp, int irq); +- u32 (*get_msi_addr)(struct pcie_port *pp); ++ phys_addr_t (*get_msi_addr)(struct pcie_port *pp); + u32 (*get_msi_data)(struct pcie_port *pp, int pos); + void (*scan_bus)(struct pcie_port *pp); + int (*msi_host_init)(struct pcie_port *pp, struct msi_controller *chip); + }; + +-int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val); +-int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val); ++int dw_pcie_cfg_read(void __iomem *addr, int size, u32 *val); ++int dw_pcie_cfg_write(void __iomem *addr, int size, u32 val); + irqreturn_t dw_handle_msi_irq(struct pcie_port *pp); + void dw_pcie_msi_init(struct pcie_port *pp); + int dw_pcie_link_up(struct pcie_port *pp); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0130-PCI-designware-remove-designware-MSI-support.patch b/target/linux/layerscape-64b/patches-4.1/0130-PCI-designware-remove-designware-MSI-support.patch new file mode 100644 index 0000000..75e09af --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0130-PCI-designware-remove-designware-MSI-support.patch @@ -0,0 +1,331 @@ +From ae8a46dc19165d6eb05d842beb97b25978e45427 Mon Sep 17 00:00:00 2001 +From: Mingkai Hu +Date: Thu, 19 Nov 2015 16:56:06 +0800 +Subject: [PATCH 130/151] PCI: designware: remove designware MSI support + +Signed-off-by: Mingkai Hu +--- + drivers/pci/host/pcie-designware.c | 265 +------------------------------------ + 1 file changed, 3 insertions(+), 262 deletions(-) + +diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c +index 540f077..d62e281 100644 +--- a/drivers/pci/host/pcie-designware.c ++++ b/drivers/pci/host/pcie-designware.c +@@ -15,7 +15,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -41,12 +40,6 @@ + #define PORT_LOGIC_LINK_WIDTH_4_LANES (0x4 << 8) + #define PORT_LOGIC_LINK_WIDTH_8_LANES (0x8 << 8) + +-#define PCIE_MSI_ADDR_LO 0x820 +-#define PCIE_MSI_ADDR_HI 0x824 +-#define PCIE_MSI_INTR0_ENABLE 0x828 +-#define PCIE_MSI_INTR0_MASK 0x82C +-#define PCIE_MSI_INTR0_STATUS 0x830 +- + #define PCIE_ATU_VIEWPORT 0x900 + #define PCIE_ATU_REGION_INBOUND (0x1 << 31) + #define PCIE_ATU_REGION_OUTBOUND (0x0 << 31) +@@ -166,220 +159,6 @@ static void dw_pcie_prog_outbound_atu(struct pcie_port *pp, int index, + dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); + } + +-static struct irq_chip dw_msi_irq_chip = { +- .name = "PCI-MSI", +- .irq_enable = pci_msi_unmask_irq, +- .irq_disable = pci_msi_mask_irq, +- .irq_mask = pci_msi_mask_irq, +- .irq_unmask = pci_msi_unmask_irq, +-}; +- +-/* MSI int handler */ +-irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) +-{ +- unsigned long val; +- int i, pos, irq; +- irqreturn_t ret = IRQ_NONE; +- +- for (i = 0; i < MAX_MSI_CTRLS; i++) { +- dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4, +- (u32 *)&val); +- if (val) { +- ret = IRQ_HANDLED; +- pos = 0; +- while ((pos = find_next_bit(&val, 32, pos)) != 32) { +- irq = irq_find_mapping(pp->irq_domain, +- i * 32 + pos); +- dw_pcie_wr_own_conf(pp, +- PCIE_MSI_INTR0_STATUS + i * 12, +- 4, 1 << pos); +- generic_handle_irq(irq); +- pos++; +- } +- } +- } +- +- return ret; +-} +- +-void dw_pcie_msi_init(struct pcie_port *pp) +-{ +- u64 msi_target; +- +- pp->msi_data = __get_free_pages(GFP_KERNEL, 0); +- msi_target = virt_to_phys((void *)pp->msi_data); +- +- /* program the msi_data */ +- dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4, +- (u32)(msi_target & 0xffffffff)); +- dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, +- (u32)(msi_target >> 32 & 0xffffffff)); +-} +- +-static void dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq) +-{ +- unsigned int res, bit, val; +- +- res = (irq / 32) * 12; +- bit = irq % 32; +- dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val); +- val &= ~(1 << bit); +- dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val); +-} +- +-static void clear_irq_range(struct pcie_port *pp, unsigned int irq_base, +- unsigned int nvec, unsigned int pos) +-{ +- unsigned int i; +- +- for (i = 0; i < nvec; i++) { +- irq_set_msi_desc_off(irq_base, i, NULL); +- /* Disable corresponding interrupt on MSI controller */ +- if (pp->ops->msi_clear_irq) +- pp->ops->msi_clear_irq(pp, pos + i); +- else +- dw_pcie_msi_clear_irq(pp, pos + i); +- } +- +- bitmap_release_region(pp->msi_irq_in_use, pos, order_base_2(nvec)); +-} +- +-static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq) +-{ +- unsigned int res, bit, val; +- +- res = (irq / 32) * 12; +- bit = irq % 32; +- dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val); +- val |= 1 << bit; +- dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val); +-} +- +-static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) +-{ +- int irq, pos0, i; +- struct pcie_port *pp = (struct pcie_port *) msi_desc_to_pci_sysdata(desc); +- +- pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS, +- order_base_2(no_irqs)); +- if (pos0 < 0) +- goto no_valid_irq; +- +- irq = irq_find_mapping(pp->irq_domain, pos0); +- if (!irq) +- goto no_valid_irq; +- +- /* +- * irq_create_mapping (called from dw_pcie_host_init) pre-allocates +- * descs so there is no need to allocate descs here. We can therefore +- * assume that if irq_find_mapping above returns non-zero, then the +- * descs are also successfully allocated. +- */ +- +- for (i = 0; i < no_irqs; i++) { +- if (irq_set_msi_desc_off(irq, i, desc) != 0) { +- clear_irq_range(pp, irq, i, pos0); +- goto no_valid_irq; +- } +- /*Enable corresponding interrupt in MSI interrupt controller */ +- if (pp->ops->msi_set_irq) +- pp->ops->msi_set_irq(pp, pos0 + i); +- else +- dw_pcie_msi_set_irq(pp, pos0 + i); +- } +- +- *pos = pos0; +- desc->nvec_used = no_irqs; +- desc->msi_attrib.multiple = order_base_2(no_irqs); +- +- return irq; +- +-no_valid_irq: +- *pos = pos0; +- return -ENOSPC; +-} +- +-static void dw_msi_setup_msg(struct pcie_port *pp, unsigned int irq, u32 pos) +-{ +- struct msi_msg msg; +- u64 msi_target; +- +- if (pp->ops->get_msi_addr) +- msi_target = pp->ops->get_msi_addr(pp); +- else +- msi_target = virt_to_phys((void *)pp->msi_data); +- +- msg.address_lo = (u32)(msi_target & 0xffffffff); +- msg.address_hi = (u32)(msi_target >> 32 & 0xffffffff); +- +- if (pp->ops->get_msi_data) +- msg.data = pp->ops->get_msi_data(pp, pos); +- else +- msg.data = pos; +- +- pci_write_msi_msg(irq, &msg); +-} +- +-static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev, +- struct msi_desc *desc) +-{ +- int irq, pos; +- struct pcie_port *pp = pdev->bus->sysdata; +- +- if (desc->msi_attrib.is_msix) +- return -EINVAL; +- +- irq = assign_irq(1, desc, &pos); +- if (irq < 0) +- return irq; +- +- dw_msi_setup_msg(pp, irq, pos); +- +- return 0; +-} +- +-static int dw_msi_setup_irqs(struct msi_controller *chip, struct pci_dev *pdev, +- int nvec, int type) +-{ +-#ifdef CONFIG_PCI_MSI +- int irq, pos; +- struct msi_desc *desc; +- struct pcie_port *pp = pdev->bus->sysdata; +- +- /* MSI-X interrupts are not supported */ +- if (type == PCI_CAP_ID_MSIX) +- return -EINVAL; +- +- WARN_ON(!list_is_singular(&pdev->dev.msi_list)); +- desc = list_entry(pdev->dev.msi_list.next, struct msi_desc, list); +- +- irq = assign_irq(nvec, desc, &pos); +- if (irq < 0) +- return irq; +- +- dw_msi_setup_msg(pp, irq, pos); +- +- return 0; +-#else +- return -EINVAL; +-#endif +-} +- +-static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq) +-{ +- struct irq_data *data = irq_get_irq_data(irq); +- struct msi_desc *msi = irq_data_get_msi_desc(data); +- struct pcie_port *pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi); +- +- clear_irq_range(pp, irq, 1, data->hwirq); +-} +- +-static struct msi_controller dw_pcie_msi_chip = { +- .setup_irq = dw_msi_setup_irq, +- .setup_irqs = dw_msi_setup_irqs, +- .teardown_irq = dw_msi_teardown_irq, +-}; +- + int dw_pcie_link_up(struct pcie_port *pp) + { + if (pp->ops->link_up) +@@ -388,19 +167,6 @@ int dw_pcie_link_up(struct pcie_port *pp) + return 0; + } + +-static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq, +- irq_hw_number_t hwirq) +-{ +- irq_set_chip_and_handler(irq, &dw_msi_irq_chip, handle_simple_irq); +- irq_set_chip_data(irq, domain->host_data); +- +- return 0; +-} +- +-static const struct irq_domain_ops msi_domain_ops = { +- .map = dw_pcie_msi_map, +-}; +- + int dw_pcie_host_init(struct pcie_port *pp) + { + struct device_node *np = pp->dev->of_node; +@@ -408,7 +174,7 @@ int dw_pcie_host_init(struct pcie_port *pp) + struct pci_bus *bus, *child; + struct resource *cfg_res; + u32 val; +- int i, ret; ++ int ret; + LIST_HEAD(res); + struct resource_entry *win; + +@@ -496,25 +262,6 @@ int dw_pcie_host_init(struct pcie_port *pp) + if (ret) + pp->lanes = 0; + +- if (IS_ENABLED(CONFIG_PCI_MSI)) { +- if (!pp->ops->msi_host_init) { +- pp->irq_domain = irq_domain_add_linear(pp->dev->of_node, +- MAX_MSI_IRQS, &msi_domain_ops, +- &dw_pcie_msi_chip); +- if (!pp->irq_domain) { +- dev_err(pp->dev, "irq domain init failed\n"); +- return -ENXIO; +- } +- +- for (i = 0; i < MAX_MSI_IRQS; i++) +- irq_create_mapping(pp->irq_domain, i); +- } else { +- ret = pp->ops->msi_host_init(pp, &dw_pcie_msi_chip); +- if (ret < 0) +- return ret; +- } +- } +- + if (pp->ops->host_init) + pp->ops->host_init(pp); + +@@ -533,14 +280,8 @@ int dw_pcie_host_init(struct pcie_port *pp) + dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val); + + pp->root_bus_nr = pp->busn->start; +- if (IS_ENABLED(CONFIG_PCI_MSI)) { +- bus = pci_scan_root_bus_msi(pp->dev, pp->root_bus_nr, +- &dw_pcie_ops, pp, &res, +- &dw_pcie_msi_chip); +- dw_pcie_msi_chip.dev = pp->dev; +- } else +- bus = pci_scan_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops, +- pp, &res); ++ bus = pci_scan_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops, ++ pp, &res); + if (!bus) + return -ENOMEM; + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0131-pci-designware-Add-support-non-dw-MSI-controller.patch b/target/linux/layerscape-64b/patches-4.1/0131-pci-designware-Add-support-non-dw-MSI-controller.patch new file mode 100644 index 0000000..8a8f152 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0131-pci-designware-Add-support-non-dw-MSI-controller.patch @@ -0,0 +1,89 @@ +From 998992bff979ed44ebb0c345372838c7b913242d Mon Sep 17 00:00:00 2001 +From: Mingkai Hu +Date: Thu, 19 Nov 2015 21:14:37 +0800 +Subject: [PATCH 131/151] pci/designware: Add support non-dw MSI controller + +Mingkai Hu +--- + drivers/pci/host/pcie-designware.c | 41 ++++++++++++++++++++++++++++++++++++++ + drivers/pci/host/pcie-designware.h | 1 + + 2 files changed, 42 insertions(+) + +diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c +index d62e281..c028174 100644 +--- a/drivers/pci/host/pcie-designware.c ++++ b/drivers/pci/host/pcie-designware.c +@@ -167,6 +167,32 @@ int dw_pcie_link_up(struct pcie_port *pp) + return 0; + } + ++static int dw_pcie_msi_ctrl_init(struct pcie_port *pp) ++{ ++ struct device_node *msi_node; ++ ++ if (!IS_ENABLED(CONFIG_PCI_MSI)) { ++ pp->msi = NULL; ++ return 0; ++ } ++ ++ if (pp->msi) ++ return 0; ++ ++ msi_node = of_parse_phandle(pp->dev->of_node, "msi-parent", 0); ++ if (msi_node) { ++ pp->msi = of_pci_find_msi_chip_by_node(msi_node); ++ if (!pp->msi) { ++ dev_err(pp->dev, "Cannot find msi chip of %s\n", ++ msi_node->full_name); ++ return -ENODEV; ++ } else ++ return 0; ++ } ++ ++ return 0; ++} ++ + int dw_pcie_host_init(struct pcie_port *pp) + { + struct device_node *np = pp->dev->of_node; +@@ -280,10 +306,25 @@ int dw_pcie_host_init(struct pcie_port *pp) + dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val); + + pp->root_bus_nr = pp->busn->start; ++#if 0 + bus = pci_scan_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops, + pp, &res); + if (!bus) + return -ENOMEM; ++#else ++ bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops, ++ pp, &res); ++ if (!bus) ++ return -ENODEV; ++ ++ ret = dw_pcie_msi_ctrl_init(pp); ++ if (ret) ++ return ret; ++ ++ bus->msi = pp->msi; ++ ++ pci_scan_child_bus(bus); ++#endif + + if (pp->ops->scan_bus) + pp->ops->scan_bus(pp); +diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h +index 2356d29..2f01284 100644 +--- a/drivers/pci/host/pcie-designware.h ++++ b/drivers/pci/host/pcie-designware.h +@@ -45,6 +45,7 @@ struct pcie_port { + int irq; + u32 lanes; + struct pcie_host_ops *ops; ++ struct msi_controller *msi; + int msi_irq; + struct irq_domain *irq_domain; + unsigned long msi_data; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0132-arm-Add-MSI-support.patch b/target/linux/layerscape-64b/patches-4.1/0132-arm-Add-MSI-support.patch new file mode 100644 index 0000000..eb5ed54 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0132-arm-Add-MSI-support.patch @@ -0,0 +1,369 @@ +From d07f74efc34ba56db2ba2b984fb6ebf346a45b4a Mon Sep 17 00:00:00 2001 +From: Minghuan Lian +Date: Mon, 30 Mar 2015 10:28:32 +0800 +Subject: [PATCH 132/151] arm: Add MSI support + +Signed-off-by: Minghuan Lian +Signed-off-by: Mingkai Hu +--- + arch/arm/include/asm/Kbuild | 1 + + drivers/irqchip/Kconfig | 6 + + drivers/irqchip/Makefile | 1 + + drivers/irqchip/irq-ls1-msi.c | 310 ++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 318 insertions(+) + create mode 100644 drivers/irqchip/irq-ls1-msi.c + +diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild +index 3c4596d..01806f5 100644 +--- a/arch/arm/include/asm/Kbuild ++++ b/arch/arm/include/asm/Kbuild +@@ -14,6 +14,7 @@ generic-y += local.h + generic-y += local64.h + generic-y += mcs_spinlock.h + generic-y += msgbuf.h ++generic-y += msi.h + generic-y += param.h + generic-y += parport.h + generic-y += poll.h +diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig +index 6de62a9..3e8cda8 100644 +--- a/drivers/irqchip/Kconfig ++++ b/drivers/irqchip/Kconfig +@@ -158,3 +158,9 @@ config KEYSTONE_IRQ + config MIPS_GIC + bool + select MIPS_CM ++ ++config LS1_MSI ++ bool ++ depends on ARM_GIC ++ depends on PCI && PCI_MSI ++ select PCI_MSI_IRQ_DOMAIN +diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile +index dda4927..7c96941 100644 +--- a/drivers/irqchip/Makefile ++++ b/drivers/irqchip/Makefile +@@ -47,3 +47,4 @@ obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o + obj-$(CONFIG_MIPS_GIC) += irq-mips-gic.o + obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o + obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o ++obj-$(CONFIG_LS1_MSI) += irq-ls1-msi.o +diff --git a/drivers/irqchip/irq-ls1-msi.c b/drivers/irqchip/irq-ls1-msi.c +new file mode 100644 +index 0000000..9b44349 +--- /dev/null ++++ b/drivers/irqchip/irq-ls1-msi.c +@@ -0,0 +1,310 @@ ++/* ++ * Layerscape MSI(-X) support ++ * ++ * Copyright (C) 2015 Freescale Semiconductor. ++ * ++ * Author: Minghuan Lian ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MAX_MSI_IRQS 32 ++ ++static int ls1_msi_idx; ++ ++struct ls1_msi { ++ char name[32]; ++ struct device_node *of_node; ++ spinlock_t lock; ++ struct msi_controller mchip; ++ struct msi_domain_info info; ++ struct irq_chip chip; ++ struct irq_domain *parent; ++ void __iomem *msir; ++ phys_addr_t msiir_addr; ++ unsigned long *bm; ++ u32 nr_irqs; ++ int msi_irq; ++}; ++ ++static void ls1_msi_compose_msg(struct irq_data *data, struct msi_msg *msg) ++{ ++ struct ls1_msi *msi_data = irq_data_get_irq_chip_data(data); ++ phys_addr_t addr = msi_data->msiir_addr; ++ ++ msg->address_hi = (u32) (addr >> 32); ++ msg->address_lo = (u32) (addr); ++ msg->data = 0xb4; //data->hwirq; ++} ++ ++static int ls1_msi_set_affinity(struct irq_data *irq_data, ++ const struct cpumask *mask, bool force) ++{ ++ return 0; ++} ++ ++static struct irq_chip ls1_msi_parent_chip = { ++ .name = "LS1-MSI", ++ .irq_compose_msi_msg = ls1_msi_compose_msg, ++ .irq_set_affinity = ls1_msi_set_affinity, ++}; ++ ++static int ls1_msi_domain_irq_alloc(struct irq_domain *domain, unsigned int virq, ++ unsigned int nr_irqs, void *args) ++{ ++ struct ls1_msi *msi_data = domain->host_data; ++ int i, pos; ++ printk("\n\nls1_msi_domain_irq_alloc\n"); ++ spin_lock(&msi_data->lock); ++ pos = bitmap_find_free_region(msi_data->bm, msi_data->nr_irqs, ++ order_base_2(nr_irqs)); ++ spin_unlock(&msi_data->lock); ++ ++ if (pos < 0) ++ return -ENOSPC; ++ ++ for (i = 0; i < nr_irqs; i++) { ++ irq_domain_set_info(domain, virq + i, pos + i, ++ &ls1_msi_parent_chip, msi_data, ++ handle_simple_irq, NULL, NULL); ++ set_irq_flags(virq, IRQF_VALID); ++ } ++ ++ return 0; ++} ++ ++static void ls1_msi_domain_irq_free(struct irq_domain *domain, ++ unsigned int virq, unsigned int nr_irqs) ++{ ++ struct irq_data *d = irq_domain_get_irq_data(domain, virq); ++ struct ls1_msi *msi_data = irq_data_get_irq_chip_data(d); ++ int pos; ++ ++ printk("\n\n\n\nls1_msi_domain_irq_free\n"); ++ pos = d->hwirq; ++ if (pos < 0 || pos >= msi_data->nr_irqs) { ++ pr_err("Failed to teardown msi. Invalid hwirq %d\n", pos); ++ return; ++ } ++ ++ spin_lock(&msi_data->lock); ++ bitmap_release_region(msi_data->bm, pos, order_base_2(nr_irqs)); ++ spin_unlock(&msi_data->lock); ++} ++ ++static const struct irq_domain_ops ls1_msi_domain_parent_ops = { ++ .alloc = ls1_msi_domain_irq_alloc, ++ .free = ls1_msi_domain_irq_free, ++}; ++ ++static irqreturn_t ls1_msi_handler(int irq, void *arg) ++{ ++ struct ls1_msi *msi_data = arg; ++ unsigned long val; ++ int pos, virq; ++ irqreturn_t ret = IRQ_NONE; ++ ++ val = ioread32be(msi_data->msir); ++ ++ { /* ls1021A */ ++ iowrite32be(cpu_to_be32(0xb4), msi_data->msir); ++ val = 1; ++ pos = 0; ++ } ++ ++ while ((pos = find_next_bit(&val, 32, pos)) != 32) { ++ virq = irq_find_mapping(msi_data->parent, pos); ++ if (virq != NO_IRQ) { ++ generic_handle_irq(virq); ++ ret = IRQ_HANDLED; ++ } ++ pos++; ++ } ++ ++ return ret; ++} ++ ++static void ls1021a_pcie_msi_fixup(struct ls1_msi *msi_data) ++{ ++ int i; ++ ++ /* ++ * LS1021A has only one MSI interrupt ++ * Set all msi interrupts as used except the first one ++ */ ++ for (i = 1; i < msi_data->nr_irqs; i++) ++ set_bit(i, msi_data->bm); ++} ++ ++static irq_hw_number_t ls1_msi_domain_ops_get_hwirq(struct msi_domain_info *info, ++ msi_alloc_info_t *arg) ++{ ++ struct ls1_msi *msi_data = container_of(info, struct ls1_msi, info); ++ ++ printk("%s %d arg->hwirq=%d\n", __func__, __LINE__, arg->hwirq); ++ arg->hwirq = find_first_zero_bit(msi_data->bm, msi_data->nr_irqs); ++ printk("%s %d arg->hwirq=%d\n", __func__, __LINE__, arg->hwirq); ++ ++ return arg->hwirq; ++} ++ ++static void ls1_msi_domain_ops_free(struct irq_domain *domain, ++ struct msi_domain_info *info, ++ unsigned int virq) ++{ ++ printk("ls1_msi_domain_ops_free\n"); ++} ++ ++static struct msi_domain_ops ls1_pci_msi_ops = { ++ .get_hwirq = ls1_msi_domain_ops_get_hwirq, ++ .msi_free = ls1_msi_domain_ops_free, ++}; ++ ++static int ls1_msi_chip_init(struct ls1_msi *msi_data) ++{ ++ int ret; ++ ++ /* Initialize MSI domain parent */ ++ msi_data->parent = irq_domain_add_linear(msi_data->of_node, ++ msi_data->nr_irqs, ++ &ls1_msi_domain_parent_ops, ++ msi_data); ++ if (!msi_data->parent) { ++ pr_err("MSI domain %s parent init failed\n", msi_data->name); ++ return -ENXIO; ++ } ++ ++ /* Initialize MSI irq chip */ ++ msi_data->chip.name = msi_data->name; ++ ++ /* Initialize MSI domain info */ ++ msi_data->info.flags = MSI_FLAG_USE_DEF_DOM_OPS | ++ MSI_FLAG_USE_DEF_CHIP_OPS | ++ MSI_FLAG_PCI_MSIX | ++ MSI_FLAG_MULTI_PCI_MSI; ++ msi_data->info.chip = &msi_data->chip; ++ msi_data->info.ops = &ls1_pci_msi_ops; ++ ++ /* Initialize MSI controller */ ++ msi_data->mchip.of_node = msi_data->of_node; ++ msi_data->mchip.domain = ++ pci_msi_create_irq_domain(msi_data->of_node, ++ &msi_data->info, ++ msi_data->parent); ++ ++ if (!msi_data->mchip.domain) { ++ pr_err("Failed to create MSI domain %s\n", msi_data->name); ++ ret = -ENOMEM; ++ goto _err; ++ } ++ ++ ++ ret = of_pci_msi_chip_add(&msi_data->mchip); ++ if (ret) { ++ pr_err("Failed to add msi_chip %s\n", msi_data->name); ++ goto _err; ++ } ++ ++ return 0; ++ ++_err: ++ if (msi_data->mchip.domain) ++ irq_domain_remove(msi_data->mchip.domain); ++ if (msi_data->parent) ++ irq_domain_remove(msi_data->parent); ++ return ret; ++} ++ ++ ++static int __init ls1_msi_probe(struct platform_device *pdev) ++{ ++ struct ls1_msi *msi_data; ++ struct resource *res; ++ int ret; ++ ++ msi_data = devm_kzalloc(&pdev->dev, sizeof(*msi_data), GFP_KERNEL); ++ if (!msi_data) { ++ dev_err(&pdev->dev, "Failed to allocate struct ls1_msi.\n"); ++ return -ENOMEM; ++ } ++ ++ msi_data->of_node = pdev->dev.of_node; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "missing msiir.\n"); ++ return -ENODEV; ++ } ++ msi_data->msiir_addr = res->start; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ if (!res) { ++ dev_err(&pdev->dev, "missing msir.\n"); ++ return -ENODEV; ++ } ++ msi_data->msir = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(msi_data->msir)) ++ return PTR_ERR(msi_data->msir); ++ ++ msi_data->msi_irq = platform_get_irq(pdev, 0); ++ if (msi_data->msi_irq <= 0) { ++ dev_err(&pdev->dev, "failed to get MSI irq\n"); ++ return -ENODEV; ++ } ++ ++ msi_data->nr_irqs = MAX_MSI_IRQS; ++ ++ msi_data->bm = devm_kzalloc(&pdev->dev, sizeof(long) * ++ BITS_TO_LONGS(msi_data->nr_irqs), ++ GFP_KERNEL); ++ if (!msi_data->bm) ++ ret = -ENOMEM; ++ ++ ls1_msi_idx++; ++ snprintf(msi_data->name, sizeof(msi_data->name), "MSI%d", ls1_msi_idx); ++ ++ spin_lock_init(&msi_data->lock); ++ ++ ret = devm_request_irq(&pdev->dev, msi_data->msi_irq, ++ ls1_msi_handler, IRQF_SHARED, ++ msi_data->name, msi_data); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to request MSI irq\n"); ++ return -ENODEV; ++ } ++ ++ ls1021a_pcie_msi_fixup(msi_data); ++ ++ return ls1_msi_chip_init(msi_data); ++} ++ ++static struct of_device_id ls1_msi_id[] = { ++ { .compatible = "fsl,1s1021a-msi", }, ++ {}, ++}; ++ ++static struct platform_driver ls1_msi_driver = { ++ .driver = { ++ .name = "ls1-msi", ++ .of_match_table = ls1_msi_id, ++ }, ++}; ++ ++module_platform_driver_probe(ls1_msi_driver, ls1_msi_probe); ++ ++MODULE_AUTHOR("Minghuan Lian "); ++MODULE_DESCRIPTION("Freescale Layerscape 1 MSI controller driver"); ++MODULE_LICENSE("GPL v2"); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0133-arm64-layerscape-Enable-PCIe-for-Layerscape.patch b/target/linux/layerscape-64b/patches-4.1/0133-arm64-layerscape-Enable-PCIe-for-Layerscape.patch new file mode 100644 index 0000000..2190160 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0133-arm64-layerscape-Enable-PCIe-for-Layerscape.patch @@ -0,0 +1,25 @@ +From b5431baf0c155b99e8b2d8a2494af432fb1b48a2 Mon Sep 17 00:00:00 2001 +From: Mingkai Hu +Date: Thu, 19 Nov 2015 12:49:50 +0800 +Subject: [PATCH 133/151] arm64/layerscape: Enable PCIe for Layerscape + +Signed-off-by: Mingkai Hu +--- + arch/arm64/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index c7314c2..09add29 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -182,6 +182,7 @@ config ARCH_EXYNOS7 + + config ARCH_LAYERSCAPE + bool "Freescale Layerscape SoC family" ++ select PCI_LAYERSCAPE if PCI + help + This enables support for Freescale Layerscape SoC family + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0134-ls1043a-msi-add-ls1043a-MSI-support.patch b/target/linux/layerscape-64b/patches-4.1/0134-ls1043a-msi-add-ls1043a-MSI-support.patch new file mode 100644 index 0000000..2f8a886 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0134-ls1043a-msi-add-ls1043a-MSI-support.patch @@ -0,0 +1,174 @@ +From 15a5b4c64be5481a8670d8385b4144a1fb9e4b45 Mon Sep 17 00:00:00 2001 +From: Minghuan Lian +Date: Mon, 8 Jun 2015 09:46:58 +0800 +Subject: [PATCH 134/151] ls1043a/msi : add ls1043a MSI support + +Signed-off-by: Minghuan Lian +Signed-off-by: Mingkai Hu +--- + arch/arm64/Kconfig | 1 + + drivers/irqchip/irq-ls1-msi.c | 47 +++++++++++++++---------------------------- + 2 files changed, 17 insertions(+), 31 deletions(-) + +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index 09add29..bcc64d1 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -183,6 +183,7 @@ config ARCH_EXYNOS7 + config ARCH_LAYERSCAPE + bool "Freescale Layerscape SoC family" + select PCI_LAYERSCAPE if PCI ++ select LS1_MSI if PCI_MSI + help + This enables support for Freescale Layerscape SoC family + +diff --git a/drivers/irqchip/irq-ls1-msi.c b/drivers/irqchip/irq-ls1-msi.c +index 9b44349..8410d8a 100644 +--- a/drivers/irqchip/irq-ls1-msi.c ++++ b/drivers/irqchip/irq-ls1-msi.c +@@ -23,8 +23,6 @@ + + #define MAX_MSI_IRQS 32 + +-static int ls1_msi_idx; +- + struct ls1_msi { + char name[32]; + struct device_node *of_node; +@@ -47,7 +45,7 @@ static void ls1_msi_compose_msg(struct irq_data *data, struct msi_msg *msg) + + msg->address_hi = (u32) (addr >> 32); + msg->address_lo = (u32) (addr); +- msg->data = 0xb4; //data->hwirq; ++ msg->data = data->hwirq * 8; + } + + static int ls1_msi_set_affinity(struct irq_data *irq_data, +@@ -67,7 +65,7 @@ static int ls1_msi_domain_irq_alloc(struct irq_domain *domain, unsigned int virq + { + struct ls1_msi *msi_data = domain->host_data; + int i, pos; +- printk("\n\nls1_msi_domain_irq_alloc\n"); ++ + spin_lock(&msi_data->lock); + pos = bitmap_find_free_region(msi_data->bm, msi_data->nr_irqs, + order_base_2(nr_irqs)); +@@ -93,7 +91,6 @@ static void ls1_msi_domain_irq_free(struct irq_domain *domain, + struct ls1_msi *msi_data = irq_data_get_irq_chip_data(d); + int pos; + +- printk("\n\n\n\nls1_msi_domain_irq_free\n"); + pos = d->hwirq; + if (pos < 0 || pos >= msi_data->nr_irqs) { + pr_err("Failed to teardown msi. Invalid hwirq %d\n", pos); +@@ -118,15 +115,10 @@ static irqreturn_t ls1_msi_handler(int irq, void *arg) + irqreturn_t ret = IRQ_NONE; + + val = ioread32be(msi_data->msir); +- +- { /* ls1021A */ +- iowrite32be(cpu_to_be32(0xb4), msi_data->msir); +- val = 1; + pos = 0; +- } + + while ((pos = find_next_bit(&val, 32, pos)) != 32) { +- virq = irq_find_mapping(msi_data->parent, pos); ++ virq = irq_find_mapping(msi_data->parent, 31 - pos); + if (virq != NO_IRQ) { + generic_handle_irq(virq); + ret = IRQ_HANDLED; +@@ -137,26 +129,12 @@ static irqreturn_t ls1_msi_handler(int irq, void *arg) + return ret; + } + +-static void ls1021a_pcie_msi_fixup(struct ls1_msi *msi_data) +-{ +- int i; +- +- /* +- * LS1021A has only one MSI interrupt +- * Set all msi interrupts as used except the first one +- */ +- for (i = 1; i < msi_data->nr_irqs; i++) +- set_bit(i, msi_data->bm); +-} +- + static irq_hw_number_t ls1_msi_domain_ops_get_hwirq(struct msi_domain_info *info, + msi_alloc_info_t *arg) + { + struct ls1_msi *msi_data = container_of(info, struct ls1_msi, info); + +- printk("%s %d arg->hwirq=%d\n", __func__, __LINE__, arg->hwirq); + arg->hwirq = find_first_zero_bit(msi_data->bm, msi_data->nr_irqs); +- printk("%s %d arg->hwirq=%d\n", __func__, __LINE__, arg->hwirq); + + return arg->hwirq; + } +@@ -165,7 +143,7 @@ static void ls1_msi_domain_ops_free(struct irq_domain *domain, + struct msi_domain_info *info, + unsigned int virq) + { +- printk("ls1_msi_domain_ops_free\n"); ++ /* Nothing need to do */ + } + + static struct msi_domain_ops ls1_pci_msi_ops = { +@@ -211,7 +189,6 @@ static int ls1_msi_chip_init(struct ls1_msi *msi_data) + goto _err; + } + +- + ret = of_pci_msi_chip_add(&msi_data->mchip); + if (ret) { + pr_err("Failed to add msi_chip %s\n", msi_data->name); +@@ -233,6 +210,7 @@ static int __init ls1_msi_probe(struct platform_device *pdev) + { + struct ls1_msi *msi_data; + struct resource *res; ++ static int ls1_msi_idx; + int ret; + + msi_data = devm_kzalloc(&pdev->dev, sizeof(*msi_data), GFP_KERNEL); +@@ -248,13 +226,21 @@ static int __init ls1_msi_probe(struct platform_device *pdev) + dev_err(&pdev->dev, "missing msiir.\n"); + return -ENODEV; + } ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "msiir"); ++ if (!res) { ++ dev_err(&pdev->dev, "missing *msiir* space\n"); ++ return -ENODEV; ++ } ++ + msi_data->msiir_addr = res->start; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "msir"); + if (!res) { +- dev_err(&pdev->dev, "missing msir.\n"); ++ dev_err(&pdev->dev, "missing *msir* space\n"); + return -ENODEV; + } ++ + msi_data->msir = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(msi_data->msir)) + return PTR_ERR(msi_data->msir); +@@ -286,13 +272,12 @@ static int __init ls1_msi_probe(struct platform_device *pdev) + return -ENODEV; + } + +- ls1021a_pcie_msi_fixup(msi_data); +- + return ls1_msi_chip_init(msi_data); + } + + static struct of_device_id ls1_msi_id[] = { + { .compatible = "fsl,1s1021a-msi", }, ++ { .compatible = "fsl,1s1043a-msi", }, + {}, + }; + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0135-arm64-add-NO_IRQ-macro.patch b/target/linux/layerscape-64b/patches-4.1/0135-arm64-add-NO_IRQ-macro.patch new file mode 100644 index 0000000..ce95b14 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0135-arm64-add-NO_IRQ-macro.patch @@ -0,0 +1,32 @@ +From 7cb963b75c3d0b59c440771772d1421f238318f8 Mon Sep 17 00:00:00 2001 +From: Mingkai Hu +Date: Thu, 19 Nov 2015 15:25:37 +0800 +Subject: [PATCH 135/151] arm64: add NO_IRQ macro + +Signed-off-by: Mingkai Hu +--- + arch/arm64/include/asm/irq.h | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/arch/arm64/include/asm/irq.h b/arch/arm64/include/asm/irq.h +index bbb251b..f315b83 100644 +--- a/arch/arm64/include/asm/irq.h ++++ b/arch/arm64/include/asm/irq.h +@@ -5,6 +5,14 @@ + + #include + ++/* ++ * Use this value to indicate lack of interrupt ++ * capability ++ */ ++#ifndef NO_IRQ ++#define NO_IRQ ((unsigned int)(-1)) ++#endif ++ + struct pt_regs; + + extern void migrate_irqs(void); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0136-drivers-gpio-Port-gpio-driver-to-support-layerscape-.patch b/target/linux/layerscape-64b/patches-4.1/0136-drivers-gpio-Port-gpio-driver-to-support-layerscape-.patch new file mode 100644 index 0000000..c651b45 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0136-drivers-gpio-Port-gpio-driver-to-support-layerscape-.patch @@ -0,0 +1,296 @@ +From 69d50dd232f51651e3e6353413dea54e075d0408 Mon Sep 17 00:00:00 2001 +From: Liu Gang +Date: Thu, 14 Jan 2016 19:48:09 +0800 +Subject: [PATCH 136/151] drivers/gpio: Port gpio driver to support layerscape + platform + +Layerscape has the same ip block/controller as +GPIO on powerpc platform(MPC8XXX). + +So use portable i/o accessors, as in_be32/out_be32 +accessors are Power architecture specific whereas +ioread32/iowrite32 and ioread32be/iowrite32be are +available in other architectures. + +Layerscape GPIO controller's registers may be big +or little endian, so the code needs to get the +endian property from DTB, then make additional +functions to fit right register read/write +operations. + +Currently the code can support ls2080a GPIO with +little endian registers. And it can also work well +on other layerscape platform with big endian GPIO +registers. + +Signed-off-by: Liu Gang +--- + drivers/gpio/Kconfig | 7 ++-- + drivers/gpio/gpio-mpc8xxx.c | 87 +++++++++++++++++++++++++++++++++------------ + 2 files changed, 68 insertions(+), 26 deletions(-) + +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index caefe80..438ad9a 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -265,12 +265,13 @@ config GPIO_MPC5200 + depends on PPC_MPC52xx + + config GPIO_MPC8XXX +- bool "MPC512x/MPC8xxx GPIO support" ++ bool "MPC512x/MPC8xxx/QorIQ GPIO support" + depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \ +- FSL_SOC_BOOKE || PPC_86xx ++ FSL_SOC_BOOKE || PPC_86xx || ARCH_LAYERSCAPE || ARM || \ ++ COMPILE_TEST + help + Say Y here if you're going to use hardware that connects to the +- MPC512x/831x/834x/837x/8572/8610 GPIOs. ++ MPC512x/831x/834x/837x/8572/8610/QorIQ GPIOs. + + config GPIO_MSM_V2 + tristate "Qualcomm MSM GPIO v2" +diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c +index a65b751..2cf1077 100644 +--- a/drivers/gpio/gpio-mpc8xxx.c ++++ b/drivers/gpio/gpio-mpc8xxx.c +@@ -1,5 +1,5 @@ + /* +- * GPIOs on MPC512x/8349/8572/8610 and compatible ++ * GPIOs on MPC512x/8349/8572/8610/QorIQ and compatible + * + * Copyright (C) 2008 Peter Korsgaard + * +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + #define MPC8XXX_GPIO_PINS 32 + +@@ -44,6 +45,27 @@ struct mpc8xxx_gpio_chip { + const void *of_dev_id_data; + }; + ++static bool gpio_little_endian; ++static inline u32 gpio_in32(void __iomem *addr) ++{ ++ u32 val; ++ ++ if (gpio_little_endian) ++ val = ioread32(addr); ++ else ++ val = ioread32be(addr); ++ ++ return val; ++} ++ ++static inline void gpio_out32(u32 val, void __iomem *addr) ++{ ++ if (gpio_little_endian) ++ iowrite32(val, addr); ++ else ++ iowrite32be(val, addr); ++} ++ + static inline u32 mpc8xxx_gpio2mask(unsigned int gpio) + { + return 1u << (MPC8XXX_GPIO_PINS - 1 - gpio); +@@ -59,9 +81,17 @@ static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm) + { + struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); + +- mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT); ++ mpc8xxx_gc->data = gpio_in32(mm->regs + GPIO_DAT); + } + ++/* Generic set and clear bits accessor ports */ ++#define bgpio_setbits32(_addr, _v) \ ++ gpio_out32(gpio_in32(_addr) | (_v), (_addr)) ++#define bgpio_clrbits32(_addr, _v) \ ++ gpio_out32(gpio_in32(_addr) & ~(_v), (_addr)) ++#define bgpio_clrsetbits32(addr, clear, set) \ ++ gpio_out32((gpio_in32(addr) & ~(clear)) | (set), (addr)) ++ + /* Workaround GPIO 1 errata on MPC8572/MPC8536. The status of GPIOs + * defined as output cannot be determined by reading GPDAT register, + * so we use shadow data register instead. The status of input pins +@@ -74,9 +104,9 @@ static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio) + struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); + u32 out_mask, out_shadow; + +- out_mask = in_be32(mm->regs + GPIO_DIR); ++ out_mask = gpio_in32(mm->regs + GPIO_DIR); + +- val = in_be32(mm->regs + GPIO_DAT) & ~out_mask; ++ val = gpio_in32(mm->regs + GPIO_DAT) & ~out_mask; + out_shadow = mpc8xxx_gc->data & out_mask; + + return (val | out_shadow) & mpc8xxx_gpio2mask(gpio); +@@ -86,7 +116,7 @@ static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio) + { + struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); + +- return in_be32(mm->regs + GPIO_DAT) & mpc8xxx_gpio2mask(gpio); ++ return gpio_in32(mm->regs + GPIO_DAT) & mpc8xxx_gpio2mask(gpio); + } + + static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) +@@ -102,7 +132,7 @@ static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) + else + mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask(gpio); + +- out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data); ++ gpio_out32(mpc8xxx_gc->data, mm->regs + GPIO_DAT); + + spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + } +@@ -128,7 +158,7 @@ static void mpc8xxx_gpio_set_multiple(struct gpio_chip *gc, + } + } + +- out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data); ++ gpio_out32(mpc8xxx_gc->data, mm->regs + GPIO_DAT); + + spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + } +@@ -141,7 +171,7 @@ static int mpc8xxx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) + + spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + +- clrbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); ++ bgpio_clrbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); + + spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + +@@ -158,7 +188,7 @@ static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val + + spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + +- setbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); ++ bgpio_setbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); + + spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + +@@ -192,7 +222,8 @@ static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc) + struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; + unsigned int mask; + +- mask = in_be32(mm->regs + GPIO_IER) & in_be32(mm->regs + GPIO_IMR); ++ mask = gpio_in32(mm->regs + GPIO_IER) ++ & gpio_in32(mm->regs + GPIO_IMR); + if (mask) + generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq, + 32 - ffs(mask))); +@@ -208,7 +239,8 @@ static void mpc8xxx_irq_unmask(struct irq_data *d) + + spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + +- setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d))); ++ bgpio_setbits32(mm->regs + GPIO_IMR, ++ mpc8xxx_gpio2mask(irqd_to_hwirq(d))); + + spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + } +@@ -221,7 +253,8 @@ static void mpc8xxx_irq_mask(struct irq_data *d) + + spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + +- clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(irqd_to_hwirq(d))); ++ bgpio_clrbits32(mm->regs + GPIO_IMR, ++ mpc8xxx_gpio2mask(irqd_to_hwirq(d))); + + spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + } +@@ -231,7 +264,7 @@ static void mpc8xxx_irq_ack(struct irq_data *d) + struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d); + struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc; + +- out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(irqd_to_hwirq(d))); ++ gpio_out32(mpc8xxx_gpio2mask(irqd_to_hwirq(d)), mm->regs + GPIO_IER); + } + + static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type) +@@ -243,15 +276,15 @@ static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type) + switch (flow_type) { + case IRQ_TYPE_EDGE_FALLING: + spin_lock_irqsave(&mpc8xxx_gc->lock, flags); +- setbits32(mm->regs + GPIO_ICR, +- mpc8xxx_gpio2mask(irqd_to_hwirq(d))); ++ bgpio_setbits32(mm->regs + GPIO_ICR, ++ mpc8xxx_gpio2mask(irqd_to_hwirq(d))); + spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + break; + + case IRQ_TYPE_EDGE_BOTH: + spin_lock_irqsave(&mpc8xxx_gc->lock, flags); +- clrbits32(mm->regs + GPIO_ICR, +- mpc8xxx_gpio2mask(irqd_to_hwirq(d))); ++ bgpio_clrbits32(mm->regs + GPIO_ICR, ++ mpc8xxx_gpio2mask(irqd_to_hwirq(d))); + spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + break; + +@@ -283,20 +316,20 @@ static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type) + case IRQ_TYPE_EDGE_FALLING: + case IRQ_TYPE_LEVEL_LOW: + spin_lock_irqsave(&mpc8xxx_gc->lock, flags); +- clrsetbits_be32(reg, 3 << shift, 2 << shift); ++ bgpio_clrsetbits32(reg, 3 << shift, 2 << shift); + spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + break; + + case IRQ_TYPE_EDGE_RISING: + case IRQ_TYPE_LEVEL_HIGH: + spin_lock_irqsave(&mpc8xxx_gc->lock, flags); +- clrsetbits_be32(reg, 3 << shift, 1 << shift); ++ bgpio_clrsetbits32(reg, 3 << shift, 1 << shift); + spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + break; + + case IRQ_TYPE_EDGE_BOTH: + spin_lock_irqsave(&mpc8xxx_gc->lock, flags); +- clrbits32(reg, 3 << shift); ++ bgpio_clrbits32(reg, 3 << shift); + spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + break; + +@@ -364,6 +397,14 @@ static int mpc8xxx_probe(struct platform_device *pdev) + mm_gc = &mpc8xxx_gc->mm_gc; + gc = &mm_gc->gc; + ++ if (of_property_read_bool(np, "little-endian")) { ++ gpio_little_endian = true; ++ dev_dbg(&pdev->dev, "GPIO REGISTERS are LITTLE endian\n"); ++ } else { ++ gpio_little_endian = false; ++ dev_dbg(&pdev->dev, "GPIO REGISTERS are BIG endian\n"); ++ } ++ + mm_gc->save_regs = mpc8xxx_gpio_save_regs; + gc->ngpio = MPC8XXX_GPIO_PINS; + gc->direction_input = mpc8xxx_gpio_dir_in; +@@ -380,7 +421,7 @@ static int mpc8xxx_probe(struct platform_device *pdev) + return ret; + + mpc8xxx_gc->irqn = irq_of_parse_and_map(np, 0); +- if (mpc8xxx_gc->irqn == NO_IRQ) ++ if (mpc8xxx_gc->irqn == 0) + return 0; + + mpc8xxx_gc->irq = irq_domain_add_linear(np, MPC8XXX_GPIO_PINS, +@@ -393,8 +434,8 @@ static int mpc8xxx_probe(struct platform_device *pdev) + mpc8xxx_gc->of_dev_id_data = id->data; + + /* ack and mask all irqs */ +- out_be32(mm_gc->regs + GPIO_IER, 0xffffffff); +- out_be32(mm_gc->regs + GPIO_IMR, 0); ++ gpio_out32(0xffffffff, mm_gc->regs + GPIO_IER); ++ gpio_out32(0, mm_gc->regs + GPIO_IMR); + + irq_set_handler_data(mpc8xxx_gc->irqn, mpc8xxx_gc); + irq_set_chained_handler(mpc8xxx_gc->irqn, mpc8xxx_gpio_irq_cascade); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0137-layerscape-dts-Update-GPIO-node.patch b/target/linux/layerscape-64b/patches-4.1/0137-layerscape-dts-Update-GPIO-node.patch new file mode 100644 index 0000000..3527c7d --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0137-layerscape-dts-Update-GPIO-node.patch @@ -0,0 +1,72 @@ +From 2be197cb1ca475abd2777432028b550eb9a9cdf0 Mon Sep 17 00:00:00 2001 +From: Liu Gang +Date: Wed, 3 Feb 2016 14:57:11 +0800 +Subject: [PATCH 137/151] layerscape/dts: Update GPIO node + +commit 62a8d1cd36b53b69e1814f1f24821ae43cc88307 +[Only picked ls1043a related content] + +For ls1043a and ls2085a, the GPIO compatible should be +changed to "fsl,qoriq-gpio". + +For ls2080a and ls2085a, the little-endian property +should be added since the GPIO register working on +little endian mode on the two platforms. + +Signed-off-by: Liu Gang +Integrated-by: Jilong Guo +--- + arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +index d7d2fa6..15e3e4f 100644 +--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi ++++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +@@ -608,8 +608,8 @@ + clocks = <&clockgen 4 0>; + }; + +- gpio1: gpio at 2300000 { +- compatible = "fsl,ls1043a-gpio"; ++ gpio0: gpio at 2300000 { ++ compatible = "fsl,qoriq-gpio"; + reg = <0x0 0x2300000 0x0 0x10000>; + interrupts = <0 66 0x4>; + gpio-controller; +@@ -618,8 +618,8 @@ + #interrupt-cells = <2>; + }; + +- gpio2: gpio at 2310000 { +- compatible = "fsl,ls1043a-gpio"; ++ gpio1: gpio at 2310000 { ++ compatible = "fsl,qoriq-gpio"; + reg = <0x0 0x2310000 0x0 0x10000>; + interrupts = <0 67 0x4>; + gpio-controller; +@@ -628,8 +628,8 @@ + #interrupt-cells = <2>; + }; + +- gpio3: gpio at 2320000 { +- compatible = "fsl,ls1043a-gpio"; ++ gpio2: gpio at 2320000 { ++ compatible = "fsl,qoriq-gpio"; + reg = <0x0 0x2320000 0x0 0x10000>; + interrupts = <0 68 0x4>; + gpio-controller; +@@ -638,8 +638,8 @@ + #interrupt-cells = <2>; + }; + +- gpio4: gpio at 2330000 { +- compatible = "fsl,ls1043a-gpio"; ++ gpio3: gpio at 2330000 { ++ compatible = "fsl,qoriq-gpio"; + reg = <0x0 0x2330000 0x0 0x10000>; + interrupts = <0 134 0x4>; + gpio-controller; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0138-fsl_ifc-Change-IO-accessor-based-on-endianness.patch b/target/linux/layerscape-64b/patches-4.1/0138-fsl_ifc-Change-IO-accessor-based-on-endianness.patch new file mode 100644 index 0000000..5e7f7e5 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0138-fsl_ifc-Change-IO-accessor-based-on-endianness.patch @@ -0,0 +1,686 @@ +From e52f875e11c53a28dc0cd2b664aae7caf1d4af7a Mon Sep 17 00:00:00 2001 +From: Jaiprakash Singh +Date: Wed, 20 May 2015 21:17:11 -0500 +Subject: [PATCH 138/151] fsl_ifc: Change IO accessor based on endianness + +IFC IO accressor are set at run time based +on IFC IP registers endianness.IFC node in +DTS file contains information about +endianness. + +Signed-off-by: Jaiprakash Singh +Signed-off-by: Scott Wood +Acked-by: Brian Norris +Signed-off-by: Raghav Dogra +--- + .../bindings/memory-controllers/fsl/ifc.txt | 3 + + drivers/memory/fsl_ifc.c | 43 ++-- + drivers/mtd/nand/fsl_ifc_nand.c | 258 +++++++++++---------- + include/linux/fsl_ifc.h | 50 ++++ + 4 files changed, 213 insertions(+), 141 deletions(-) + +diff --git a/Documentation/devicetree/bindings/memory-controllers/fsl/ifc.txt b/Documentation/devicetree/bindings/memory-controllers/fsl/ifc.txt +index d5e3704..89427b0 100644 +--- a/Documentation/devicetree/bindings/memory-controllers/fsl/ifc.txt ++++ b/Documentation/devicetree/bindings/memory-controllers/fsl/ifc.txt +@@ -18,6 +18,8 @@ Properties: + interrupt (NAND_EVTER_STAT). If there is only one, + that interrupt reports both types of event. + ++- little-endian : If this property is absent, the big-endian mode will ++ be in use as default for registers. + + - ranges : Each range corresponds to a single chipselect, and covers + the entire access window as configured. +@@ -34,6 +36,7 @@ Example: + #size-cells = <1>; + reg = <0x0 0xffe1e000 0 0x2000>; + interrupts = <16 2 19 2>; ++ little-endian; + + /* NOR, NAND Flashes and CPLD on board */ + ranges = <0x0 0x0 0x0 0xee000000 0x02000000 +diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c +index 5f6d42d..8436c59 100644 +--- a/drivers/memory/fsl_ifc.c ++++ b/drivers/memory/fsl_ifc.c +@@ -62,7 +62,7 @@ int fsl_ifc_find(phys_addr_t addr_base) + return -ENODEV; + + for (i = 0; i < fsl_ifc_ctrl_dev->banks; i++) { +- u32 cspr = in_be32(&fsl_ifc_ctrl_dev->regs->cspr_cs[i].cspr); ++ u32 cspr = ifc_in32(&fsl_ifc_ctrl_dev->regs->cspr_cs[i].cspr); + if (cspr & CSPR_V && (cspr & CSPR_BA) == + convert_ifc_address(addr_base)) + return i; +@@ -79,16 +79,16 @@ static int fsl_ifc_ctrl_init(struct fsl_ifc_ctrl *ctrl) + /* + * Clear all the common status and event registers + */ +- if (in_be32(&ifc->cm_evter_stat) & IFC_CM_EVTER_STAT_CSER) +- out_be32(&ifc->cm_evter_stat, IFC_CM_EVTER_STAT_CSER); ++ if (ifc_in32(&ifc->cm_evter_stat) & IFC_CM_EVTER_STAT_CSER) ++ ifc_out32(IFC_CM_EVTER_STAT_CSER, &ifc->cm_evter_stat); + + /* enable all error and events */ +- out_be32(&ifc->cm_evter_en, IFC_CM_EVTER_EN_CSEREN); ++ ifc_out32(IFC_CM_EVTER_EN_CSEREN, &ifc->cm_evter_en); + + /* enable all error and event interrupts */ +- out_be32(&ifc->cm_evter_intr_en, IFC_CM_EVTER_INTR_EN_CSERIREN); +- out_be32(&ifc->cm_erattr0, 0x0); +- out_be32(&ifc->cm_erattr1, 0x0); ++ ifc_out32(IFC_CM_EVTER_INTR_EN_CSERIREN, &ifc->cm_evter_intr_en); ++ ifc_out32(0x0, &ifc->cm_erattr0); ++ ifc_out32(0x0, &ifc->cm_erattr1); + + return 0; + } +@@ -127,9 +127,9 @@ static u32 check_nand_stat(struct fsl_ifc_ctrl *ctrl) + + spin_lock_irqsave(&nand_irq_lock, flags); + +- stat = in_be32(&ifc->ifc_nand.nand_evter_stat); ++ stat = ifc_in32(&ifc->ifc_nand.nand_evter_stat); + if (stat) { +- out_be32(&ifc->ifc_nand.nand_evter_stat, stat); ++ ifc_out32(stat, &ifc->ifc_nand.nand_evter_stat); + ctrl->nand_stat = stat; + wake_up(&ctrl->nand_wait); + } +@@ -161,16 +161,16 @@ static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data) + irqreturn_t ret = IRQ_NONE; + + /* read for chip select error */ +- cs_err = in_be32(&ifc->cm_evter_stat); ++ cs_err = ifc_in32(&ifc->cm_evter_stat); + if (cs_err) { + dev_err(ctrl->dev, "transaction sent to IFC is not mapped to" + "any memory bank 0x%08X\n", cs_err); + /* clear the chip select error */ +- out_be32(&ifc->cm_evter_stat, IFC_CM_EVTER_STAT_CSER); ++ ifc_out32(IFC_CM_EVTER_STAT_CSER, &ifc->cm_evter_stat); + + /* read error attribute registers print the error information */ +- status = in_be32(&ifc->cm_erattr0); +- err_addr = in_be32(&ifc->cm_erattr1); ++ status = ifc_in32(&ifc->cm_erattr0); ++ err_addr = ifc_in32(&ifc->cm_erattr1); + + if (status & IFC_CM_ERATTR0_ERTYP_READ) + dev_err(ctrl->dev, "Read transaction error" +@@ -231,6 +231,23 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) + goto err; + } + ++ version = ifc_in32(&fsl_ifc_ctrl_dev->regs->ifc_rev) & ++ FSL_IFC_VERSION_MASK; ++ banks = (version == FSL_IFC_VERSION_1_0_0) ? 4 : 8; ++ dev_info(&dev->dev, "IFC version %d.%d, %d banks\n", ++ version >> 24, (version >> 16) & 0xf, banks); ++ ++ fsl_ifc_ctrl_dev->version = version; ++ fsl_ifc_ctrl_dev->banks = banks; ++ ++ if (of_property_read_bool(dev->dev.of_node, "little-endian")) { ++ fsl_ifc_ctrl_dev->little_endian = true; ++ dev_dbg(&dev->dev, "IFC REGISTERS are LITTLE endian\n"); ++ } else { ++ fsl_ifc_ctrl_dev->little_endian = false; ++ dev_dbg(&dev->dev, "IFC REGISTERS are BIG endian\n"); ++ } ++ + version = ioread32be(&fsl_ifc_ctrl_dev->regs->ifc_rev) & + FSL_IFC_VERSION_MASK; + banks = (version == FSL_IFC_VERSION_1_0_0) ? 4 : 8; +diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c +index 51394e5..a4e27e8 100644 +--- a/drivers/mtd/nand/fsl_ifc_nand.c ++++ b/drivers/mtd/nand/fsl_ifc_nand.c +@@ -238,8 +238,8 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) + + ifc_nand_ctrl->page = page_addr; + /* Program ROW0/COL0 */ +- iowrite32be(page_addr, &ifc->ifc_nand.row0); +- iowrite32be((oob ? IFC_NAND_COL_MS : 0) | column, &ifc->ifc_nand.col0); ++ ifc_out32(page_addr, &ifc->ifc_nand.row0); ++ ifc_out32((oob ? IFC_NAND_COL_MS : 0) | column, &ifc->ifc_nand.col0); + + buf_num = page_addr & priv->bufnum_mask; + +@@ -301,19 +301,19 @@ static void fsl_ifc_run_command(struct mtd_info *mtd) + int i; + + /* set the chip select for NAND Transaction */ +- iowrite32be(priv->bank << IFC_NAND_CSEL_SHIFT, +- &ifc->ifc_nand.nand_csel); ++ ifc_out32(priv->bank << IFC_NAND_CSEL_SHIFT, ++ &ifc->ifc_nand.nand_csel); + + dev_vdbg(priv->dev, + "%s: fir0=%08x fcr0=%08x\n", + __func__, +- ioread32be(&ifc->ifc_nand.nand_fir0), +- ioread32be(&ifc->ifc_nand.nand_fcr0)); ++ ifc_in32(&ifc->ifc_nand.nand_fir0), ++ ifc_in32(&ifc->ifc_nand.nand_fcr0)); + + ctrl->nand_stat = 0; + + /* start read/write seq */ +- iowrite32be(IFC_NAND_SEQ_STRT_FIR_STRT, &ifc->ifc_nand.nandseq_strt); ++ ifc_out32(IFC_NAND_SEQ_STRT_FIR_STRT, &ifc->ifc_nand.nandseq_strt); + + /* wait for command complete flag or timeout */ + wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat, +@@ -336,7 +336,7 @@ static void fsl_ifc_run_command(struct mtd_info *mtd) + int sector_end = sector + chip->ecc.steps - 1; + + for (i = sector / 4; i <= sector_end / 4; i++) +- eccstat[i] = ioread32be(&ifc->ifc_nand.nand_eccstat[i]); ++ eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]); + + for (i = sector; i <= sector_end; i++) { + errors = check_read_ecc(mtd, ctrl, eccstat, i); +@@ -376,33 +376,33 @@ static void fsl_ifc_do_read(struct nand_chip *chip, + + /* Program FIR/IFC_NAND_FCR0 for Small/Large page */ + if (mtd->writesize > 512) { +- iowrite32be((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | +- (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | +- (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | +- (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) | +- (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT), +- &ifc->ifc_nand.nand_fir0); +- iowrite32be(0x0, &ifc->ifc_nand.nand_fir1); +- +- iowrite32be((NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) | +- (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT), +- &ifc->ifc_nand.nand_fcr0); ++ ifc_out32((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | ++ (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | ++ (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | ++ (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) | ++ (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT), ++ &ifc->ifc_nand.nand_fir0); ++ ifc_out32(0x0, &ifc->ifc_nand.nand_fir1); ++ ++ ifc_out32((NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) | ++ (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT), ++ &ifc->ifc_nand.nand_fcr0); + } else { +- iowrite32be((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | +- (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | +- (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | +- (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT), +- &ifc->ifc_nand.nand_fir0); +- iowrite32be(0x0, &ifc->ifc_nand.nand_fir1); ++ ifc_out32((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | ++ (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | ++ (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | ++ (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT), ++ &ifc->ifc_nand.nand_fir0); ++ ifc_out32(0x0, &ifc->ifc_nand.nand_fir1); + + if (oob) +- iowrite32be(NAND_CMD_READOOB << +- IFC_NAND_FCR0_CMD0_SHIFT, +- &ifc->ifc_nand.nand_fcr0); ++ ifc_out32(NAND_CMD_READOOB << ++ IFC_NAND_FCR0_CMD0_SHIFT, ++ &ifc->ifc_nand.nand_fcr0); + else +- iowrite32be(NAND_CMD_READ0 << +- IFC_NAND_FCR0_CMD0_SHIFT, +- &ifc->ifc_nand.nand_fcr0); ++ ifc_out32(NAND_CMD_READ0 << ++ IFC_NAND_FCR0_CMD0_SHIFT, ++ &ifc->ifc_nand.nand_fcr0); + } + } + +@@ -422,7 +422,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, + switch (command) { + /* READ0 read the entire buffer to use hardware ECC. */ + case NAND_CMD_READ0: +- iowrite32be(0, &ifc->ifc_nand.nand_fbcr); ++ ifc_out32(0, &ifc->ifc_nand.nand_fbcr); + set_addr(mtd, 0, page_addr, 0); + + ifc_nand_ctrl->read_bytes = mtd->writesize + mtd->oobsize; +@@ -437,7 +437,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, + + /* READOOB reads only the OOB because no ECC is performed. */ + case NAND_CMD_READOOB: +- iowrite32be(mtd->oobsize - column, &ifc->ifc_nand.nand_fbcr); ++ ifc_out32(mtd->oobsize - column, &ifc->ifc_nand.nand_fbcr); + set_addr(mtd, column, page_addr, 1); + + ifc_nand_ctrl->read_bytes = mtd->writesize + mtd->oobsize; +@@ -453,19 +453,19 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, + if (command == NAND_CMD_PARAM) + timing = IFC_FIR_OP_RBCD; + +- iowrite32be((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | +- (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | +- (timing << IFC_NAND_FIR0_OP2_SHIFT), +- &ifc->ifc_nand.nand_fir0); +- iowrite32be(command << IFC_NAND_FCR0_CMD0_SHIFT, +- &ifc->ifc_nand.nand_fcr0); +- iowrite32be(column, &ifc->ifc_nand.row3); ++ ifc_out32((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | ++ (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | ++ (timing << IFC_NAND_FIR0_OP2_SHIFT), ++ &ifc->ifc_nand.nand_fir0); ++ ifc_out32(command << IFC_NAND_FCR0_CMD0_SHIFT, ++ &ifc->ifc_nand.nand_fcr0); ++ ifc_out32(column, &ifc->ifc_nand.row3); + + /* + * although currently it's 8 bytes for READID, we always read + * the maximum 256 bytes(for PARAM) + */ +- iowrite32be(256, &ifc->ifc_nand.nand_fbcr); ++ ifc_out32(256, &ifc->ifc_nand.nand_fbcr); + ifc_nand_ctrl->read_bytes = 256; + + set_addr(mtd, 0, 0, 0); +@@ -480,16 +480,16 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, + + /* ERASE2 uses the block and page address from ERASE1 */ + case NAND_CMD_ERASE2: +- iowrite32be((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | +- (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) | +- (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT), +- &ifc->ifc_nand.nand_fir0); ++ ifc_out32((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | ++ (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) | ++ (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT), ++ &ifc->ifc_nand.nand_fir0); + +- iowrite32be((NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) | +- (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT), +- &ifc->ifc_nand.nand_fcr0); ++ ifc_out32((NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) | ++ (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT), ++ &ifc->ifc_nand.nand_fcr0); + +- iowrite32be(0, &ifc->ifc_nand.nand_fbcr); ++ ifc_out32(0, &ifc->ifc_nand.nand_fbcr); + ifc_nand_ctrl->read_bytes = 0; + fsl_ifc_run_command(mtd); + return; +@@ -506,19 +506,18 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, + (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) | + (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT); + +- iowrite32be( +- (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | +- (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | +- (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | +- (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) | +- (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT), +- &ifc->ifc_nand.nand_fir0); +- iowrite32be( +- (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) | +- (IFC_FIR_OP_RDSTAT << +- IFC_NAND_FIR1_OP6_SHIFT) | +- (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT), +- &ifc->ifc_nand.nand_fir1); ++ ifc_out32( ++ (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | ++ (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | ++ (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | ++ (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) | ++ (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT), ++ &ifc->ifc_nand.nand_fir0); ++ ifc_out32( ++ (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) | ++ (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR1_OP6_SHIFT) | ++ (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT), ++ &ifc->ifc_nand.nand_fir1); + } else { + nand_fcr0 = ((NAND_CMD_PAGEPROG << + IFC_NAND_FCR0_CMD1_SHIFT) | +@@ -527,20 +526,19 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, + (NAND_CMD_STATUS << + IFC_NAND_FCR0_CMD3_SHIFT)); + +- iowrite32be( ++ ifc_out32( + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) | + (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) | + (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) | + (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT), + &ifc->ifc_nand.nand_fir0); +- iowrite32be( +- (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) | +- (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) | +- (IFC_FIR_OP_RDSTAT << +- IFC_NAND_FIR1_OP7_SHIFT) | +- (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT), +- &ifc->ifc_nand.nand_fir1); ++ ifc_out32( ++ (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) | ++ (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) | ++ (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR1_OP7_SHIFT) | ++ (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT), ++ &ifc->ifc_nand.nand_fir1); + + if (column >= mtd->writesize) + nand_fcr0 |= +@@ -555,7 +553,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, + column -= mtd->writesize; + ifc_nand_ctrl->oob = 1; + } +- iowrite32be(nand_fcr0, &ifc->ifc_nand.nand_fcr0); ++ ifc_out32(nand_fcr0, &ifc->ifc_nand.nand_fcr0); + set_addr(mtd, column, page_addr, ifc_nand_ctrl->oob); + return; + } +@@ -563,24 +561,26 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, + /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ + case NAND_CMD_PAGEPROG: { + if (ifc_nand_ctrl->oob) { +- iowrite32be(ifc_nand_ctrl->index - +- ifc_nand_ctrl->column, +- &ifc->ifc_nand.nand_fbcr); ++ ifc_out32(ifc_nand_ctrl->index - ++ ifc_nand_ctrl->column, ++ &ifc->ifc_nand.nand_fbcr); + } else { +- iowrite32be(0, &ifc->ifc_nand.nand_fbcr); ++ ifc_out32(0, &ifc->ifc_nand.nand_fbcr); + } + + fsl_ifc_run_command(mtd); + return; + } + +- case NAND_CMD_STATUS: +- iowrite32be((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | +- (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT), +- &ifc->ifc_nand.nand_fir0); +- iowrite32be(NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT, +- &ifc->ifc_nand.nand_fcr0); +- iowrite32be(1, &ifc->ifc_nand.nand_fbcr); ++ case NAND_CMD_STATUS: { ++ void __iomem *addr; ++ ++ ifc_out32((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | ++ (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT), ++ &ifc->ifc_nand.nand_fir0); ++ ifc_out32(NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT, ++ &ifc->ifc_nand.nand_fcr0); ++ ifc_out32(1, &ifc->ifc_nand.nand_fbcr); + set_addr(mtd, 0, 0, 0); + ifc_nand_ctrl->read_bytes = 1; + +@@ -590,17 +590,19 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, + * The chip always seems to report that it is + * write-protected, even when it is not. + */ ++ addr = ifc_nand_ctrl->addr; + if (chip->options & NAND_BUSWIDTH_16) +- setbits16(ifc_nand_ctrl->addr, NAND_STATUS_WP); ++ ifc_out16(ifc_in16(addr) | (NAND_STATUS_WP), addr); + else +- setbits8(ifc_nand_ctrl->addr, NAND_STATUS_WP); ++ ifc_out8(ifc_in8(addr) | (NAND_STATUS_WP), addr); + return; ++ } + + case NAND_CMD_RESET: +- iowrite32be(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT, +- &ifc->ifc_nand.nand_fir0); +- iowrite32be(NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT, +- &ifc->ifc_nand.nand_fcr0); ++ ifc_out32(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT, ++ &ifc->ifc_nand.nand_fir0); ++ ifc_out32(NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT, ++ &ifc->ifc_nand.nand_fcr0); + fsl_ifc_run_command(mtd); + return; + +@@ -658,7 +660,7 @@ static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd) + */ + if (ifc_nand_ctrl->index < ifc_nand_ctrl->read_bytes) { + offset = ifc_nand_ctrl->index++; +- return in_8(ifc_nand_ctrl->addr + offset); ++ return ifc_in8(ifc_nand_ctrl->addr + offset); + } + + dev_err(priv->dev, "%s: beyond end of buffer\n", __func__); +@@ -680,7 +682,7 @@ static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd) + * next byte. + */ + if (ifc_nand_ctrl->index < ifc_nand_ctrl->read_bytes) { +- data = in_be16(ifc_nand_ctrl->addr + ifc_nand_ctrl->index); ++ data = ifc_in16(ifc_nand_ctrl->addr + ifc_nand_ctrl->index); + ifc_nand_ctrl->index += 2; + return (uint8_t) data; + } +@@ -726,18 +728,18 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) + u32 nand_fsr; + + /* Use READ_STATUS command, but wait for the device to be ready */ +- iowrite32be((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | +- (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT), +- &ifc->ifc_nand.nand_fir0); +- iowrite32be(NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT, +- &ifc->ifc_nand.nand_fcr0); +- iowrite32be(1, &ifc->ifc_nand.nand_fbcr); ++ ifc_out32((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | ++ (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT), ++ &ifc->ifc_nand.nand_fir0); ++ ifc_out32(NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT, ++ &ifc->ifc_nand.nand_fcr0); ++ ifc_out32(1, &ifc->ifc_nand.nand_fbcr); + set_addr(mtd, 0, 0, 0); + ifc_nand_ctrl->read_bytes = 1; + + fsl_ifc_run_command(mtd); + +- nand_fsr = ioread32be(&ifc->ifc_nand.nand_fsr); ++ nand_fsr = ifc_in32(&ifc->ifc_nand.nand_fsr); + + /* + * The chip always seems to report that it is +@@ -829,34 +831,34 @@ static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv) + uint32_t cs = priv->bank; + + /* Save CSOR and CSOR_ext */ +- csor = ioread32be(&ifc->csor_cs[cs].csor); +- csor_ext = ioread32be(&ifc->csor_cs[cs].csor_ext); ++ csor = ifc_in32(&ifc->csor_cs[cs].csor); ++ csor_ext = ifc_in32(&ifc->csor_cs[cs].csor_ext); + + /* chage PageSize 8K and SpareSize 1K*/ + csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000; +- iowrite32be(csor_8k, &ifc->csor_cs[cs].csor); +- iowrite32be(0x0000400, &ifc->csor_cs[cs].csor_ext); ++ ifc_out32(csor_8k, &ifc->csor_cs[cs].csor); ++ ifc_out32(0x0000400, &ifc->csor_cs[cs].csor_ext); + + /* READID */ +- iowrite32be((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | +- (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | +- (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT), +- &ifc->ifc_nand.nand_fir0); +- iowrite32be(NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT, +- &ifc->ifc_nand.nand_fcr0); +- iowrite32be(0x0, &ifc->ifc_nand.row3); ++ ifc_out32((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | ++ (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | ++ (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT), ++ &ifc->ifc_nand.nand_fir0); ++ ifc_out32(NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT, ++ &ifc->ifc_nand.nand_fcr0); ++ ifc_out32(0x0, &ifc->ifc_nand.row3); + +- iowrite32be(0x0, &ifc->ifc_nand.nand_fbcr); ++ ifc_out32(0x0, &ifc->ifc_nand.nand_fbcr); + + /* Program ROW0/COL0 */ +- iowrite32be(0x0, &ifc->ifc_nand.row0); +- iowrite32be(0x0, &ifc->ifc_nand.col0); ++ ifc_out32(0x0, &ifc->ifc_nand.row0); ++ ifc_out32(0x0, &ifc->ifc_nand.col0); + + /* set the chip select for NAND Transaction */ +- iowrite32be(cs << IFC_NAND_CSEL_SHIFT, &ifc->ifc_nand.nand_csel); ++ ifc_out32(cs << IFC_NAND_CSEL_SHIFT, &ifc->ifc_nand.nand_csel); + + /* start read seq */ +- iowrite32be(IFC_NAND_SEQ_STRT_FIR_STRT, &ifc->ifc_nand.nandseq_strt); ++ ifc_out32(IFC_NAND_SEQ_STRT_FIR_STRT, &ifc->ifc_nand.nandseq_strt); + + /* wait for command complete flag or timeout */ + wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat, +@@ -866,8 +868,8 @@ static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv) + printk(KERN_ERR "fsl-ifc: Failed to Initialise SRAM\n"); + + /* Restore CSOR and CSOR_ext */ +- iowrite32be(csor, &ifc->csor_cs[cs].csor); +- iowrite32be(csor_ext, &ifc->csor_cs[cs].csor_ext); ++ ifc_out32(csor, &ifc->csor_cs[cs].csor); ++ ifc_out32(csor_ext, &ifc->csor_cs[cs].csor_ext); + } + + static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) +@@ -884,7 +886,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) + + /* fill in nand_chip structure */ + /* set up function call table */ +- if ((ioread32be(&ifc->cspr_cs[priv->bank].cspr)) & CSPR_PORT_SIZE_16) ++ if ((ifc_in32(&ifc->cspr_cs[priv->bank].cspr)) & CSPR_PORT_SIZE_16) + chip->read_byte = fsl_ifc_read_byte16; + else + chip->read_byte = fsl_ifc_read_byte; +@@ -898,13 +900,13 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) + chip->bbt_td = &bbt_main_descr; + chip->bbt_md = &bbt_mirror_descr; + +- iowrite32be(0x0, &ifc->ifc_nand.ncfgr); ++ ifc_out32(0x0, &ifc->ifc_nand.ncfgr); + + /* set up nand options */ + chip->bbt_options = NAND_BBT_USE_FLASH; + chip->options = NAND_NO_SUBPAGE_WRITE; + +- if (ioread32be(&ifc->cspr_cs[priv->bank].cspr) & CSPR_PORT_SIZE_16) { ++ if (ifc_in32(&ifc->cspr_cs[priv->bank].cspr) & CSPR_PORT_SIZE_16) { + chip->read_byte = fsl_ifc_read_byte16; + chip->options |= NAND_BUSWIDTH_16; + } else { +@@ -917,7 +919,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) + chip->ecc.read_page = fsl_ifc_read_page; + chip->ecc.write_page = fsl_ifc_write_page; + +- csor = ioread32be(&ifc->csor_cs[priv->bank].csor); ++ csor = ifc_in32(&ifc->csor_cs[priv->bank].csor); + + /* Hardware generates ECC per 512 Bytes */ + chip->ecc.size = 512; +@@ -1006,7 +1008,7 @@ static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv) + static int match_bank(struct fsl_ifc_regs __iomem *ifc, int bank, + phys_addr_t addr) + { +- u32 cspr = ioread32be(&ifc->cspr_cs[bank].cspr); ++ u32 cspr = ifc_in32(&ifc->cspr_cs[bank].cspr); + + if (!(cspr & CSPR_V)) + return 0; +@@ -1092,16 +1094,16 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) + + dev_set_drvdata(priv->dev, priv); + +- iowrite32be(IFC_NAND_EVTER_EN_OPC_EN | +- IFC_NAND_EVTER_EN_FTOER_EN | +- IFC_NAND_EVTER_EN_WPER_EN, +- &ifc->ifc_nand.nand_evter_en); ++ ifc_out32(IFC_NAND_EVTER_EN_OPC_EN | ++ IFC_NAND_EVTER_EN_FTOER_EN | ++ IFC_NAND_EVTER_EN_WPER_EN, ++ &ifc->ifc_nand.nand_evter_en); + + /* enable NAND Machine Interrupts */ +- iowrite32be(IFC_NAND_EVTER_INTR_OPCIR_EN | +- IFC_NAND_EVTER_INTR_FTOERIR_EN | +- IFC_NAND_EVTER_INTR_WPERIR_EN, +- &ifc->ifc_nand.nand_evter_intr_en); ++ ifc_out32(IFC_NAND_EVTER_INTR_OPCIR_EN | ++ IFC_NAND_EVTER_INTR_FTOERIR_EN | ++ IFC_NAND_EVTER_INTR_WPERIR_EN, ++ &ifc->ifc_nand.nand_evter_intr_en); + priv->mtd.name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start); + if (!priv->mtd.name) { + ret = -ENOMEM; +diff --git a/include/linux/fsl_ifc.h b/include/linux/fsl_ifc.h +index bf0321e..0023088 100644 +--- a/include/linux/fsl_ifc.h ++++ b/include/linux/fsl_ifc.h +@@ -841,9 +841,59 @@ struct fsl_ifc_ctrl { + + u32 nand_stat; + wait_queue_head_t nand_wait; ++ bool little_endian; + }; + + extern struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev; + ++static inline u32 ifc_in32(void __iomem *addr) ++{ ++ u32 val; ++ ++ if (fsl_ifc_ctrl_dev->little_endian) ++ val = ioread32(addr); ++ else ++ val = ioread32be(addr); ++ ++ return val; ++} ++ ++static inline u16 ifc_in16(void __iomem *addr) ++{ ++ u16 val; ++ ++ if (fsl_ifc_ctrl_dev->little_endian) ++ val = ioread16(addr); ++ else ++ val = ioread16be(addr); ++ ++ return val; ++} ++ ++static inline u8 ifc_in8(void __iomem *addr) ++{ ++ return ioread8(addr); ++} ++ ++static inline void ifc_out32(u32 val, void __iomem *addr) ++{ ++ if (fsl_ifc_ctrl_dev->little_endian) ++ iowrite32(val, addr); ++ else ++ iowrite32be(val, addr); ++} ++ ++static inline void ifc_out16(u16 val, void __iomem *addr) ++{ ++ if (fsl_ifc_ctrl_dev->little_endian) ++ iowrite16(val, addr); ++ else ++ iowrite16be(val, addr); ++} ++ ++static inline void ifc_out8(u8 val, void __iomem *addr) ++{ ++ iowrite8(val, addr); ++} + + #endif /* __ASM_FSL_IFC_H */ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0139-drivers-memory-Add-deep-sleep-support-for-IFC.patch b/target/linux/layerscape-64b/patches-4.1/0139-drivers-memory-Add-deep-sleep-support-for-IFC.patch new file mode 100644 index 0000000..b1efbba --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0139-drivers-memory-Add-deep-sleep-support-for-IFC.patch @@ -0,0 +1,240 @@ +From 75474750ed5fbe3c382dd035acc944236f9675c2 Mon Sep 17 00:00:00 2001 +From: Raghav Dogra +Date: Fri, 15 Jan 2016 17:10:09 +0530 +Subject: [PATCH 139/151] drivers/memory: Add deep sleep support for IFC + +Add support of suspend, resume function to support deep sleep. +Also make sure of SRAM initialization during resume. + +Signed-off-by: Raghav Dogra +--- + drivers/memory/fsl_ifc.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++ + include/linux/fsl_ifc.h | 6 ++ + 2 files changed, 169 insertions(+) + +diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c +index 8436c59..054809e 100644 +--- a/drivers/memory/fsl_ifc.c ++++ b/drivers/memory/fsl_ifc.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -34,6 +35,8 @@ + + struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev; + EXPORT_SYMBOL(fsl_ifc_ctrl_dev); ++#define FSL_IFC_V1_3_0 0x01030000 ++#define IFC_TIMEOUT_MSECS 100000 /* 100ms */ + + /* + * convert_ifc_address - convert the base address +@@ -308,6 +311,161 @@ err: + return ret; + } + ++#ifdef CONFIG_PM_SLEEP ++/* save ifc registers */ ++static int fsl_ifc_suspend(struct device *dev) ++{ ++ struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(dev); ++ struct fsl_ifc_regs __iomem *ifc = ctrl->regs; ++ __be32 nand_evter_intr_en, cm_evter_intr_en, nor_evter_intr_en, ++ gpcm_evter_intr_en; ++ ++ ctrl->saved_regs = kzalloc(sizeof(struct fsl_ifc_regs), GFP_KERNEL); ++ if (!ctrl->saved_regs) ++ return -ENOMEM; ++ ++ cm_evter_intr_en = ifc_in32(&ifc->cm_evter_intr_en); ++ nand_evter_intr_en = ifc_in32(&ifc->ifc_nand.nand_evter_intr_en); ++ nor_evter_intr_en = ifc_in32(&ifc->ifc_nor.nor_evter_intr_en); ++ gpcm_evter_intr_en = ifc_in32(&ifc->ifc_gpcm.gpcm_evter_intr_en); ++ ++/* IFC interrupts disabled */ ++ ++ ifc_out32(0x0, &ifc->cm_evter_intr_en); ++ ifc_out32(0x0, &ifc->ifc_nand.nand_evter_intr_en); ++ ifc_out32(0x0, &ifc->ifc_nor.nor_evter_intr_en); ++ ifc_out32(0x0, &ifc->ifc_gpcm.gpcm_evter_intr_en); ++ ++ memcpy_fromio(ctrl->saved_regs, ifc, sizeof(struct fsl_ifc_regs)); ++ ++/* save the interrupt values */ ++ ctrl->saved_regs->cm_evter_intr_en = cm_evter_intr_en; ++ ctrl->saved_regs->ifc_nand.nand_evter_intr_en = nand_evter_intr_en; ++ ctrl->saved_regs->ifc_nor.nor_evter_intr_en = nor_evter_intr_en; ++ ctrl->saved_regs->ifc_gpcm.gpcm_evter_intr_en = gpcm_evter_intr_en; ++ ++ return 0; ++} ++ ++/* restore ifc registers */ ++static int fsl_ifc_resume(struct device *dev) ++{ ++ struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(dev); ++ struct fsl_ifc_regs __iomem *ifc = ctrl->regs; ++ struct fsl_ifc_regs *savd_regs = ctrl->saved_regs; ++ uint32_t ver = 0, ncfgr, status, ifc_bank, i; ++ ++/* ++ * IFC interrupts disabled ++ */ ++ ifc_out32(0x0, &ifc->cm_evter_intr_en); ++ ifc_out32(0x0, &ifc->ifc_nand.nand_evter_intr_en); ++ ifc_out32(0x0, &ifc->ifc_nor.nor_evter_intr_en); ++ ifc_out32(0x0, &ifc->ifc_gpcm.gpcm_evter_intr_en); ++ ++ ++ if (ctrl->saved_regs) { ++ for (ifc_bank = 0; ifc_bank < FSL_IFC_BANK_COUNT; ifc_bank++) { ++ ifc_out32(savd_regs->cspr_cs[ifc_bank].cspr_ext, ++ &ifc->cspr_cs[ifc_bank].cspr_ext); ++ ifc_out32(savd_regs->cspr_cs[ifc_bank].cspr, ++ &ifc->cspr_cs[ifc_bank].cspr); ++ ifc_out32(savd_regs->amask_cs[ifc_bank].amask, ++ &ifc->amask_cs[ifc_bank].amask); ++ ifc_out32(savd_regs->csor_cs[ifc_bank].csor_ext, ++ &ifc->csor_cs[ifc_bank].csor_ext); ++ ifc_out32(savd_regs->csor_cs[ifc_bank].csor, ++ &ifc->csor_cs[ifc_bank].csor); ++ for (i = 0; i < 4; i++) { ++ ifc_out32(savd_regs->ftim_cs[ifc_bank].ftim[i], ++ &ifc->ftim_cs[ifc_bank].ftim[i]); ++ } ++ } ++ ifc_out32(savd_regs->ifc_gcr, &ifc->ifc_gcr); ++ ifc_out32(savd_regs->cm_evter_en, &ifc->cm_evter_en); ++ ++/* ++* IFC controller NAND machine registers ++*/ ++ ifc_out32(savd_regs->ifc_nand.ncfgr, &ifc->ifc_nand.ncfgr); ++ ifc_out32(savd_regs->ifc_nand.nand_fcr0, ++ &ifc->ifc_nand.nand_fcr0); ++ ifc_out32(savd_regs->ifc_nand.nand_fcr1, ++ &ifc->ifc_nand.nand_fcr1); ++ ifc_out32(savd_regs->ifc_nand.row0, &ifc->ifc_nand.row0); ++ ifc_out32(savd_regs->ifc_nand.row1, &ifc->ifc_nand.row1); ++ ifc_out32(savd_regs->ifc_nand.col0, &ifc->ifc_nand.col0); ++ ifc_out32(savd_regs->ifc_nand.col1, &ifc->ifc_nand.col1); ++ ifc_out32(savd_regs->ifc_nand.row2, &ifc->ifc_nand.row2); ++ ifc_out32(savd_regs->ifc_nand.col2, &ifc->ifc_nand.col2); ++ ifc_out32(savd_regs->ifc_nand.row3, &ifc->ifc_nand.row3); ++ ifc_out32(savd_regs->ifc_nand.col3, &ifc->ifc_nand.col3); ++ ifc_out32(savd_regs->ifc_nand.nand_fbcr, ++ &ifc->ifc_nand.nand_fbcr); ++ ifc_out32(savd_regs->ifc_nand.nand_fir0, ++ &ifc->ifc_nand.nand_fir0); ++ ifc_out32(savd_regs->ifc_nand.nand_fir1, ++ &ifc->ifc_nand.nand_fir1); ++ ifc_out32(savd_regs->ifc_nand.nand_fir2, ++ &ifc->ifc_nand.nand_fir2); ++ ifc_out32(savd_regs->ifc_nand.nand_csel, ++ &ifc->ifc_nand.nand_csel); ++ ifc_out32(savd_regs->ifc_nand.nandseq_strt, ++ &ifc->ifc_nand.nandseq_strt); ++ ifc_out32(savd_regs->ifc_nand.nand_evter_en, ++ &ifc->ifc_nand.nand_evter_en); ++ ifc_out32(savd_regs->ifc_nand.nanndcr, &ifc->ifc_nand.nanndcr); ++ ++/* ++* IFC controller NOR machine registers ++*/ ++ ifc_out32(savd_regs->ifc_nor.nor_evter_en, ++ &ifc->ifc_nor.nor_evter_en); ++ ifc_out32(savd_regs->ifc_nor.norcr, &ifc->ifc_nor.norcr); ++ ++/* ++ * IFC controller GPCM Machine registers ++ */ ++ ifc_out32(savd_regs->ifc_gpcm.gpcm_evter_en, ++ &ifc->ifc_gpcm.gpcm_evter_en); ++ ++ ++ ++/* ++ * IFC interrupts enabled ++ */ ++ ifc_out32(ctrl->saved_regs->cm_evter_intr_en, &ifc->cm_evter_intr_en); ++ ifc_out32(ctrl->saved_regs->ifc_nand.nand_evter_intr_en, ++ &ifc->ifc_nand.nand_evter_intr_en); ++ ifc_out32(ctrl->saved_regs->ifc_nor.nor_evter_intr_en, ++ &ifc->ifc_nor.nor_evter_intr_en); ++ ifc_out32(ctrl->saved_regs->ifc_gpcm.gpcm_evter_intr_en, ++ &ifc->ifc_gpcm.gpcm_evter_intr_en); ++ ++ kfree(ctrl->saved_regs); ++ ctrl->saved_regs = NULL; ++ } ++ ++ ver = ifc_in32(&ctrl->regs->ifc_rev); ++ ncfgr = ifc_in32(&ifc->ifc_nand.ncfgr); ++ if (ver >= FSL_IFC_V1_3_0) { ++ ++ ifc_out32(ncfgr | IFC_NAND_SRAM_INIT_EN, ++ &ifc->ifc_nand.ncfgr); ++ /* wait for SRAM_INIT bit to be clear or timeout */ ++ status = spin_event_timeout( ++ !(ifc_in32(&ifc->ifc_nand.ncfgr) ++ & IFC_NAND_SRAM_INIT_EN), ++ IFC_TIMEOUT_MSECS, 0); ++ ++ if (!status) ++ dev_err(ctrl->dev, "Timeout waiting for IFC SRAM INIT"); ++ } ++ ++ return 0; ++} ++#endif /* CONFIG_PM_SLEEP */ ++ + static const struct of_device_id fsl_ifc_match[] = { + { + .compatible = "fsl,ifc", +@@ -315,10 +473,15 @@ static const struct of_device_id fsl_ifc_match[] = { + {}, + }; + ++static const struct dev_pm_ops ifc_pm_ops = { ++ SET_SYSTEM_SLEEP_PM_OPS(fsl_ifc_suspend, fsl_ifc_resume) ++}; ++ + static struct platform_driver fsl_ifc_ctrl_driver = { + .driver = { + .name = "fsl-ifc", + .of_match_table = fsl_ifc_match, ++ .pm = &ifc_pm_ops, + }, + .probe = fsl_ifc_ctrl_probe, + .remove = fsl_ifc_ctrl_remove, +diff --git a/include/linux/fsl_ifc.h b/include/linux/fsl_ifc.h +index 0023088..7c4075e 100644 +--- a/include/linux/fsl_ifc.h ++++ b/include/linux/fsl_ifc.h +@@ -270,6 +270,8 @@ + */ + /* Auto Boot Mode */ + #define IFC_NAND_NCFGR_BOOT 0x80000000 ++/* SRAM INIT EN */ ++#define IFC_NAND_SRAM_INIT_EN 0x20000000 + /* Addressing Mode-ROW0+n/COL0 */ + #define IFC_NAND_NCFGR_ADDR_MODE_RC0 0x00000000 + /* Addressing Mode-ROW0+n/COL0+n */ +@@ -842,6 +844,10 @@ struct fsl_ifc_ctrl { + u32 nand_stat; + wait_queue_head_t nand_wait; + bool little_endian; ++#ifdef CONFIG_PM_SLEEP ++ /*save regs when system goes to deep sleep*/ ++ struct fsl_ifc_regs *saved_regs; ++#endif + }; + + extern struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev; +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0140-driver-memory-Update-dependency-of-IFC-for-Layerscap.patch b/target/linux/layerscape-64b/patches-4.1/0140-driver-memory-Update-dependency-of-IFC-for-Layerscap.patch new file mode 100644 index 0000000..7ab7fc5 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0140-driver-memory-Update-dependency-of-IFC-for-Layerscap.patch @@ -0,0 +1,61 @@ +From 3076c26f54514b02764b2e28f1226dfc104d2af1 Mon Sep 17 00:00:00 2001 +From: Raghav Dogra +Date: Wed, 16 Dec 2015 16:11:50 +0530 +Subject: [PATCH 140/151] driver/memory: Update dependency of IFC for + Layerscape + +IFC NAND is not working on ARM layescape platform due to +undefined macro FSL_SOC. +This patch fixes the dependency to enable NAND. + +Signed-off-by: Raghav Dogra +--- + drivers/memory/Kconfig | 2 +- + drivers/memory/fsl_ifc.c | 4 +++- + drivers/mtd/nand/Kconfig | 2 +- + 3 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig +index 868036f..3ec473a 100644 +--- a/drivers/memory/Kconfig ++++ b/drivers/memory/Kconfig +@@ -81,7 +81,7 @@ config FSL_CORENET_CF + + config FSL_IFC + bool +- depends on FSL_SOC ++ depends on FSL_SOC || ARCH_LAYERSCAPE + + config JZ4780_NEMC + bool "Ingenic JZ4780 SoC NEMC driver" +diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c +index 054809e..f82a245 100644 +--- a/drivers/memory/fsl_ifc.c ++++ b/drivers/memory/fsl_ifc.c +@@ -31,7 +31,9 @@ + #include + #include + #include +-#include ++#include ++#include ++#include + + struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev; + EXPORT_SYMBOL(fsl_ifc_ctrl_dev); +diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig +index 5897d8d..0d6509b 100644 +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -431,7 +431,7 @@ config MTD_NAND_FSL_ELBC + + config MTD_NAND_FSL_IFC + tristate "NAND support for Freescale IFC controller" +- depends on MTD_NAND && FSL_SOC ++ depends on MTD_NAND && (FSL_SOC || ARCH_LAYERSCAPE) + select FSL_IFC + select MEMORY + help +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0141-mtd-ifc-Segregate-IFC-fcm-and-runtime-registers.patch b/target/linux/layerscape-64b/patches-4.1/0141-mtd-ifc-Segregate-IFC-fcm-and-runtime-registers.patch new file mode 100644 index 0000000..218e7c7 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0141-mtd-ifc-Segregate-IFC-fcm-and-runtime-registers.patch @@ -0,0 +1,713 @@ +From 092fdadb408bbad7dc5fcac66a3396ff5cac7213 Mon Sep 17 00:00:00 2001 +From: Raghav Dogra +Date: Wed, 20 Jan 2016 13:06:32 +0530 +Subject: [PATCH 141/151] mtd/ifc: Segregate IFC fcm and runtime registers + +IFC has two set of registers viz FCM (Flash control machine) +aka global and run time registers. These set are defined in two +memory map PAGES. Upto IFC 1.4 PAGE size is 4 KB and from IFC2.0 +PAGE size is 64KB + +Signed-off-by: Jaiprakash Singh +Signed-off-by: Raghav Dogra +--- + drivers/memory/fsl_ifc.c | 251 +++++++++++++++++++++------------------- + drivers/mtd/nand/fsl_ifc_nand.c | 72 ++++++------ + include/linux/fsl_ifc.h | 48 +++++--- + 3 files changed, 203 insertions(+), 168 deletions(-) + +diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c +index f82a245..e2bd85b 100644 +--- a/drivers/memory/fsl_ifc.c ++++ b/drivers/memory/fsl_ifc.c +@@ -63,11 +63,11 @@ int fsl_ifc_find(phys_addr_t addr_base) + { + int i = 0; + +- if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs) ++ if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->gregs) + return -ENODEV; + + for (i = 0; i < fsl_ifc_ctrl_dev->banks; i++) { +- u32 cspr = ifc_in32(&fsl_ifc_ctrl_dev->regs->cspr_cs[i].cspr); ++ u32 cspr = ifc_in32(&fsl_ifc_ctrl_dev->gregs->cspr_cs[i].cspr); + if (cspr & CSPR_V && (cspr & CSPR_BA) == + convert_ifc_address(addr_base)) + return i; +@@ -79,7 +79,7 @@ EXPORT_SYMBOL(fsl_ifc_find); + + static int fsl_ifc_ctrl_init(struct fsl_ifc_ctrl *ctrl) + { +- struct fsl_ifc_regs __iomem *ifc = ctrl->regs; ++ struct fsl_ifc_fcm __iomem *ifc = ctrl->gregs; + + /* + * Clear all the common status and event registers +@@ -108,7 +108,7 @@ static int fsl_ifc_ctrl_remove(struct platform_device *dev) + irq_dispose_mapping(ctrl->nand_irq); + irq_dispose_mapping(ctrl->irq); + +- iounmap(ctrl->regs); ++ iounmap(ctrl->gregs); + + dev_set_drvdata(&dev->dev, NULL); + kfree(ctrl); +@@ -126,7 +126,7 @@ static DEFINE_SPINLOCK(nand_irq_lock); + + static u32 check_nand_stat(struct fsl_ifc_ctrl *ctrl) + { +- struct fsl_ifc_regs __iomem *ifc = ctrl->regs; ++ struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; + unsigned long flags; + u32 stat; + +@@ -161,7 +161,7 @@ static irqreturn_t fsl_ifc_nand_irq(int irqno, void *data) + static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data) + { + struct fsl_ifc_ctrl *ctrl = data; +- struct fsl_ifc_regs __iomem *ifc = ctrl->regs; ++ struct fsl_ifc_fcm __iomem *ifc = ctrl->gregs; + u32 err_axiid, err_srcid, status, cs_err, err_addr; + irqreturn_t ret = IRQ_NONE; + +@@ -219,6 +219,7 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) + { + int ret = 0; + int version, banks; ++ void __iomem *addr; + + dev_info(&dev->dev, "Freescale Integrated Flash Controller\n"); + +@@ -229,22 +230,13 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) + dev_set_drvdata(&dev->dev, fsl_ifc_ctrl_dev); + + /* IOMAP the entire IFC region */ +- fsl_ifc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0); +- if (!fsl_ifc_ctrl_dev->regs) { ++ fsl_ifc_ctrl_dev->gregs = of_iomap(dev->dev.of_node, 0); ++ if (!fsl_ifc_ctrl_dev->gregs) { + dev_err(&dev->dev, "failed to get memory region\n"); + ret = -ENODEV; + goto err; + } + +- version = ifc_in32(&fsl_ifc_ctrl_dev->regs->ifc_rev) & +- FSL_IFC_VERSION_MASK; +- banks = (version == FSL_IFC_VERSION_1_0_0) ? 4 : 8; +- dev_info(&dev->dev, "IFC version %d.%d, %d banks\n", +- version >> 24, (version >> 16) & 0xf, banks); +- +- fsl_ifc_ctrl_dev->version = version; +- fsl_ifc_ctrl_dev->banks = banks; +- + if (of_property_read_bool(dev->dev.of_node, "little-endian")) { + fsl_ifc_ctrl_dev->little_endian = true; + dev_dbg(&dev->dev, "IFC REGISTERS are LITTLE endian\n"); +@@ -253,8 +245,9 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) + dev_dbg(&dev->dev, "IFC REGISTERS are BIG endian\n"); + } + +- version = ioread32be(&fsl_ifc_ctrl_dev->regs->ifc_rev) & ++ version = ifc_in32(&fsl_ifc_ctrl_dev->gregs->ifc_rev) & + FSL_IFC_VERSION_MASK; ++ + banks = (version == FSL_IFC_VERSION_1_0_0) ? 4 : 8; + dev_info(&dev->dev, "IFC version %d.%d, %d banks\n", + version >> 24, (version >> 16) & 0xf, banks); +@@ -262,6 +255,14 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) + fsl_ifc_ctrl_dev->version = version; + fsl_ifc_ctrl_dev->banks = banks; + ++ addr = fsl_ifc_ctrl_dev->gregs; ++ if (version >= FSL_IFC_VERSION_2_0_0) ++ fsl_ifc_ctrl_dev->rregs = ++ (struct fsl_ifc_runtime *)(addr + PGOFFSET_64K); ++ else ++ fsl_ifc_ctrl_dev->rregs = ++ (struct fsl_ifc_runtime *)(addr + PGOFFSET_4K); ++ + /* get the Controller level irq */ + fsl_ifc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0); + if (fsl_ifc_ctrl_dev->irq == 0) { +@@ -318,33 +319,39 @@ err: + static int fsl_ifc_suspend(struct device *dev) + { + struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(dev); +- struct fsl_ifc_regs __iomem *ifc = ctrl->regs; ++ struct fsl_ifc_fcm __iomem *fcm = ctrl->gregs; ++ struct fsl_ifc_runtime __iomem *runtime = ctrl->rregs; + __be32 nand_evter_intr_en, cm_evter_intr_en, nor_evter_intr_en, + gpcm_evter_intr_en; + +- ctrl->saved_regs = kzalloc(sizeof(struct fsl_ifc_regs), GFP_KERNEL); +- if (!ctrl->saved_regs) ++ ctrl->saved_gregs = kzalloc(sizeof(struct fsl_ifc_fcm), GFP_KERNEL); ++ if (!ctrl->saved_gregs) ++ return -ENOMEM; ++ ctrl->saved_rregs = kzalloc(sizeof(struct fsl_ifc_runtime), GFP_KERNEL); ++ if (!ctrl->saved_rregs) + return -ENOMEM; + +- cm_evter_intr_en = ifc_in32(&ifc->cm_evter_intr_en); +- nand_evter_intr_en = ifc_in32(&ifc->ifc_nand.nand_evter_intr_en); +- nor_evter_intr_en = ifc_in32(&ifc->ifc_nor.nor_evter_intr_en); +- gpcm_evter_intr_en = ifc_in32(&ifc->ifc_gpcm.gpcm_evter_intr_en); ++ cm_evter_intr_en = ifc_in32(&fcm->cm_evter_intr_en); ++ nand_evter_intr_en = ifc_in32(&runtime->ifc_nand.nand_evter_intr_en); ++ nor_evter_intr_en = ifc_in32(&runtime->ifc_nor.nor_evter_intr_en); ++ gpcm_evter_intr_en = ifc_in32(&runtime->ifc_gpcm.gpcm_evter_intr_en); + + /* IFC interrupts disabled */ + +- ifc_out32(0x0, &ifc->cm_evter_intr_en); +- ifc_out32(0x0, &ifc->ifc_nand.nand_evter_intr_en); +- ifc_out32(0x0, &ifc->ifc_nor.nor_evter_intr_en); +- ifc_out32(0x0, &ifc->ifc_gpcm.gpcm_evter_intr_en); ++ ifc_out32(0x0, &fcm->cm_evter_intr_en); ++ ifc_out32(0x0, &runtime->ifc_nand.nand_evter_intr_en); ++ ifc_out32(0x0, &runtime->ifc_nor.nor_evter_intr_en); ++ ifc_out32(0x0, &runtime->ifc_gpcm.gpcm_evter_intr_en); + +- memcpy_fromio(ctrl->saved_regs, ifc, sizeof(struct fsl_ifc_regs)); ++ memcpy_fromio(ctrl->saved_gregs, fcm, sizeof(struct fsl_ifc_fcm)); ++ memcpy_fromio(ctrl->saved_rregs, runtime, ++ sizeof(struct fsl_ifc_runtime)); + + /* save the interrupt values */ +- ctrl->saved_regs->cm_evter_intr_en = cm_evter_intr_en; +- ctrl->saved_regs->ifc_nand.nand_evter_intr_en = nand_evter_intr_en; +- ctrl->saved_regs->ifc_nor.nor_evter_intr_en = nor_evter_intr_en; +- ctrl->saved_regs->ifc_gpcm.gpcm_evter_intr_en = gpcm_evter_intr_en; ++ ctrl->saved_gregs->cm_evter_intr_en = cm_evter_intr_en; ++ ctrl->saved_rregs->ifc_nand.nand_evter_intr_en = nand_evter_intr_en; ++ ctrl->saved_rregs->ifc_nor.nor_evter_intr_en = nor_evter_intr_en; ++ ctrl->saved_rregs->ifc_gpcm.gpcm_evter_intr_en = gpcm_evter_intr_en; + + return 0; + } +@@ -353,110 +360,116 @@ static int fsl_ifc_suspend(struct device *dev) + static int fsl_ifc_resume(struct device *dev) + { + struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(dev); +- struct fsl_ifc_regs __iomem *ifc = ctrl->regs; +- struct fsl_ifc_regs *savd_regs = ctrl->saved_regs; ++ struct fsl_ifc_fcm __iomem *fcm = ctrl->gregs; ++ struct fsl_ifc_runtime __iomem *runtime = ctrl->rregs; ++ struct fsl_ifc_fcm *savd_gregs = ctrl->saved_gregs; ++ struct fsl_ifc_runtime *savd_rregs = ctrl->saved_rregs; + uint32_t ver = 0, ncfgr, status, ifc_bank, i; + + /* + * IFC interrupts disabled + */ +- ifc_out32(0x0, &ifc->cm_evter_intr_en); +- ifc_out32(0x0, &ifc->ifc_nand.nand_evter_intr_en); +- ifc_out32(0x0, &ifc->ifc_nor.nor_evter_intr_en); +- ifc_out32(0x0, &ifc->ifc_gpcm.gpcm_evter_intr_en); ++ ifc_out32(0x0, &fcm->cm_evter_intr_en); ++ ifc_out32(0x0, &runtime->ifc_nand.nand_evter_intr_en); ++ ifc_out32(0x0, &runtime->ifc_nor.nor_evter_intr_en); ++ ifc_out32(0x0, &runtime->ifc_gpcm.gpcm_evter_intr_en); + + +- if (ctrl->saved_regs) { ++ if (ctrl->saved_gregs) { + for (ifc_bank = 0; ifc_bank < FSL_IFC_BANK_COUNT; ifc_bank++) { +- ifc_out32(savd_regs->cspr_cs[ifc_bank].cspr_ext, +- &ifc->cspr_cs[ifc_bank].cspr_ext); +- ifc_out32(savd_regs->cspr_cs[ifc_bank].cspr, +- &ifc->cspr_cs[ifc_bank].cspr); +- ifc_out32(savd_regs->amask_cs[ifc_bank].amask, +- &ifc->amask_cs[ifc_bank].amask); +- ifc_out32(savd_regs->csor_cs[ifc_bank].csor_ext, +- &ifc->csor_cs[ifc_bank].csor_ext); +- ifc_out32(savd_regs->csor_cs[ifc_bank].csor, +- &ifc->csor_cs[ifc_bank].csor); ++ ifc_out32(savd_gregs->cspr_cs[ifc_bank].cspr_ext, ++ &fcm->cspr_cs[ifc_bank].cspr_ext); ++ ifc_out32(savd_gregs->cspr_cs[ifc_bank].cspr, ++ &fcm->cspr_cs[ifc_bank].cspr); ++ ifc_out32(savd_gregs->amask_cs[ifc_bank].amask, ++ &fcm->amask_cs[ifc_bank].amask); ++ ifc_out32(savd_gregs->csor_cs[ifc_bank].csor_ext, ++ &fcm->csor_cs[ifc_bank].csor_ext); ++ ifc_out32(savd_gregs->csor_cs[ifc_bank].csor, ++ &fcm->csor_cs[ifc_bank].csor); + for (i = 0; i < 4; i++) { +- ifc_out32(savd_regs->ftim_cs[ifc_bank].ftim[i], +- &ifc->ftim_cs[ifc_bank].ftim[i]); ++ ifc_out32(savd_gregs->ftim_cs[ifc_bank].ftim[i], ++ &fcm->ftim_cs[ifc_bank].ftim[i]); + } + } +- ifc_out32(savd_regs->ifc_gcr, &ifc->ifc_gcr); +- ifc_out32(savd_regs->cm_evter_en, &ifc->cm_evter_en); +- +-/* +-* IFC controller NAND machine registers +-*/ +- ifc_out32(savd_regs->ifc_nand.ncfgr, &ifc->ifc_nand.ncfgr); +- ifc_out32(savd_regs->ifc_nand.nand_fcr0, +- &ifc->ifc_nand.nand_fcr0); +- ifc_out32(savd_regs->ifc_nand.nand_fcr1, +- &ifc->ifc_nand.nand_fcr1); +- ifc_out32(savd_regs->ifc_nand.row0, &ifc->ifc_nand.row0); +- ifc_out32(savd_regs->ifc_nand.row1, &ifc->ifc_nand.row1); +- ifc_out32(savd_regs->ifc_nand.col0, &ifc->ifc_nand.col0); +- ifc_out32(savd_regs->ifc_nand.col1, &ifc->ifc_nand.col1); +- ifc_out32(savd_regs->ifc_nand.row2, &ifc->ifc_nand.row2); +- ifc_out32(savd_regs->ifc_nand.col2, &ifc->ifc_nand.col2); +- ifc_out32(savd_regs->ifc_nand.row3, &ifc->ifc_nand.row3); +- ifc_out32(savd_regs->ifc_nand.col3, &ifc->ifc_nand.col3); +- ifc_out32(savd_regs->ifc_nand.nand_fbcr, +- &ifc->ifc_nand.nand_fbcr); +- ifc_out32(savd_regs->ifc_nand.nand_fir0, +- &ifc->ifc_nand.nand_fir0); +- ifc_out32(savd_regs->ifc_nand.nand_fir1, +- &ifc->ifc_nand.nand_fir1); +- ifc_out32(savd_regs->ifc_nand.nand_fir2, +- &ifc->ifc_nand.nand_fir2); +- ifc_out32(savd_regs->ifc_nand.nand_csel, +- &ifc->ifc_nand.nand_csel); +- ifc_out32(savd_regs->ifc_nand.nandseq_strt, +- &ifc->ifc_nand.nandseq_strt); +- ifc_out32(savd_regs->ifc_nand.nand_evter_en, +- &ifc->ifc_nand.nand_evter_en); +- ifc_out32(savd_regs->ifc_nand.nanndcr, &ifc->ifc_nand.nanndcr); +- +-/* +-* IFC controller NOR machine registers +-*/ +- ifc_out32(savd_regs->ifc_nor.nor_evter_en, +- &ifc->ifc_nor.nor_evter_en); +- ifc_out32(savd_regs->ifc_nor.norcr, &ifc->ifc_nor.norcr); +- +-/* +- * IFC controller GPCM Machine registers +- */ +- ifc_out32(savd_regs->ifc_gpcm.gpcm_evter_en, +- &ifc->ifc_gpcm.gpcm_evter_en); +- +- ++ ifc_out32(savd_gregs->rb_map, &fcm->rb_map); ++ ifc_out32(savd_gregs->wb_map, &fcm->wb_map); ++ ifc_out32(savd_gregs->ifc_gcr, &fcm->ifc_gcr); ++ ifc_out32(savd_gregs->ddr_ccr_low, &fcm->ddr_ccr_low); ++ ifc_out32(savd_gregs->cm_evter_en, &fcm->cm_evter_en); ++ } + +-/* +- * IFC interrupts enabled +- */ +- ifc_out32(ctrl->saved_regs->cm_evter_intr_en, &ifc->cm_evter_intr_en); +- ifc_out32(ctrl->saved_regs->ifc_nand.nand_evter_intr_en, +- &ifc->ifc_nand.nand_evter_intr_en); +- ifc_out32(ctrl->saved_regs->ifc_nor.nor_evter_intr_en, +- &ifc->ifc_nor.nor_evter_intr_en); +- ifc_out32(ctrl->saved_regs->ifc_gpcm.gpcm_evter_intr_en, +- &ifc->ifc_gpcm.gpcm_evter_intr_en); +- +- kfree(ctrl->saved_regs); +- ctrl->saved_regs = NULL; ++ if (ctrl->saved_rregs) { ++ /* IFC controller NAND machine registers */ ++ ifc_out32(savd_rregs->ifc_nand.ncfgr, ++ &runtime->ifc_nand.ncfgr); ++ ifc_out32(savd_rregs->ifc_nand.nand_fcr0, ++ &runtime->ifc_nand.nand_fcr0); ++ ifc_out32(savd_rregs->ifc_nand.nand_fcr1, ++ &runtime->ifc_nand.nand_fcr1); ++ ifc_out32(savd_rregs->ifc_nand.row0, &runtime->ifc_nand.row0); ++ ifc_out32(savd_rregs->ifc_nand.row1, &runtime->ifc_nand.row1); ++ ifc_out32(savd_rregs->ifc_nand.col0, &runtime->ifc_nand.col0); ++ ifc_out32(savd_rregs->ifc_nand.col1, &runtime->ifc_nand.col1); ++ ifc_out32(savd_rregs->ifc_nand.row2, &runtime->ifc_nand.row2); ++ ifc_out32(savd_rregs->ifc_nand.col2, &runtime->ifc_nand.col2); ++ ifc_out32(savd_rregs->ifc_nand.row3, &runtime->ifc_nand.row3); ++ ifc_out32(savd_rregs->ifc_nand.col3, &runtime->ifc_nand.col3); ++ ifc_out32(savd_rregs->ifc_nand.nand_fbcr, ++ &runtime->ifc_nand.nand_fbcr); ++ ifc_out32(savd_rregs->ifc_nand.nand_fir0, ++ &runtime->ifc_nand.nand_fir0); ++ ifc_out32(savd_rregs->ifc_nand.nand_fir1, ++ &runtime->ifc_nand.nand_fir1); ++ ifc_out32(savd_rregs->ifc_nand.nand_fir2, ++ &runtime->ifc_nand.nand_fir2); ++ ifc_out32(savd_rregs->ifc_nand.nand_csel, ++ &runtime->ifc_nand.nand_csel); ++ ifc_out32(savd_rregs->ifc_nand.nandseq_strt, ++ &runtime->ifc_nand.nandseq_strt); ++ ifc_out32(savd_rregs->ifc_nand.nand_evter_en, ++ &runtime->ifc_nand.nand_evter_en); ++ ifc_out32(savd_rregs->ifc_nand.nanndcr, ++ &runtime->ifc_nand.nanndcr); ++ ifc_out32(savd_rregs->ifc_nand.nand_dll_lowcfg0, ++ &runtime->ifc_nand.nand_dll_lowcfg0); ++ ifc_out32(savd_rregs->ifc_nand.nand_dll_lowcfg1, ++ &runtime->ifc_nand.nand_dll_lowcfg1); ++ ++ /* IFC controller NOR machine registers */ ++ ifc_out32(savd_rregs->ifc_nor.nor_evter_en, ++ &runtime->ifc_nor.nor_evter_en); ++ ifc_out32(savd_rregs->ifc_nor.norcr, &runtime->ifc_nor.norcr); ++ ++ /* IFC controller GPCM Machine registers */ ++ ifc_out32(savd_rregs->ifc_gpcm.gpcm_evter_en, ++ &runtime->ifc_gpcm.gpcm_evter_en); ++ ++ /* IFC interrupts enabled */ ++ ifc_out32(ctrl->saved_gregs->cm_evter_intr_en, ++ &fcm->cm_evter_intr_en); ++ ifc_out32(ctrl->saved_rregs->ifc_nand.nand_evter_intr_en, ++ &runtime->ifc_nand.nand_evter_intr_en); ++ ifc_out32(ctrl->saved_rregs->ifc_nor.nor_evter_intr_en, ++ &runtime->ifc_nor.nor_evter_intr_en); ++ ifc_out32(ctrl->saved_rregs->ifc_gpcm.gpcm_evter_intr_en, ++ &runtime->ifc_gpcm.gpcm_evter_intr_en); ++ ++ kfree(ctrl->saved_gregs); ++ kfree(ctrl->saved_rregs); ++ ctrl->saved_gregs = NULL; ++ ctrl->saved_rregs = NULL; + } + +- ver = ifc_in32(&ctrl->regs->ifc_rev); +- ncfgr = ifc_in32(&ifc->ifc_nand.ncfgr); ++ ver = ifc_in32(&fcm->ifc_rev); ++ ncfgr = ifc_in32(&runtime->ifc_nand.ncfgr); + if (ver >= FSL_IFC_V1_3_0) { + + ifc_out32(ncfgr | IFC_NAND_SRAM_INIT_EN, +- &ifc->ifc_nand.ncfgr); ++ &runtime->ifc_nand.ncfgr); + /* wait for SRAM_INIT bit to be clear or timeout */ + status = spin_event_timeout( +- !(ifc_in32(&ifc->ifc_nand.ncfgr) ++ !(ifc_in32(&runtime->ifc_nand.ncfgr) + & IFC_NAND_SRAM_INIT_EN), + IFC_TIMEOUT_MSECS, 0); + +diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c +index a4e27e8..ca36b35 100644 +--- a/drivers/mtd/nand/fsl_ifc_nand.c ++++ b/drivers/mtd/nand/fsl_ifc_nand.c +@@ -233,7 +233,7 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) + struct nand_chip *chip = mtd->priv; + struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_ctrl *ctrl = priv->ctrl; +- struct fsl_ifc_regs __iomem *ifc = ctrl->regs; ++ struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; + int buf_num; + + ifc_nand_ctrl->page = page_addr; +@@ -296,7 +296,7 @@ static void fsl_ifc_run_command(struct mtd_info *mtd) + struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_ctrl *ctrl = priv->ctrl; + struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl; +- struct fsl_ifc_regs __iomem *ifc = ctrl->regs; ++ struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; + u32 eccstat[4]; + int i; + +@@ -372,7 +372,7 @@ static void fsl_ifc_do_read(struct nand_chip *chip, + { + struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_ctrl *ctrl = priv->ctrl; +- struct fsl_ifc_regs __iomem *ifc = ctrl->regs; ++ struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; + + /* Program FIR/IFC_NAND_FCR0 for Small/Large page */ + if (mtd->writesize > 512) { +@@ -412,7 +412,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, + struct nand_chip *chip = mtd->priv; + struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_ctrl *ctrl = priv->ctrl; +- struct fsl_ifc_regs __iomem *ifc = ctrl->regs; ++ struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; + + /* clear the read buffer */ + ifc_nand_ctrl->read_bytes = 0; +@@ -724,7 +724,7 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) + { + struct fsl_ifc_mtd *priv = chip->priv; + struct fsl_ifc_ctrl *ctrl = priv->ctrl; +- struct fsl_ifc_regs __iomem *ifc = ctrl->regs; ++ struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; + u32 nand_fsr; + + /* Use READ_STATUS command, but wait for the device to be ready */ +@@ -826,39 +826,42 @@ static int fsl_ifc_chip_init_tail(struct mtd_info *mtd) + static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv) + { + struct fsl_ifc_ctrl *ctrl = priv->ctrl; +- struct fsl_ifc_regs __iomem *ifc = ctrl->regs; ++ struct fsl_ifc_runtime __iomem *ifc_runtime = ctrl->rregs; ++ struct fsl_ifc_fcm __iomem *ifc_global = ctrl->gregs; + uint32_t csor = 0, csor_8k = 0, csor_ext = 0; + uint32_t cs = priv->bank; + + /* Save CSOR and CSOR_ext */ +- csor = ifc_in32(&ifc->csor_cs[cs].csor); +- csor_ext = ifc_in32(&ifc->csor_cs[cs].csor_ext); ++ csor = ifc_in32(&ifc_global->csor_cs[cs].csor); ++ csor_ext = ifc_in32(&ifc_global->csor_cs[cs].csor_ext); + + /* chage PageSize 8K and SpareSize 1K*/ + csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000; +- ifc_out32(csor_8k, &ifc->csor_cs[cs].csor); +- ifc_out32(0x0000400, &ifc->csor_cs[cs].csor_ext); ++ ifc_out32(csor_8k, &ifc_global->csor_cs[cs].csor); ++ ifc_out32(0x0000400, &ifc_global->csor_cs[cs].csor_ext); + + /* READID */ + ifc_out32((IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | +- (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | +- (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT), +- &ifc->ifc_nand.nand_fir0); ++ (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | ++ (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT), ++ &ifc_runtime->ifc_nand.nand_fir0); + ifc_out32(NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT, +- &ifc->ifc_nand.nand_fcr0); +- ifc_out32(0x0, &ifc->ifc_nand.row3); ++ &ifc_runtime->ifc_nand.nand_fcr0); ++ ifc_out32(0x0, &ifc_runtime->ifc_nand.row3); + +- ifc_out32(0x0, &ifc->ifc_nand.nand_fbcr); ++ ifc_out32(0x0, &ifc_runtime->ifc_nand.nand_fbcr); + + /* Program ROW0/COL0 */ +- ifc_out32(0x0, &ifc->ifc_nand.row0); +- ifc_out32(0x0, &ifc->ifc_nand.col0); ++ ifc_out32(0x0, &ifc_runtime->ifc_nand.row0); ++ ifc_out32(0x0, &ifc_runtime->ifc_nand.col0); + + /* set the chip select for NAND Transaction */ +- ifc_out32(cs << IFC_NAND_CSEL_SHIFT, &ifc->ifc_nand.nand_csel); ++ ifc_out32(cs << IFC_NAND_CSEL_SHIFT, ++ &ifc_runtime->ifc_nand.nand_csel); + + /* start read seq */ +- ifc_out32(IFC_NAND_SEQ_STRT_FIR_STRT, &ifc->ifc_nand.nandseq_strt); ++ ifc_out32(IFC_NAND_SEQ_STRT_FIR_STRT, ++ &ifc_runtime->ifc_nand.nandseq_strt); + + /* wait for command complete flag or timeout */ + wait_event_timeout(ctrl->nand_wait, ctrl->nand_stat, +@@ -868,14 +871,15 @@ static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv) + printk(KERN_ERR "fsl-ifc: Failed to Initialise SRAM\n"); + + /* Restore CSOR and CSOR_ext */ +- ifc_out32(csor, &ifc->csor_cs[cs].csor); +- ifc_out32(csor_ext, &ifc->csor_cs[cs].csor_ext); ++ ifc_out32(csor, &ifc_global->csor_cs[cs].csor); ++ ifc_out32(csor_ext, &ifc_global->csor_cs[cs].csor_ext); + } + + static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) + { + struct fsl_ifc_ctrl *ctrl = priv->ctrl; +- struct fsl_ifc_regs __iomem *ifc = ctrl->regs; ++ struct fsl_ifc_fcm __iomem *ifc_global = ctrl->gregs; ++ struct fsl_ifc_runtime __iomem *ifc_runtime = ctrl->rregs; + struct nand_chip *chip = &priv->chip; + struct nand_ecclayout *layout; + u32 csor; +@@ -886,7 +890,8 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) + + /* fill in nand_chip structure */ + /* set up function call table */ +- if ((ifc_in32(&ifc->cspr_cs[priv->bank].cspr)) & CSPR_PORT_SIZE_16) ++ if ((ifc_in32(&ifc_global->cspr_cs[priv->bank].cspr)) ++ & CSPR_PORT_SIZE_16) + chip->read_byte = fsl_ifc_read_byte16; + else + chip->read_byte = fsl_ifc_read_byte; +@@ -900,13 +905,14 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) + chip->bbt_td = &bbt_main_descr; + chip->bbt_md = &bbt_mirror_descr; + +- ifc_out32(0x0, &ifc->ifc_nand.ncfgr); ++ ifc_out32(0x0, &ifc_runtime->ifc_nand.ncfgr); + + /* set up nand options */ + chip->bbt_options = NAND_BBT_USE_FLASH; + chip->options = NAND_NO_SUBPAGE_WRITE; + +- if (ifc_in32(&ifc->cspr_cs[priv->bank].cspr) & CSPR_PORT_SIZE_16) { ++ if (ifc_in32(&ifc_global->cspr_cs[priv->bank].cspr) ++ & CSPR_PORT_SIZE_16) { + chip->read_byte = fsl_ifc_read_byte16; + chip->options |= NAND_BUSWIDTH_16; + } else { +@@ -919,7 +925,7 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) + chip->ecc.read_page = fsl_ifc_read_page; + chip->ecc.write_page = fsl_ifc_write_page; + +- csor = ifc_in32(&ifc->csor_cs[priv->bank].csor); ++ csor = ifc_in32(&ifc_global->csor_cs[priv->bank].csor); + + /* Hardware generates ECC per 512 Bytes */ + chip->ecc.size = 512; +@@ -1005,10 +1011,10 @@ static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv) + return 0; + } + +-static int match_bank(struct fsl_ifc_regs __iomem *ifc, int bank, ++static int match_bank(struct fsl_ifc_fcm __iomem *ifc_global, int bank, + phys_addr_t addr) + { +- u32 cspr = ifc_in32(&ifc->cspr_cs[bank].cspr); ++ u32 cspr = ifc_in32(&ifc_global->cspr_cs[bank].cspr); + + if (!(cspr & CSPR_V)) + return 0; +@@ -1022,7 +1028,7 @@ static DEFINE_MUTEX(fsl_ifc_nand_mutex); + + static int fsl_ifc_nand_probe(struct platform_device *dev) + { +- struct fsl_ifc_regs __iomem *ifc; ++ struct fsl_ifc_runtime __iomem *ifc; + struct fsl_ifc_mtd *priv; + struct resource res; + static const char *part_probe_types[] +@@ -1033,9 +1039,9 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) + struct mtd_part_parser_data ppdata; + + ppdata.of_node = dev->dev.of_node; +- if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs) ++ if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->rregs) + return -ENODEV; +- ifc = fsl_ifc_ctrl_dev->regs; ++ ifc = fsl_ifc_ctrl_dev->rregs; + + /* get, allocate and map the memory resource */ + ret = of_address_to_resource(node, 0, &res); +@@ -1046,7 +1052,7 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) + + /* find which chip select it is connected to */ + for (bank = 0; bank < fsl_ifc_ctrl_dev->banks; bank++) { +- if (match_bank(ifc, bank, res.start)) ++ if (match_bank(fsl_ifc_ctrl_dev->gregs, bank, res.start)) + break; + } + +diff --git a/include/linux/fsl_ifc.h b/include/linux/fsl_ifc.h +index 7c4075e..1770224 100644 +--- a/include/linux/fsl_ifc.h ++++ b/include/linux/fsl_ifc.h +@@ -39,6 +39,10 @@ + #define FSL_IFC_VERSION_MASK 0x0F0F0000 + #define FSL_IFC_VERSION_1_0_0 0x01000000 + #define FSL_IFC_VERSION_1_1_0 0x01010000 ++#define FSL_IFC_VERSION_2_0_0 0x02000000 ++ ++#define PGOFFSET_64K (64*1024) ++#define PGOFFSET_4K (4*1024) + + /* + * CSPR - Chip Select Property Register +@@ -725,20 +729,26 @@ struct fsl_ifc_nand { + __be32 nand_evter_en; + u32 res17[0x2]; + __be32 nand_evter_intr_en; +- u32 res18[0x2]; ++ __be32 nand_vol_addr_stat; ++ u32 res18; + __be32 nand_erattr0; + __be32 nand_erattr1; + u32 res19[0x10]; + __be32 nand_fsr; +- u32 res20; +- __be32 nand_eccstat[4]; +- u32 res21[0x20]; ++ u32 res20[0x3]; ++ __be32 nand_eccstat[6]; ++ u32 res21[0x1c]; + __be32 nanndcr; + u32 res22[0x2]; + __be32 nand_autoboot_trgr; + u32 res23; + __be32 nand_mdr; +- u32 res24[0x5C]; ++ u32 res24[0x1C]; ++ __be32 nand_dll_lowcfg0; ++ __be32 nand_dll_lowcfg1; ++ u32 res25; ++ __be32 nand_dll_lowstat; ++ u32 res26[0x3c]; + }; + + /* +@@ -773,13 +783,12 @@ struct fsl_ifc_gpcm { + __be32 gpcm_erattr1; + __be32 gpcm_erattr2; + __be32 gpcm_stat; +- u32 res4[0x1F3]; + }; + + /* + * IFC Controller Registers + */ +-struct fsl_ifc_regs { ++struct fsl_ifc_fcm { + __be32 ifc_rev; + u32 res1[0x2]; + struct { +@@ -805,21 +814,26 @@ struct fsl_ifc_regs { + } ftim_cs[FSL_IFC_BANK_COUNT]; + u32 res9[0x30]; + __be32 rb_stat; +- u32 res10[0x2]; ++ __be32 rb_map; ++ __be32 wb_map; + __be32 ifc_gcr; +- u32 res11[0x2]; ++ u32 res10[0x2]; + __be32 cm_evter_stat; +- u32 res12[0x2]; ++ u32 res11[0x2]; + __be32 cm_evter_en; +- u32 res13[0x2]; ++ u32 res12[0x2]; + __be32 cm_evter_intr_en; +- u32 res14[0x2]; ++ u32 res13[0x2]; + __be32 cm_erattr0; + __be32 cm_erattr1; +- u32 res15[0x2]; ++ u32 res14[0x2]; + __be32 ifc_ccr; + __be32 ifc_csr; +- u32 res16[0x2EB]; ++ __be32 ddr_ccr_low; ++}; ++ ++ ++struct fsl_ifc_runtime { + struct fsl_ifc_nand ifc_nand; + struct fsl_ifc_nor ifc_nor; + struct fsl_ifc_gpcm ifc_gpcm; +@@ -833,7 +847,8 @@ extern int fsl_ifc_find(phys_addr_t addr_base); + struct fsl_ifc_ctrl { + /* device info */ + struct device *dev; +- struct fsl_ifc_regs __iomem *regs; ++ struct fsl_ifc_fcm __iomem *gregs; ++ struct fsl_ifc_runtime __iomem *rregs; + int irq; + int nand_irq; + spinlock_t lock; +@@ -846,7 +861,8 @@ struct fsl_ifc_ctrl { + bool little_endian; + #ifdef CONFIG_PM_SLEEP + /*save regs when system goes to deep sleep*/ +- struct fsl_ifc_regs *saved_regs; ++ struct fsl_ifc_fcm *saved_gregs; ++ struct fsl_ifc_runtime *saved_rregs; + #endif + }; + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0142-drivers-memory-Fix-build-error-for-arm64.patch b/target/linux/layerscape-64b/patches-4.1/0142-drivers-memory-Fix-build-error-for-arm64.patch new file mode 100644 index 0000000..0a6e8b0 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0142-drivers-memory-Fix-build-error-for-arm64.patch @@ -0,0 +1,58 @@ +From b4c2eb1257d62105b872df5b9ff697ffc2b2e5fd Mon Sep 17 00:00:00 2001 +From: Raghav Dogra +Date: Wed, 24 Feb 2016 23:12:58 +0530 +Subject: [PATCH 142/151] drivers/memory: Fix build error for arm64 + +Replace spin_event_timeout() with arch independent macro + +Signed-off-by: Raghav Dogra +Signed-off-by: Prabhakar Kushwaha +--- + drivers/memory/fsl_ifc.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c +index e2bd85b..8056505 100644 +--- a/drivers/memory/fsl_ifc.c ++++ b/drivers/memory/fsl_ifc.c +@@ -38,7 +38,7 @@ + struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev; + EXPORT_SYMBOL(fsl_ifc_ctrl_dev); + #define FSL_IFC_V1_3_0 0x01030000 +-#define IFC_TIMEOUT_MSECS 100000 /* 100ms */ ++#define IFC_TIMEOUT_MSECS 1000 /* 1000ms */ + + /* + * convert_ifc_address - convert the base address +@@ -364,7 +364,7 @@ static int fsl_ifc_resume(struct device *dev) + struct fsl_ifc_runtime __iomem *runtime = ctrl->rregs; + struct fsl_ifc_fcm *savd_gregs = ctrl->saved_gregs; + struct fsl_ifc_runtime *savd_rregs = ctrl->saved_rregs; +- uint32_t ver = 0, ncfgr, status, ifc_bank, i; ++ uint32_t ver = 0, ncfgr, timeout, ifc_bank, i; + + /* + * IFC interrupts disabled +@@ -468,12 +468,14 @@ static int fsl_ifc_resume(struct device *dev) + ifc_out32(ncfgr | IFC_NAND_SRAM_INIT_EN, + &runtime->ifc_nand.ncfgr); + /* wait for SRAM_INIT bit to be clear or timeout */ +- status = spin_event_timeout( +- !(ifc_in32(&runtime->ifc_nand.ncfgr) +- & IFC_NAND_SRAM_INIT_EN), +- IFC_TIMEOUT_MSECS, 0); ++ timeout = 10; ++ while ((ifc_in32(&runtime->ifc_nand.ncfgr) & ++ IFC_NAND_SRAM_INIT_EN) && timeout) { ++ mdelay(IFC_TIMEOUT_MSECS); ++ timeout--; ++ } + +- if (!status) ++ if (!timeout) + dev_err(ctrl->dev, "Timeout waiting for IFC SRAM INIT"); + } + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0143-fsl-ifc-fix-compilation-error-when-COMPAT-not-enable.patch b/target/linux/layerscape-64b/patches-4.1/0143-fsl-ifc-fix-compilation-error-when-COMPAT-not-enable.patch new file mode 100644 index 0000000..8523d62 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0143-fsl-ifc-fix-compilation-error-when-COMPAT-not-enable.patch @@ -0,0 +1,34 @@ +From b1dbc51f1769f42deb99fc50ca2b352181341a84 Mon Sep 17 00:00:00 2001 +From: Lijun Pan +Date: Wed, 23 Sep 2015 17:06:01 -0500 +Subject: [PATCH 143/151] fsl-ifc: fix compilation error when COMPAT not + enabled + +When CONFIG_COMPAT is not enabled for cases when 64K pages +are enabled, there are a series of include dependencies that +result in some definitions in sched.h that get missed (e.g. + TASK_NORMAL). Explictly include sched.h to resolve this. +(This seems to be what other drivers do as well) + +Signed-off-by: Lijun Pan +[Stuart: updated subject and commit message] +Signed-off-by: Stuart Yoder +--- + drivers/memory/fsl_ifc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c +index 8056505..bd2b9b1 100644 +--- a/drivers/memory/fsl_ifc.c ++++ b/drivers/memory/fsl_ifc.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev; + EXPORT_SYMBOL(fsl_ifc_ctrl_dev); +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0144-mmc-sdhci-esdhc-add-default-quirk-SDHCI_QUIRK_NO_HIS.patch b/target/linux/layerscape-64b/patches-4.1/0144-mmc-sdhci-esdhc-add-default-quirk-SDHCI_QUIRK_NO_HIS.patch new file mode 100644 index 0000000..bc0d851 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0144-mmc-sdhci-esdhc-add-default-quirk-SDHCI_QUIRK_NO_HIS.patch @@ -0,0 +1,32 @@ +From 2c737f477b8f1ea86e3a4abca915ffd2b60f9022 Mon Sep 17 00:00:00 2001 +From: Yangbo Lu +Date: Fri, 10 Jul 2015 11:42:37 +0800 +Subject: [PATCH 144/151] mmc: sdhci-esdhc: add default quirk + SDHCI_QUIRK_NO_HISPD_BIT + +eSDHC supports high speed mode, but has no enabling bit for it. +Add this quirk to avoid writing to eSDHC_PROCTL[DTW] by mistake. + +Signed-off-by: Yangbo Lu +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/sdhci-esdhc.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h +index a870c42..163ac99 100644 +--- a/drivers/mmc/host/sdhci-esdhc.h ++++ b/drivers/mmc/host/sdhci-esdhc.h +@@ -21,7 +21,8 @@ + #define ESDHC_DEFAULT_QUIRKS (SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \ + SDHCI_QUIRK_NO_BUSY_IRQ | \ + SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \ +- SDHCI_QUIRK_PIO_NEEDS_DELAY) ++ SDHCI_QUIRK_PIO_NEEDS_DELAY | \ ++ SDHCI_QUIRK_NO_HISPD_BIT) + + #define ESDHC_SYSTEM_CONTROL 0x2c + #define ESDHC_CLOCK_MASK 0x0000fff0 +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0145-mmc-block-add-fixup-of-broken-CMD23-for-Sandisk-card.patch b/target/linux/layerscape-64b/patches-4.1/0145-mmc-block-add-fixup-of-broken-CMD23-for-Sandisk-card.patch new file mode 100644 index 0000000..1955555 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0145-mmc-block-add-fixup-of-broken-CMD23-for-Sandisk-card.patch @@ -0,0 +1,42 @@ +From c8bf749e25917d6d5abc18dcbbcc6a1ef3524f0e Mon Sep 17 00:00:00 2001 +From: Yangbo Lu +Date: Fri, 10 Jul 2015 11:44:03 +0800 +Subject: [PATCH 145/151] mmc: block: add fixup of broken CMD23 for Sandisk + card + +Some Sandisk cards(such as "SDMB-32" and "SDM032" cards) +can't support CMD23, and would generate CMD timeout. So add +FIX-UP for these two types Sandisk cards. + +Error log: +mmcblk0: timed out sending SET_BLOCK_COUNT command, card status 0x400900 +mmcblk0: timed out sending SET_BLOCK_COUNT command, card status 0x400900 +mmcblk0: timed out sending SET_BLOCK_COUNT command, card status 0x400900 +end_request: I/O error, dev mmcblk0, sector 0 +Buffer I/O error on device mmcblk0, logical block 0 +mmcblk0: timed out sending SET_BLOCK_COUNT command, card status 0x400900 + +Signed-off-by: Yangbo Lu +Signed-off-by: Ulf Hansson +--- + drivers/mmc/card/block.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c +index 31d2627..44e3e6a 100644 +--- a/drivers/mmc/card/block.c ++++ b/drivers/mmc/card/block.c +@@ -2395,6 +2395,10 @@ static const struct mmc_fixup blk_fixups[] = + * + * N.B. This doesn't affect SD cards. + */ ++ MMC_FIXUP("SDMB-32", CID_MANFID_SANDISK, CID_OEMID_ANY, add_quirk_mmc, ++ MMC_QUIRK_BLK_NO_CMD23), ++ MMC_FIXUP("SDM032", CID_MANFID_SANDISK, CID_OEMID_ANY, add_quirk_mmc, ++ MMC_QUIRK_BLK_NO_CMD23), + MMC_FIXUP("MMC08G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc, + MMC_QUIRK_BLK_NO_CMD23), + MMC_FIXUP("MMC16G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc, +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0146-mmc-dt-add-DT-binding-for-little-endian-eSDHC-host-c.patch b/target/linux/layerscape-64b/patches-4.1/0146-mmc-dt-add-DT-binding-for-little-endian-eSDHC-host-c.patch new file mode 100644 index 0000000..7f8263c --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0146-mmc-dt-add-DT-binding-for-little-endian-eSDHC-host-c.patch @@ -0,0 +1,28 @@ +From 05702f8d221ea1328068c07906f4d1ca4ce7c2c9 Mon Sep 17 00:00:00 2001 +From: yangbo lu +Date: Thu, 8 Oct 2015 18:36:23 +0800 +Subject: [PATCH 146/151] mmc: dt: add DT binding for little-endian eSDHC host + controller + +Signed-off-by: Yangbo Lu +Signed-off-by: Ulf Hansson +--- + Documentation/devicetree/bindings/mmc/fsl-esdhc.txt | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt +index b7943f3..dedfb02 100644 +--- a/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt ++++ b/Documentation/devicetree/bindings/mmc/fsl-esdhc.txt +@@ -22,6 +22,8 @@ Optional properties: + - voltage-ranges : two cells are required, first cell specifies minimum + slot voltage (mV), second cell specifies maximum slot voltage (mV). + Several ranges could be specified. ++ - little-endian : If the host controller is little-endian mode, specify ++ this property. The default endian mode is big-endian. + + Example: + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0147-mmc-sdhci-of-esdhc-support-both-BE-and-LE-host-contr.patch b/target/linux/layerscape-64b/patches-4.1/0147-mmc-sdhci-of-esdhc-support-both-BE-and-LE-host-contr.patch new file mode 100644 index 0000000..2bdae9a --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0147-mmc-sdhci-of-esdhc-support-both-BE-and-LE-host-contr.patch @@ -0,0 +1,643 @@ +From 421ca26f01ed478a930a1d445ae6c9a3d5f39eb0 Mon Sep 17 00:00:00 2001 +From: yangbo lu +Date: Tue, 19 Apr 2016 09:35:51 +0800 +Subject: [PATCH 147/151] mmc: sdhci-of-esdhc: support both BE and LE host + controller + +commit 32bc02f8764fca837b713297a767f72b4268eeee +[context adjustment] + +To support little endian eSDHC controller, we redefine both BE and +LE IO accessors. In the new accessors, use ioread*/iowrite* instead +of in_be32/out_be32 and will select accessors according to endian +mode in probe function. + +Signed-off-by: Yangbo Lu +Signed-off-by: Ulf Hansson +Integrated-by: Zhao Qiang +--- + drivers/mmc/host/sdhci-esdhc.h | 2 + + drivers/mmc/host/sdhci-of-esdhc.c | 445 ++++++++++++++++++++++++++++---------- + 2 files changed, 338 insertions(+), 109 deletions(-) + +diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h +index 163ac99..de132e2 100644 +--- a/drivers/mmc/host/sdhci-esdhc.h ++++ b/drivers/mmc/host/sdhci-esdhc.h +@@ -24,6 +24,8 @@ + SDHCI_QUIRK_PIO_NEEDS_DELAY | \ + SDHCI_QUIRK_NO_HISPD_BIT) + ++#define ESDHC_PROCTL 0x28 ++ + #define ESDHC_SYSTEM_CONTROL 0x2c + #define ESDHC_CLOCK_MASK 0x0000fff0 + #define ESDHC_PREDIV_SHIFT 8 +diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c +index 22e9111..c8cfba7 100644 +--- a/drivers/mmc/host/sdhci-of-esdhc.c ++++ b/drivers/mmc/host/sdhci-of-esdhc.c +@@ -24,122 +24,318 @@ + + #define VENDOR_V_22 0x12 + #define VENDOR_V_23 0x13 +-static u32 esdhc_readl(struct sdhci_host *host, int reg) ++ ++struct sdhci_esdhc { ++ u8 vendor_ver; ++ u8 spec_ver; ++}; ++ ++/** ++ * esdhc_read*_fixup - Fixup the value read from incompatible eSDHC register ++ * to make it compatible with SD spec. ++ * ++ * @host: pointer to sdhci_host ++ * @spec_reg: SD spec register address ++ * @value: 32bit eSDHC register value on spec_reg address ++ * ++ * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC ++ * registers are 32 bits. There are differences in register size, register ++ * address, register function, bit position and function between eSDHC spec ++ * and SD spec. ++ * ++ * Return a fixed up register value ++ */ ++static u32 esdhc_readl_fixup(struct sdhci_host *host, ++ int spec_reg, u32 value) + { ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_esdhc *esdhc = pltfm_host->priv; + u32 ret; + +- ret = in_be32(host->ioaddr + reg); + /* + * The bit of ADMA flag in eSDHC is not compatible with standard + * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is + * supported by eSDHC. + * And for many FSL eSDHC controller, the reset value of field +- * SDHCI_CAN_DO_ADMA1 is one, but some of them can't support ADMA, ++ * SDHCI_CAN_DO_ADMA1 is 1, but some of them can't support ADMA, + * only these vendor version is greater than 2.2/0x12 support ADMA. +- * For FSL eSDHC, must aligned 4-byte, so use 0xFC to read the +- * the verdor version number, oxFE is SDHCI_HOST_VERSION. + */ +- if ((reg == SDHCI_CAPABILITIES) && (ret & SDHCI_CAN_DO_ADMA1)) { +- u32 tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS); +- tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; +- if (tmp > VENDOR_V_22) +- ret |= SDHCI_CAN_DO_ADMA2; ++ if ((spec_reg == SDHCI_CAPABILITIES) && (value & SDHCI_CAN_DO_ADMA1)) { ++ if (esdhc->vendor_ver > VENDOR_V_22) { ++ ret = value | SDHCI_CAN_DO_ADMA2; ++ return ret; ++ } + } +- ++ ret = value; + return ret; + } + +-static u16 esdhc_readw(struct sdhci_host *host, int reg) ++static u16 esdhc_readw_fixup(struct sdhci_host *host, ++ int spec_reg, u32 value) + { + u16 ret; +- int base = reg & ~0x3; +- int shift = (reg & 0x2) * 8; ++ int shift = (spec_reg & 0x2) * 8; + +- if (unlikely(reg == SDHCI_HOST_VERSION)) +- ret = in_be32(host->ioaddr + base) & 0xffff; ++ if (spec_reg == SDHCI_HOST_VERSION) ++ ret = value & 0xffff; + else +- ret = (in_be32(host->ioaddr + base) >> shift) & 0xffff; ++ ret = (value >> shift) & 0xffff; + return ret; + } + +-static u8 esdhc_readb(struct sdhci_host *host, int reg) ++static u8 esdhc_readb_fixup(struct sdhci_host *host, ++ int spec_reg, u32 value) + { +- int base = reg & ~0x3; +- int shift = (reg & 0x3) * 8; +- u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff; ++ u8 ret; ++ u8 dma_bits; ++ int shift = (spec_reg & 0x3) * 8; ++ ++ ret = (value >> shift) & 0xff; + + /* + * "DMA select" locates at offset 0x28 in SD specification, but on + * P5020 or P3041, it locates at 0x29. + */ +- if (reg == SDHCI_HOST_CONTROL) { +- u32 dma_bits; +- +- dma_bits = in_be32(host->ioaddr + reg); ++ if (spec_reg == SDHCI_HOST_CONTROL) { + /* DMA select is 22,23 bits in Protocol Control Register */ +- dma_bits = (dma_bits >> 5) & SDHCI_CTRL_DMA_MASK; +- ++ dma_bits = (value >> 5) & SDHCI_CTRL_DMA_MASK; + /* fixup the result */ + ret &= ~SDHCI_CTRL_DMA_MASK; + ret |= dma_bits; + } +- + return ret; + } + +-static void esdhc_writel(struct sdhci_host *host, u32 val, int reg) ++/** ++ * esdhc_write*_fixup - Fixup the SD spec register value so that it could be ++ * written into eSDHC register. ++ * ++ * @host: pointer to sdhci_host ++ * @spec_reg: SD spec register address ++ * @value: 8/16/32bit SD spec register value that would be written ++ * @old_value: 32bit eSDHC register value on spec_reg address ++ * ++ * In SD spec, there are 8/16/32/64 bits registers, while all of eSDHC ++ * registers are 32 bits. There are differences in register size, register ++ * address, register function, bit position and function between eSDHC spec ++ * and SD spec. ++ * ++ * Return a fixed up register value ++ */ ++static u32 esdhc_writel_fixup(struct sdhci_host *host, ++ int spec_reg, u32 value, u32 old_value) + { ++ u32 ret; ++ + /* +- * Enable IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE] +- * when SYSCTL[RSTD]) is set for some special operations. +- * No any impact other operation. ++ * Enabling IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE] ++ * when SYSCTL[RSTD] is set for some special operations. ++ * No any impact on other operation. + */ +- if (reg == SDHCI_INT_ENABLE) +- val |= SDHCI_INT_BLK_GAP; +- sdhci_be32bs_writel(host, val, reg); ++ if (spec_reg == SDHCI_INT_ENABLE) ++ ret = value | SDHCI_INT_BLK_GAP; ++ else ++ ret = value; ++ ++ return ret; + } + +-static void esdhc_writew(struct sdhci_host *host, u16 val, int reg) ++static u32 esdhc_writew_fixup(struct sdhci_host *host, ++ int spec_reg, u16 value, u32 old_value) + { +- if (reg == SDHCI_BLOCK_SIZE) { ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ int shift = (spec_reg & 0x2) * 8; ++ u32 ret; ++ ++ switch (spec_reg) { ++ case SDHCI_TRANSFER_MODE: ++ /* ++ * Postpone this write, we must do it together with a ++ * command write that is down below. Return old value. ++ */ ++ pltfm_host->xfer_mode_shadow = value; ++ return old_value; ++ case SDHCI_COMMAND: ++ ret = (value << 16) | pltfm_host->xfer_mode_shadow; ++ return ret; ++ } ++ ++ ret = old_value & (~(0xffff << shift)); ++ ret |= (value << shift); ++ ++ if (spec_reg == SDHCI_BLOCK_SIZE) { + /* + * Two last DMA bits are reserved, and first one is used for + * non-standard blksz of 4096 bytes that we don't support + * yet. So clear the DMA boundary bits. + */ +- val &= ~SDHCI_MAKE_BLKSZ(0x7, 0); ++ ret &= (~SDHCI_MAKE_BLKSZ(0x7, 0)); + } +- sdhci_be32bs_writew(host, val, reg); ++ return ret; + } + +-static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg) ++static u32 esdhc_writeb_fixup(struct sdhci_host *host, ++ int spec_reg, u8 value, u32 old_value) + { ++ u32 ret; ++ u32 dma_bits; ++ u8 tmp; ++ int shift = (spec_reg & 0x3) * 8; ++ + /* + * "DMA select" location is offset 0x28 in SD specification, but on + * P5020 or P3041, it's located at 0x29. + */ +- if (reg == SDHCI_HOST_CONTROL) { +- u32 dma_bits; +- ++ if (spec_reg == SDHCI_HOST_CONTROL) { + /* + * If host control register is not standard, exit + * this function + */ + if (host->quirks2 & SDHCI_QUIRK2_BROKEN_HOST_CONTROL) +- return; ++ return old_value; + + /* DMA select is 22,23 bits in Protocol Control Register */ +- dma_bits = (val & SDHCI_CTRL_DMA_MASK) << 5; +- clrsetbits_be32(host->ioaddr + reg , SDHCI_CTRL_DMA_MASK << 5, +- dma_bits); +- val &= ~SDHCI_CTRL_DMA_MASK; +- val |= in_be32(host->ioaddr + reg) & SDHCI_CTRL_DMA_MASK; ++ dma_bits = (value & SDHCI_CTRL_DMA_MASK) << 5; ++ ret = (old_value & (~(SDHCI_CTRL_DMA_MASK << 5))) | dma_bits; ++ tmp = (value & (~SDHCI_CTRL_DMA_MASK)) | ++ (old_value & SDHCI_CTRL_DMA_MASK); ++ ret = (ret & (~0xff)) | tmp; ++ ++ /* Prevent SDHCI core from writing reserved bits (e.g. HISPD) */ ++ ret &= ~ESDHC_HOST_CONTROL_RES; ++ return ret; + } + +- /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */ +- if (reg == SDHCI_HOST_CONTROL) +- val &= ~ESDHC_HOST_CONTROL_RES; +- sdhci_be32bs_writeb(host, val, reg); ++ ret = (old_value & (~(0xff << shift))) | (value << shift); ++ return ret; ++} ++ ++static u32 esdhc_be_readl(struct sdhci_host *host, int reg) ++{ ++ u32 ret; ++ u32 value; ++ ++ value = ioread32be(host->ioaddr + reg); ++ ret = esdhc_readl_fixup(host, reg, value); ++ ++ return ret; ++} ++ ++static u32 esdhc_le_readl(struct sdhci_host *host, int reg) ++{ ++ u32 ret; ++ u32 value; ++ ++ value = ioread32(host->ioaddr + reg); ++ ret = esdhc_readl_fixup(host, reg, value); ++ ++ return ret; ++} ++ ++static u16 esdhc_be_readw(struct sdhci_host *host, int reg) ++{ ++ u16 ret; ++ u32 value; ++ int base = reg & ~0x3; ++ ++ value = ioread32be(host->ioaddr + base); ++ ret = esdhc_readw_fixup(host, reg, value); ++ return ret; ++} ++ ++static u16 esdhc_le_readw(struct sdhci_host *host, int reg) ++{ ++ u16 ret; ++ u32 value; ++ int base = reg & ~0x3; ++ ++ value = ioread32(host->ioaddr + base); ++ ret = esdhc_readw_fixup(host, reg, value); ++ return ret; ++} ++ ++static u8 esdhc_be_readb(struct sdhci_host *host, int reg) ++{ ++ u8 ret; ++ u32 value; ++ int base = reg & ~0x3; ++ ++ value = ioread32be(host->ioaddr + base); ++ ret = esdhc_readb_fixup(host, reg, value); ++ return ret; ++} ++ ++static u8 esdhc_le_readb(struct sdhci_host *host, int reg) ++{ ++ u8 ret; ++ u32 value; ++ int base = reg & ~0x3; ++ ++ value = ioread32(host->ioaddr + base); ++ ret = esdhc_readb_fixup(host, reg, value); ++ return ret; ++} ++ ++static void esdhc_be_writel(struct sdhci_host *host, u32 val, int reg) ++{ ++ u32 value; ++ ++ value = esdhc_writel_fixup(host, reg, val, 0); ++ iowrite32be(value, host->ioaddr + reg); ++} ++ ++static void esdhc_le_writel(struct sdhci_host *host, u32 val, int reg) ++{ ++ u32 value; ++ ++ value = esdhc_writel_fixup(host, reg, val, 0); ++ iowrite32(value, host->ioaddr + reg); ++} ++ ++static void esdhc_be_writew(struct sdhci_host *host, u16 val, int reg) ++{ ++ int base = reg & ~0x3; ++ u32 value; ++ u32 ret; ++ ++ value = ioread32be(host->ioaddr + base); ++ ret = esdhc_writew_fixup(host, reg, val, value); ++ if (reg != SDHCI_TRANSFER_MODE) ++ iowrite32be(ret, host->ioaddr + base); ++} ++ ++static void esdhc_le_writew(struct sdhci_host *host, u16 val, int reg) ++{ ++ int base = reg & ~0x3; ++ u32 value; ++ u32 ret; ++ ++ value = ioread32(host->ioaddr + base); ++ ret = esdhc_writew_fixup(host, reg, val, value); ++ if (reg != SDHCI_TRANSFER_MODE) ++ iowrite32(ret, host->ioaddr + base); ++} ++ ++static void esdhc_be_writeb(struct sdhci_host *host, u8 val, int reg) ++{ ++ int base = reg & ~0x3; ++ u32 value; ++ u32 ret; ++ ++ value = ioread32be(host->ioaddr + base); ++ ret = esdhc_writeb_fixup(host, reg, val, value); ++ iowrite32be(ret, host->ioaddr + base); ++} ++ ++static void esdhc_le_writeb(struct sdhci_host *host, u8 val, int reg) ++{ ++ int base = reg & ~0x3; ++ u32 value; ++ u32 ret; ++ ++ value = ioread32(host->ioaddr + base); ++ ret = esdhc_writeb_fixup(host, reg, val, value); ++ iowrite32(ret, host->ioaddr + base); + } + + /* +@@ -149,19 +345,17 @@ static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg) + * For Continue, apply soft reset for data(SYSCTL[RSTD]); + * and re-issue the entire read transaction from beginning. + */ +-static void esdhci_of_adma_workaround(struct sdhci_host *host, u32 intmask) ++static void esdhc_of_adma_workaround(struct sdhci_host *host, u32 intmask) + { +- u32 tmp; ++ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); ++ struct sdhci_esdhc *esdhc = pltfm_host->priv; + bool applicable; + dma_addr_t dmastart; + dma_addr_t dmanow; + +- tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS); +- tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; +- + applicable = (intmask & SDHCI_INT_DATA_END) && +- (intmask & SDHCI_INT_BLK_GAP) && +- (tmp == VENDOR_V_23); ++ (intmask & SDHCI_INT_BLK_GAP) && ++ (esdhc->vendor_ver == VENDOR_V_23); + if (!applicable) + return; + +@@ -179,7 +373,11 @@ static void esdhci_of_adma_workaround(struct sdhci_host *host, u32 intmask) + + static int esdhc_of_enable_dma(struct sdhci_host *host) + { +- setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP); ++ u32 value; ++ ++ value = sdhci_readl(host, ESDHC_DMA_SYSCTL); ++ value |= ESDHC_DMA_SNOOP; ++ sdhci_writel(host, value, ESDHC_DMA_SYSCTL); + return 0; + } + +@@ -241,39 +439,26 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) + mdelay(1); + } + +-static void esdhc_of_platform_init(struct sdhci_host *host) +-{ +- u32 vvn; +- +- vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS); +- vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; +- if (vvn == VENDOR_V_22) +- host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; +- +- if (vvn > VENDOR_V_22) +- host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; +-} +- + static void esdhc_pltfm_set_bus_width(struct sdhci_host *host, int width) + { + u32 ctrl; + ++ ctrl = sdhci_readl(host, ESDHC_PROCTL); ++ ctrl &= (~ESDHC_CTRL_BUSWIDTH_MASK); + switch (width) { + case MMC_BUS_WIDTH_8: +- ctrl = ESDHC_CTRL_8BITBUS; ++ ctrl |= ESDHC_CTRL_8BITBUS; + break; + + case MMC_BUS_WIDTH_4: +- ctrl = ESDHC_CTRL_4BITBUS; ++ ctrl |= ESDHC_CTRL_4BITBUS; + break; + + default: +- ctrl = 0; + break; + } + +- clrsetbits_be32(host->ioaddr + SDHCI_HOST_CONTROL, +- ESDHC_CTRL_BUSWIDTH_MASK, ctrl); ++ sdhci_writel(host, ctrl, ESDHC_PROCTL); + } + + static void esdhc_reset(struct sdhci_host *host, u8 mask) +@@ -284,32 +469,13 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask) + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); + } + +-static const struct sdhci_ops sdhci_esdhc_ops = { +- .read_l = esdhc_readl, +- .read_w = esdhc_readw, +- .read_b = esdhc_readb, +- .write_l = esdhc_writel, +- .write_w = esdhc_writew, +- .write_b = esdhc_writeb, +- .set_clock = esdhc_of_set_clock, +- .enable_dma = esdhc_of_enable_dma, +- .get_max_clock = esdhc_of_get_max_clock, +- .get_min_clock = esdhc_of_get_min_clock, +- .platform_init = esdhc_of_platform_init, +- .adma_workaround = esdhci_of_adma_workaround, +- .set_bus_width = esdhc_pltfm_set_bus_width, +- .reset = esdhc_reset, +- .set_uhs_signaling = sdhci_set_uhs_signaling, +-}; +- + #ifdef CONFIG_PM +- + static u32 esdhc_proctl; + static int esdhc_of_suspend(struct device *dev) + { + struct sdhci_host *host = dev_get_drvdata(dev); + +- esdhc_proctl = sdhci_be32bs_readl(host, SDHCI_HOST_CONTROL); ++ esdhc_proctl = sdhci_readl(host, SDHCI_HOST_CONTROL); + + return sdhci_suspend_host(host); + } +@@ -322,9 +488,8 @@ static int esdhc_of_resume(struct device *dev) + if (ret == 0) { + /* Isn't this already done by sdhci_resume_host() ? --rmk */ + esdhc_of_enable_dma(host); +- sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL); ++ sdhci_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL); + } +- + return ret; + } + +@@ -337,30 +502,92 @@ static const struct dev_pm_ops esdhc_pmops = { + #define ESDHC_PMOPS NULL + #endif + +-static const struct sdhci_pltfm_data sdhci_esdhc_pdata = { +- /* +- * card detection could be handled via GPIO +- * eSDHC cannot support End Attribute in NOP ADMA descriptor +- */ ++static const struct sdhci_ops sdhci_esdhc_be_ops = { ++ .read_l = esdhc_be_readl, ++ .read_w = esdhc_be_readw, ++ .read_b = esdhc_be_readb, ++ .write_l = esdhc_be_writel, ++ .write_w = esdhc_be_writew, ++ .write_b = esdhc_be_writeb, ++ .set_clock = esdhc_of_set_clock, ++ .enable_dma = esdhc_of_enable_dma, ++ .get_max_clock = esdhc_of_get_max_clock, ++ .get_min_clock = esdhc_of_get_min_clock, ++ .adma_workaround = esdhc_of_adma_workaround, ++ .set_bus_width = esdhc_pltfm_set_bus_width, ++ .reset = esdhc_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, ++}; ++ ++static const struct sdhci_ops sdhci_esdhc_le_ops = { ++ .read_l = esdhc_le_readl, ++ .read_w = esdhc_le_readw, ++ .read_b = esdhc_le_readb, ++ .write_l = esdhc_le_writel, ++ .write_w = esdhc_le_writew, ++ .write_b = esdhc_le_writeb, ++ .set_clock = esdhc_of_set_clock, ++ .enable_dma = esdhc_of_enable_dma, ++ .get_max_clock = esdhc_of_get_max_clock, ++ .get_min_clock = esdhc_of_get_min_clock, ++ .adma_workaround = esdhc_of_adma_workaround, ++ .set_bus_width = esdhc_pltfm_set_bus_width, ++ .reset = esdhc_reset, ++ .set_uhs_signaling = sdhci_set_uhs_signaling, ++}; ++ ++static const struct sdhci_pltfm_data sdhci_esdhc_be_pdata = { ++ .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION ++ | SDHCI_QUIRK_NO_CARD_NO_RESET ++ | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, ++ .ops = &sdhci_esdhc_be_ops, ++}; ++ ++static const struct sdhci_pltfm_data sdhci_esdhc_le_pdata = { + .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION + | SDHCI_QUIRK_NO_CARD_NO_RESET + | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, +- .ops = &sdhci_esdhc_ops, ++ .ops = &sdhci_esdhc_le_ops, + }; + ++static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) ++{ ++ struct sdhci_pltfm_host *pltfm_host; ++ struct sdhci_esdhc *esdhc; ++ u16 host_ver; ++ ++ pltfm_host = sdhci_priv(host); ++ esdhc = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_esdhc), ++ GFP_KERNEL); ++ ++ host_ver = sdhci_readw(host, SDHCI_HOST_VERSION); ++ esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >> ++ SDHCI_VENDOR_VER_SHIFT; ++ esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK; ++ ++ pltfm_host->priv = esdhc; ++} ++ + static int sdhci_esdhc_probe(struct platform_device *pdev) + { + struct sdhci_host *host; + struct device_node *np; + int ret; + +- host = sdhci_pltfm_init(pdev, &sdhci_esdhc_pdata, 0); ++ np = pdev->dev.of_node; ++ ++ if (of_get_property(np, "little-endian", NULL)) ++ host = sdhci_pltfm_init(pdev, &sdhci_esdhc_le_pdata, 0); ++ else ++ host = sdhci_pltfm_init(pdev, &sdhci_esdhc_be_pdata, 0); ++ + if (IS_ERR(host)) + return PTR_ERR(host); + ++ esdhc_init(pdev, host); ++ + sdhci_get_of_property(pdev); + +- np = pdev->dev.of_node; + if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { + /* + * Freescale messed up with P2020 as it has a non-standard +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0148-mmc-kconfig-reconfigure-MMC_SDHCI_OF_ESDHC-option.patch b/target/linux/layerscape-64b/patches-4.1/0148-mmc-kconfig-reconfigure-MMC_SDHCI_OF_ESDHC-option.patch new file mode 100644 index 0000000..61e8429 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0148-mmc-kconfig-reconfigure-MMC_SDHCI_OF_ESDHC-option.patch @@ -0,0 +1,42 @@ +From f3fe0dbea54b234d6f78f033ad9d8da747e0f401 Mon Sep 17 00:00:00 2001 +From: yangbo lu +Date: Thu, 8 Oct 2015 18:36:47 +0800 +Subject: [PATCH 148/151] mmc: kconfig: reconfigure MMC_SDHCI_OF_ESDHC option + +Freescale eSDHC driver now supports both little-endian and +big-endian mode eSDHC IPs for ARM and PPC. So, MMC_SDHCI_OF_ESDHC +option needs to be reconfigured. + +Signed-off-by: Yangbo Lu +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/Kconfig | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig +index 03e5886..906502b 100644 +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -67,7 +67,7 @@ config MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER + has the effect of scrambling the addresses and formats of data + accessed in sizes other than the datum size. + +- This is the case for the Freescale eSDHC and Nintendo Wii SDHCI. ++ This is the case for the Nintendo Wii SDHCI. + + config MMC_SDHCI_PCI + tristate "SDHCI support on PCI bus" +@@ -132,8 +132,8 @@ config MMC_SDHCI_OF_ARASAN + config MMC_SDHCI_OF_ESDHC + tristate "SDHCI OF support for the Freescale eSDHC controller" + depends on MMC_SDHCI_PLTFM +- depends on PPC +- select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER ++ depends on PPC || ARCH_MXC || ARCH_LAYERSCAPE ++ select MMC_SDHCI_IO_ACCESSORS + help + This selects the Freescale eSDHC controller support. + +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0149-mmc-sdhci-of-esdhc-avoid-writing-power-control-regis.patch b/target/linux/layerscape-64b/patches-4.1/0149-mmc-sdhci-of-esdhc-avoid-writing-power-control-regis.patch new file mode 100644 index 0000000..cf7172c --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0149-mmc-sdhci-of-esdhc-avoid-writing-power-control-regis.patch @@ -0,0 +1,36 @@ +From c9892dce30afb74e8ae99c3df97045dc14ed4b10 Mon Sep 17 00:00:00 2001 +From: yangbo lu +Date: Fri, 16 Oct 2015 15:44:03 +0800 +Subject: [PATCH 149/151] mmc: sdhci-of-esdhc: avoid writing power control + register + +The eSDHC doesn't have a standard power control register, so when +writing this register in stack we should do nothing to avoid +incorrect operation. + +Signed-off-by: Yangbo Lu +Signed-off-by: Ulf Hansson +--- + drivers/mmc/host/sdhci-of-esdhc.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c +index c8cfba7..c346ee5 100644 +--- a/drivers/mmc/host/sdhci-of-esdhc.c ++++ b/drivers/mmc/host/sdhci-of-esdhc.c +@@ -183,6 +183,12 @@ static u32 esdhc_writeb_fixup(struct sdhci_host *host, + int shift = (spec_reg & 0x3) * 8; + + /* ++ * eSDHC doesn't have a standard power control register, so we do ++ * nothing here to avoid incorrect operation. ++ */ ++ if (spec_reg == SDHCI_POWER_CONTROL) ++ return old_value; ++ /* + * "DMA select" location is offset 0x28 in SD specification, but on + * P5020 or P3041, it's located at 0x29. + */ +-- +2.1.0.27.g96db324 + diff --git a/target/linux/layerscape-64b/patches-4.1/0150-mmc-sdhci-of-esdhc-add-remove-some-quirks-according-.patch b/target/linux/layerscape-64b/patches-4.1/0150-mmc-sdhci-of-esdhc-add-remove-some-quirks-according-.patch new file mode 100644 index 0000000..4a10df2 --- /dev/null +++ b/target/linux/layerscape-64b/patches-4.1/0150-mmc-sdhci-of-esdhc-add-remove-some-quirks-according-.patch @@ -0,0 +1,65 @@ +From ba6b66490b3e53296008045d488d6dc5c76c78fe Mon Sep 17 00:00:00 2001 +From: yangbo lu +Date: Tue, 19 Apr 2016 09:47:15 +0800 +Subject: [PATCH 150/151] mmc: sdhci-of-esdhc: add/remove some quirks according + to vendor version + +commit 6c42cb309fee2e126beed6b96a986dc7d85a033d +[context adjustment] + +A previous patch had removed esdhc_of_platform_init() by mistake. +static void esdhc_of_platform_init(struct sdhci_host *host) +{ + u32 vvn; + + vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS); + vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; + if (vvn == VENDOR_V_22) + host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; + + if (vvn > VENDOR_V_22) + host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; +} + +This patch is used to fix it by add/remove some quirks according to +verdor version in probe. + +Signed-off-by: Yangbo Lu +Fixes: f4932cfd22f1 ("mmc: sdhci-of-esdhc: support both BE and LE host controller") +Signed-off-by: Ulf Hansson +Integrated-by: Zhao Qiang +--- + drivers/mmc/host/sdhci-of-esdhc.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c +index c346ee5..0c266d5 100644 +--- a/drivers/mmc/host/sdhci-of-esdhc.c ++++ b/drivers/mmc/host/sdhci-of-esdhc.c +@@ -578,6 +578,8 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) + { + struct sdhci_host *host; + struct device_node *np; ++ struct sdhci_pltfm_host *pltfm_host; ++ struct sdhci_esdhc *esdhc; + int ret; + + np = pdev->dev.of_node; +@@ -594,6 +596,14 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) + + sdhci_get_of_property(pdev); + ++ pltfm_host = sdhci_priv(host); ++ esdhc = pltfm_host->priv; ++ if (esdhc->vendor_ver == VENDOR_V_22) ++ host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; ++ ++ if (esdhc->vendor_ver > VENDOR_V_22) ++ host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; ++ + if (of_device_is_compatible(np, "fsl,p2020-esdhc")) { + /* + * Freescale messed up with P2020 as it has a non-standard +-- +2.1.0.27.g96db324 + -- 1.7.9.5 _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From ronaldo at ronaldoafonso.com.br Wed Jul 13 16:27:26 2016 From: ronaldo at ronaldoafonso.com.br (Ronaldo Afonso) Date: Wed, 13 Jul 2016 17:27:26 -0300 Subject: [OpenWrt-Devel] How to check if its the first boot ever? Message-ID: Hi all, I'm doing a customized OpenWrt firmware and I need to know at boot time if its the first time my OpenWrt firmware has been booted. More specifically, my scripts at "/etc/uci-defaults" need to know if they are being executed by flashing over a "router original firmware" (factory.bin) or a previews OpenWrt firmware (sysupgrade.bin). For example: I need to set the network.lan.ipaddr to the IP address "192.168.120.1" if it is the first time I'm flashing my router, otherwise I need to preserve the IP address the was configured before. Any help would be appreciated. Thanks in advance ... -- Ronaldo Afonso 11 9 5252 0484 www.ronaldoafonso.com.br -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From me at ndoo.sg Wed Jul 13 23:37:19 2016 From: me at ndoo.sg (Andrew Yong) Date: Thu, 14 Jul 2016 11:37:19 +0800 Subject: [OpenWrt-Devel] How to check if its the first boot ever? In-Reply-To: References: Message-ID: You could customize the files that sysupgrade retains, that should be the easiest way. On Thu, Jul 14, 2016 at 4:27 AM, Ronaldo Afonso wrote: > Hi all, > > I'm doing a customized OpenWrt firmware and I need to know at boot time if > its the first time my OpenWrt firmware has been booted. > > More specifically, my scripts at "/etc/uci-defaults" need to know if they > are being executed by flashing over a "router original firmware" > (factory.bin) or a previews OpenWrt firmware (sysupgrade.bin). > > For example: > > I need to set the network.lan.ipaddr to the IP address "192.168.120.1" if > it is the first time I'm flashing my router, otherwise I need to preserve > the IP address the was configured before. > > Any help would be appreciated. > > Thanks in advance ... > > -- > Ronaldo Afonso > 11 9 5252 0484 > www.ronaldoafonso.com.br > > _______________________________________________ > openwrt-devel mailing list > openwrt-devel at lists.openwrt.org > https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel > _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From zajec5 at gmail.com Thu Jul 14 02:41:39 2016 From: zajec5 at gmail.com (=?UTF-8?B?UmFmYcWCIE1pxYJlY2tp?=) Date: Thu, 14 Jul 2016 08:41:39 +0200 Subject: [OpenWrt-Devel] How to check if its the first boot ever? In-Reply-To: References: Message-ID: On 13 July 2016 at 22:27, Ronaldo Afonso wrote: > More specifically, my scripts at "/etc/uci-defaults" need to know if they > are being executed by flashing over a "router original firmware" > (factory.bin) or a previews OpenWrt firmware (sysupgrade.bin). What about using something like /etc/config/ronaldo with some option like "firstboot"? Of course you should add this file to the list of preserved config files. _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From yutang.jiang at nxp.com Thu Jul 14 03:05:09 2016 From: yutang.jiang at nxp.com (Yutang Jiang) Date: Thu, 14 Jul 2016 07:05:09 +0000 Subject: [OpenWrt-Devel] [PATCH 1/2] layerscape: add ls1043ardb-64b target In-Reply-To: References: <1468432570-7202-1-git-send-email-yutang.jiang@nxp.com> Message-ID: Hi Jonas, Thanks you for your advise! It is first time for our team to submit patch to Openwrt, we will following your suggestion to update our patches. Summary: 1.update codebase to 4.4 kernel. 2.merge two patches to one and put it on github repository. 3.remove README.ls1043ardb, then add this information to the wiki. 4.update image build code to Device/* sections 5.find Build/check-size and Device/Build/check_size, replace checkimagesize.sh 6.minimize kernel config. 7.replace subtargets with device/profile. Thanks & Best Regards Jiang Yutang -----Original Message----- From: Jonas Gorski [mailto:jonas.gorski at gmail.com] Sent: Wednesday, July 13, 2016 6:42 PM To: Yutang Jiang Cc: OpenWrt Development List Subject: Re: [OpenWrt-Devel] [PATCH 1/2] layerscape: add ls1043ardb-64b target Hi, On 13 July 2016 at 19:56, wrote: > From: Yutang Jiang > > Add support for NXP layerscape ls1043ardb-64b Dev board. Nice to see support for it here. A few things first, though > > ls1043ardb-64b target is using 4.1 kernel and rcw/u-boot/fman images > from NXP QorIQ SDK V2.0 release. Please update your codebase to 4.4 first. The next release kernel is currently planned to be 4.4. > All of 4.1 kernel patches will be in the second patch, it have more > than > 100 kernel patches: platform/flash/dpaa/mmc/usb/pcie etc, porting > from SDK release or upstream. Please add them at the same time. If it's too large for an email, you can also put the commit in a public git repository. You can also create a pull request on github. I guess several of the patches will be obsolete with the switch to 4.4 anyway? > > Signed-off-by: Yutang Jiang > --- > target/linux/layerscape-64b/Makefile | 26 + > target/linux/layerscape-64b/README.ls1043ardb | 860 ++++++ > target/linux/layerscape-64b/base-files/etc/inittab | 6 + > target/linux/layerscape-64b/image/Makefile | 64 + > .../linux/layerscape-64b/image/checkimagesize.sh | 16 + > .../linux/layerscape-64b/ls1043ardb/config-default | 3146 ++++++++++++++++++++ > target/linux/layerscape-64b/ls1043ardb/target.mk | 16 + > 7 files changed, 4134 insertions(+) > create mode 100644 target/linux/layerscape-64b/Makefile > create mode 100644 target/linux/layerscape-64b/README.ls1043ardb > create mode 100644 target/linux/layerscape-64b/base-files/etc/inittab > create mode 100644 target/linux/layerscape-64b/image/Makefile > create mode 100755 > target/linux/layerscape-64b/image/checkimagesize.sh > create mode 100644 > target/linux/layerscape-64b/ls1043ardb/config-default > create mode 100644 target/linux/layerscape-64b/ls1043ardb/target.mk > > diff --git a/target/linux/layerscape-64b/Makefile > b/target/linux/layerscape-64b/Makefile > new file mode 100644 > index 0000000..63d55b9 > --- /dev/null > +++ b/target/linux/layerscape-64b/Makefile > @@ -0,0 +1,26 @@ > +# > +# Copyright (C) 2016 OpenWrt.org > +# > +# This is free software, licensed under the GNU General Public License v2. > +# See /LICENSE for more information. > +# > +include $(TOPDIR)/rules.mk > + > +ARCH:=aarch64 > +BOARD:=layerscape-64b > +BOARDNAME:=layerscape 64b > +CFLAGS:=-Os -pipe -fno-caller-saves > +DEVICE_TYPE:=developerboard > +KERNEL_PATCHVER:=4.1 > +KERNELNAME:=Image dtbs > +FEATURES:=squashfs > +SUBTARGETS:=ls1043ardb > +MAINTAINER:=Jiang Yutang > + > +include $(INCLUDE_DIR)/target.mk > + > +define Target/Description > + Build firmware images for $(BOARDNAME) SoC devices. > +endef > + > +$(eval $(call BuildTarget)) > diff --git a/target/linux/layerscape-64b/README.ls1043ardb > b/target/linux/layerscape-64b/README.ls1043ardb > new file mode 100644 > index 0000000..9f6a0af > --- /dev/null > +++ b/target/linux/layerscape-64b/README.ls1043ardb > @@ -0,0 +1,860 @@ (snip) I think a lot of this information (like the bootlog) is better served on the wiki, or shouldn't be here at all (like the contents of various uci files, which are subject to change, and nobody will remember to update the example output here). > diff --git a/target/linux/layerscape-64b/image/Makefile > b/target/linux/layerscape-64b/image/Makefile > new file mode 100644 > index 0000000..43e7269 > --- /dev/null > +++ b/target/linux/layerscape-64b/image/Makefile > @@ -0,0 +1,64 @@ > +# > +# Copyright (C) 2016 OpenWrt.org > +# > +# This is free software, licensed under the GNU General Public License v2. > +# See /LICENSE for more information. > +# > +include $(TOPDIR)/rules.mk > +include $(INCLUDE_DIR)/image.mk > + > +# make uImage and dtb > +define Image/uImage-dtb > + gzip -9c < $(KDIR)/Image > $(KDIR)/Image.gz > + $(eval ARCH_BACK = $(ARCH)) > + $(eval ARCH = $(LINUX_KARCH)) > + $(call Image/BuildKernel/MkuImage, gzip, $(KERNEL_LOADADDR), \ > + $(KERNEL_ENTRY_POINT), $(KDIR)/Image.gz, \ > + $(KDIR)/$(IMG_PREFIX)-uImage) > + $(eval ARCH = $(ARCH_BACK)) > + > + $(call > +Image/BuildDTB,$(DTS_DIR)/$(DEVICE_DTS).dts,$(KDIR)/$(IMG_PREFIX)-dtb > +) > +endef > + > +# $(1) source image name > +# $(2) partition image name > +# $(3) partition image size(M) > +define Image/Build/flashpartitionimage > + ./checkimagesize.sh $(1) $(3) > + dd if=/dev/zero bs=1M count=$(3) | sed 's/\x00/\xff/g' > $(2) > + dd if=$(1) of=$(2) conv=notrunc endef > + > +# make squashfs then merge uImage/dtb/squashfs to one firmware image > +arranged # by individual partition define Image/Build/squashfs > + $(call prepare_generic_squashfs,$(KDIR)/root.squashfs) > + > + $(call Image/Build/flashpartitionimage,$(KDIR)/$(IMG_PREFIX)-dtb,$(KDIR)/$(IMG_PREFIX)-dtb-par,$(DTB_PARTITION_SIZE)) > + $(call Image/Build/flashpartitionimage,$(KDIR)/$(IMG_PREFIX)-uImage,$(KDIR)/$(IMG_PREFIX)-uImage-par,$(KERNEL_PARTITION_SIZE)) > + $(call Image/Build/flashpartitionimage,$(KDIR)/root.squashfs,$(KDIR)/root.squashfs-par,$(SQUASHFS_PARTITION_SIZE)) > + cat $(KDIR)/$(IMG_PREFIX)-dtb-par $(KDIR)/$(IMG_PREFIX)-uImage-par \ > + $(KDIR)/root.squashfs-par > $(BIN_DIR)/$(IMG_PREFIX)-firmware > + $(RM) $(KDIR)/$(IMG_PREFIX)-dtb-par $(KDIR)/$(IMG_PREFIX)-uImage-par \ > + $(KDIR)/root.squashfs-par endef > + > +# target macros > +define Target/Default > + KERNEL_LOADADDR = 0x80080000 > + KERNEL_ENTRY_POINT = 0x80080000 endef > + > +# callback function: Image/BuildKernel define Image/BuildKernel > + $(eval $(call Target/Default)) > + $(eval $(call Subtarget/Default)) > + $(call Image/uImage-dtb) > +endef > + > +# callback function: Image/Build > +define Image/Build > + $(call Image/Build/$(1),$(1)) > +endef > + > +$(eval $(call BuildImage)) Please update your image build code to the new image code with defining appropriate Device/* sections. This will then also eliminate > diff --git a/target/linux/layerscape-64b/image/checkimagesize.sh > b/target/linux/layerscape-64b/image/checkimagesize.sh > new file mode 100755 > index 0000000..e65c7fe > --- /dev/null > +++ b/target/linux/layerscape-64b/image/checkimagesize.sh this file, as there is a size check build step available. > diff --git a/target/linux/layerscape-64b/ls1043ardb/config-default > b/target/linux/layerscape-64b/ls1043ardb/config-default > new file mode 100644 > index 0000000..1543907 > --- /dev/null > +++ b/target/linux/layerscape-64b/ls1043ardb/config-default > @@ -0,0 +1,3146 @@ > +# > +# Automatically generated file; DO NOT EDIT. > +# Linux/arm64 4.1.23 Kernel Configuration # > (snip) Please minimize this config by running "make kernel_defconfig CONFIG_TARGET=subtarget" (or put this as the "main" config as target/layerscape-64b/config-default, then run just "make kernel_defconfig"). > diff --git a/target/linux/layerscape-64b/ls1043ardb/target.mk > b/target/linux/layerscape-64b/ls1043ardb/target.mk > new file mode 100644 > index 0000000..9f2580b > --- /dev/null > +++ b/target/linux/layerscape-64b/ls1043ardb/target.mk > @@ -0,0 +1,16 @@ > +# > +# Copyright (C) 2016 OpenWrt.org > +# > +# This is free software, licensed under the GNU General Public License v2. > +# See /LICENSE for more information. > +# > +BOARDNAME += $(SUBTARGET) > + > +# subtarget macros > +# PARTITION_SIZE unit: (M) > +define Subtarget/Default > + DEVICE_DTS = freescale/fsl-ls1043a-rdb > + DTB_PARTITION_SIZE = 1 > + KERNEL_PARTITION_SIZE = 5 > + SQUASHFS_PARTITION_SIZE = 54 > +endef Please don't use subtargets for single boards - subtargets should be limited for variants that require different, incompatible compiler options or kernel options (e.g. little vs big endian, 32 vs 64 bit etc). Just make this the default device/profile of the target then. Regards Jonas _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hojuruku at gmail.com Thu Jul 14 03:29:41 2016 From: hojuruku at gmail.com (Luke McKee) Date: Thu, 14 Jul 2016 14:29:41 +0700 Subject: [OpenWrt-Devel] ar71xx: add tp-link 841nd-v9-vn board - 8mbit flash isp oem variant Message-ID: https://github.com/openwrt/openwrt/pull/29 https://github.com/openwrt/openwrt/pull/29/commits/84c616f66390230a2938f8db691e8093f1669ec2 Please see the commit message or the forum. This has been run-tested on the new hardware which is basically the same as a v9 board just with the larger flash size https://forum.openwrt.org/viewtopic.php?id=65786 Users can install factory.bin's via tp-link firmware, or use sysupgrade - both tested successfully. As you can see from the factory rom extracted via uboot, it really does have different HWID's used by tp-link to distinguish the OEM order for larger flash size. They add a 1 at the end of the HWID to denote that. If a user bricks a tp-link 841nd v9 , the factory bootloader has a tftp recovery method as demonstrated. In any case -v9-vn firmware will not install on -v9 firwmare and visa versa. There isn't much need for pico''s patched u-boot I think, except for the frills of a web-browser to upgrade the flash and loosing your Ethernet mac address. https://www.youtube.com/watch?v=0k1sxwX5pMk _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From dedeckeh at gmail.com Thu Jul 14 04:14:13 2016 From: dedeckeh at gmail.com (Hans Dedecker) Date: Thu, 14 Jul 2016 10:14:13 +0200 Subject: [OpenWrt-Devel] [PATCH netifd 1/3] proto-shell: Model config parameter "no-proto-task" as a proto flag Message-ID: <1468484055-27341-1-git-send-email-dedeckeh@gmail.com> Export the config parameter "no-proto-task" as a proto flag so it can be checked by other netifd modules Signed-off-by: Hans Dedecker --- proto-shell.c | 6 +++--- proto.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/proto-shell.c b/proto-shell.c index 25dec00..1922024 100644 --- a/proto-shell.c +++ b/proto-shell.c @@ -44,7 +44,6 @@ struct proto_shell_handler { char *config_buf; char *script_name; bool init_available; - bool no_proto_task; struct uci_blob_param_list config; }; @@ -306,7 +305,7 @@ proto_shell_task_finish(struct proto_shell_state *state, if (state->renew_pending) proto_shell_handler(&state->proto, PROTO_CMD_RENEW, false); - else if (!state->handler->no_proto_task && + else if (!(state->handler->proto.flags & PROTO_FLAG_NO_TASK) && !state->proto_task.uloop.pending && state->sm == S_SETUP) proto_shell_handler(&state->proto, @@ -892,7 +891,8 @@ proto_shell_add_handler(const char *script, const char *name, json_object *obj) handler->proto.flags |= PROTO_FLAG_NODEV; tmp = json_get_field(obj, "no-proto-task", json_type_boolean); - handler->no_proto_task = tmp && json_object_get_boolean(tmp); + if (tmp && json_object_get_boolean(tmp)) + handler->proto.flags |= PROTO_FLAG_NO_TASK; tmp = json_get_field(obj, "available", json_type_boolean); if (tmp && json_object_get_boolean(tmp)) diff --git a/proto.h b/proto.h index 87dec4e..4c4d824 100644 --- a/proto.h +++ b/proto.h @@ -38,6 +38,7 @@ enum { PROTO_FLAG_RENEW_AVAILABLE = (1 << 3), PROTO_FLAG_FORCE_LINK_DEFAULT = (1 << 4), PROTO_FLAG_LASTERROR = (1 << 5), + PROTO_FLAG_NO_TASK = (1 << 6), }; struct interface_proto_state { -- 1.9.1 _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From dedeckeh at gmail.com Thu Jul 14 04:14:14 2016 From: dedeckeh at gmail.com (Hans Dedecker) Date: Thu, 14 Jul 2016 10:14:14 +0200 Subject: [OpenWrt-Devel] [PATCH netifd 2/3] interface: Only teardown interfaces having no proto task when l3_dev link lost In-Reply-To: <1468484055-27341-1-git-send-email-dedeckeh@gmail.com> References: <1468484055-27341-1-git-send-email-dedeckeh@gmail.com> Message-ID: <1468484055-27341-2-git-send-email-dedeckeh@gmail.com> Commit c6858766 adds teardown support when l3_dev link is lost especially for shell protocols that have no proto task. However shell protocols which have a proto task running like ppp will also be teared down which is not always the expected action. As an example the PPP daemon can be put into persist state trying to re-establish the link via a hold off mechanism which is not possible when the daemon is terminated by the proto shell teardown. Therefore restrict the teardown action for shell protocols having no proto task. Signed-off-by: Hans Dedecker --- interface.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface.c b/interface.c index 7b18cef..8d9dc9c 100644 --- a/interface.c +++ b/interface.c @@ -408,7 +408,8 @@ interface_l3_dev_cb(struct device_user *dep, enum device_event ev) switch (ev) { case DEV_EVENT_LINK_DOWN: - interface_proto_event(iface->proto, PROTO_CMD_TEARDOWN, false); + if (iface->proto->handler->flags & PROTO_FLAG_NO_TASK) + interface_proto_event(iface->proto, PROTO_CMD_TEARDOWN, false); break; default: break; -- 1.9.1 _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From dedeckeh at gmail.com Thu Jul 14 04:14:15 2016 From: dedeckeh at gmail.com (Hans Dedecker) Date: Thu, 14 Jul 2016 10:14:15 +0200 Subject: [OpenWrt-Devel] [PATCH netifd 3/3] proto: Display proto flags when dumping the protocol handlers in ubus In-Reply-To: <1468484055-27341-1-git-send-email-dedeckeh@gmail.com> References: <1468484055-27341-1-git-send-email-dedeckeh@gmail.com> Message-ID: <1468484055-27341-3-git-send-email-dedeckeh@gmail.com> Signed-off-by: Hans Dedecker --- proto.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/proto.c b/proto.c index 45eeb4b..4cbf3f4 100644 --- a/proto.c +++ b/proto.c @@ -567,7 +567,13 @@ proto_dump_handlers(struct blob_buf *b) blobmsg_add_string(b, p->config_params->params[i].name, uci_get_validate_string(p->config_params, i)); blobmsg_close_table(b, v); } + blobmsg_add_u8(b, "immediate", !!(p->flags & PROTO_FLAG_IMMEDIATE)); blobmsg_add_u8(b, "no_device", !!(p->flags & PROTO_FLAG_NODEV)); + blobmsg_add_u8(b, "init_available", !!(p->flags & PROTO_FLAG_INIT_AVAILABLE)); + blobmsg_add_u8(b, "renew_available", !!(p->flags & PROTO_FLAG_RENEW_AVAILABLE)); + blobmsg_add_u8(b, "force_link_default", !!(p->flags & PROTO_FLAG_FORCE_LINK_DEFAULT)); + blobmsg_add_u8(b, "last_error", !!(p->flags & PROTO_FLAG_LASTERROR)); + blobmsg_add_u8(b, "no_task", !!(p->flags & PROTO_FLAG_NO_TASK)); blobmsg_close_table(b, c); } } -- 1.9.1 _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hauke at hauke-m.de Thu Jul 14 08:07:43 2016 From: hauke at hauke-m.de (Hauke Mehrtens) Date: Thu, 14 Jul 2016 14:07:43 +0200 Subject: [OpenWrt-Devel] [RFD] Future telephone meeting In-Reply-To: References: Message-ID: Hi, Like I said I would prefer a telephone conference over an in person meeting, because that would not exclude people who can not effort traveling. We could have an in person meeting afterwards. As nothing happened in the last week regarding this topic I created this dudle to find a time when we can have a telephone meeting. All OpenWrt core developers and all LEDE committers are encouraged to take part in the meeting. Please fill out the dudle to find a date and time: https://dudle.inf.tu-dresden.de/openwrt_lede/ The suggested dates are from 21.7 to 31.7. The first suggested time slot starts at 9 AM CEST and the last time slot starts at 10 PM CEST. The meeting will probably take one hour. Has anybody a suggestion what tool to use? Google handouts, fuze, other suggestions? Many of us will probably be at the Embedded Linux conference Europe (ELCE) in Berlin from 11. to 13. October 2016, John suggested that we should meet there in person in addition to a telephone conference. The prplWrt summit will also take place as part of the ELCE. I hope we can solve most of the problems before October. I have nothing planed for ELCE, but taking part at an potential meeting should be possible without paying for ELCE. To not exclude people having problems with traveling, it would be good if we could solve most of the problems before the ELCE. Hauke _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From ronaldo at ronaldoafonso.com.br Thu Jul 14 09:15:40 2016 From: ronaldo at ronaldoafonso.com.br (Ronaldo Afonso) Date: Thu, 14 Jul 2016 10:15:40 -0300 Subject: [OpenWrt-Devel] How to check if its the first boot ever? In-Reply-To: References: Message-ID: Hi, Thanks very much for all your replies. I'll try to do some like that. Maybe an "uci get system. at system [0].fistboot". []s Ronaldo 2016-07-14 3:41 GMT-03:00 Rafa? Mi?ecki : > On 13 July 2016 at 22:27, Ronaldo Afonso > wrote: > > More specifically, my scripts at "/etc/uci-defaults" need to know if > they > > are being executed by flashing over a "router original firmware" > > (factory.bin) or a previews OpenWrt firmware (sysupgrade.bin). > > What about using something like /etc/config/ronaldo with some option > like "firstboot"? Of course you should add this file to the list of > preserved config files. > -- Ronaldo Afonso 11 9 5252 0484 www.ronaldoafonso.com.br -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From david.fernandez.work at googlemail.com Fri Jul 15 04:07:07 2016 From: david.fernandez.work at googlemail.com (David Fernandez) Date: Fri, 15 Jul 2016 09:07:07 +0100 Subject: [OpenWrt-Devel] Having a [kernel] package setting kernel CONFIG_XXX. Message-ID: <38f49067-349d-917d-5738-34c7493810a4@googlemail.com> Hi there, I'm trying to have a kernel package to emnable some kernel configuration settings. I've tried using the KCONFIG:=CONFIG_XXX in the kernel packages, or creating "config KERNEL_XXX" in any kind of package. Only to find that the setting makes it as far as $(LINUX_DIR)/.config.set but never into $(LINUX_DIR)/.config Is there a way to do this? I''ve tried with top of trunk, as well as some older trunk commits. Is it broken there? Thanks in advance. _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From baptiste at bitsofnetworks.org Sat Jul 16 09:35:28 2016 From: baptiste at bitsofnetworks.org (Baptiste Jonglez) Date: Sat, 16 Jul 2016 15:35:28 +0200 Subject: [OpenWrt-Devel] Having a [kernel] package setting kernel CONFIG_XXX. In-Reply-To: <38f49067-349d-917d-5738-34c7493810a4@googlemail.com> References: <38f49067-349d-917d-5738-34c7493810a4@googlemail.com> Message-ID: <20160716133527.GB24880@lud.polynome.dn42> Hi, On Fri, Jul 15, 2016 at 09:07:07AM +0100, David Fernandez wrote: > I'm trying to have a kernel package to emnable some kernel configuration > settings. > > I've tried using the KCONFIG:=CONFIG_XXX in the kernel packages, or creating > "config KERNEL_XXX" in any kind of package. > > Only to find that the setting makes it as far as $(LINUX_DIR)/.config.set > but never into $(LINUX_DIR)/.config > > Is there a way to do this? There is a strange bug with Kconfig, maybe you are hitting it. Basically, if a Kconfig symbol does not have a string description attached to it, it is not possible to select it directly. Have a look at all the "kconfig hacks" patches that are here as workaround, for instance: https://git.lede-project.org/?p=source.git;a=blob;f=target/linux/generic/patches-4.4/254-textsearch_kconfig_hacks.patch;hb=HEAD I tried to track the bug down, but it's quite complex. It definitely looks like it comes from the scripts/kconfig tool upstream, not from OpenWRT/LEDE. OpenWRT/LEDE passes all the kernel symbols it wants to select to scripts/kconfig from Linux, presumably to handle symbol dependencies in the kernel. But kconfig seems to ignore symbols for which there is no string description (in the KConfig file that defines the symbol). -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: not available URL: -------------- next part -------------- _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hojuruku at gmail.com Sat Jul 16 16:24:24 2016 From: hojuruku at gmail.com (Luke McKee) Date: Sun, 17 Jul 2016 03:24:24 +0700 Subject: [OpenWrt-Devel] pppd: Someone please fix the Makefile to install net/pppd_defs.h so my pull request for rp-pppoe can go through Message-ID: https://github.com/openwrt/packages/pull/2974 Attention @jow- @champtar Also users with historical interest with rp-pppoe http://git.openwrt.org/?p=packages.git;a=history;f=net/rp-pppoe;h=c4c326bf49614aa8ef4ef224b747af01100ef242;hb=HEAD @hauke @nbd168 Quote: 6bcfc3a For this package to compile, it just needs openwrt pppd to install net/ppp_defs.h into the staging area that requires a small modification to package pppd Makefile openwrt/openwrt at 5de3ef3 < i.e. this change to pppd Makefile : https://github.com/openwrt/openwrt/commit/5de3ef3 > from pull request: openwrt/openwrt#15 Could the package maintainer please expedite this, as @jow said every package should copy the file from pppd and patch it in which is just insane. rp-pppoe is not recommended for production environments nearly everone on the internet as an access concentrator, but it's better than nothing (what openwrt has now). In the near future I'll also try to merge accel-ppp, that is much better as it supports snmp, doesn't fork pppd processes and is completely kernel mode only. Changes made. 1) Stopped building installing the pppoe client (usermode) & rp-pppoe.so as it's already provided by pppd to prevent conflicts. 2) Did a fix for musl 1.1 compatibility inspired by: e76f394 3) Saw a very large free memory limit hardcoded into rp-pppoe that was ignored if you bought the commercial verison. Lowered it to a more conservative value considering musl apps compiled with -Os 3) Saw a very large free memory limit hardcoded into rp-pppoe that was ignored if you bought the commercial verison. Lowered it to a more conserative value considering musl apps compiled with -Os 3) Saw a very large free memory limit hard-coded into rp-pppoe that was ignored if you bought the commercial verison. Lowered it to a more conserative value considering compiling with musl & -Os have much less memory demands 4) changed the default options 5) Overrode configure to use the already installed rp-pppoe.so, the location of this library and even the mtu 1492 (if larger than 1500 is set) is hardcoded in the pppoe-server binary There is no uci or procd init scripts support yet. Most people wont want this and will use their own ppp if-up/down scripts to manage how their want their PPPOE access concentrator set up. If there is demand for this I will do it, if I get package maintainer status for this one. Compile-tested: Openwrt Buildroot, gcc 5.0, fortify, RELRO, SSP conserative Run-Tested: Not yet, but great care was taken the package was configured correctly reviewing the source, config.h and the defines. You may leave the pull request open until my testing is complete. I rather just get it out there now the minority of openwrt users who are interested in using this. Signed-off-by: Luke McKee hojuruku at gmail.com https://dev.openwrt.org/ticket/21350 Seven months ago someone nagged for this to be fixed. That makes only two people that want this :) >Changed 7 months ago by @nbd168 >Resolution set to wontfix >Status changed from new to closed >rp-pppoe is unmaintained, no changes will be made until it is cleaned up and submitted to the github repo. DONE. _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From cuero.bugot at gmail.com Sun Jul 17 08:08:34 2016 From: cuero.bugot at gmail.com (Cuero Bugot) Date: Sun, 17 Jul 2016 14:08:34 +0200 Subject: [OpenWrt-Devel] [PATCH] [Build] Allows external kernel tree to be a relative path In-Reply-To: References: Message-ID: Should I include more description for this change? This is quite interesting when using an external tree for the kernel sources and yet want to share the project in the team (thus absolute path is not an option). I do not mind keeping this patch on my private fork, only I thought it could be interesting to other people too. On Mon, Jul 11, 2016 at 4:44 PM, Cuero Bugot wrote: > From: Cuero Bugot > > CONFIG_EXTERNAL_KERNEL_TREE .config settings allows building the kernel > from an external tree directory. It currently only accept absolute path. > This patch is about allowing relative path. This is particularly > convenient if you have your openwrt and kernel sources hosted remotely, > have several persons working on the same sources, but possibly on different > location on their machine! > The code bellow check if the path is relative or absolute, and if relative > prepend it with openwrt TOPDIR path. > > --- > > diff --git a/config/Config-devel.in b/config/Config-devel.in > index 938f0b3..5ab32d6 100644 > --- a/config/Config-devel.in > +++ b/config/Config-devel.in > @@ -64,6 +64,9 @@ menuconfig DEVEL > config EXTERNAL_KERNEL_TREE > string "Use external kernel tree" if DEVEL > default "" > + help > + Path to the external kernel source tree. If the provided path is not > absolute, it is > + relative to the openwrt top directory. > > config KERNEL_GIT_CLONE_URI > string "Enter git repository to clone" if DEVEL > diff --git a/include/kernel-defaults.mk b/include/kernel-defaults.mk > index 406fd46..fdfcb23 100644 > --- a/include/kernel-defaults.mk > +++ b/include/kernel-defaults.mk > @@ -63,7 +63,13 @@ else > if [ -d $(LINUX_DIR) ]; then \ > rmdir $(LINUX_DIR); \ > fi > - ln -s $(CONFIG_EXTERNAL_KERNEL_TREE) $(LINUX_DIR) > + # Check if the provided external path is absolute or relative > + # if the path is relative, build the proper path from the openwrt top > dir. > + if [ "${CONFIG_EXTERNAL_KERNEL_TREE:0:1}" = "/" ]; then \ > + ln -s $(CONFIG_EXTERNAL_KERNEL_TREE) $(LINUX_DIR); \ > + else \ > + ln -s $(TOPDIR)/$(CONFIG_EXTERNAL_KERNEL_TREE) $(LINUX_DIR); \ > + fi > endef > endif > > > Signed-off-by: Cuero Bugot > > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From tpham3783 at gmail.com Sun Jul 17 17:42:48 2016 From: tpham3783 at gmail.com (Toan Pham) Date: Sun, 17 Jul 2016 17:42:48 -0400 Subject: [OpenWrt-Devel] [solved] Linksys E1700 firmware upload throws "incorrect Firmware" In-Reply-To: References: <573CC961.4090503@sbg.at> <573E0C8B.8070807@sbg.at> Message-ID: I know that this is an old post; but I would like to bring up two issues with the current e1700 build. Please let me know if any of you're experiencing the same issues. 1. Openwrt only supports 100BaseT ethernet (the original/manufacturer FW supports 1gigabit). 2. Wifi access point behave very strangely, I could not get it to work reliably, so I had to revert back to the manufacturer FW. TP ? -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From baptiste at bitsofnetworks.org Wed Jul 20 02:29:13 2016 From: baptiste at bitsofnetworks.org (Baptiste Jonglez) Date: Wed, 20 Jul 2016 08:29:13 +0200 Subject: [OpenWrt-Devel] [PATCH] buildroot: improve git submodule handling for packages In-Reply-To: <1456536772-14653-1-git-send-email-karlp@tweak.net.au> References: <1456536772-14653-1-git-send-email-karlp@tweak.net.au> Message-ID: <20160720062913.GA7376@lud.polynome.dn42> On Sat, Feb 27, 2016 at 01:32:52AM +0000, Karl Palsson wrote: > This changes the buildroot dependency from git-1.6.2 to git 1.7.12.2, > which was released September 2012. I find this annoying, since Debian wheezy only has git 1.7.10.4. Actually, sometimes I use a squeeze box for building, and it works perfectly fine. > Signed-off-by: Darik Horn > Signed-off-by: Karl Palsson > --- > include/download.mk | 5 +++-- > include/prereq-build.mk | 4 ++-- > 2 files changed, 5 insertions(+), 4 deletions(-) > > > Note: this does NOT help with CONFIG_SRC_TREE_OVERRIDE=y! > > diff --git a/include/download.mk b/include/download.mk > index 8619734..a118aad 100644 > --- a/include/download.mk > +++ b/include/download.mk > @@ -90,8 +90,9 @@ define DownloadMethod/git > cd $(TMP_DIR)/dl && \ > rm -rf $(SUBDIR) && \ > [ \! -d $(SUBDIR) ] && \ > - git clone $(URL) $(SUBDIR) --recursive && \ > - (cd $(SUBDIR) && git checkout $(VERSION) && git submodule update) && \ > + git clone $(URL) $(SUBDIR) && \ > + (cd $(SUBDIR) && git checkout $(VERSION) && \ > + git submodule update --init --recursive) && \ > echo "Packing checkout..." && \ > rm -rf $(SUBDIR)/.git && \ > $(call dl_pack,$(TMP_DIR)/dl/$(FILE),$(SUBDIR)) && \ > diff --git a/include/prereq-build.mk b/include/prereq-build.mk > index bcb2103..23a5b93 100644 > --- a/include/prereq-build.mk > +++ b/include/prereq-build.mk > @@ -154,8 +154,8 @@ $(eval $(call SetupHostCommand,python,Please install Python 2.x, \ > $(eval $(call SetupHostCommand,svn,Please install the Subversion client, \ > svn --version | grep Subversion)) > > -$(eval $(call SetupHostCommand,git,Please install Git (git-core) >= 1.6.5, \ > - git clone 2>&1 | grep -- --recursive)) > +$(eval $(call SetupHostCommand,git,Please install Git (git-core) >= 1.7.12.2, \ > + git submodule update --help 2>&1 | grep -- --recursive)) > > $(eval $(call SetupHostCommand,file,Please install the 'file' package, \ > file --version 2>&1 | grep file)) -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: not available URL: -------------- next part -------------- _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From fengling.qin at gmail.com Thu Jul 21 05:08:37 2016 From: fengling.qin at gmail.com (fengling.qin) Date: Thu, 21 Jul 2016 17:08:37 +0800 Subject: [OpenWrt-Devel] Create Avnet brand in the new data entry page Message-ID: <4CCA6F3F-C768-4B40-A258-B7C7AD19A969@gmail.com> Hi, I am starting develop with Avnet Zedboard, based Zynq-7000 ARM/FPGA Soc. I found the code below was added but without documents, so I wanna create a new data entry page for documents, but without success. The page is https://wiki.openwrt.org/meta/create_new_dataentry_page Can some some here add Avnet to the brand list ? Attach some commits here: https://github.com/openwrt/openwrt/commit/addbde1976b932f70cf3d2f682e75b55cb1db9e9#diff-a4a7c5b9de6e062ee563f05332a6063d https://github.com/openwrt/openwrt/commit/24ef2c55861b889503decd6a45d281c0184d0eea#diff-a4a7c5b9de6e062ee563f05332a6063d Yours, Fengling -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From Alexey.Brodkin at synopsys.com Thu Jul 21 13:45:36 2016 From: Alexey.Brodkin at synopsys.com (Alexey Brodkin) Date: Thu, 21 Jul 2016 17:45:36 +0000 Subject: [OpenWrt-Devel] Add ARC platforms to platforms wiki Message-ID: <1469123051.2370.36.camel@synopsys.com> Hello, I'm wondering if there's a chance to add information about ARC platforms in the Wiki here?https://dev.openwrt.org/wiki/platforms? I think something like this will work ================================================================================================== Target name Platform ? ? ? ? ? ? ? ?Architecture Endianness Developer(s) Known Issues/Notes -------------------------------------------------------------------------------------------------- arc770 ? ? ? ? ?Synopsys DesignWare ARC 770D ? ARC ? ? ? ? ? ? ?little ? ? ? ? ?abrodkin ? ? ? ?arc770 archs38 ? ? ? ? Synopsys DesignWare ARC HS38? ?ARC ? ? ? ? ? ? ?little ? ? ? ? ?abrodkin ? ? ? ?archs38 ================================================================================================== Regards, Alexey _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From f.fainelli at gmail.com Thu Jul 21 14:23:08 2016 From: f.fainelli at gmail.com (Florian Fainelli) Date: Thu, 21 Jul 2016 11:23:08 -0700 Subject: [OpenWrt-Devel] Add ARC platforms to platforms wiki In-Reply-To: <1469123051.2370.36.camel@synopsys.com> References: <1469123051.2370.36.camel@synopsys.com> Message-ID: On 07/21/2016 10:45 AM, Alexey Brodkin wrote: > Hello, > > I'm wondering if there's a chance to add information about ARC > platforms in the Wiki here https://dev.openwrt.org/wiki/platforms? Done > > I think something like this will work > ================================================================================================== > Target name Platform Architecture Endianness Developer(s) Known > Issues/Notes > -------------------------------------------------------------------------------------------------- > arc770 Synopsys DesignWare ARC 770D ARC little abrodkin arc770 > archs38 Synopsys DesignWare ARC HS38 ARC little abrodkin archs38 > ================================================================================================== > > Regards, > Alexey > _______________________________________________ > openwrt-devel mailing list > openwrt-devel at lists.openwrt.org > https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel > -- Florian _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From Alexey.Brodkin at synopsys.com Thu Jul 21 14:43:55 2016 From: Alexey.Brodkin at synopsys.com (Alexey Brodkin) Date: Thu, 21 Jul 2016 18:43:55 +0000 Subject: [OpenWrt-Devel] Add ARC platforms to platforms wiki In-Reply-To: References: <1469123051.2370.36.camel@synopsys.com> Message-ID: <1469126551.2370.38.camel@synopsys.com> Hi Florian, On Thu, 2016-07-21 at 11:23 -0700, Florian Fainelli wrote: > On 07/21/2016 10:45 AM, Alexey Brodkin wrote: > > > > Hello, > > > > I'm wondering if there's a chance to add information about ARC > > platforms in the Wiki here https://dev.openwrt.org/wiki/platforms? > > Done Thanks a lot! -Alexey _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From Alexey.Brodkin at synopsys.com Fri Jul 22 04:58:30 2016 From: Alexey.Brodkin at synopsys.com (Alexey Brodkin) Date: Fri, 22 Jul 2016 08:58:30 +0000 Subject: [OpenWrt-Devel] Do we really need 000-keep_initrafs_the_default.patch? Message-ID: <1469177824.10779.15.camel@synopsys.com> Hello, I'm wondering why there's a need for "000-keep_initrafs_the_default.patch"? It could be found here: ---------------------->8-------------------- target/linux/generic/patches-3.18/000-keep_initrafs_the_default.patch target/linux/generic/patches-4.1/000-keep_initrafs_the_default.patch target/linux/generic/patches-4.4/000-keep_initrafs_the_default.patch ---------------------->8-------------------- With that patch in place for initramfs no additional options are reported for "/" partition. What's really important is missing info about sizes. Which in its turn makes opkg think that there's no space on "/" partition to install software. I understand that's a sort of corner-case, people rarely install packages on ramfs but anyways why not? Just in case that's what I see with the patch: ---------------------->8-------------------- root at lede:/# cat /proc/mounts rootfs / rootfs rw 0 0 proc /proc proc rw,nosuid,nodev,noexec,noatime 0 0 sysfs /sys sysfs rw,nosuid,nodev,noexec,noatime 0 0 tmpfs /tmp tmpfs rw,nosuid,nodev,noatime 0 0 tmpfs /dev tmpfs rw,nosuid,relatime,size=512k,mode=755 0 0 devpts /dev/pts devpts rw,nosuid,noexec,relatime,mode=600 0 0 debugfs /sys/kernel/debug debugfs rw,noatime 0 0 ---------------------->8-------------------- And without: ---------------------->8-------------------- root at lede:/# cat /proc/mounts rootfs / rootfs rw,size=256168k,nr_inodes=32021 0 0 proc /proc proc rw,nosuid,nodev,noexec,noatime 0 0 sysfs /sys sysfs rw,nosuid,nodev,noexec,noatime 0 0 tmpfs /tmp tmpfs rw,nosuid,nodev,noatime 0 0 tmpfs /dev tmpfs rw,nosuid,relatime,size=512k,mode=755 0 0 devpts /dev/pts devpts rw,nosuid,noexec,relatime,mode=600 0 0 debugfs /sys/kernel/debug debugfs rw,noatime 0 0 ---------------------->8-------------------- Note how different is entry for rootfs. If there're no objections I'll go ahead and send a patch that gets rid of all 3 patches mentioned above. -Alexey _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From nbd at nbd.name Fri Jul 22 05:14:46 2016 From: nbd at nbd.name (Felix Fietkau) Date: Fri, 22 Jul 2016 11:14:46 +0200 Subject: [OpenWrt-Devel] [LEDE-DEV] Do we really need 000-keep_initrafs_the_default.patch? In-Reply-To: <1469177824.10779.15.camel@synopsys.com> References: <1469177824.10779.15.camel@synopsys.com> Message-ID: <878a1b60-bcf9-6373-ae2b-df10041bfd1d@nbd.name> On 2016-07-22 10:58, Alexey Brodkin wrote: > Hello, > > I'm wondering why there's a need for "000-keep_initrafs_the_default.patch"? > It could be found here: > ---------------------->8-------------------- > target/linux/generic/patches-3.18/000-keep_initrafs_the_default.patch > target/linux/generic/patches-4.1/000-keep_initrafs_the_default.patch > target/linux/generic/patches-4.4/000-keep_initrafs_the_default.patch > ---------------------->8-------------------- > > With that patch in place for initramfs no additional options are reported > for "/" partition. What's really important is missing info about sizes. > Which in its turn makes opkg think that there's no space on "/" partition > to install software. > > I understand that's a sort of corner-case, people rarely install packages on > ramfs but anyways why not? > > Just in case that's what I see with the patch: > ---------------------->8-------------------- > root at lede:/# cat /proc/mounts > rootfs / rootfs rw 0 0 > proc /proc proc rw,nosuid,nodev,noexec,noatime 0 0 > sysfs /sys sysfs rw,nosuid,nodev,noexec,noatime 0 0 > tmpfs /tmp tmpfs rw,nosuid,nodev,noatime 0 0 > tmpfs /dev tmpfs rw,nosuid,relatime,size=512k,mode=755 0 0 > devpts /dev/pts devpts rw,nosuid,noexec,relatime,mode=600 0 0 > debugfs /sys/kernel/debug debugfs rw,noatime 0 0 > ---------------------->8-------------------- > > And without: > ---------------------->8-------------------- > root at lede:/# cat /proc/mounts > rootfs / rootfs rw,size=256168k,nr_inodes=32021 0 0 > proc /proc proc rw,nosuid,nodev,noexec,noatime 0 0 > sysfs /sys sysfs rw,nosuid,nodev,noexec,noatime 0 0 > tmpfs /tmp tmpfs rw,nosuid,nodev,noatime 0 0 > tmpfs /dev tmpfs rw,nosuid,relatime,size=512k,mode=755 0 0 > devpts /dev/pts devpts rw,nosuid,noexec,relatime,mode=600 0 0 > debugfs /sys/kernel/debug debugfs rw,noatime 0 0 > ---------------------->8-------------------- > > Note how different is entry for rootfs. > > If there're no objections I'll go ahead and send a patch that > gets rid of all 3 patches mentioned above. No objections from me. I looked at the commit that added this patch for the first time, and it does not explain the reason for making this change at all. - Felix _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From Alexey.Brodkin at synopsys.com Fri Jul 22 06:04:06 2016 From: Alexey.Brodkin at synopsys.com (Alexey Brodkin) Date: Fri, 22 Jul 2016 13:04:06 +0300 Subject: [OpenWrt-Devel] [PATCH] sunxi/pcduino3: Remove selection of absent rtl8188eu Message-ID: <1469181846-5158-1-git-send-email-abrodkin@synopsys.com> Since commit 217a64375547 "wireless: remove rtl8188eu (staging)" there's no point in selection of the missing module. Signed-off-by: Alexey Brodkin Cc: John Crispin Cc: Zoltan Herpai --- target/linux/sunxi/profiles/pcduino3.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/sunxi/profiles/pcduino3.mk b/target/linux/sunxi/profiles/pcduino3.mk index 4d6dcb1..1c4e753 100644 --- a/target/linux/sunxi/profiles/pcduino3.mk +++ b/target/linux/sunxi/profiles/pcduino3.mk @@ -9,7 +9,7 @@ define Profile/Linksprite_pcDuino3 NAME:=pcDuino3 PACKAGES:=\ uboot-sunxi-Linksprite_pcDuino3 kmod-sun4i-emac kmod-rtc-sunxi \ - kmod-net-rtl8188eu kmod-ata-core kmod-ata-sunxi + kmod-ata-core kmod-ata-sunxi endef define Profile/Linksprite_pcDuino3/Description -- 2.7.4 _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From Alexey.Brodkin at synopsys.com Fri Jul 22 06:18:41 2016 From: Alexey.Brodkin at synopsys.com (Alexey Brodkin) Date: Fri, 22 Jul 2016 13:18:41 +0300 Subject: [OpenWrt-Devel] [PATCH] linux: Get rid of 000-keep_initrafs_the_default.patch Message-ID: <1469182721-6375-1-git-send-email-abrodkin@synopsys.com> With that patch in place for initramfs no additional options are reported for "/" partition. What's really important is missing info about sizes. Which in its turn makes opkg think that there's no space on "/" partition to install software. I understand that's a sort of corner-case, people rarely install packages on ramfs but anyways why not? Just in case that's what I see with the patch: ---------------------->8-------------------- root at lede:/# cat /proc/mounts rootfs / rootfs rw 0 0 proc /proc proc rw,nosuid,nodev,noexec,noatime 0 0 sysfs /sys sysfs rw,nosuid,nodev,noexec,noatime 0 0 tmpfs /tmp tmpfs rw,nosuid,nodev,noatime 0 0 tmpfs /dev tmpfs rw,nosuid,relatime,size=512k,mode=755 0 0 devpts /dev/pts devpts rw,nosuid,noexec,relatime,mode=600 0 0 debugfs /sys/kernel/debug debugfs rw,noatime 0 0 ---------------------->8-------------------- And without: ---------------------->8-------------------- root at lede:/# cat /proc/mounts rootfs / rootfs rw,size=256168k,nr_inodes=32021 0 0 proc /proc proc rw,nosuid,nodev,noexec,noatime 0 0 sysfs /sys sysfs rw,nosuid,nodev,noexec,noatime 0 0 tmpfs /tmp tmpfs rw,nosuid,nodev,noatime 0 0 tmpfs /dev tmpfs rw,nosuid,relatime,size=512k,mode=755 0 0 devpts /dev/pts devpts rw,nosuid,noexec,relatime,mode=600 0 0 debugfs /sys/kernel/debug debugfs rw,noatime 0 0 ---------------------->8-------------------- Note how different is entry for rootfs. And given there's no known rationale for that patch we're getting rid of it. Signed-off-by: Alexey Brodkin Cc: Jonas Gorski Cc: Rafa? Mi?ecki Cc: John Crispin Cc: Felix Fietkau --- .../000-keep_initrafs_the_default.patch | 25 ---------------------- .../000-keep_initrafs_the_default.patch | 25 ---------------------- .../000-keep_initrafs_the_default.patch | 25 ---------------------- 3 files changed, 75 deletions(-) delete mode 100644 target/linux/generic/patches-3.18/000-keep_initrafs_the_default.patch delete mode 100644 target/linux/generic/patches-4.1/000-keep_initrafs_the_default.patch delete mode 100644 target/linux/generic/patches-4.4/000-keep_initrafs_the_default.patch diff --git a/target/linux/generic/patches-3.18/000-keep_initrafs_the_default.patch b/target/linux/generic/patches-3.18/000-keep_initrafs_the_default.patch deleted file mode 100644 index d4164ca..0000000 --- a/target/linux/generic/patches-3.18/000-keep_initrafs_the_default.patch +++ /dev/null @@ -1,25 +0,0 @@ -Upstream changed the default rootfs to tmpfs when none has been passed -to the kernel - this doesn't fit our purposes, so change it back. - -Signed-off-by: Imre Kaloz - ---- a/init/do_mounts.c -+++ b/init/do_mounts.c -@@ -623,6 +623,7 @@ int __init init_rootfs(void) - if (err) - return err; - -+#if 0 - if (IS_ENABLED(CONFIG_TMPFS) && !saved_root_name[0] && - (!root_fs_names || strstr(root_fs_names, "tmpfs"))) { - err = shmem_init(); -@@ -630,6 +631,9 @@ int __init init_rootfs(void) - } else { - err = init_ramfs_fs(); - } -+#else -+ err = init_ramfs_fs(); -+#endif - - if (err) - unregister_filesystem(&rootfs_fs_type); diff --git a/target/linux/generic/patches-4.1/000-keep_initrafs_the_default.patch b/target/linux/generic/patches-4.1/000-keep_initrafs_the_default.patch deleted file mode 100644 index 5e56d44..0000000 --- a/target/linux/generic/patches-4.1/000-keep_initrafs_the_default.patch +++ /dev/null @@ -1,25 +0,0 @@ -Upstream changed the default rootfs to tmpfs when none has been passed -to the kernel - this doesn't fit our purposes, so change it back. - -Signed-off-by: Imre Kaloz - ---- a/init/do_mounts.c -+++ b/init/do_mounts.c -@@ -628,6 +628,7 @@ int __init init_rootfs(void) - if (err) - return err; - -+#if 0 - if (IS_ENABLED(CONFIG_TMPFS) && !saved_root_name[0] && - (!root_fs_names || strstr(root_fs_names, "tmpfs"))) { - err = shmem_init(); -@@ -635,6 +636,9 @@ int __init init_rootfs(void) - } else { - err = init_ramfs_fs(); - } -+#else -+ err = init_ramfs_fs(); -+#endif - - if (err) - unregister_filesystem(&rootfs_fs_type); diff --git a/target/linux/generic/patches-4.4/000-keep_initrafs_the_default.patch b/target/linux/generic/patches-4.4/000-keep_initrafs_the_default.patch deleted file mode 100644 index e6f1be4..0000000 --- a/target/linux/generic/patches-4.4/000-keep_initrafs_the_default.patch +++ /dev/null @@ -1,25 +0,0 @@ -Upstream changed the default rootfs to tmpfs when none has been passed -to the kernel - this doesn't fit our purposes, so change it back. - -Signed-off-by: Imre Kaloz - ---- a/init/do_mounts.c -+++ b/init/do_mounts.c -@@ -633,6 +633,7 @@ int __init init_rootfs(void) - if (err) - return err; - -+#if 0 - if (IS_ENABLED(CONFIG_TMPFS) && !saved_root_name[0] && - (!root_fs_names || strstr(root_fs_names, "tmpfs"))) { - err = shmem_init(); -@@ -640,6 +641,9 @@ int __init init_rootfs(void) - } else { - err = init_ramfs_fs(); - } -+#else -+ err = init_ramfs_fs(); -+#endif - - if (err) - unregister_filesystem(&rootfs_fs_type); -- 2.7.4 _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From eschultz at prplfoundation.org Fri Jul 22 17:19:12 2016 From: eschultz at prplfoundation.org (Eric Schultz) Date: Fri, 22 Jul 2016 16:19:12 -0500 Subject: [OpenWrt-Devel] SSL Cert Message-ID: Just wanted to let folks know that the SSL cert expired on openwrt.org which makes openwrt.org inaccessible. Eric -- Eric Schultz, Community Manager, prpl Foundation http://www.prplfoundation.org eschultz at prplfoundation.org cell: 920-539-0404 -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From jonas.gorski at gmail.com Sat Jul 23 06:43:17 2016 From: jonas.gorski at gmail.com (Jonas Gorski) Date: Sat, 23 Jul 2016 12:43:17 +0200 Subject: [OpenWrt-Devel] [PATCH] linux: Get rid of 000-keep_initrafs_the_default.patch In-Reply-To: <1469182721-6375-1-git-send-email-abrodkin@synopsys.com> References: <1469182721-6375-1-git-send-email-abrodkin@synopsys.com> Message-ID: Hi, On 22 July 2016 at 12:18, Alexey Brodkin wrote: > With that patch in place for initramfs no additional options are > reported for "/" partition. What's really important is missing > info about sizes. Which in its turn makes opkg think that there's > no space on "/" partition to install software. > > I understand that's a sort of corner-case, people rarely install > packages on ramfs but anyways why not? > > Just in case that's what I see with the patch: > ---------------------->8-------------------- > root at lede:/# cat /proc/mounts > rootfs / rootfs rw 0 0 > proc /proc proc rw,nosuid,nodev,noexec,noatime 0 0 > sysfs /sys sysfs rw,nosuid,nodev,noexec,noatime 0 0 > tmpfs /tmp tmpfs rw,nosuid,nodev,noatime 0 0 > tmpfs /dev tmpfs rw,nosuid,relatime,size=512k,mode=755 0 0 > devpts /dev/pts devpts rw,nosuid,noexec,relatime,mode=600 0 0 > debugfs /sys/kernel/debug debugfs rw,noatime 0 0 > ---------------------->8-------------------- > > And without: > ---------------------->8-------------------- > root at lede:/# cat /proc/mounts > rootfs / rootfs rw,size=256168k,nr_inodes=32021 0 0 > proc /proc proc rw,nosuid,nodev,noexec,noatime 0 0 > sysfs /sys sysfs rw,nosuid,nodev,noexec,noatime 0 0 > tmpfs /tmp tmpfs rw,nosuid,nodev,noatime 0 0 > tmpfs /dev tmpfs rw,nosuid,relatime,size=512k,mode=755 0 0 > devpts /dev/pts devpts rw,nosuid,noexec,relatime,mode=600 0 0 > debugfs /sys/kernel/debug debugfs rw,noatime 0 0 > ---------------------->8-------------------- > > Note how different is entry for rootfs. > > And given there's no known rationale for that patch we're > getting rid of it. I gave this a small spin on brcm63xx and didn't see anything broken by it. Actually I didn't see anything changing at all, the /proc/mounts contents stayed the same with or without the patch. Jonas _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hojuruku at gmail.com Sat Jul 23 15:11:50 2016 From: hojuruku at gmail.com (Luke McKee) Date: Sun, 24 Jul 2016 02:11:50 +0700 Subject: [OpenWrt-Devel] [PATCH] fix include/cmake.mk so it allows out of source tree builds Message-ID: If you change PKG_BUILD_DIR it could work - but then you can't patch the source directory. https://github.com/openwrt/openwrt/pull/41 Some packages need out of source tree building with cmake, for example when building kernel modules. See an example here: https://sourceforge.net/p/accel-ppp/code/ci/master/tree/README This adds a new variable that can be used in Makefiles $(CMAKE_BINARY_DIR) Signed-off-by: Luke McKee hojuruku at gmail.com @nbd168 agrees, patching the include is the only way to go. This also needs to get merged into LEDE or a new package I'm working on accel-ppp (give me a week of testing etc) won't work. diff --git a/include/cmake.mk b/include/cmake.mk index 009c6c2..d75b3ef 100644 --- a/include/cmake.mk +++ b/include/cmake.mk @@ -6,7 +6,8 @@ ifneq ($(findstring c,$(OPENWRT_VERBOSE)),) MAKE_FLAGS+=VERBOSE=1 endif -CMAKE_SOURCE_DIR:=. +CMAKE_BINARY_DIR?=$(PKG_BUILD_DIR) +CMAKE_SOURCE_DIR?=. ifeq ($(CONFIG_EXTERNAL_TOOLCHAIN),) cmake_tool=$(TOOLCHAIN_DIR)/bin/$(1) @@ -35,7 +36,7 @@ CMAKE_HOST_FIND_ROOT_PATH:=$(STAGING_DIR)/host;$(STAGING_DIR_HOST) CMAKE_SHARED_LDFLAGS:=-Wl,-Bsymbolic-functions define Build/Configure/Default - (cd $(PKG_BUILD_DIR); \ + (cd $(CMAKE_BINARY_DIR); \ CFLAGS="$(TARGET_CFLAGS) $(EXTRA_CFLAGS)" \ CXXFLAGS="$(TARGET_CFLAGS) $(EXTRA_CFLAGS)" \ LDFLAGS="$(TARGET_LDFLAGS) $(EXTRA_LDFLAGS)" \ _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hauke at hauke-m.de Sat Jul 23 18:09:48 2016 From: hauke at hauke-m.de (Hauke Mehrtens) Date: Sun, 24 Jul 2016 00:09:48 +0200 Subject: [OpenWrt-Devel] SSL Cert In-Reply-To: References: Message-ID: <09b7b127-c41e-6b67-b461-d8be30c32920@hauke-m.de> Hi Kaloz, could you please change the ssl certificate. With HSTS it is pretty hard to circumvent the warning. Hauke On 07/22/2016 11:19 PM, Eric Schultz wrote: > Just wanted to let folks know that the SSL cert expired on openwrt.org > which makes openwrt.org > inaccessible. > > Eric _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From kris.braun at gmail.com Sat Jul 23 23:40:52 2016 From: kris.braun at gmail.com (Kris Braun) Date: Sun, 24 Jul 2016 03:40:52 +0000 Subject: [OpenWrt-Devel] Adding TL-WA850RE v2 support, eth0 not working Message-ID: I'm having trouble getting Ethernet working while developing a patch to add support for TL-WA850RE v2 based on TL-WR841N v9. Using a PC that connects to stock OpenWRT on a WA850RE v1, ethtool shows a connection but arp shows "(incomplete)" (i.e. no MAC address). All commands like telnet fail with "no route to host". Can anyone suggest changes or debugging I should try? I tried leaving everything exactly as TL-WR841N v9 with the exception of the TPLINK-HWID. Then I changed the eth init to only init eth0 like this: ath79_switch_data.phy4_mii_en = 1; ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ath79_eth0_data.phy_mask = BIT(4); ath79_eth0_data.duplex = DUPLEX_FULL; ath79_eth0_data.speed = SPEED_100; ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ath79_register_eth(0); And changed 02_network to only init eth0 like this: ucidef_set_interface_lan "eth0" Interestingly, with the first approach (no changes), a LED flashes when Ethernet is connected which doesn't happen for the second approach. But neither seem active at the ARP level. Thanks, Kris -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From hojuruku at gmail.com Sun Jul 24 04:03:29 2016 From: hojuruku at gmail.com (Luke McKee) Date: Sun, 24 Jul 2016 15:03:29 +0700 Subject: [OpenWrt-Devel] tdestroy in musl works differently to glibc? Message-ID: Slowly getting the accel-pppd package done... Lots of missing headers, as their usually are with musl vs glibc and a problem relating to atomic memory ops are already fixed as openwrt people bumped into the same issue with rtorrent. https://github.com/rakshasa/rtorrent/issues/156 error: '__free_fn_t' undeclared (first use in this function) that's used with tdestroy (search.h) with glibc, where's the docs on tdestroy with musl? Other's have run into this: http://www.openwall.com/lists/musl/2014/09/09/5 http://fossies.org/dox/musl-1.1.15/tdestroy_8c.html vs http://www.delorie.com/gnu/docs/glibc/libc_146.html Normally I'd spend some more time trying to patch alone. Already got 3 down and 67% of it building. TARGET_CFLAGS+= -D_GNU_SOURCE and __free_fn_t still isn't declared. Alsa-lib has it's own bundled include/search.h that includes the necessary typedef __free_fn_t #ifdef __USE_GNU /* Callback type for function to free a tree node. If the keys are atomic data this function should do nothing. */ typedef void (*__free_fn_t) __PMT ((void *__nodep)); /* Destroy the whole tree, call FREEFCT for each node or leaf. */ extern void tdestroy __PMT ((void *__root, __free_fn_t __freefct)); #endif This is the code needing fixing: static void l2tp_tunnel_free_sessions(struct l2tp_conn_t *conn) { void *sessions = conn->sessions; conn->sessions = NULL; tdestroy(sessions, (__free_fn_t)l2tp_session_free); /* Let l2tp_session_free() handle the session counter and * the reference held by the tunnel. */ } _______________________________________________ openwrt-devel mailing list openwrt-devel at lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel From sh-list at posteo.net Sun Jul 24 04:56:24 2016 From: sh-list at posteo.net (Stephan Hennig) Date: Sun, 24 Jul 2016 10:56:24 +0200 Subject: [OpenWrt-Devel] problem with uci delete In-Reply-To: <1d4b1b05-a11d-bfda-4ff2-e2cf8a72770a@posteo.net> References: <1d4b1b05-a11d-bfda-4ff2-e2cf8a72770a@posteo.net> Message-ID: <3c7db93c-9a2a-fd8b-0fee-5c0cda9e7312@posteo.net> [moving to devel, since there has been no response on the users list] Hi, uci help has this on the delete command > root at uap:~# uci > Usage: uci [] [] > > Commands: [...] > delete [.
[[.